gpt4 book ai didi

android - 实时/零延迟视频流 : what codec parameters to use?

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:51:13 26 4
gpt4 key购买 nike

我正在编写一个 Android 应用程序,其中包括从台式电脑发送和接收视频流。为了让应用程序正常运行,我们需要尽可能少的延迟,必要时牺牲视频质量。我们在两端都使用了 gstreamer 1.45,但是根据当前的管道,我们在 Galaxy Note S2 上至少有 0.5 秒的延迟,如果两个设备都在同一个网络上(稍后这应该可以通过VPN)。

发送者管道

appsrc name=vs_src format=time do-timestamp=true
caps="video/x-raw, format=(string)RGB, width=(int)640, height=(int)480, framerate=(fraction)15/1000"
! videoconvert
! x264enc speed-preset=ultrafast tune=zerolatency byte-stream=true threads=1 key-int-max=15 intra-refresh=true ! h264parse ! rtph264pay pt=96
! queue ! udpsink name=vs_sink host=%s port=%d async=false

接收者管道

udpsrc name=vr_src 
caps="application/x-rtp, media=(string)video, clock-rate=(int)90000, payload=(int)96, encoding-name=(string)H264"
! rtpjitterbuffer
! rtph264depay ! h264parse ! avdec_h264
! videorate ! videoconvert
! glimagesink name=vr_sink async=false

设置 threads=2 或更高会发出 gstreamer 警告,它是在没有多线程支持的情况下编译的。我知道有些设备提供硬件解码器,但可靠地访问它们的唯一方法似乎是通过 encodebin/decodebin。我已经尝试使用 decodebin 但出于某种原因它提示找不到所需的插件(例如 No decoder to handle media type 'video/x-h264' ).

在流媒体和视频编码/解码方面,我绝不是专家,让应用程序达到工作点已经是一场噩梦:/如果 H264 不合适,我们可以切换到 gstreamer 支持的任何其他编解码器.有谁能够帮我?

最佳答案

我们从台式 PC 到 Raspberry Pis 进行实时视频流传输,我们花费了大量时间来调整系统的编码和解码部分。不幸的是,大多数库和工具都有针对转码或一般视频播放(非实时)的开箱即用设置。我们最终编写了自己的 GStreamer 元素来进行编码(使用 vaapi),并编写了我们自己的 Raspberry Pi 程序来进行解码(使用 OMX)。

我可以为您提供一些想法,但不幸的是,没有针对 Android 解码场景的具体想法。

  • 如果您在功能强大的桌面(例如 i3-i7)上进行编码,请确保为任何重要操作添加队列:色彩空间转换、缩放、编码等。因此,在您的管道中,请确保有一个“videoconvert”和“x264enc”之间的“队列”,因此它们在单独的线程上运行。

  • 正如 Ralf 提到的,您可能只想使用 P 帧,而不是 B 帧,并且您的 x264enc 设置可能已经这样做了。

  • 与使用大型 jitter buffer 相比,我们通常更喜欢丢帧和显示垃圾。我们还即时调整 QP(编码质量)以使其在我们的网络范围内。所以我建议将 sync=false 添加到您的接收程序中。您想在获得帧后立即渲染它。这可能会使您的视频不那么流畅,但是如果您有一个大的 jitter buffer ,您总是会被延迟。最好将流调整到网络并摆脱缓冲区。 x264enc 具有您可以尝试的“qp-min”和“qp-max”属性。

  • 尝试调整 rtpjitterbuffer 的“延迟”和“延迟延迟”属性,或者尝试完全摆脱它。

  • 我们发现的一个非常糟糕的事情是,在 Raspberry Pi 解码器中它似乎总是有某种内置延迟,无论我们的流如何实时优化。事实证明,在 h264 流中有一种称为 VUI 数据包的东西,可用于告诉解码器预期的流类型,当我们提供此数据包时,解码器的 react 非常不同。

bitstream_restriction_flag : 1motion_vectors_over_pic_boundaries_flag : 1 max_bytes_per_pic_denom : 0 max_bits_per_mb_denom : 0 log2_max_mv_length_horizontal : 10 log2_max_mv_length_vertical : 10 num_reorder_frames : 0 max_dec_frame_buffering : 1   --- this makes a huge difference

For reference: https://www.raspberrypi.org/forums/viewtopic.php?t=41053

So in the above VUI settings I tell the decoder that we'll have a max of one P frame that it needs to buffer. It's crazy how much this helped. Of course we had to also make sure our encoder did only send the one P frame. I'm not sure this is possible to do do with x264enc.

This stuff can get pretty scary. Hopefully someone else has the Android video chops to give you a simpler answer!

EDIT: Regarding queues, I don't parameterize them at all, and in a live streaming situation if your queues fill up you need to scale back (resolution, quality, whatever) anyway. In GStreamer the queue element causes GStreamer to launch a new thread to handle the following portion of the pipeline. You just want to make sure your encode/scaling/colorspace conversion elements work in isolation.

gst-launch-1.0 [GET RAW VIDEO DATA] queue [SCALE] queue [COLORSPACE CONVERT] queue [ENCODE] queue [SEND WHEREVER]

The above will give you five threads.

If you get nothing here, my recommendation is to hit up an Android video API subforum or mailing list to see if anyone else has live video going and if so what tweaks they made to their stream and decoder.

--- Addendum 1-5-18

We've also noticed that some streams can fill up the kernel socket buffer and result in packet drops--particularly on large keyframes. So if you have a larger stream I recommend checking the kernel buffer size using sysctl:

sysctl net.core.rmem_max;  sysctl net.core.rmem_default
net.core.rmem_max = 212992
net.core.rmem_default = 212992

在接收设备的/etc/sysctl.conf 中附加 net.core.rmem_max = whatever,并在 udpsrc 上设置 buffer-size 到这个新的最大值。您可以通过运行以下命令来判断您是否仍然看到掉落:

watch -d 'cat /proc/net/snmp | grep Udp: '

...或在您的接收管道上类似这样的内容:

export GST_DEBUG=2,rtpjitterbuffer:5

gst-launch-1.0 udpsrc port=5100 buffer-size=825984 ! application/x-rtp,encoding-name=H264,payload=96 ! rtpjitterbuffer latency=200 ! rtph264depay ! h264parse disable-passthrough=true ! queue ! avdec_h264 output-corrupt=true ! queue ! videoconvert ! ximagesink 2>&1 | grep -i "buffer discon

--- 附录 1-11-19

如果您有办法了解专利情况,Cisco 的 openh264 库可以很好地工作。它非常适合直播。

https://github.com/cisco/openh264

https://www.openh264.org/BINARY_LICENSE.txt

gst-plugins-bad 下有一个 GStreamer 插件。

关于android - 实时/零延迟视频流 : what codec parameters to use?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30730082/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com