繁体   English   中英

使用 GStreamer OpenCV Videocapture 时的灰色视频帧 C++

[英]Grey Video frames when using OpenCV Videocapture with GStreamer C++

收到的帧

嘿,我是 Gstreamer 的新手,想通过 a.network 将从摄像机捕获并使用 OpenCV 处理的视频发送到接收部分。 然后接收部分读取它并显示它。 这应实时完成。 它基本上适用于下面的代码/gstreamer 设置,但是一旦帧丢失(至少我认为这是原因),视频就会以灰色部分的形式损坏(附图)。

OpenCV 发送部分:

cv::VideoWriter videoTransmitter("appsrc ! videoconvert ! videoscale ! x264enc ! rtph264pay config-interval=1 pt=96 ! udpsink host=192.168.168.99 port=5000", cv::VideoWriter::fourcc('H', '2', '6', '4'), 10, videoTransmitter_imageSize, true);

OpenCV 接收部分:

cv::VideoCapture videoReceiver("udpsrc port=5000 ! application/x-rtp ! rtpjitterbuffer ! rtph264depay ! avdec_h264 ! videoconvert ! appsink", cv::CAP_GSTREAMER);

它基本上可以工作,但我经常在视频中看到灰色部分,然后停留一段时间直到视频正确显示。 我猜它总是在由于传输而丢失帧时发生。 但是,我怎样才能摆脱这些灰色/损坏的框架? 任何提示? 我需要设置任何 Gstreamer 参数来调整结果吗? 有没有更好的方法来 stream 与 opencv over.network 的视频?

任何帮助表示赞赏!

不,Gstreamer 中没有任何机制来检测损坏的帧,因为这没有意义。

在大多数现代视频编解码器中,帧不再完整发送,而是分成几片(意味着只有帧的一小部分)。 它可以采用多个内部数据包(每个数据包包含多个切片)来构建一个完整的帧,这是一件好事,因为它使您的 stream 对错误更具弹性,并允许对切片进行多线程解码(例如)。

为了实现你想要的,你有多种解决方案:

  1. 仅在 UDP 上使用 RTP/RTCP 而不是 RTP 至少 RTP 包含一个序列号和“帧结束”标记,因此可以检测到一些数据包丢失。 默认情况下,Gstreamer 不关心这些,除非您启动了 RTP/RTCP session。如果您使用 RTCP 设置 session,您可以在某些数据包丢失时收到报告。 我不确定是否有一种管道方式可以在丢弃数据包时得到通知,因此您可能仍需要在 gstreamer 管道中编写一个 appsink 来添加一些代码来检测此事件。 但是,这会告诉您出了什么问题,但不会告诉您什么时候可以恢复或错误有多大。 在 Gstreamer 中,它称为 RTPSession,您对stats::XXX_nack_count 属性感兴趣,
  2. 添加一些附加协议来计算编码器的 output 帧/NAL/数据包的校验和并进行带外传输。 确保解码器还计算传入帧/NAL/数据包的校验和,如果不匹配,您就会知道解码失败。 当心可能会干扰您的算法的数据包/帧重新排序(通常 B 帧将在它们的依赖关系之后重新排序)。 同样,您无法知道何时在出现错误时恢复。 如果您只有部分数据包丢失,使用 TCP 而不是 UDP 可能足以修复它,但如果它是带宽问题,它将无法恢复(如果视频带宽>.网络带宽,它会崩溃,因为 TCP不能' t丢弃数据包以适应)
  3. 仅使用内部视频编解码器(如 APNG 或 JPEG) JPEG 也可以部分解码,但 gstreamer 的默认软件 jpeg 解码器不会 output 部分 JPEG 帧。
  4. 在编码器中设置一个封闭且更短的 GOP 许多编码器都有一个伪“gop = 图片组”参数,并在错误后解码时计算解码器中的帧数。 GOP 确保无论编码的 state 是什么,在 GOP 帧之后,编码器将发出一组非依赖帧(可能有足够的内部帧/切片来重建完整的帧)。 这将允许在错误后通过丢弃GOP - 1帧来恢复(你必须解码它们,但你不能使用它们,它们可能已损坏),你需要一种检测错误的方法,请参见上面的第 1 点或第 2 点. 对于x264enc ,该参数称为key-int-max 您可能还想尝试intra-refresh=true ,这样错误时的破帧效果会更短。 缺点是相同视频质量的带宽增加。
  5. 使用具有可缩放视频编码的视频编解码器(例如,SVC 而不是 AVC)。 在这种情况下,如果出现解码错误,您将获得质量较低的帧而不是损坏的帧。 据我所知,Gstreamer 中没有任何免费的 SVC 编码器。
  6. 处理它 用 OpenCV 计算图片的饱和度 map 并计算其偏差和均值。 如果它与之前的图片有很大不同,则停止计算,直到 GOP 过去并且饱和度回到预期水平。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM