在RTP流中暂停/恢复视频:Gstreamer

3
我正在构建一个 GStreamer 管道,从网络源接收两个 RTP 流:
  1. ILBC 音频流 + 相应的 RTCP 流
  2. H263 视频流 + 相应的 RTCP 流
所有内容都被放入一个 GStreamer 管道中,因此它将使用两个流的 RTCP 来同步音频/视频。到目前为止,我已经想出了这个管道(使用 gst-launch 进行原型设计):
gst-launch -vvv  gstrtpbin name=rtpbin
  udpsrc caps="application/x-rtp,media=(string)video,clock-rate=(int)90000,encoding-name=(string)H263-2000" port=40000 ! rtpbin.recv_rtp_sink_0
  rtpbin. ! rtph263pdepay ! ffdec_h263 ! xvimagesink
  udpsrc port=40001 ! rtpbin.recv_rtcp_sink_0
  rtpbin.send_rtcp_src_0 ! udpsink port=40002 sync=false async=false

  udpsrc caps="application/x-rtp,media=(string)audio,clock-rate=(int)8000,encoding-name=(string)PCMU,encoding-params=(string)1,octet-align=(string)1" port=60000 rtpbin.recv_rtp_sink_1
  rtpbin. ! rtppcmudepay ! autoaudiosink
  udpsrc port=60001 ! rtpbin.recv_rtcp_sink_1 
  rtpbin.send_rtcp_src_1 ! udpsink port=60002 sync=false async=false

如果网络源一开始就发送视频和音频,这个流水线效果很好。如果稍后暂停视频流,gstreamer仍将播放音频,甚至在网络源恢复视频流时开始播放视频。
然而,我的问题是,如果网络源一开始只有音频流(视频可能稍后添加),则该流水线似乎会暂停/冻结,直到视频流也开始。由于视频是可选的(用户可以随意添加/删除),我是否可以连接一个“videotestsrc”,以提供某种备用视频数据,以保持当没有网络视频数据时流水线运行?
我尝试过使用“videotestsrc”和一个称为“videomixer”的东西进行实验,但我认为混合器仍需要两个流都活着。非常感谢您的任何反馈!
1个回答

3
我提供一个简单的函数,可通过更改存储区来暂停/恢复。在以下示例中,我提供了动态更改目标存储区的逻辑。我相信这不会完全停止管道。类似的逻辑也可以用于源存储区。在这里,您可以删除网络源存储区及其相关的解码器/分离器存储区,并添加videotestsrc存储区。
private static void dynamic_bin_replacement(Pipeline pipe, Element src_bin, Element dst_bin_new, Element dst_bin_old) {
pipe.pause();
src_bin.unlink(dst_bin_old);                     
pipe.remove(dst_bin_old);
pipe.add(dst_bin_new);
dst_bin_new.syncStateWithParent();
src_bin.link(dst_bin_new);
pipe.ready();                    
pipe.play();
}

你可能想尝试的另一种逻辑是“锁定”。请查看以下帖子。

http://cgit.freedesktop.org/gstreamer/gstreamer/tree/docs/design/part-block.txt

并且

http://web.archiveorange.com/archive/v/8yxpz7FmOlGqxVYtkPb4

并且

在GStreamer管道中动态添加和移除音频源

更新

  1. 尝试使用output-selectorinput-selector bin,因为它们似乎是更好的选择。我发现它们最可靠,并且运气非常好。我分别使用fakesinkfakesrc作为选择器的另一端。

  2. valve bin是我发现不需要fakesinkfakesrc bin的另一个选择。它也非常可靠。

此外,媒体文件源的正确状态转换顺序为

NULL -> READY -> PAUSED -> PLAYING(向上)

PLAYING -> PAUSED -> READY -> NULL(向下)

在上面的例子中,我的顺序应该进行更正,即ready()应该在pause()之前。另外,我倾向于认为取消链接应该在null()状态之后而不是在暂停之后执行。我还没有尝试这些更改,但从理论上讲,它们应该可以工作。
请查看以下链接获取详细信息。

http://cgit.freedesktop.org/gstreamer/gstreamer/tree/docs/design/part-states.txt?h=BRANCH-RELEASE-0_10_19


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接