Subliminal update
This commit is contained in:
+62
-64
@@ -1,8 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# enzyme - Video metadata parser
|
||||
# Copyright (C) 2011 Antoine Bertin <diaoulael@gmail.com>
|
||||
# Copyright (C) 2003-2006 Thomas Schueppel <stain@acm.org>
|
||||
# Copyright (C) 2003-2006 Dirk Meyer <dischi@freevo.org>
|
||||
# Copyright 2011-2012 Antoine Bertin <diaoulael@gmail.com>
|
||||
# Copyright 2003-2006 Thomas Schueppel <stain@acm.org>
|
||||
# Copyright 2003-2006 Dirk Meyer <dischi@freevo.org>
|
||||
#
|
||||
# This file is part of enzyme.
|
||||
#
|
||||
@@ -17,30 +17,29 @@
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# along with enzyme. If not, see <http://www.gnu.org/licenses/>.
|
||||
from exceptions import ParseError
|
||||
import core
|
||||
import logging
|
||||
import string
|
||||
import struct
|
||||
|
||||
|
||||
__all__ = ['Parser']
|
||||
|
||||
import struct
|
||||
import string
|
||||
import logging
|
||||
from exceptions import *
|
||||
import core
|
||||
|
||||
# get logging object
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
def _guid(input):
|
||||
# Remove any '-'
|
||||
s = string.join(string.split(input,'-'), '')
|
||||
s = string.join(string.split(input, '-'), '')
|
||||
r = ''
|
||||
if len(s) != 32:
|
||||
return ''
|
||||
x = ''
|
||||
for i in range(0,16):
|
||||
r+=chr(int(s[2*i:2*i+2],16))
|
||||
guid = struct.unpack('>IHHBB6s',r)
|
||||
for i in range(0, 16):
|
||||
r += chr(int(s[2 * i:2 * i + 2], 16))
|
||||
guid = struct.unpack('>IHHBB6s', r)
|
||||
return guid
|
||||
|
||||
GUIDS = {
|
||||
@@ -93,8 +92,7 @@ GUIDS = {
|
||||
'ASF_Web_Stream_Format' : _guid('DA1E6B13-8359-4050-B398-388E965BF00C'),
|
||||
|
||||
'ASF_No_Error_Correction' : _guid('20FB5700-5B55-11CF-A8FD-00805F5C442B'),
|
||||
'ASF_Audio_Spread' : _guid('BFC3CD50-618F-11CF-8BB2-00AA00B4E220'),
|
||||
}
|
||||
'ASF_Audio_Spread' : _guid('BFC3CD50-618F-11CF-8BB2-00AA00B4E220')}
|
||||
|
||||
|
||||
class Asf(core.AVContainer):
|
||||
@@ -114,7 +112,7 @@ class Asf(core.AVContainer):
|
||||
raise ParseError()
|
||||
|
||||
(guidstr, objsize, objnum, reserved1, \
|
||||
reserved2) = struct.unpack('<16sQIBB',h)
|
||||
reserved2) = struct.unpack('<16sQIBB', h)
|
||||
guid = self._parseguid(guidstr)
|
||||
|
||||
if (guid != GUIDS['ASF_Header_Object']):
|
||||
@@ -122,9 +120,9 @@ class Asf(core.AVContainer):
|
||||
if reserved1 != 0x01 or reserved2 != 0x02:
|
||||
raise ParseError()
|
||||
|
||||
log.debug("asf header size: %d / %d objects" % (objsize,objnum))
|
||||
header = file.read(objsize-30)
|
||||
for i in range(0,objnum):
|
||||
log.debug(u'Header size: %d / %d objects' % (objsize, objnum))
|
||||
header = file.read(objsize - 30)
|
||||
for _ in range(0, objnum):
|
||||
h = self._getnextheader(header)
|
||||
header = header[h[1]:]
|
||||
|
||||
@@ -148,19 +146,19 @@ class Asf(core.AVContainer):
|
||||
stream._appendtable('ASFMETADATA', metadata)
|
||||
|
||||
|
||||
def _parseguid(self,string):
|
||||
def _parseguid(self, string):
|
||||
return struct.unpack('<IHHBB6s', string[:16])
|
||||
|
||||
|
||||
def _parsekv(self,s):
|
||||
def _parsekv(self, s):
|
||||
pos = 0
|
||||
(descriptorlen,) = struct.unpack('<H', s[pos:pos+2])
|
||||
(descriptorlen,) = struct.unpack('<H', s[pos:pos + 2])
|
||||
pos += 2
|
||||
descriptorname = s[pos:pos+descriptorlen]
|
||||
descriptorname = s[pos:pos + descriptorlen]
|
||||
pos += descriptorlen
|
||||
descriptortype, valuelen = struct.unpack('<HH', s[pos:pos+4])
|
||||
descriptortype, valuelen = struct.unpack('<HH', s[pos:pos + 4])
|
||||
pos += 4
|
||||
descriptorvalue = s[pos:pos+valuelen]
|
||||
descriptorvalue = s[pos:pos + valuelen]
|
||||
pos += valuelen
|
||||
value = None
|
||||
if descriptortype == 0x0000:
|
||||
@@ -182,17 +180,17 @@ class Asf(core.AVContainer):
|
||||
# WORD
|
||||
value = struct.unpack('<H', descriptorvalue)[0]
|
||||
else:
|
||||
log.debug("Unknown Descriptor Type %d" % descriptortype)
|
||||
return (pos,descriptorname,value)
|
||||
log.debug(u'Unknown Descriptor Type %d' % descriptortype)
|
||||
return (pos, descriptorname, value)
|
||||
|
||||
|
||||
def _parsekv2(self,s):
|
||||
def _parsekv2(self, s):
|
||||
pos = 0
|
||||
strno, descriptorlen, descriptortype, valuelen = struct.unpack('<2xHHHI', s[pos:pos+12])
|
||||
strno, descriptorlen, descriptortype, valuelen = struct.unpack('<2xHHHI', s[pos:pos + 12])
|
||||
pos += 12
|
||||
descriptorname = s[pos:pos+descriptorlen]
|
||||
descriptorname = s[pos:pos + descriptorlen]
|
||||
pos += descriptorlen
|
||||
descriptorvalue = s[pos:pos+valuelen]
|
||||
descriptorvalue = s[pos:pos + valuelen]
|
||||
pos += valuelen
|
||||
value = None
|
||||
|
||||
@@ -216,25 +214,25 @@ class Asf(core.AVContainer):
|
||||
# WORD
|
||||
value = struct.unpack('<H', descriptorvalue)[0]
|
||||
else:
|
||||
log.debug("Unknown Descriptor Type %d" % descriptortype)
|
||||
return (pos,descriptorname,value,strno)
|
||||
log.debug(u'Unknown Descriptor Type %d' % descriptortype)
|
||||
return (pos, descriptorname, value, strno)
|
||||
|
||||
|
||||
def _getnextheader(self,s):
|
||||
r = struct.unpack('<16sQ',s[:24])
|
||||
(guidstr,objsize) = r
|
||||
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])
|
||||
log.debug(u'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
|
||||
self.length = duration / 10000000.0
|
||||
|
||||
elif guid == GUIDS['ASF_Stream_Properties_Object']:
|
||||
log.debug("Stream Properties Object [%d]" % objsize)
|
||||
log.debug(u'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])
|
||||
@@ -244,15 +242,15 @@ class Asf(core.AVContainer):
|
||||
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.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.samplebits, = struct.unpack('<HHIIHH', s[78:78 + 16])
|
||||
ai.bitrate = 8 * bitrate
|
||||
ai.codec = twocc
|
||||
ai.id = strno
|
||||
self.audio.append(ai)
|
||||
@@ -260,8 +258,8 @@ class Asf(core.AVContainer):
|
||||
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])
|
||||
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:
|
||||
@@ -271,31 +269,31 @@ class Asf(core.AVContainer):
|
||||
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]
|
||||
log.debug(u'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:")
|
||||
log.debug(u'Sub:')
|
||||
h = self._getnextheader(data)
|
||||
data = data[h[1]:]
|
||||
|
||||
elif guid == GUIDS['ASF_Codec_List_Object']:
|
||||
log.debug("List Object")
|
||||
log.debug(u'List Object')
|
||||
pass
|
||||
|
||||
elif guid == GUIDS['ASF_Error_Correction_Object']:
|
||||
log.debug("Error Correction")
|
||||
log.debug(u'Error Correction')
|
||||
pass
|
||||
|
||||
elif guid == GUIDS['ASF_Content_Description_Object']:
|
||||
log.debug("Content Description Object")
|
||||
val = struct.unpack('<5H', s[24:24+10])
|
||||
log.debug(u'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()
|
||||
ss = s[pos:pos + i].replace('\0', '').lstrip().rstrip()
|
||||
strings.append(ss)
|
||||
pos+=i
|
||||
pos += i
|
||||
|
||||
# Set empty strings to None
|
||||
strings = [x or None for x in strings]
|
||||
@@ -318,7 +316,7 @@ class Asf(core.AVContainer):
|
||||
streams = {}
|
||||
for i in range(0, count):
|
||||
# Read additional content descriptors
|
||||
size,key,value,strno = self._parsekv2(s[pos:])
|
||||
size, key, value, strno = self._parsekv2(s[pos:])
|
||||
if strno not in streams:
|
||||
streams[strno] = {}
|
||||
streams[strno][key] = value
|
||||
@@ -334,12 +332,12 @@ class Asf(core.AVContainer):
|
||||
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]
|
||||
idlen = struct.unpack('<B', s[pos:pos + 1])[0]
|
||||
idstring = s[pos + 1:pos + 1 + idlen]
|
||||
idstring = unicode(idstring, 'utf-16').replace('\0', '')
|
||||
log.debug("Language: %d/%d: %s" % (i+1, count, idstring))
|
||||
log.debug(u'Language: %d/%d: %r' % (i + 1, count, idstring))
|
||||
self._languages.append(idstring)
|
||||
pos += 1+idlen
|
||||
pos += 1 + idlen
|
||||
|
||||
elif guid == GUIDS['ASF_Stream_Bitrate_Properties_Object']:
|
||||
# This record contains stream bitrate with payload overhead. For
|
||||
@@ -356,11 +354,11 @@ class Asf(core.AVContainer):
|
||||
# Just print the type:
|
||||
for h in GUIDS.keys():
|
||||
if GUIDS[h] == guid:
|
||||
log.debug("Unparsed %s [%d]" % (h,objsize))
|
||||
log.debug(u'Unparsed %r [%d]' % (h, objsize))
|
||||
break
|
||||
else:
|
||||
u = "%.8X-%.4X-%.4X-%.2X%.2X-%s" % guid
|
||||
log.debug("unknown: len=%d [%d]" % (len(u), objsize))
|
||||
log.debug(u'unknown: len=%d [%d]' % (len(u), objsize))
|
||||
return r
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user