tss.py 異常終了の原因

2011/12/16 by happybreeding Leave a reply »

tss.pyは、MPEG-2 TSのデータから、先頭のプログラムを抽出するもの。典型的には、地デジを録画したデータから、HDストリームを抽出するために使われていると思われます。Windows方面では、TsSplitter.exeが担当する分野。

さて、そんなスクリプトですが、どういうわけか手元の環境では異常終了してしまうケースが多く、その割にはWebではまったくといっていいほど話題になっていないことを不思議に思っていたりしたのです。

Traceback (most recent call last):
  File "tss.py", line 101, in <module>
    N += 4 + ((ord(x[N+3])&0x0F)<<4) + ord(x[N+4]) + 1
IndexError: string index out of range

仮にtss.pyが異常終了したとしても、他の手段で対応できなくはないので、例によって放置していたのですが、ちょっとその気になったので原因究明してみることにしました。

過程をずらずら書いてもしょうがないので結論だけにしてしまいますが、PMTのサイズが1パケットを超えるデータのときにこのエラーが発生しています。

手元のデータをいくつか確認してみると、MBS毎日放送を録画したものがこの状態になっているのですが、これがこの局特有で、東京の局では発生しない現象だとすれば、騒ぎになっていないというのも、まあ理解できなくはないところ。

というわけでパッチ貼っておきますが、仕様書を確認せずに実データを観察した結果なので誤っている可能性があります。その上pythonは初めてなのでどこかおかしいかもしれません。一応手元ではちゃんと動いているように見えます。作者さんに連絡とろうかとも思ったけど、もう興味なくしてるみたいでちょっとお悩み中。

--- tss.py.orig    2008-09-24 01:38:22.000000000 +0900
+++ tss.py    2011-12-14 17:10:51.000000000 +0900
@@ -49,6 +49,9 @@
 # PAT差し替えデータを初期化
 z = ""

+# PMTパケットデータを初期化
+w = ""
+
 ### 残すPIDを捜索
 while True:
 x = fi.read(188)
@@ -87,21 +90,23 @@

 # PMT
 if pid == pmt :
-        Nall = ((ord(x[6])&0x0F)<<4) + ord(x[7])
-        
-        # PCR
-        pcr = "0x%02x%02x" % ( ord(x[13])&0x1F, ord(x[14]) )
-        pids.append( pcr )
-        N = ((ord(x[15])&0x0F)<<4) + ord(x[16]) + 16 +1
+        w += x if w == "" else x[4:]
+        Nall = ((ord(w[6])&0x0F)<<4) + ord(w[7])

-        # EPID
-        while N < Nall +8 -4 :
-            if  ord(x[N]) != 0x0d :
-                pids.append( "0x%02x%02x" % ( ord(x[N+1])&0x1F, ord(x[N+2]) ) )
-            N += 4 + ((ord(x[N+3])&0x0F)<<4) + ord(x[N+4]) + 1
+        if len(w) >= Nall + 8 :
+            # PCR
+            pcr = "0x%02x%02x" % ( ord(w[13])&0x1F, ord(w[14]) )
+            pids.append( pcr )
+            N = ((ord(w[15])&0x0F)<<4) + ord(w[16]) + 16 +1
+            
+            # EPID
+            while N < Nall +8 -4 :
+                if  ord(w[N]) != 0x0d :
+                    pids.append( "0x%02x%02x" % ( ord(w[N+1])&0x1F, ord(w[N+2]) ) )
+                N += 4 + ((ord(w[N+3])&0x0F)<<4) + ord(w[N+4]) + 1

-        print pids
-        break
+            print pids
+            break

 ### PATを修正しつつ、残すPIDのみ出力

コメントを残す