为什么在发送器/接收器管道中使用H264会引入巨大的延迟?

时间:2010-05-23 20:54:01

标签: video gstreamer h.264 rtp x264

当我尝试创建使用H264传输视频的管道时,我得到一些巨大的延迟,最多10秒钟将视频从我的机器传输到...我的机器!这对我的目标来说是不可接受的,我想咨询StackOverflow,了解我(或其他人)做错了什么。

我从gstrtpbin文档页面获取了管道并稍加修改它们以使用Speex:

这是发件人管道:     #!/ bin / sh的

gst-launch -v gstrtpbin name=rtpbin \
        v4l2src ! ffmpegcolorspace ! ffenc_h263 ! rtph263ppay ! rtpbin.send_rtp_sink_0 \
                  rtpbin.send_rtp_src_0 ! udpsink host=127.0.0.1 port=5000                            \
                  rtpbin.send_rtcp_src_0 ! udpsink host=127.0.0.1 port=5001 sync=false async=false    \
                  udpsrc port=5005 ! rtpbin.recv_rtcp_sink_0                           \
        pulsesrc ! audioconvert ! audioresample  ! audio/x-raw-int,rate=16000 !    \
                  speexenc bitrate=16000 ! rtpspeexpay ! rtpbin.send_rtp_sink_1                   \
                  rtpbin.send_rtp_src_1 ! udpsink host=127.0.0.1 port=5002                            \
                  rtpbin.send_rtcp_src_1 ! udpsink host=127.0.0.1 port=5003 sync=false async=false    \
                  udpsrc port=5007 ! rtpbin.recv_rtcp_sink_1

接收器管道:

!/ bin / sh的

gst-launch -v\
    gstrtpbin name=rtpbin                                          \
    udpsrc caps="application/x-rtp,media=(string)video, clock-rate=(int)90000, encoding-name=(string)H263-1998" \
            port=5000 ! rtpbin.recv_rtp_sink_0                                \
        rtpbin. ! rtph263pdepay ! ffdec_h263 ! xvimagesink                    \
     udpsrc port=5001 ! rtpbin.recv_rtcp_sink_0                               \
     rtpbin.send_rtcp_src_0 ! udpsink port=5005 sync=false async=false        \
    udpsrc caps="application/x-rtp,media=(string)audio, clock-rate=(int)16000, encoding-name=(string)SPEEX, encoding-params=(string)1, payload=(int)110" \
            port=5002 ! rtpbin.recv_rtp_sink_1                                \
        rtpbin. ! rtpspeexdepay ! speexdec ! audioresample ! audioconvert ! alsasink \
     udpsrc port=5003 ! rtpbin.recv_rtcp_sink_1                               \
     rtpbin.send_rtcp_src_1 ! udpsink host=127.0.0.1 port=5007 sync=false async=false

这些管道,H263和Speex的组合,运行得很好。我用手指靠近相机和micropohne,然后我看到了移动并同时听到了声音。

然后我改变了管道以沿着视频路径使用H264。

发件人变为:     #!/ bin / sh的

gst-launch -v gstrtpbin name=rtpbin \
        v4l2src ! ffmpegcolorspace ! x264enc bitrate=300 ! rtph264pay ! rtpbin.send_rtp_sink_0 \
                  rtpbin.send_rtp_src_0 ! udpsink host=127.0.0.1 port=5000                            \
                  rtpbin.send_rtcp_src_0 ! udpsink host=127.0.0.1 port=5001 sync=false async=false    \
                  udpsrc port=5005 ! rtpbin.recv_rtcp_sink_0                           \
        pulsesrc ! audioconvert ! audioresample  ! audio/x-raw-int,rate=16000 !    \
                  speexenc bitrate=16000 ! rtpspeexpay ! rtpbin.send_rtp_sink_1                   \
                  rtpbin.send_rtp_src_1 ! udpsink host=127.0.0.1 port=5002                            \
                  rtpbin.send_rtcp_src_1 ! udpsink host=127.0.0.1 port=5003 sync=false async=false    \
                  udpsrc port=5007 ! rtpbin.recv_rtcp_sink_1

接收者变成:     #!/ bin / sh的

gst-launch -v\
    gstrtpbin name=rtpbin                                          \
    udpsrc caps="application/x-rtp,media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264" \
            port=5000 ! rtpbin.recv_rtp_sink_0                                \
        rtpbin. ! rtph264depay ! ffdec_h264 ! xvimagesink                    \
     udpsrc port=5001 ! rtpbin.recv_rtcp_sink_0                               \
     rtpbin.send_rtcp_src_0 ! udpsink port=5005 sync=false async=false        \
    udpsrc caps="application/x-rtp,media=(string)audio, clock-rate=(int)16000, encoding-name=(string)SPEEX, encoding-params=(string)1, payload=(int)110" \
            port=5002 ! rtpbin.recv_rtp_sink_1                                \
        rtpbin. ! rtpspeexdepay ! speexdec ! audioresample ! audioconvert ! alsasink \
     udpsrc port=5003 ! rtpbin.recv_rtcp_sink_1                               \
     rtpbin.send_rtcp_src_1 ! udpsink host=127.0.0.1 port=5007 sync=false async=false

这是在Ubuntu 10.04下发生的事情。我没有注意到Ubuntu 9.04上出现如此大的延迟 - 延迟时间为2-3秒,AFAIR。

3 个答案:

答案 0 :(得分:2)

在Freenode的#x264“Sharktooth”的帮助下,我发现gst-plugins-ugly的git版本支持“零延迟”预设。

http://cgit.freedesktop.org/gstreamer/gst-plugins-ugly

我调整了你的例子来设置“x264enc pass = qual quantizer = 20 tune = zerolatency”,延迟似乎保持在0.7-0.9秒。我无法弄清楚如何降低它。

答案 1 :(得分:1)

其中有东西是缓冲,很可能是编码器。它必须处理的数据越多,它可以实现的压缩效率就越高。我不熟悉那个编码器,但通常有缓冲量的设置。

答案 2 :(得分:1)

默认情况下,x264缓冲输入以使更多数据可供使用。 Ubuntu 10.04的延迟增加很可能是因为它在引入-mbtree和--rc-lookahead之前停留在旧的x264版本上。

This page of Mewiki中,您可以看到如何计算延迟,帧数和以下内容,以及应首先禁用的内容,以减少延迟:

  

可以降低x264的延迟,但会降低质量。如果您不想延迟,请设置--tune zerolatency。如果你可以处理一个小的延迟(即不到1秒),那么调整选项以允许这一点是非常值得的。以下是您可以遵循的一系列步骤,以逐步减少延迟。当您的延迟足够低时停止:

     
      
  1. 以默认值开头
  2.   
  3. Kill sync-lookahead
  4.   
  5. 将rc-lookahead降至不低于~10
  6.   
  7. 将线程拖放到较低的值(即说6而不是12)
  8.   
  9. 使用切片线程
  10.   
  11. 禁用rc-lookahead
  12.   
  13. 禁用b帧
  14.   
  15. 现在你正处于--tune zerolatency
  16.   

因此,您应该首先尝试添加类似

的命令行

sync-lookahead = 0,rc-lookahead = 10(我不确定应用程序中命令行的格式化)

这应该以低压缩效率成本削减大部分延迟。如果你有很多核心(例如一个带有HT的四核),它也可能值得做4号,速度很快。

根据Sharktooth的建议,使用tune = zerolatency,如果这还不够。

有关该主题的更多信息:http://x264dev.multimedia.cx/archives/249