Browse Source

AVI rate conversion hack

James Bowman 6 years ago
parent
commit
ed630524c8
1 changed files with 102 additions and 0 deletions
  1. 102 0
      avirate.py

+ 102 - 0
avirate.py

@@ -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))