Armadilloフォーラム

MPEG2-TSで多重化されたH.264ストリームのデコード

yseki

2015年12月16日 11時52分

MPEG2-TTSで多重化されたH.264ストリームをデコードしたいのですが、エラーが出て止まってしまいます。
tsdemuxの出力をfakesinkでダンプすると、TTSのヘッダは正常に処理されているようです。

申し訳ありませんが、アドバイスいただけないでしょうか。

gst-launch-1.0 -v udpsrc uri=udp://239.192.0.20:37004 multicast-iface=eth0 auto-multicast=true ! tsdemux ! video/x-h264,framerate=30/1,width=1920,height=1080 !  h264parse ! acmh264dec stride=800 ! video/x-raw,width=800,height=480 ! acmfbdevsink sync=false device=/dev/fb1
Setting pipeline to PAUSED ...
Pipeline is live and does not need PREROLL ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
/GstPipeline:pipeline0/GstCapsFilter:capsfilter2: caps = video/x-h264, framerate=(fraction)30/1, width=(int)1920, height=(int)1080
/GstPipeline:pipeline0/GstCapsFilter:capsfilter2.GstPad:src: caps = video/x-h264, framerate=(fraction)30/1, width=(int)1920, height=(int)1080, stream-format=(string)byte-stream, alignment=(string)nal
/GstPipeline:pipeline0/GstQueue:queue0.GstPad:src: caps = video/x-h264, framerate=(fraction)30/1, width=(int)1920, height=(int)1080, stream-format=(string)byte-stream, alignment=(string)nal
/GstPipeline:pipeline0/GstH264Parse:h264parse0.GstPad:sink: caps = video/x-h264, framerate=(fraction)30/1, width=(int)1920, height=(int)1080, stream-format=(string)byte-stream, alignment=(string)nal
/GstPipeline:pipeline0/GstQueue:queue0.GstPad:sink: caps = video/x-h264, framerate=(fraction)30/1, width=(int)1920, height=(int)1080, stream-format=(string)byte-stream, alignment=(string)nal
/GstPipeline:pipeline0/GstCapsFilter:capsfilter2.GstPad:sink: caps = video/x-h264, stream-format=(string)byte-stream, alignment=(string)nal
/GstPipeline:pipeline0/GstH264Parse:h264parse0.GstPad:src: caps = video/x-h264, framerate=(fraction)30/1, width=(int)1920, height=(int)1080, stream-format=(string)avc, alignment=(string)au, parsed=(boolean)true
/GstPipeline:pipeline0/GstAcmH264Dec:acmh264dec0.GstPad:sink: caps = video/x-h264, framerate=(fraction)30/1, width=(int)1920, height=(int)1080, stream-format=(string)avc, alignment=(string)au, parsed=(boolean)true
/GstPipeline:pipeline0/GstAcmH264Dec:acmh264dec0.GstPad:src: caps = video/x-raw, format=(string)RGBx, width=(int)800, height=(int)480, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, colorimetry=(string)1:1:0:0, framerate=(fraction)30/1, stride=(int)800, x-offset=(int)0, y-offset=(int)0
/GstPipeline:pipeline0/GstCapsFilter:capsfilter1.GstPad:src: caps = video/x-raw, format=(string)RGBx, width=(int)800, height=(int)480, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, colorimetry=(string)1:1:0:0, framerate=(fraction)30/1, stride=(int)800, x-offset=(int)0, y-offset=(int)0
/GstPipeline:pipeline0/GstAcmFBDevSink:acmfbdevsink0.GstPad:sink: caps = video/x-raw, format=(string)RGBx, width=(int)800, height=(int)480, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, colorimetry=(string)1:1:0:0, framerate=(fraction)30/1, stride=(int)800, x-offset=(int)0, y-offset=(int)0
/GstPipeline:pipeline0/GstCapsFilter:capsfilter1.GstPad:sink: caps = video/x-raw, format=(string)RGBx, width=(int)800, height=(int)480, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, colorimetry=(string)1:1:0:0, framerate=(fraction)30/1, stride=(int)800, x-offset=(int)0, y-offset=(int)0
/GstPipeline:pipeline0/GstH264Parse:h264parse0.GstPad:src: caps = video/x-h264, framerate=(fraction)30/1, width=(int)1920, height=(int)1080, stream-format=(string)avc, alignment=(string)au, parsed=(boolean)true
/GstPipeline:pipeline0/GstAcmH264Dec:acmh264dec0.GstPad:sink: caps = video/x-h264, framerate=(fraction)30/1, width=(int)1920, height=(int)1080, stream-format=(string)avc, alignment=(string)au, parsed=(boolean)true
/GstPipeline:pipeline0/GstH264Parse:h264parse0.GstPad:src: caps = video/x-h264, framerate=(fraction)30/1, width=(int)1920, height=(int)1080, stream-format=(string)avc, alignment=(string)au, parsed=(boolean)true
/GstPipeline:pipeline0/GstAcmH264Dec:acmh264dec0.GstPad:sink: caps = video/x-h264, framerate=(fraction)30/1, width=(int)1920, height=(int)1080, stream-format=(string)avc, alignment=(string)au, parsed=(boolean)true
ERROR: from element /GstPipeline:pipeline0/GstAcmH264Dec:acmh264dec0: Could not decode stream.
Additional debug info:
gstacmh264dec.c(2059): gst_acm_h264_dec_handle_in_frame (): /GstPipeline:pipeline0/GstAcmH264Dec:acmh264dec0:
could not queue buffer 5 (Input/output error)
Execution ended after 237515583 ns.
Setting pipeline to PAUSED ...
Setting pipeline to READY ...
Setting pipeline to NULL ...
Freeing pipeline ...
コメント

> MPEG2-TTSで多重化されたH.264ストリームをデコードしたいのですが、エラーが出て止まってしまいます。
> tsdemuxの出力をfakesinkでダンプすると、TTSのヘッダは正常に処理されているようです。
[...]
> ERROR: from element /GstPipeline:pipeline0/GstAcmH264Dec:acmh264dec0: Could not decode stream.

デコーダーがデコードできてないですね。

udpで多重化しているストリームを受けているようですが、

1) 多重化しないと、うまく動きますか?
2) udpを通さないと、多重化していていもうまくいきますか?

まずは、切り分けをして問題が再現する最小構成を作るところからでしょうか。

何回か実行すると、たまに成功することがあります。
コマンド実行時に最初に受信するパケットに依存するのかと思いますが、いかがでしょうか。
問題のないパケットまで読み飛ばす方法はありますでしょうか。
実行を繰り返すしかないのでしょうか。

gst-launch-1.0 -v udpsrc uri=udp://224.168.101.100:50100/ multicast-iface=eth0 auto-multicast=true ! tsdemux ! video/x-h264,framerate=30/1,width=1920,height=1080,pixel-aspect-ratio=1/1 ! h264parse ! acmh264dec stride=800 ! video/x-raw,width=800,height=480 ! acmfbdevsink sync=false device=/dev/fb1
ファイル ファイルの説明
成功.txt 成功時のログ
失敗.txt 失敗時のログ

> 何回か実行すると、たまに成功することがあります。
> コマンド実行時に最初に受信するパケットに依存するのかと思いますが、いかがでしょうか。

あ、本当ですね。

sps/ppsがとれないから失敗しているようです。
解決方法は、2つでしょうか
- 送信側で、頻繁に送信
- 受信側で、パイプラインに指定 (streamheader)

streamheader については、ソースコードのgstreamer/docs/random/streamheader に記載があります。
gstbaseparse.c で実装されているので、h264parse に指定すればよかったはずです。

# 前に試したことがあるような気がするのですが、gst-launchの例が出てこない...。
# 思い出したら、また投稿します。

色々調べたところ、h264parseの修正コードがあるようです。
gsth264parse.cが対象のようなのですが、 ユーザランド(v20151218)中に該当するソースコードが見つかりませんでした。
h264parseのコード箇所を教えていただけないでしょうか。

自己レスです。
下記のブログを参考にgst-plugins-badのビルド環境を構築しました。
 https://users.atmark-techno.com/blog/750/1374
wheezyパッケージから引いてこれないものが増えているようです。

下記を参考にh264parseを修正して、streamheader指定無しでデコードできるようになりました。
 http://lists.freedesktop.org/archives/gstreamer-commits/2013-June/07211…

ありがとうございました。