]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
support: add mkvcmp.py script
authorJaroslav Kysela <perex@perex.cz>
Fri, 23 Oct 2015 22:18:38 +0000 (00:18 +0200)
committerJaroslav Kysela <perex@perex.cz>
Fri, 23 Oct 2015 22:28:01 +0000 (00:28 +0200)
support/mkvcmp.py [new file with mode: 0755]

diff --git a/support/mkvcmp.py b/support/mkvcmp.py
new file mode 100755 (executable)
index 0000000..a3027cc
--- /dev/null
@@ -0,0 +1,180 @@
+#!/usr/bin/python
+
+import os
+import sys
+import difflib
+
+GOOD="demuxing_fails.mkv"
+WRONG="a.mkv"
+FRAMES=100
+
+def peek32(d, i):
+  return (ord(d[i+0]) << 24) | (ord(d[i+1]) << 16) | \
+         (ord(d[i+2]) << 8) | ord(d[i+3])
+
+SLICES = {
+  1:  'NAL_SLICE',
+  2:  'NAL_DPA',
+  3:  'NAL_DPB',
+  4:  'NAL_DPC',
+  5:  'NAL_IDR_SLICE',
+  6:  'NAL_SEI',
+  7:  'NAL_SPS',
+  8:  'NAL_PPS',
+  9:  'NAL_AUD',
+  10: 'NAL_END_SEQUENCE',
+  11: 'NAL_END_STREAM',
+  12: 'NAL_FILLER_DATA',
+  13: 'NAL_SPS_EXT',
+  19: 'NAL_AUXILIARY_SLICE',
+}
+
+class NAL:
+
+  def __init__(self, bin):
+    self.bin = bin
+
+  def len(self):
+    return len(self.bin)
+
+  def tohex(self):
+    r = ''
+    d = self.bin
+    for i in range(len(d)):
+      r += '%02x ' % ord(d[i])
+      if (i % 16) == 15:
+        r += '\n'
+    return r and r + '\n' or ''
+
+  def name(self):
+    i = ord(self.bin[0]) & 0x1f
+    return SLICES[i]
+
+class NALs:
+
+  def __init__(self):
+    self._nals = []
+
+  def nals(self):
+    return self._nals
+
+  def len(self):
+    return len(self._nals)
+
+  def append(self, nal):
+    self._nals.append(nal)
+
+  def remove(self, nal):
+    for i in range(len(self._nals)):
+      if self._nals[i].bin == nal.bin:
+        self._nals.pop(i)
+        return True
+    return False
+
+  def gethex(self, i):
+    return self._nals[i].tohex()
+
+  def nlen(self, i):
+    return self._nals[i].len()
+
+  def nname(self, i):
+    return self._nals[i].name()
+
+class Frame:
+
+  def __init__(self, hexdump):
+    self.dump = ''
+    self._nals = None
+    for i in range(0, len(hexdump), 3):
+      v = hexdump[i:i+2]
+      if v == 'at':
+        break
+      self.dump += chr(int(v, 16))
+
+  def len(self):
+    return len(self.dump)
+
+  def match(self, other):
+    return self.dump == other.dump
+
+  def compare(self, other, desc1='NALS1', desc2='NALS2'):
+    nals1 = self.nals()
+    nals2 = other.nals()
+    if nals1.len() == nals2.len():
+      for i in range(nals1.len()):
+        print('      NAL%d: %06d (%-15s) %06d (%-15s)' % \
+              (i, nals1.nlen(i), nals1.nname(i), nals2.nlen(i), nals2.nname(i)))
+    loop = True
+    while loop:
+      loop = False
+      for n in nals1.nals():
+        if nals2.remove(n):
+          nals1.remove(n)
+          loop = True
+          break
+    loop = True
+    while loop:
+      loop = False
+      for n in nals2.nals():
+        if nals1.remove(n):
+          nals2.remove(n)
+          loop = True
+          break
+    if nals1.len() == 0 and nals2.len() == 0:
+      print('      NALs match')
+      return True
+    print('      NALS NOT MATCHED', nals1.len(), nals2.len())
+    if nals1.len() == 1 and nals2.len() == 1:
+      print('      %d %d' % (nals1.nlen(0), nals2.nlen(0)))
+      h1 = nals1.gethex(0).splitlines(True)
+      h2 = nals2.gethex(0).splitlines(True)
+      sys.stdout.writelines(difflib.unified_diff(h1, h2, desc1, desc2))
+      print
+    return False
+
+  def nals(self):
+    if not self._nals:
+      self._nals = NALs()
+      i = 0
+      d = self.dump
+      while i < len(d):
+        p = peek32(d, i)
+        if p > len(d) - (i + 4): raise
+        self._nals.append(NAL(d[i+4:i+p+4]))
+        i += p + 4
+      if i != len(d): raise
+    return self._nals
+
+def grab_frames(file, track):
+  frames = []
+  f = os.popen("LC_ALL=C mkvinfo -v -v -X " + file, "r", 1)
+  parse = False
+  first = True
+  while len(frames) < FRAMES:
+    x = f.readline()
+    if not x:
+      break
+    if 'SimpleBlock' in x:
+      parse = ('track number %s,' % track) in x
+    elif parse:
+      pos = x.find(' hexdump ')
+      if pos >= 0 and not first:
+        frames.append(Frame(x[pos+9:]))
+        sys.stdout.write('%s: %s\r' % (file, len(frames)))
+      first = False
+  os.system("killall -9 mkvinfo")
+  f.close()
+  print
+  return frames
+  
+f1 = grab_frames(GOOD, 1)
+f2 = grab_frames(WRONG, 1)
+
+for i in range(0, min(len(f1), len(f2))):
+  a1 = f1[i]
+  a2 = f2[i]
+  match = a1.match(a2)
+  print("%04s: %08s %08s %s" % (i, a1.len(), a2.len(), match))
+  if not match:
+    if not a2.compare(a1, 'WRONG', 'GOOD'):
+      break