转载地址:
http://blog.csdn.net/jack0106/article/details/5592557
之前开发过一个小程序,就是用gstreamer做了一个简单的IP电话,就是建立了两个pipeline,代码片段分别如下:
speaker
= "gstrtpbin name=rtpbin "
"pulsesrc ! audioconvert ! audioresample ! mulawenc ! rtppcmupay ! rtpbin.send_rtp_sink_0 "
"rtpbin.send_rtp_src_0 ! udpsink name=speaker_udpsink "
"rtpbin.send_rtcp_src_0 ! udpsink name=speaker_udpsinkrtcp sync=false async=false "
"udpsrc name=speaker_udpsrc ! rtpbin.recv_rtcp_sink_0";
listener
= "gstrtpbin name=rtpbin "
"udpsrc name=listener_udpsrcrtp caps=/"application/x-rtp,media=(string)audio,clock-rate=(int)8000,encoding-name=(string)PCMA/" ! rtpbin.recv_rtp_sink_0 "
"rtpbin. ! rtppcmudepay ! mulawdec ! audioconvert ! audioresample ! pulsesink "
"udpsrc name=listener_udpsrcrtcp ! rtpbin.recv_rtcp_sink_0 "
"rtpbin.send_rtcp_src_0 ! udpsink name=listener_udpsink sync=false async=false";
在局域网中测试的时候,没有啥问题,但是和sip协商过程联合测试的时候,就出了点问题,原因两三句话不太好描述,反正解决的办法,就是要让上面代码片段中红色的udpsink和udpsrc使用同一个socket描述符。
本来,udpsink和udpsrc,都分别有一个属性,就是用来设置自定义的socket描述符的,但是,当我用同一个socket描述符同时设置这两个插件的时候,运行的效果和想象的并不一样,调试了半天,分析出的结果是udpsink和udpsrc虽然可以设置socket,但是,并不能同时使用同一个socket。
后来,找到一个解决办法,就是使用appsink,把第一个pipeline改成如下形式
speaker
= "gstrtpbin name=rtpbin "
"pulsesrc ! audioconvert ! audioresample ! mulawenc ! rtppcmupay ! rtpbin.send_rtp_sink_0 "
"rtpbin.send_rtp_src_0 ! appsink name=appsink "
"rtpbin.send_rtcp_src_0 ! udpsink name=speaker_udpsinkrtcp sync=false async=false "
"udpsrc name=speaker_udpsrc ! rtpbin.recv_rtcp_sink_0";
手动创建一个socket,设置到前面给出的红色的udpsrc上,同时,在appsink的信号处理函数中,再直接调用send函数,往同一个socket上发送数据,这样问题就解决了,而且socket本身就是全双工工作的,连线程同步都不要考虑了。
自己动手写gstreamer插件,是一件比较困难的事情,目前我还没有那个能力,不过还好发现了appsink和appsrc,可以在一定程度上避免编写gstreamer插件,同时又可以在pipeline中调用第三方的代码。gstreamer的确是linux上多媒体开发的王者!