|
@@ -0,0 +1,102 @@
|
|
|
+import sys
|
|
|
+import struct
|
|
|
+from fractions import Fraction
|
|
|
+
|
|
|
+def pp4(fourcc):
|
|
|
+ (a,b,c,d) = struct.unpack("4B", fourcc)
|
|
|
+ return "%02x%02x%02x%02x" % (d, c, b, a)
|
|
|
+
|
|
|
+class Avi:
|
|
|
+ def __init__(self, filename):
|
|
|
+ self.f = open(filename, "r+b")
|
|
|
+ self.atime = 0
|
|
|
+ self.vtime = 0
|
|
|
+
|
|
|
+ def get(self, n):
|
|
|
+ return self.f.read(n)
|
|
|
+
|
|
|
+ def unpack(self, fmt):
|
|
|
+ sz = struct.calcsize(fmt)
|
|
|
+ return struct.unpack(fmt, self.get(sz))
|
|
|
+
|
|
|
+ def parse(self, level = 0):
|
|
|
+ fourcc = self.get(4)
|
|
|
+ (size, ) = self.unpack("I")
|
|
|
+ if fourcc in ('RIFF', 'LIST'):
|
|
|
+ print (" " * level)+ fourcc, pp4(fourcc), size
|
|
|
+ if fourcc == 'RIFF':
|
|
|
+ self.remainder = size - 4
|
|
|
+ else:
|
|
|
+ self.remainder -= 12
|
|
|
+ _ = self.get(4)
|
|
|
+ sz = size - 4
|
|
|
+ while sz:
|
|
|
+ sz -= self.parse(level + 1)
|
|
|
+ assert 0 <= sz
|
|
|
+ else:
|
|
|
+ if fourcc == 'avih':
|
|
|
+ (
|
|
|
+ _,_,_,
|
|
|
+ dwFlags,dwTotalFrames,_,dwStreams,_,
|
|
|
+ dwWidth,dwHeight,
|
|
|
+ _,_,_,_
|
|
|
+ ) = self.unpack("IIIIIIIIIIIIII")
|
|
|
+ print (" " * level)+'flags', '%04x' % dwFlags, dwTotalFrames,dwStreams,dwWidth,dwHeight
|
|
|
+ elif fourcc == 'strh':
|
|
|
+ o = self.f.tell()
|
|
|
+ (
|
|
|
+ fccType, fccHandler,
|
|
|
+ dwFlags, wPriority,
|
|
|
+ wLanguage, dwInitialFrames,
|
|
|
+ dwScale, dwRate,
|
|
|
+ dwStart, dwLength,
|
|
|
+ dwSuggestedBufferSize,
|
|
|
+ dwQuality,
|
|
|
+ dwSampleSize,
|
|
|
+ _,_,_,_) = self.unpack("4s4sIHHIIIIIIII4H")
|
|
|
+ if fccType == 'vids':
|
|
|
+ print 'offset', o
|
|
|
+ self.rate_offset = o + 20
|
|
|
+ print (
|
|
|
+ fccType, fccHandler,
|
|
|
+ dwFlags,
|
|
|
+ wPriority, wLanguage,
|
|
|
+ dwInitialFrames,
|
|
|
+ dwScale, dwRate,
|
|
|
+ dwStart, dwLength,
|
|
|
+ dwSuggestedBufferSize,
|
|
|
+ dwQuality,
|
|
|
+ dwSampleSize)
|
|
|
+ print float(dwRate) / dwScale, 'samples/s'
|
|
|
+ elif fourcc == 'strf':
|
|
|
+ d = self.get(size)
|
|
|
+ if 0:
|
|
|
+ if size == 16:
|
|
|
+ print struct.unpack("HHIIHH", d)
|
|
|
+ if size == 18:
|
|
|
+ print struct.unpack("HHIIHHH", d)
|
|
|
+ elif fourcc == '01dc':
|
|
|
+ d = self.get(size)
|
|
|
+ if d:
|
|
|
+ self.vtime += 1 / 30.
|
|
|
+ elif fourcc == '01wb':
|
|
|
+ self.samples.write(self.get(size)[4:])
|
|
|
+ self.atime += (size - 0) / 44100.
|
|
|
+ else:
|
|
|
+ self.get(size)
|
|
|
+ # "A=%7.3f V=%7.3f %7.3f" % (self.atime, self.vtime, self.atime - self.vtime)
|
|
|
+ # print (" " * level) + 'chunk', fourcc, pp4(fourcc), size, "%08x" % (self.remainder)
|
|
|
+ self.remainder -= ((9 + size) & -2)
|
|
|
+ if size & 1:
|
|
|
+ self.get(1)
|
|
|
+ # return 8 + ((size + 1) & -2)
|
|
|
+ return (9 + size) & -2
|
|
|
+
|
|
|
+if __name__ == '__main__':
|
|
|
+ rate = Fraction(sys.argv[1])
|
|
|
+ print repr(rate)
|
|
|
+
|
|
|
+ a = Avi(sys.argv[2])
|
|
|
+ a.parse()
|
|
|
+ a.f.seek(a.rate_offset)
|
|
|
+ a.f.write(struct.pack("II", rate.denominator, rate.numerator))
|