コード例 #1
0
    def process_audio_track(self, elements):
        track = core.AudioStream()
        track.codec = 'Unknown'
        self.set_track_defaults(track)

        for elem in elements:
            elem_id = elem.get_id()
            if elem_id == MATROSKA_CODEC_ID:
                track.codec = elem.get_str()
            elif elem_id == MATROSKA_AUDIO_SETTINGS_ID:
                for settings_elem in self.process_one_level(elem):
                    settings_elem_id = settings_elem.get_id()
                    if settings_elem_id == MATROSKA_AUDIO_SAMPLERATE_ID:
                        track.samplerate = settings_elem.get_float_value()
                    elif settings_elem_id == MATROSKA_AUDIO_CHANNELS_ID:
                        track.channels = settings_elem.get_value()
            else:
                self.process_track_common(elem, track)


        if track.codec in FOURCCMap:
            track.codec = FOURCCMap[track.codec]
        elif '/' in track.codec and track.codec.split('/')[0] + '/' in FOURCCMap:
            track.codec = FOURCCMap[track.codec.split('/')[0] + '/']
        elif track.codec.startswith('A_'):
            track.codec = track.codec[2:]

        track.id = len(self.audio)
        self.audio.append(track)
        return track
コード例 #2
0
    def _parseSTRF(self, t, strh):
        fccType = strh['fccType']
        retval = {}
        if fccType == b'auds':
            (retval['wFormatTag'],
              retval['nChannels'],
              retval['nSamplesPerSec'],
              retval['nAvgBytesPerSec'],
              retval['nBlockAlign'],
              retval['nBitsPerSample'],
            ) = struct.unpack('<HHHHHH', t[0:12])
            ai = core.AudioStream()
            ai.samplerate = retval['nSamplesPerSec']
            ai.channels = retval['nChannels']
            # FIXME: Bitrate calculation is completely wrong.
            # ai.samplebits = retval['nBitsPerSample']
            # ai.bitrate = retval['nAvgBytesPerSec'] * 8

            # TODO: set code if possible
            # http://www.stats.uwa.edu.au/Internal/Specs/DXALL/FileSpec/\
            #    Languages
            # ai.language = strh['wLanguage']
            ai.codec = retval['wFormatTag']
            self.audio.append(ai)
        elif fccType == b'vids':
            v = struct.unpack('<IIIHH', t[0:16])
            (retval['biSize'],
              retval['biWidth'],
              retval['biHeight'],
              retval['biPlanes'],
              retval['biBitCount'],) = v
            v = struct.unpack('IIIII', t[20:40])
            (retval['biSizeImage'],
              retval['biXPelsPerMeter'],
              retval['biYPelsPerMeter'],
              retval['biClrUsed'],
              retval['biClrImportant'],) = v
            vi = core.VideoStream()
            vi.codec = t[16:20]
            vi.width = retval['biWidth']
            vi.height = retval['biHeight']
            # FIXME: Bitrate calculation is completely wrong.
            # vi.bitrate = strh['dwRate']
            vi.fps = float(strh['dwRate']) / strh['dwScale']

            log.debug("Define video length : strh['dwLength'] / vi.fps")
            vi.length = strh['dwLength'] / vi.fps
            self.video.append(vi)
        return retval
コード例 #3
0
ファイル: mp4.py プロジェクト: niol/deejayd
    def _readatom(self, file):
        s = file.read(8)
        if len(s) < 8:
            return 0

        atomsize, atomtype = struct.unpack('>I4s', s)
        if not atomtype.decode('latin1').isalnum():
            # stop at nonsense data
            return 0

        log.debug('%r [%X]' % (atomtype, atomsize))

        if atomtype == b'udta':
            # Userdata (Metadata)
            pos = 0
            tabl = {}
            i18ntabl = {}
            atomdata = file.read(atomsize - 8)
            while pos < atomsize - 12:
                (datasize, datatype) = struct.unpack('>I4s',
                                                     atomdata[pos:pos + 8])
                if datatype[0] == 169:
                    # i18n Metadata...
                    mypos = 8 + pos
                    while mypos + 4 < datasize + pos:
                        # first 4 Bytes are i18n header
                        (tlen, lang) = struct.unpack('>HH',
                                                     atomdata[mypos:mypos + 4])
                        i18ntabl[lang] = i18ntabl.get(lang, {})
                        l = atomdata[mypos + 4:mypos + tlen + 4]
                        i18ntabl[lang][datatype[1:]] = l
                        mypos += tlen + 4
                elif datatype == b'WLOC':
                    # Drop Window Location
                    pass
                else:
                    if atomdata[pos + 8:pos + datasize][0] > 1:
                        tabl[datatype] = atomdata[pos + 8:pos + datasize]
                pos += datasize
            if len(i18ntabl) > 0:
                for k in i18ntabl:
                    if k in QTLANGUAGES and QTLANGUAGES[k] == 'en':
                        self._appendtable('QTUDTA', i18ntabl[k])
                        self._appendtable('QTUDTA', tabl)
            else:
                log.debug('NO i18')
                self._appendtable('QTUDTA', tabl)

        elif atomtype == b'trak':
            atomdata = file.read(atomsize - 8)
            pos = 0
            trackinfo = {}
            tracktype = None
            while pos < atomsize - 8:
                (datasize, datatype) = struct.unpack('>I4s',
                                                     atomdata[pos:pos + 8])

                if datatype == b'tkhd':
                    tkhd = struct.unpack('>6I8x4H36xII',
                                         atomdata[pos + 8:pos + datasize])
                    trackinfo['width'] = tkhd[10] >> 16
                    trackinfo['height'] = tkhd[11] >> 16
                    trackinfo['id'] = tkhd[3]

                    try:
                        # XXX Timestamp of Seconds is since January 1st 1904!
                        # XXX 2082844800 is the difference between Unix and
                        # XXX Apple time. FIXME to work on Apple, too
                        self.timestamp = int(tkhd[1]) - 2082844800
                    except Exception as e:
                        log.err('There was trouble extracting timestamp')

                elif datatype == b'mdia':
                    pos += 8
                    datasize -= 8
                    log.debug('--> mdia information')

                    while datasize:
                        mdia = struct.unpack('>I4s', atomdata[pos:pos + 8])
                        if mdia[1] == b'mdhd':
                            # Parse based on version of mdhd header.  See
                            # http://wiki.multimedia.cx/index.php?title=QuickTime_container#mdhd
                            ver = atomdata[pos + 8]
                            if ver == 0:
                                mdhd = struct.unpack(
                                    '>IIIIIhh', atomdata[pos + 8:pos + 8 + 24])
                            elif ver == 1:
                                mdhd = struct.unpack(
                                    '>IQQIQhh', atomdata[pos + 8:pos + 8 + 36])
                            else:
                                mdhd = None

                            if mdhd:
                                # duration / time scale
                                trackinfo['length'] = mdhd[4] / mdhd[3]
                                if mdhd[5] in QTLANGUAGES:
                                    trackinfo['language'] = QTLANGUAGES[
                                        mdhd[5]]
                                # mdhd[6] == quality
                                self.length = max(self.length,
                                                  mdhd[4] / mdhd[3])
                        elif mdia[1] == b'minf':
                            # minf has only atoms inside
                            pos -= (mdia[0] - 8)
                            datasize += (mdia[0] - 8)
                        elif mdia[1] == b'stbl':
                            # stbl has only atoms inside
                            pos -= (mdia[0] - 8)
                            datasize += (mdia[0] - 8)
                        elif mdia[1] == b'hdlr':
                            hdlr = struct.unpack(
                                '>I4s4s', atomdata[pos + 8:pos + 8 + 12])
                            if hdlr[1] == b'mhlr':
                                if hdlr[2] == b'vide':
                                    tracktype = 'video'
                                if hdlr[2] == b'soun':
                                    tracktype = 'audio'
                        elif mdia[1] == b'stsd':
                            stsd = struct.unpack('>2I',
                                                 atomdata[pos + 8:pos + 8 + 8])
                            if stsd[1] > 0:
                                codec = atomdata[pos + 16:pos + 16 + 8]
                                codec = struct.unpack('>I4s', codec)
                                trackinfo['codec'] = codec[1]
                                if codec[1] == b'jpeg':
                                    tracktype = 'image'
                        elif mdia[1] == b'dinf':
                            dref = struct.unpack('>I4s',
                                                 atomdata[pos + 8:pos + 8 + 8])
                            log.debug('  --> %r, %r (useless)' % mdia)
                            if dref[1] == b'dref':
                                num = struct.unpack(
                                    '>I', atomdata[pos + 20:pos + 20 + 4])[0]
                                rpos = pos + 20 + 4
                                for ref in range(num):
                                    # FIXME: do somthing if this references
                                    ref = struct.unpack(
                                        '>I3s', atomdata[rpos:rpos + 7])
                                    data = atomdata[rpos + 7:rpos + ref[0]]
                                    rpos += ref[0]
                        else:
                            if mdia[1].startswith(b'st'):
                                log.debug('  --> %r, %r (sample)' % mdia)
                            elif mdia[1] == b'vmhd' and not tracktype:
                                # indicates that this track is video
                                tracktype = 'video'
                            elif mdia[1] in [b'vmhd', b'smhd'
                                             ] and not tracktype:
                                # indicates that this track is audio
                                tracktype = 'audio'
                            else:
                                log.debug('  --> %r, %r (unknown)' % mdia)

                        pos += mdia[0]
                        datasize -= mdia[0]

                elif datatype == b'udta':
                    log.debug(str(struct.unpack('>I4s', atomdata[:8])))
                else:
                    if datatype == b'edts':
                        log.debug('--> %r [%d] (edit list)' % \
                                  (datatype, datasize))
                    else:
                        log.debug('--> %r [%d] (unknown)' % \
                                  (datatype, datasize))
                pos += datasize

            info = None
            if tracktype == 'video':
                info = core.VideoStream()
                self.video.append(info)
            if tracktype == 'audio':
                info = core.AudioStream()
                self.audio.append(info)
            if info:
                for key, value in list(trackinfo.items()):
                    setattr(info, key, value)

        elif atomtype == b'mvhd':
            # movie header
            mvhd = struct.unpack('>6I2h', file.read(28))
            self.length = max(self.length, mvhd[4] / mvhd[3])
            self.volume = mvhd[6]
            file.seek(atomsize - 8 - 28, 1)

        elif atomtype == b'cmov':
            # compressed movie
            datasize, atomtype = struct.unpack('>I4s', file.read(8))
            if not atomtype == b'dcom':
                return atomsize

            method = struct.unpack('>4s', file.read(datasize - 8))[0]

            datasize, atomtype = struct.unpack('>I4s', file.read(8))
            if not atomtype == b'cmvd':
                return atomsize

            if method == b'zlib':
                data = file.read(datasize - 8)
                try:
                    decompressed = zlib.decompress(data)
                except Exception as e:
                    try:
                        decompressed = zlib.decompress(data[4:])
                    except Exception as e:
                        log.err('There was a proble decompressiong atom')
                        return atomsize

                decompressedIO = io.StringIO(decompressed)
                while self._readatom(decompressedIO):
                    pass

            else:
                log.info('unknown compression %r' % method)
                # unknown compression method
                file.seek(datasize - 8, 1)

        elif atomtype == b'moov':
            # decompressed movie info
            while self._readatom(file):
                pass

        elif atomtype == b'mdat':
            pos = file.tell() + atomsize - 8
            # maybe there is data inside the mdat
            log.info('parsing mdat')
            while self._readatom(file):
                pass
            log.info('end of mdat')
            file.seek(pos, 0)

        elif atomtype == b'rmra':
            # reference list
            while self._readatom(file):
                pass

        elif atomtype == b'rmda':
            # reference
            atomdata = file.read(atomsize - 8)
            pos = 0
            url = ''
            quality = 0
            datarate = 0
            while pos < atomsize - 8:
                (datasize, datatype) = struct.unpack('>I4s',
                                                     atomdata[pos:pos + 8])
                if datatype == b'rdrf':
                    rflags, rtype, rlen = struct.unpack(
                        '>I4sI', atomdata[pos + 8:pos + 20])
                    if rtype == b'url ':
                        url = atomdata[pos + 20:pos + 20 + rlen]
                        if url.find('\0') > 0:
                            url = url[:url.find('\0')]
                elif datatype == b'rmqu':
                    quality = struct.unpack('>I',
                                            atomdata[pos + 8:pos + 12])[0]

                elif datatype == b'rmdr':
                    datarate = struct.unpack('>I',
                                             atomdata[pos + 12:pos + 16])[0]

                pos += datasize
            if url:
                self._references.append((url, quality, datarate))

        else:
            if not atomtype in [b'wide', b'free']:
                log.info('unhandled base atom %r' % atomtype)

            # Skip unknown atoms
            try:
                file.seek(atomsize - 8, 1)
            except IOError:
                return 0

        return atomsize
コード例 #4
0
    def _getnextheader(self, s):
        r = struct.unpack('<16sQ', s[:24])
        (guidstr, objsize) = r
        guid = self._parseguid(guidstr)
        if guid == GUIDS['ASF_File_Properties_Object']:
            log.debug('File Properties Object')
            val = struct.unpack('<16s6Q4I', s[24:24 + 80])
            (fileid, size, date, packetcount, duration, \
             senddur, preroll, flags, minpack, maxpack, maxbr) = \
             val
            # FIXME: parse date to timestamp
            self.length = duration / 10000000.0

        elif guid == GUIDS['ASF_Stream_Properties_Object']:
            log.debug('Stream Properties Object [%d]' % objsize)
            streamtype = self._parseguid(s[24:40])
            errortype = self._parseguid(s[40:56])
            offset, typelen, errorlen, flags = struct.unpack('<QIIH', s[56:74])
            strno = flags & 0x7f
            encrypted = flags >> 15
            if encrypted:
                self._set('encrypted', True)
            if streamtype == GUIDS['ASF_Video_Media']:
                vi = core.VideoStream()
                vi.width, vi.height, depth, codec, = struct.unpack(
                    '<4xII2xH4s', s[89:89 + 20])
                vi.codec = codec
                vi.id = strno
                self.video.append(vi)
            elif streamtype == GUIDS['ASF_Audio_Media']:
                ai = core.AudioStream()
                twocc, ai.channels, ai.samplerate, bitrate, block, \
                       ai.samplebits, = struct.unpack('<HHIIHH', s[78:78 + 16])
                ai.bitrate = 8 * bitrate
                ai.codec = twocc
                ai.id = strno
                self.audio.append(ai)

            self._apply_extinfo(strno)

        elif guid == GUIDS['ASF_Extended_Stream_Properties_Object']:
            streamid, langid, frametime = struct.unpack('<HHQ', s[72:84])
            (bitrate, ) = struct.unpack('<I', s[40:40 + 4])
            if streamid not in self._extinfo:
                self._extinfo[streamid] = [None, None, None, {}]
            if frametime == 0:
                # Problaby VFR, report as 1000fps (which is what MPlayer does)
                frametime = 10000.0
            self._extinfo[streamid][:3] = [
                bitrate, 10000000.0 / frametime, langid
            ]
            self._apply_extinfo(streamid)

        elif guid == GUIDS['ASF_Header_Extension_Object']:
            log.debug('ASF_Header_Extension_Object %d' % objsize)
            size = struct.unpack('<I', s[42:46])[0]
            data = s[46:46 + size]
            while len(data):
                log.debug('Sub:')
                h = self._getnextheader(data)
                data = data[h[1]:]

        elif guid == GUIDS['ASF_Codec_List_Object']:
            log.debug('List Object')
            pass

        elif guid == GUIDS['ASF_Error_Correction_Object']:
            log.debug('Error Correction')
            pass

        elif guid == GUIDS['ASF_Content_Description_Object']:
            log.debug('Content Description Object')
            val = struct.unpack('<5H', s[24:24 + 10])
            pos = 34
            strings = []
            for i in val:
                ss = s[pos:pos + i].replace('\0', '').lstrip().rstrip()
                strings.append(ss)
                pos += i

            # Set empty strings to None
            strings = [x or None for x in strings]
            self.title, self.artist, self.copyright, self.caption, rating = strings

        elif guid == GUIDS['ASF_Extended_Content_Description_Object']:
            (count, ) = struct.unpack('<H', s[24:26])
            pos = 26
            descriptor = {}
            for i in range(0, count):
                # Read additional content descriptors
                d = self._parsekv(s[pos:])
                pos += d[0]
                descriptor[d[1]] = d[2]
            self._appendtable('ASFDESCRIPTOR', descriptor)

        elif guid == GUIDS['ASF_Metadata_Object']:
            (count, ) = struct.unpack('<H', s[24:26])
            pos = 26
            streams = {}
            for i in range(0, count):
                # Read additional content descriptors
                size, key, value, strno = self._parsekv2(s[pos:])
                if strno not in streams:
                    streams[strno] = {}
                streams[strno][key] = value
                pos += size

            for strno, metadata in list(streams.items()):
                if strno not in self._extinfo:
                    self._extinfo[strno] = [None, None, None, {}]
                self._extinfo[strno][3].update(metadata)
                self._apply_extinfo(strno)

        elif guid == GUIDS['ASF_Language_List_Object']:
            count = struct.unpack('<H', s[24:26])[0]
            pos = 26
            for i in range(0, count):
                idlen = struct.unpack('<B', s[pos:pos + 1])[0]
                idstring = s[pos + 1:pos + 1 + idlen]
                idstring = str(idstring, 'utf-16').replace('\0', '')
                log.debug('Language: %d/%d: %r' % (i + 1, count, idstring))
                self._languages.append(idstring)
                pos += 1 + idlen

        elif guid == GUIDS['ASF_Stream_Bitrate_Properties_Object']:
            # This record contains stream bitrate with payload overhead.  For
            # audio streams, we should have the average bitrate from
            # ASF_Stream_Properties_Object.  For video streams, we get it from
            # ASF_Extended_Stream_Properties_Object.  So this record is not
            # used.
            pass

        elif guid == GUIDS['ASF_Content_Encryption_Object'] or \
             guid == GUIDS['ASF_Extended_Content_Encryption_Object']:
            self._set('encrypted', True)
        else:
            # Just print the type:
            for h in list(GUIDS.keys()):
                if GUIDS[h] == guid:
                    log.debug('Unparsed %r [%d]' % (h, objsize))
                    break
            else:
                u = "%.8X-%.4X-%.4X-%.2X%.2X-%s" % guid
                log.debug('unknown: len=%d [%d]' % (len(u), objsize))
        return r
コード例 #5
0
ファイル: mpeg.py プロジェクト: niol/deejayd
    def ReadPESHeader(self, offset, buffer, id=0):
        """
        Parse a PES header.
        Since it starts with 0x00 0x00 0x01 like 'normal' mpegs, this
        function will return (0, None) when it is no PES header or
        (packet length, timestamp position (maybe None))

        http://dvd.sourceforge.net/dvdinfo/pes-hdr.html
        """
        if not buffer[0:3] == '\x00\x00\x01':
            return 0, None

        packet_length = (buffer[4] << 8) + buffer[5] + 6
        align = buffer[6] & 4
        header_length = buffer[8]

        # PES ID (starting with 001)
        if buffer[3] & 0xE0 == 0xC0:
            id = id or buffer[3] & 0x1F
            for a in self.audio:
                if a.id == id:
                    break
            else:
                self.audio.append(core.AudioStream())
                self.audio[-1]._set('id', id)

        elif buffer[3] & 0xF0 == 0xE0:
            id = id or buffer[3] & 0xF
            for v in self.video:
                if v.id == id:
                    break
            else:
                self.video.append(core.VideoStream())
                self.video[-1]._set('id', id)

            # new mpeg starting
            if buffer[header_length + 9:header_length + 13] == \
                   '\x00\x00\x01\xB3' and not self.sequence_header_offset:
                # yes, remember offset for later use
                self.sequence_header_offset = offset + header_length + 9
        elif buffer[3] == 189 or buffer[3] == 191:
            # private stream. we don't know, but maybe we can guess later
            id = id or buffer[3] & 0xF
            if align and \
                   buffer[header_length + 9:header_length + 11] == '\x0b\x77':
                # AC3 stream
                for a in self.audio:
                    if a.id == id:
                        break
                else:
                    self.audio.append(core.AudioStream())
                    self.audio[-1]._set('id', id)
                    self.audio[-1].codec = 0x2000  # AC3

        else:
            # unknown content
            pass

        ptsdts = buffer[7] >> 6

        if ptsdts and ptsdts == buffer[9] >> 4:
            if buffer[9] >> 4 != ptsdts:
                log.info('WARNING: bad PTS/DTS, please contact us')
                return packet_length, None

            return packet_length, 9

        return packet_length, None
コード例 #6
0
ファイル: mpeg.py プロジェクト: niol/deejayd
    def ReadHeader(self, buffer, offset):
        """
        Handle MPEG header in buffer on position offset
        Return None on error, new offset or 0 if the new offset can't be scanned
        """
        if buffer[offset:offset + 3] != '\x00\x00\x01':
            return None

        id = buffer[offset + 3]

        if id == PADDING_PKT:
            return offset + (buffer[offset + 4] << 8) + \
                   buffer[offset + 5] + 6

        if id == PACK_PKT:
            if buffer[offset + 4] & 0xF0 == 0x20:
                self.type = 'MPEG-1 Video'
                self.get_time = self.ReadSCRMpeg1
                self.mpeg_version = 1
                return offset + 12
            elif (buffer[offset + 4] & 0xC0) == 0x40:
                self.type = 'MPEG-2 Video'
                self.get_time = self.ReadSCRMpeg2
                return offset + (buffer[offset + 13] & 0x07) + 14
            else:
                # I have no idea what just happened, but for some DVB
                # recordings done with mencoder this points to a
                # PACK_PKT describing something odd. Returning 0 here
                # (let's hope there are no extensions in the header)
                # fixes it.
                return 0

        if 0xC0 <= id <= 0xDF:
            # code for audio stream
            for a in self.audio:
                if a.id == id:
                    break
            else:
                self.audio.append(core.AudioStream())
                self.audio[-1]._set('id', id)
            return 0

        if 0xE0 <= id <= 0xEF:
            # code for video stream
            for v in self.video:
                if v.id == id:
                    break
            else:
                self.video.append(core.VideoStream())
                self.video[-1]._set('id', id)
            return 0

        if id == SEQ_HEAD:
            # sequence header, remember that position for later use
            self.sequence_header_offset = offset
            return 0

        if id in [PRIVATE_STREAM1, PRIVATE_STREAM2]:
            # private stream. we don't know, but maybe we can guess later
            add = buffer[offset + 8]
            # if (ord(buffer[offset+6]) & 4) or 1:
            # id = ord(buffer[offset+10+add])
            if buffer[offset + 11 + add:offset + 15 +
                      add].find('\x0b\x77') != -1:
                # AC3 stream
                for a in self.audio:
                    if a.id == id:
                        break
                else:
                    self.audio.append(core.AudioStream())
                    self.audio[-1]._set('id', id)
                    self.audio[-1].codec = 0x2000  # AC3
            return 0

        if id == SYS_PKT:
            return 0

        if id == EXT_START:
            return 0

        return 0
コード例 #7
0
    def _parseHeader(self, header, granule):
        headerlen = len(header)
        flags = header[0]

        if headerlen >= 30 and header[1:7] == 'vorbis':
            ai = core.AudioStream()
            ai.version, ai.channels, ai.samplerate, bitrate_max, ai.bitrate, \
                        bitrate_min, blocksize, framing = \
                        struct.unpack('<IBIiiiBB', header[7:7 + 23])
            ai.codec = 'Vorbis'
            # ai.granule = granule
            # ai.length = granule / ai.samplerate
            self.audio.append(ai)
            self.all_streams.append(ai)

        elif headerlen >= 7 and header[1:7] == 'theora':
            # Theora Header
            # XXX Finish Me
            vi = core.VideoStream()
            vi.codec = 'theora'
            self.video.append(vi)
            self.all_streams.append(vi)

        elif headerlen >= 142 and \
                 header[1:36] == 'Direct Show Samples embedded in Ogg':
            # Old Directshow format
            # XXX Finish Me
            vi = core.VideoStream()
            vi.codec = 'dshow'
            self.video.append(vi)
            self.all_streams.append(vi)

        elif flags & PACKET_TYPE_BITS == PACKET_TYPE_HEADER and \
                 headerlen >= struct.calcsize(STREAM_HEADER_VIDEO) + 1:
            # New Directshow Format
            htype = header[1:9]

            if htype[:5] == 'video':
                sh = header[9:struct.calcsize(STREAM_HEADER_VIDEO) + 9]
                streamheader = struct.unpack(STREAM_HEADER_VIDEO, sh)
                vi = core.VideoStream()
                (type, ssize, timeunit, samplerate, vi.length, buffersize, \
                 vi.bitrate, vi.width, vi.height) = streamheader

                vi.width /= 65536
                vi.height /= 65536
                # XXX length, bitrate are very wrong
                vi.codec = type
                vi.fps = 10000000 / timeunit
                self.video.append(vi)
                self.all_streams.append(vi)

            elif htype[:5] == 'audio':
                sha = header[9:struct.calcsize(STREAM_HEADER_AUDIO) + 9]
                streamheader = struct.unpack(STREAM_HEADER_AUDIO, sha)
                ai = core.AudioStream()
                (type, ssize, timeunit, ai.samplerate, ai.length, buffersize, \
                 ai.bitrate, ai.channels, bloc, ai.bitrate) = streamheader
                self.samplerate = ai.samplerate
                log.debug('Samplerate %d' % self.samplerate)
                self.audio.append(ai)
                self.all_streams.append(ai)

            elif htype[:4] == 'text':
                subtitle = core.Subtitle()
                # FIXME: add more info
                self.subtitles.append(subtitle)
                self.all_streams.append(subtitle)

        else:
            log.debug('Unknown Header')