1 | #if 0 |
---|
2 | # $Id: riffinfo.py,v 1.33 2005/03/15 17:50:45 dischi Exp $ |
---|
3 | # $Log: riffinfo.py,v $ |
---|
4 | # Revision 1.33 2005/03/15 17:50:45 dischi |
---|
5 | # check for corrupt avi |
---|
6 | # |
---|
7 | # Revision 1.32 2005/03/04 17:41:29 dischi |
---|
8 | # handle broken avi files |
---|
9 | # |
---|
10 | # Revision 1.31 2004/12/13 10:19:07 dischi |
---|
11 | # more debug, support LIST > 20000 (new max is 80000) |
---|
12 | # |
---|
13 | # Revision 1.30 2004/08/25 16:18:14 dischi |
---|
14 | # detect aspect ratio |
---|
15 | # |
---|
16 | # Revision 1.29 2004/05/24 16:17:09 dischi |
---|
17 | # Small changes for future updates |
---|
18 | # |
---|
19 | # Revision 1.28 2004/01/31 12:23:46 dischi |
---|
20 | # remove bad chars from table (e.g. char 0 is True) |
---|
21 | # |
---|
22 | # Revision 1.27 2003/10/04 14:30:08 dischi |
---|
23 | # add audio delay for avi |
---|
24 | # |
---|
25 | # Revision 1.26 2003/07/10 11:18:11 the_krow |
---|
26 | # few more attributes added |
---|
27 | # |
---|
28 | # Revision 1.25 2003/07/07 21:36:44 dischi |
---|
29 | # make fps a float and round it to two digest after the comma |
---|
30 | # |
---|
31 | # Revision 1.24 2003/07/05 19:36:37 the_krow |
---|
32 | # length fixed |
---|
33 | # fps introduced |
---|
34 | # |
---|
35 | # Revision 1.23 2003/07/02 11:17:30 the_krow |
---|
36 | # language is now part of the table key |
---|
37 | # |
---|
38 | # Revision 1.22 2003/07/01 21:06:50 dischi |
---|
39 | # no need to import factory (and when, use "from mmpython import factory" |
---|
40 | # |
---|
41 | # Revision 1.21 2003/06/30 13:17:20 the_krow |
---|
42 | # o Refactored mediainfo into factory, synchronizedobject |
---|
43 | # o Parsers now register directly at mmpython not at mmpython.mediainfo |
---|
44 | # o use mmpython.Factory() instead of mmpython.mediainfo.get_singleton() |
---|
45 | # o Bugfix in PNG parser |
---|
46 | # o Renamed disc.AudioInfo into disc.AudioDiscInfo |
---|
47 | # o Renamed disc.DataInfo into disc.DataDiscInfo |
---|
48 | # |
---|
49 | # Revision 1.20 2003/06/23 20:48:11 the_krow |
---|
50 | # width + height fixes for OGM files |
---|
51 | # |
---|
52 | # Revision 1.19 2003/06/23 20:38:04 the_krow |
---|
53 | # Support for larger LIST chunks because some files did not work. |
---|
54 | # |
---|
55 | # Revision 1.18 2003/06/20 19:17:22 dischi |
---|
56 | # remove filename again and use file.name |
---|
57 | # |
---|
58 | # Revision 1.17 2003/06/20 19:05:56 dischi |
---|
59 | # scan for subtitles |
---|
60 | # |
---|
61 | # Revision 1.16 2003/06/20 15:29:42 the_krow |
---|
62 | # Metadata Mapping |
---|
63 | # |
---|
64 | # Revision 1.15 2003/06/20 14:43:57 the_krow |
---|
65 | # Putting Metadata into MediaInfo from AVIInfo Table |
---|
66 | # |
---|
67 | # Revision 1.14 2003/06/09 16:10:52 dischi |
---|
68 | # error handling |
---|
69 | # |
---|
70 | # Revision 1.13 2003/06/08 19:53:21 dischi |
---|
71 | # also give the filename to init for additional data tests |
---|
72 | # |
---|
73 | # Revision 1.12 2003/06/08 13:44:58 dischi |
---|
74 | # Changed all imports to use the complete mmpython path for mediainfo |
---|
75 | # |
---|
76 | # Revision 1.11 2003/06/08 13:11:38 dischi |
---|
77 | # removed print at the end and moved it into register |
---|
78 | # |
---|
79 | # Revision 1.10 2003/06/07 23:10:50 the_krow |
---|
80 | # Changed mp3 into new format. |
---|
81 | # |
---|
82 | # Revision 1.9 2003/06/07 22:30:22 the_krow |
---|
83 | # added new avinfo structure |
---|
84 | # |
---|
85 | # Revision 1.8 2003/06/07 21:48:47 the_krow |
---|
86 | # Added Copying info |
---|
87 | # started changing riffinfo to new AV stuff |
---|
88 | # |
---|
89 | # Revision 1.7 2003/05/13 12:31:43 the_krow |
---|
90 | # + Copyright Notice |
---|
91 | # |
---|
92 | # |
---|
93 | # MMPython - Media Metadata for Python |
---|
94 | # Copyright (C) 2003 Thomas Schueppel, Dirk Meyer |
---|
95 | # |
---|
96 | # This program is free software; you can redistribute it and/or modify |
---|
97 | # it under the terms of the GNU General Public License as published by |
---|
98 | # the Free Software Foundation; either version 2 of the License, or |
---|
99 | # (at your option) any later version. |
---|
100 | # |
---|
101 | # This program is distributed in the hope that it will be useful, but |
---|
102 | # WITHOUT ANY WARRANTY; without even the implied warranty of MER- |
---|
103 | # CHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General |
---|
104 | # Public License for more details. |
---|
105 | # |
---|
106 | # You should have received a copy of the GNU General Public License along |
---|
107 | # with this program; if not, write to the Free Software Foundation, Inc., |
---|
108 | # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
---|
109 | # |
---|
110 | # ----------------------------------------------------------------------- |
---|
111 | #endif |
---|
112 | |
---|
113 | import re |
---|
114 | import struct |
---|
115 | import string |
---|
116 | import fourcc |
---|
117 | # import factory |
---|
118 | |
---|
119 | import mmpython |
---|
120 | from mmpython import mediainfo |
---|
121 | |
---|
122 | |
---|
123 | # List of tags |
---|
124 | # http://kibus1.narod.ru/frames_eng.htm?sof/abcavi/infotags.htm |
---|
125 | # http://www.divx-digest.com/software/avitags_dll.html |
---|
126 | # File Format |
---|
127 | # http://www.taenam.co.kr/pds/documents/odmlff2.pdf |
---|
128 | |
---|
129 | _print = mediainfo._debug |
---|
130 | |
---|
131 | AVIINFO_tags = { 'title': 'INAM', |
---|
132 | 'artist': 'IART', |
---|
133 | 'product': 'IPRD', |
---|
134 | 'date': 'ICRD', |
---|
135 | 'comment': 'ICMT', |
---|
136 | 'language': 'ILNG', |
---|
137 | 'keywords': 'IKEY', |
---|
138 | 'trackno': 'IPRT', |
---|
139 | 'trackof': 'IFRM', |
---|
140 | 'producer': 'IPRO', |
---|
141 | 'writer': 'IWRI', |
---|
142 | 'genre': 'IGNR', |
---|
143 | 'copyright': 'ICOP', |
---|
144 | 'trackno': 'IPRT', |
---|
145 | 'trackof': 'IFRM', |
---|
146 | 'comment': 'ICMT', |
---|
147 | } |
---|
148 | |
---|
149 | |
---|
150 | |
---|
151 | class RiffInfo(mediainfo.AVInfo): |
---|
152 | def __init__(self,file): |
---|
153 | mediainfo.AVInfo.__init__(self) |
---|
154 | # read the header |
---|
155 | h = file.read(12) |
---|
156 | if h[:4] != "RIFF" and h[:4] != 'SDSS': |
---|
157 | self.valid = 0 |
---|
158 | return |
---|
159 | self.valid = 1 |
---|
160 | self.mime = 'application/x-wave' |
---|
161 | self.has_idx = False |
---|
162 | self.header = {} |
---|
163 | self.junkStart = None |
---|
164 | self.infoStart = None |
---|
165 | self.type = h[8:12] |
---|
166 | self.tag_map = { ('AVIINFO', 'en') : AVIINFO_tags } |
---|
167 | if self.type == 'AVI ': |
---|
168 | self.mime = 'video/avi' |
---|
169 | elif self.type == 'WAVE': |
---|
170 | self.mime = 'application/x-wave' |
---|
171 | try: |
---|
172 | while self.parseRIFFChunk(file): |
---|
173 | pass |
---|
174 | except IOError: |
---|
175 | if mediainfo.DEBUG: |
---|
176 | print 'error in file, stop parsing' |
---|
177 | |
---|
178 | self.find_subtitles(file.name) |
---|
179 | |
---|
180 | # Copy Metadata from tables into the main set of attributes |
---|
181 | for k in self.tag_map.keys(): |
---|
182 | map(lambda x:self.setitem(x,self.gettable(k[0],k[1]),self.tag_map[k][x]), |
---|
183 | self.tag_map[k].keys()) |
---|
184 | if not self.has_idx: |
---|
185 | _print('WARNING: avi has no index') |
---|
186 | self.corrupt = 1 |
---|
187 | self.keys.append('corrupt') |
---|
188 | |
---|
189 | |
---|
190 | def _extractHeaderString(self,h,offset,len): |
---|
191 | return h[offset:offset+len] |
---|
192 | |
---|
193 | def parseAVIH(self,t): |
---|
194 | retval = {} |
---|
195 | v = struct.unpack('<IIIIIIIIIIIIII',t[0:56]) |
---|
196 | ( retval['dwMicroSecPerFrame'], |
---|
197 | retval['dwMaxBytesPerSec'], |
---|
198 | retval['dwPaddingGranularity'], |
---|
199 | retval['dwFlags'], |
---|
200 | retval['dwTotalFrames'], |
---|
201 | retval['dwInitialFrames'], |
---|
202 | retval['dwStreams'], |
---|
203 | retval['dwSuggestedBufferSize'], |
---|
204 | retval['dwWidth'], |
---|
205 | retval['dwHeight'], |
---|
206 | retval['dwScale'], |
---|
207 | retval['dwRate'], |
---|
208 | retval['dwStart'], |
---|
209 | retval['dwLength'] ) = v |
---|
210 | if retval['dwMicroSecPerFrame'] == 0: |
---|
211 | _print("ERROR: Corrupt AVI") |
---|
212 | self.valid = 0 |
---|
213 | return {} |
---|
214 | return retval |
---|
215 | |
---|
216 | def parseSTRH(self,t): |
---|
217 | retval = {} |
---|
218 | retval['fccType'] = t[0:4] |
---|
219 | _print("parseSTRH(%s) : %d bytes" % ( retval['fccType'], len(t))) |
---|
220 | if retval['fccType'] != 'auds': |
---|
221 | retval['fccHandler'] = t[4:8] |
---|
222 | v = struct.unpack('<IHHIIIIIIIII',t[8:52]) |
---|
223 | ( retval['dwFlags'], |
---|
224 | retval['wPriority'], |
---|
225 | retval['wLanguage'], |
---|
226 | retval['dwInitialFrames'], |
---|
227 | retval['dwScale'], |
---|
228 | retval['dwRate'], |
---|
229 | retval['dwStart'], |
---|
230 | retval['dwLength'], |
---|
231 | retval['dwSuggestedBufferSize'], |
---|
232 | retval['dwQuality'], |
---|
233 | retval['dwSampleSize'], |
---|
234 | retval['rcFrame'], ) = v |
---|
235 | else: |
---|
236 | try: |
---|
237 | v = struct.unpack('<IHHIIIIIIIII',t[8:52]) |
---|
238 | ( retval['dwFlags'], |
---|
239 | retval['wPriority'], |
---|
240 | retval['wLanguage'], |
---|
241 | retval['dwInitialFrames'], |
---|
242 | retval['dwScale'], |
---|
243 | retval['dwRate'], |
---|
244 | retval['dwStart'], |
---|
245 | retval['dwLength'], |
---|
246 | retval['dwSuggestedBufferSize'], |
---|
247 | retval['dwQuality'], |
---|
248 | retval['dwSampleSize'], |
---|
249 | retval['rcFrame'], ) = v |
---|
250 | self.delay = float(retval['dwStart']) / \ |
---|
251 | (float(retval['dwRate']) / retval['dwScale']) |
---|
252 | except: |
---|
253 | pass |
---|
254 | |
---|
255 | return retval |
---|
256 | |
---|
257 | def parseSTRF(self,t,strh): |
---|
258 | fccType = strh['fccType'] |
---|
259 | retval = {} |
---|
260 | if fccType == 'auds': |
---|
261 | ( retval['wFormatTag'], |
---|
262 | retval['nChannels'], |
---|
263 | retval['nSamplesPerSec'], |
---|
264 | retval['nAvgBytesPerSec'], |
---|
265 | retval['nBlockAlign'], |
---|
266 | retval['nBitsPerSample'], |
---|
267 | ) = struct.unpack('<HHHHHH',t[0:12]) |
---|
268 | ai = mediainfo.AudioInfo() |
---|
269 | ai.samplerate = retval['nSamplesPerSec'] |
---|
270 | ai.channels = retval['nChannels'] |
---|
271 | ai.samplebits = retval['nBitsPerSample'] |
---|
272 | ai.bitrate = retval['nAvgBytesPerSec'] * 8 |
---|
273 | # TODO: set code if possible |
---|
274 | # http://www.stats.uwa.edu.au/Internal/Specs/DXALL/FileSpec/Languages |
---|
275 | # ai.language = strh['wLanguage'] |
---|
276 | try: |
---|
277 | ai.codec = fourcc.RIFFWAVE[retval['wFormatTag']] |
---|
278 | except: |
---|
279 | ai.codec = "Unknown" |
---|
280 | self.audio.append(ai) |
---|
281 | elif fccType == 'vids': |
---|
282 | v = struct.unpack('<IIIHH',t[0:16]) |
---|
283 | ( retval['biSize'], |
---|
284 | retval['biWidth'], |
---|
285 | retval['biHeight'], |
---|
286 | retval['biPlanes'], |
---|
287 | retval['biBitCount'], ) = v |
---|
288 | retval['fourcc'] = t[16:20] |
---|
289 | v = struct.unpack('IIIII',t[20:40]) |
---|
290 | ( retval['biSizeImage'], |
---|
291 | retval['biXPelsPerMeter'], |
---|
292 | retval['biYPelsPerMeter'], |
---|
293 | retval['biClrUsed'], |
---|
294 | retval['biClrImportant'], ) = v |
---|
295 | vi = mediainfo.VideoInfo() |
---|
296 | try: |
---|
297 | vi.codec = fourcc.RIFFCODEC[t[16:20]] |
---|
298 | except: |
---|
299 | vi.codec = "Unknown" |
---|
300 | vi.width = retval['biWidth'] |
---|
301 | vi.height = retval['biHeight'] |
---|
302 | vi.bitrate = strh['dwRate'] |
---|
303 | vi.fps = round(float(strh['dwRate'] * 100) / strh['dwScale']) / 100 |
---|
304 | vi.length = strh['dwLength'] / vi.fps |
---|
305 | self.video.append(vi) |
---|
306 | return retval |
---|
307 | |
---|
308 | |
---|
309 | def parseSTRL(self,t): |
---|
310 | retval = {} |
---|
311 | size = len(t) |
---|
312 | i = 0 |
---|
313 | key = t[i:i+4] |
---|
314 | sz = struct.unpack('<I',t[i+4:i+8])[0] |
---|
315 | i+=8 |
---|
316 | value = t[i:] |
---|
317 | |
---|
318 | if key == 'strh': |
---|
319 | retval[key] = self.parseSTRH(value) |
---|
320 | i += sz |
---|
321 | else: |
---|
322 | _print("parseSTRL: Error") |
---|
323 | key = t[i:i+4] |
---|
324 | sz = struct.unpack('<I',t[i+4:i+8])[0] |
---|
325 | i+=8 |
---|
326 | value = t[i:] |
---|
327 | |
---|
328 | if key == 'strf': |
---|
329 | retval[key] = self.parseSTRF(value, retval['strh']) |
---|
330 | i += sz |
---|
331 | return ( retval, i ) |
---|
332 | |
---|
333 | |
---|
334 | def parseODML(self,t): |
---|
335 | retval = {} |
---|
336 | size = len(t) |
---|
337 | i = 0 |
---|
338 | key = t[i:i+4] |
---|
339 | sz = struct.unpack('<I',t[i+4:i+8])[0] |
---|
340 | i += 8 |
---|
341 | value = t[i:] |
---|
342 | if key == 'dmlh': |
---|
343 | pass |
---|
344 | else: |
---|
345 | _print("parseODML: Error") |
---|
346 | |
---|
347 | i += sz - 8 |
---|
348 | return ( retval, i ) |
---|
349 | |
---|
350 | |
---|
351 | def parseVPRP(self,t): |
---|
352 | retval = {} |
---|
353 | v = struct.unpack('<IIIIIIIIII',t[:4*10]) |
---|
354 | |
---|
355 | ( retval['VideoFormat'], |
---|
356 | retval['VideoStandard'], |
---|
357 | retval['RefreshRate'], |
---|
358 | retval['HTotalIn'], |
---|
359 | retval['VTotalIn'], |
---|
360 | retval['FrameAspectRatio'], |
---|
361 | retval['wPixel'], |
---|
362 | retval['hPixel'] ) = v[1:-1] |
---|
363 | |
---|
364 | # I need an avi with more informations |
---|
365 | # enum {FORMAT_UNKNOWN, FORMAT_PAL_SQUARE, FORMAT_PAL_CCIR_601, |
---|
366 | # FORMAT_NTSC_SQUARE, FORMAT_NTSC_CCIR_601,...} VIDEO_FORMAT; |
---|
367 | # enum {STANDARD_UNKNOWN, STANDARD_PAL, STANDARD_NTSC, STANDARD_SECAM} |
---|
368 | # VIDEO_STANDARD; |
---|
369 | # |
---|
370 | r = retval['FrameAspectRatio'] |
---|
371 | r = float(r >> 16) / (r & 0xFFFF) |
---|
372 | retval['FrameAspectRatio'] = r |
---|
373 | if self.video: |
---|
374 | map(lambda v: setattr(v, 'aspect', r), self.video) |
---|
375 | return ( retval, v[0] ) |
---|
376 | |
---|
377 | |
---|
378 | def parseLIST(self,t): |
---|
379 | retval = {} |
---|
380 | i = 0 |
---|
381 | size = len(t) |
---|
382 | |
---|
383 | while i < size-8: |
---|
384 | # skip zero |
---|
385 | if ord(t[i]) == 0: i += 1 |
---|
386 | key = t[i:i+4] |
---|
387 | sz = 0 |
---|
388 | |
---|
389 | if key == 'LIST': |
---|
390 | sz = struct.unpack('<I',t[i+4:i+8])[0] |
---|
391 | _print("-> SUBLIST: len: %d, %d" % ( sz, i+4 )) |
---|
392 | i+=8 |
---|
393 | key = "LIST:"+t[i:i+4] |
---|
394 | value = self.parseLIST(t[i:i+sz]) |
---|
395 | _print("<-") |
---|
396 | if key == 'strl': |
---|
397 | for k in value.keys(): |
---|
398 | retval[k] = value[k] |
---|
399 | else: |
---|
400 | retval[key] = value |
---|
401 | i+=sz |
---|
402 | elif key == 'avih': |
---|
403 | _print("SUBAVIH") |
---|
404 | sz = struct.unpack('<I',t[i+4:i+8])[0] |
---|
405 | i += 8 |
---|
406 | value = self.parseAVIH(t[i:i+sz]) |
---|
407 | i += sz |
---|
408 | retval[key] = value |
---|
409 | elif key == 'strl': |
---|
410 | i += 4 |
---|
411 | (value, sz) = self.parseSTRL(t[i:]) |
---|
412 | _print("SUBSTRL: len: %d" % sz) |
---|
413 | key = value['strh']['fccType'] |
---|
414 | i += sz |
---|
415 | retval[key] = value |
---|
416 | elif key == 'odml': |
---|
417 | i += 4 |
---|
418 | (value, sz) = self.parseODML(t[i:]) |
---|
419 | _print("ODML: len: %d" % sz) |
---|
420 | i += sz |
---|
421 | elif key == 'vprp': |
---|
422 | i += 4 |
---|
423 | (value, sz) = self.parseVPRP(t[i:]) |
---|
424 | _print("VPRP: len: %d" % sz) |
---|
425 | retval[key] = value |
---|
426 | i += sz |
---|
427 | elif key == 'JUNK': |
---|
428 | sz = struct.unpack('<I',t[i+4:i+8])[0] |
---|
429 | i += sz + 8 |
---|
430 | _print("Skipping %d bytes of Junk" % sz) |
---|
431 | else: |
---|
432 | sz = struct.unpack('<I',t[i+4:i+8])[0] |
---|
433 | _print("Unknown Key: %s, len: %d" % (key,sz)) |
---|
434 | i+=8 |
---|
435 | value = self._extractHeaderString(t,i,sz) |
---|
436 | value = value.replace('\0', '').lstrip().rstrip() |
---|
437 | if value: |
---|
438 | retval[key] = value |
---|
439 | i+=sz |
---|
440 | return retval |
---|
441 | |
---|
442 | |
---|
443 | def parseRIFFChunk(self,file): |
---|
444 | h = file.read(8) |
---|
445 | if len(h) < 4: |
---|
446 | return False |
---|
447 | name = h[:4] |
---|
448 | size = struct.unpack('<I',h[4:8])[0] |
---|
449 | |
---|
450 | if name == 'LIST' and size < 80000: |
---|
451 | pos = file.tell() - 8 |
---|
452 | t = file.read(size) |
---|
453 | key = t[:4] |
---|
454 | _print('parse RIFF LIST: %d bytes' % (size)) |
---|
455 | value = self.parseLIST(t[4:]) |
---|
456 | self.header[key] = value |
---|
457 | if key == 'INFO': |
---|
458 | self.infoStart = pos |
---|
459 | self.appendtable( 'AVIINFO', value ) |
---|
460 | elif key == 'MID ': |
---|
461 | self.appendtable( 'AVIMID', value ) |
---|
462 | elif key in ('hdrl', ): |
---|
463 | # no need to add this info to a table |
---|
464 | pass |
---|
465 | else: |
---|
466 | _print('Skipping table info %s' % key) |
---|
467 | |
---|
468 | elif name == 'JUNK': |
---|
469 | self.junkStart = file.tell() - 8 |
---|
470 | self.junkSize = size |
---|
471 | file.seek(size, 1) |
---|
472 | elif name == 'idx1': |
---|
473 | self.has_idx = True |
---|
474 | _print('idx1: %s bytes' % size) |
---|
475 | # no need to parse this |
---|
476 | t = file.seek(size,1) |
---|
477 | elif name == 'LIST': |
---|
478 | _print('RIFF LIST to long to parse: %s bytes' % size) |
---|
479 | # no need to parse this |
---|
480 | t = file.seek(size,1) |
---|
481 | elif name == 'RIFF': |
---|
482 | _print("New RIFF chunk, extended avi [%i]" % size) |
---|
483 | type = file.read(4) |
---|
484 | if type != 'AVIX': |
---|
485 | _print("Second RIFF chunk is %s, not AVIX, skipping", type) |
---|
486 | file.seek(size-4, 1) |
---|
487 | # that's it, no new informations should be in AVIX |
---|
488 | return False |
---|
489 | elif not name.strip(string.printable + string.whitespace): |
---|
490 | # check if name is something usefull at all, maybe it is no |
---|
491 | # avi or broken |
---|
492 | t = file.seek(size,1) |
---|
493 | _print("Skipping %s [%i]" % (name,size)) |
---|
494 | else: |
---|
495 | # bad avi |
---|
496 | _print("Bad or broken avi") |
---|
497 | return False |
---|
498 | return True |
---|
499 | |
---|
500 | def buildTag(self,key,value): |
---|
501 | text = value + '\0' |
---|
502 | l = len(text) |
---|
503 | return struct.pack('<4sI%ds'%l, key[:4], l, text[:l]) |
---|
504 | |
---|
505 | |
---|
506 | def setInfo(self,file,hash): |
---|
507 | if self.junkStart == None: |
---|
508 | raise "junkstart missing" |
---|
509 | tags = [] |
---|
510 | size = 4 # Length of 'INFO' |
---|
511 | # Build String List and compute req. size |
---|
512 | for key in hash.keys(): |
---|
513 | tag = self.buildTag( key, hash[key] ) |
---|
514 | if (len(tag))%2 == 1: tag += '\0' |
---|
515 | tags.append(tag) |
---|
516 | size += len(tag) |
---|
517 | _print("Tag [%i]: %s" % (len(tag),tag)) |
---|
518 | if self.infoStart != None: |
---|
519 | _print("Infostart found. %i" % (self.infoStart)) |
---|
520 | # Read current info size |
---|
521 | file.seek(self.infoStart,0) |
---|
522 | s = file.read(12) |
---|
523 | (list, oldsize, info) = struct.unpack('<4sI4s',s) |
---|
524 | self.junkSize += oldsize + 8 |
---|
525 | else: |
---|
526 | self.infoStart = self.junkStart |
---|
527 | _print("Infostart computed. %i" % (self.infoStart)) |
---|
528 | file.seek(self.infoStart,0) |
---|
529 | if ( size > self.junkSize - 8 ): |
---|
530 | raise "Too large" |
---|
531 | file.write( "LIST" + struct.pack('<I',size) + "INFO" ) |
---|
532 | for tag in tags: |
---|
533 | file.write( tag ) |
---|
534 | _print("Junksize %i" % (self.junkSize-size-8)) |
---|
535 | file.write( "JUNK" + struct.pack('<I',self.junkSize-size-8) ) |
---|
536 | |
---|
537 | |
---|
538 | |
---|
539 | mmpython.registertype( 'video/avi', ('avi',), mediainfo.TYPE_AV, RiffInfo ) |
---|