今天终于解决了困扰已久的video播放显示的问题,可以总结一下了。

我要做的是用Gstream播放avi等等我们可能需要支持的视频 文件,需要用到的plugin除了基本的filesrc,ffmpegcolorspace之外,还另外装了 avidemux,mpegdemux,mpeg2dec等等解码插件,最后播放的就是dfbvideosink.

而整个过程是这样的:

1,最开始测试用 gst-launch -v videotestsrc ! dfbvideosink,然后接到系统报错:streaming stopped, reason not-negotiated.
    我当然就很郁闷阿,连最简单的开始的测试都跑不过去,怎么办 ?
    之后阴差阳错居然发现directfb文件夹下有一个dfb-example的小例子,顺手就测试了一下,没有想到居然出来了,心里虽然觉得奇怪,但是还 是很高兴的就接受了这个事实。这里例子里面就是简单的用videotestsrc 和 dfbvideosink创建了一个pipeline,为什么就没有出现那个什么not-negotiated的错误。
    那个时候也注意到了dfb-example的代码里面比用gst-launch可能是多了一个directFB的surface之类的东西,但是也就没有去深究了。

2, 接下来尝试用gst-launch -v filesrc location=/convert.avi ! avidemux name=demux  demux.video_00 ! mpeg2dec ! ffmpegcolorspace ! dfbvideosink
当然也是不行的,一样的not-negotiated的错误。
     于是也在gst-devel的mailing list里面提问了。大家建议是用decodebin来代替avidemux和mpeg2dec。怕我用的文件里面的视频的codec跟 avidemux,mpeg2dec不兼容。为此我还在我的PC上面装了个mplayer,以便进行格式转换和格式检查。
    先尝试了decodebin这回可好了,冒出来另外一个错误:
  ERROR: from element /pipeline0/demux/avidemux0: Internal data stream error.
  Additional debug info:
  gstavidemux.c(3577): gst_avi_demux_loop (): /pipeline0/demux/avidemux0:
  streaming stopped, reason not-linked。
怎 么都觉得这个错误更严重。用GST_DEBUG看了一下调试信息,终于找到了原因所在,decodebin会自动接受并搜索所有的pad,我的avi里面 是有audio的部分的,但是我的pipeline里面没有连接这部分,所以给出来的信息自然是not-linked。关于GST_DEBUG看调试信息 也经历了一番周折,下面另外再说。还是接着用mpeg2dec之类的好了。
    我想到的自然就是自己在dfb-example里面尝试一下,毕竟在这个里面videotestsrc是成功的。吭哧吭哧的改了几行代码,中间还包括看了 一下动态的pad的东西,用来连接avidemux生成的video_00和audio_00这两个pad。花费了一份功夫,终于这个小应用build通 过了,满怀着希望放到板子上面跑,结果是:
0:00:01.613967000 [332m 1633[00m 0x1af80 [32;01mINFO [00m [00;01;34m           GST_EVENT gstpad.c:4242:gst_pad_send_event:<mpeg2dec0:sink>[00m Received event on flushing pad. Discarding
0:00:01.614717000 [332m 1633[00m 0x1af80 [32;01mINFO [00m [00;01;34m           GST_EVENT gstpad.c:4242:gst_pad_send_event:<mpeg2dec0:sink>[00m Received event on flushing pad. Discarding
0:00:01.616135000 [332m 1633[00m 0x1af80 [32;01mINFO [00m [00;01;34m           GST_EVENT gstpad.c:4242:gst_pad_send_event:<mpeg2dec0:sink>[00m Received event on flushing pad. Discarding
0:00:01.617260000 [332m 1633[00m 0x1af80 [33;01mWARN [00m [00m            avidemux gstavidemux.c:3548:gst_avi_demux_loop:[00m stream_movi flow: wrong-state / ok
  这个我就更加郁闷了,最开始pipeline的事件就不接收,要调试估计老痛苦了,这条路线还是先放着。

3,一计 不成又生一计。还是老办法,二分法:先把avi文件decode变成相应格式的raw data写入一个临时文件,然后把这个文件以相应的格式读入传送到dfbvideosink里面。看看问题究竟出在那里。原来调试audio的时候,也是 这样尝试的,虽然现在audio还未成功,但是这种思想还是可以借鉴的。
生成Raw data还是比较容易的,pileline的建立一次性通过,这就证明avidemux和mpeg2dec这些插件是正常的。
gst-launch -v filesrc location=/convert.avi ! avidemux name=demux  demux.video_00 ! mpeg2dec ! ffmpegcolorspace ! video/x-raw-rgb,bpp=32,depth=32 ! filesink location="/t3"
但是找这个颜色转换的格式还是费了一点时间,因为之前也不知道颜色有那些格式,而当前的directfb以及framebuffer支持那些格式的颜色。一次一次尝试得来的。
然后要从这个raw data中播放出来图像就有点费劲了:
 gst-launch -v filesrc location="/t3" !   video/x-raw-rgb,bpp=32,depth=32 ! dfbvideosink
运 行这个命令,出来一个assertion:说dfbvideosink里面的caps是NULL,然后 gst_dfbvideosink_show_frame()里面自然就有warning说不能创建一个大小为0的buffer,反正我也先不管对不对, 只要你有东西显示就行。于是大刀阔斧的把里面需要创建的surface图像的大小传进去了,然后屏幕上终于出现了一块有显示的区域,虽然不是什么漂亮的图 像,就是一些乱七八糟的东西,但是我也觉的离成功不不远了。
果然,第二天过来,就是修改格式了,还有那个blocksize也是需要根据你的图像大小,以及bpp自己算的,w*h*bpp,毕竟raw data了么,谁知道你的frame是什么格式的。
gst-launch -v filesrc location="/t3" blocksize=57344 ! video/x-raw-rgb,bpp=32,depth=32,width=128,height=112,framerate=25/1,endianness=4321 ! dfbvideosink
终于能看到一桢一桢的图像了,颜色也还算正常。

4,看起来应该是decoder跟dfbvideosink播放分别都没有问题了,还是把两头都凑起来好了。
恩 恩, 还是是用gst-launch好了:gst-launch -v filesrc location=/convert.avi ! avidemux name=demux  demux.video_00 ! mpeg2dec ! ffmpegcolorspace ! dfbvideosink,当然还是那个not-negotiated的错误。没有办法,只有硬着头皮看代码,打印调试信息了。
经过一天多的痛 苦,终于大概了解了gstreamer的negotiation大概的过程了,之前苦于在网上也搜不到相关的文档,直接硬生生的看代码人是会发疯的。其实 gstreamer还是有一些基本的设计文档放在网上的,虽然是英文,但是看懂也没有太大问题。这次帮我大忙的就是那个part- negotiation.txt,有空的话,应该所有的design文档都看一遍。
最后锁定了问题还是出在dfbvideosink,跟那个surface,也还有点关系。
dfbvideosink 在getcaps的时候,会把所有的可能支持的格式基本遍历一遍,检查是否有硬件加速之类的,如果有加速,才会将这个格式添加到caps里面,但是我的 dfb偏偏所有的加速都没有,人家当然返回empty的caps了,除了caps是ANY以外,其他的caps跟empty的交集自然是empty,所以 那些negotiation当然会失败了。
这样看起来,之前的raw data就是因为filesrc的caps是ANY,所以建立这个pipeline没有问题,而videotestsrc之类的caps自然不是ANY,报错是正常的。
但是dfb-example为什么是好的?再看代码,人家有ext_surface,getcaps的时候根本就不会挨个检查格式,直接把那个ext_surface支持的caps丢过去完事了。
终于可以播放视频了,但是又有新问题,只播放了几秒就停住了,另外有个mpeg的文件,连一秒都不放。

5,开始看了半天没有头绪,因为在dfbvideosink里面看不到任何的异常 ,就是忽然数据流停住了。
     后来怀疑这个跟audiosink有一样的问题,就是cpu太慢,然后解码达不到速度的要求,就把迟来的数据丢弃了,一打调试信息一看,果然 basesink里面大把的dropped信息。找了一下解决方法,把dfbvideosink的sync=FALSE就好了, 呵呵,终于还算流畅的播放视频了,速度也还好,我是能够接受了。

6,最后说一下那个GST_DEBUG的问题,这个用来看调试消息真的好阿。但是在PC上面所有的调试信息,即使级别为5都没有问题,但是一到板子上面,就会出来一个奇怪的错误:
Caught SIGSEGV accessing address (nil)
Spinning.  Please run 'gdb gst-launch 1532' to continue debugging, Ctrl-C to quit, or Ctrl-\ to dump core.
我的板子也没有gdb server,也懒得去弄了,然后看不到调试信息自然郁闷了。
不知道怎么阴差阳错的,知道了这个问题的原因,GST_PTR_FORMAT这个很多地方打印调试信息都会用到,在我的板子上这个应该是被define成P,但是一遇到这样的语句就会出来问题:
GST_WARNING ("unknown caps name received %" GST_PTR_FORMAT, caps);
于是我就把它define成p,这样是不会出来以前的错误了,但是也看不到具体的caps里面的内容了,很郁闷。
最后找到一个办法:GST_WARNING ("unknown caps name received %s", gst_caps_to_string (caps));
这样就可以看到caps里面具体的信息了,哈哈,不过应该还有很多地方会用到GST_PTR_FORMAT这个东西,到时候看清况再看怎么改,caps一类的这样应该没有问题咯。

好了,写了这么多,也差不多了,欢迎大家讨论以及提出来自己意见哈~!

总结完毕,回家~!