- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在编写一个 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/
Closed. This question is opinion-based。它当前不接受答案。 想改善这个问题吗?更新问题,以便editing this post用事实和引用来回答。 2年前关闭。
我想显示我的网站上所有用户都在线(实时;就像任何聊天模块一样)。我正在使用下面提到的脚本来执行此操作。 HTML: Javascript: var doClose = false; documen
有什么方法可以知道 Algolia 何时成功处理了排队作业,或者与上次重新索引相比,Algolia 是否索引了新文档? 我们希望建立一个系统,每当新文档被索引时,浏览网站的用户都会收到实时更新警告,并
构建将在“桌面”而不是浏览器中运行的 Java 应用程序的推荐策略是什么。该应用程序的特点是: 1. Multiple application instances would be running o
这是场景: 我正在编写一个医疗相关程序,可以在没有连接的情况下使用。当采取某些措施时,程序会将时间写入CoreData记录。 这就是问题所在,如果他们的设备将时间设置为比实际时间早的时间。那将是一个大
我有: $(document).ready(function () { $(".div1, .div2, .div3, .div4, .div5").draggable();
我有以下 jquery 代码: $("a[id*='Add_']").live('click', function() { //Get parentID to add to. var
我有一个 jsp 文件,其中包含一个表单。提交表单会调用处理发送的数据的 servlet。我希望当我点击提交按钮时,一个文本区域被跨越并且应该实时显示我的应用程序的日志。我正在使用 Tomcat 7。
我编辑了我的问题,我在 Default.aspx 页面中有一个提交按钮和文本框。我打开两个窗口Default.aspx。我想在这个窗口中向文本框输入文本并按提交,其他窗口将实时更新文本框。 请帮助我!
我用 php 创建了一个小型 CMS,如果其他用户在线或离线,我想显示已登录的用户。 目前,我只创建一个查询请求,但这不会一直更新。我希望用户在发生某些事情时立即看到更改。我正在寻找一个类似于 fac
我有以下问题需要解决。我必须构建一个图形查看器来查看海量数据集。 我们有一些特定格式的文件,其中包含数百万条代表实验结果的记录。每条记录代表大图上的一个样本点。我见过的最大的文件有 4370 万条记录
我最近完成了申请,但遇到了一个大问题。我一次只需要允许 1 个用户访问它。每个用户每次都可以访问一个索引页面和“开始”按钮。当用户点击开始时,应用程序锁定,其他人需要等到用户完成。当用户关闭选项卡/浏
我是 Android 开发新手。我正在寻找任何将音高变换应用到输出声音(实时)的方法。但我找不到任何起点。 我找到了这个 topic但我仍然不知道如何应用它。 有什么建议吗? 最佳答案 一般来说,该算
背景 用户计算机上的桌面应用程序从调制解调器获取电话号码,并在接到电话后将其发送到 PHP 脚本。目前,我可以通过 PHP 在指定端口上接收数据/数据包。然后我有一个连接到 411 数据库并返回指定电
很抱歉提出抽象问题,但我正在寻找一些关于在循环中执行一些等效操作的应用程序类型的示例/建议/文章,并且循环的每次迭代都应该在特定时间部分公开其结果(例如, 10 秒)。 我的应用程序在外部 WCF 服
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: What specifically are wall-clock-time, user-cpu-time,
我最近遇到了一个叫做 LiveChart 的工具,决定试用一下。 不幸的是,我在弄清楚如何实时更新图表值时遇到了一些问题。我很确定有一种干净正确的方法可以做到这一点,但我找不到它。 我希望能够通过 p
我正在实现实时 flutter 库 https://pub.dartlang.org/packages/true_time 遇到错误 W/DiskCacheClient(26153): Cannot
我一直在使用 instagram 的实时推送 api ( http://instagram.com/developer/realtime/ ) 来获取特定位置的更新。我使用“半径”的最大可能值,即 5
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve thi
我是一名优秀的程序员,十分优秀!