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

Gstreamer:暂停/恢复RTP流中的视频,gstreamer,Gstreamer,我正在构建一个gstreamer管道,它从网络源接收两个RTP流: ILBC音频流+相应的RTCP流 H263视频流+对应RTCP流 所有内容都放在一个gstreamer管道中,因此它将使用来自两个流的RTCP来同步音频/视频。到目前为止,我已经想到了这个(使用gst启动进行原型设计): 如果网络源从发送视频和音频开始,那么这个管道工作得很好。如果视频流稍后暂停,gstreamer仍将播放音频,甚至在网络源恢复视频流时开始播放视频 但是,我的问题是,如果网络源仅以音频流开始(稍后可能会添加视频)

我正在构建一个gstreamer管道,它从网络源接收两个RTP流:

  • ILBC音频流+相应的RTCP流
  • H263视频流+对应RTCP流
  • 所有内容都放在一个gstreamer管道中,因此它将使用来自两个流的RTCP来同步音频/视频。到目前为止,我已经想到了这个(使用gst启动进行原型设计):

    如果网络源从发送视频和音频开始,那么这个管道工作得很好。如果视频流稍后暂停,gstreamer仍将播放音频,甚至在网络源恢复视频流时开始播放视频

    但是,我的问题是,如果网络源仅以音频流开始(稍后可能会添加视频),管道似乎会暂停/冻结,直到视频流也开始

    由于视频在我的应用程序中是可选的(并且可以由用户随意添加/删除),我有没有办法连接一个“videotestsrc”,它将提供某种回退视频数据,以便在没有网络视频数据时保持管道运行


    我尝试过使用“videotestsrc”和一种叫做“videomixer”的东西进行实验,但我认为混合器仍然需要两个流都是活动的。非常感谢您的反馈

    我提供了一个简单的函数,可以通过更改存储箱来暂停恢复。在下面的示例中,我提供了动态更改目标箱的逻辑。我相信这不会完全阻止你所寻求的管道。类似的逻辑可用于src箱。在这里,您可以删除网络源箱和相关解码器/解复用箱,并添加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();
    }
    
    您可能想尝试的另一种逻辑是“挂锁”。请看下面的帖子

    更新

  • 尝试输出选择器和输入选择器,因为它们似乎是更好的选择。我发现他们最可靠,并且与他们有着巨大的运气。我分别使用fakesinkfakesrc作为选择器的另一端

  • valve垃圾箱是我发现的另一种选择,它甚至不需要fakesinkfakesrc垃圾箱。它也非常可靠

  • 还有媒体文件源的正确状态转换顺序

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

    播放->暂停->准备->空值(向下)

    在上面的例子中,我的顺序应该在ready()出现在pause()之前的地方更正。另外,我倾向于认为取消链接应该在null()状态之后执行,而不是在pause()之后执行。我还没有尝试过这些改变,但理论上它们应该是有效的

    有关详细信息,请参阅以下链接

    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();
    }