简体   繁体   English

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

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

收到的帧

Hey, I am new to Gstreamer and want to send a video that is captured from a camera and manipulated with OpenCV over a.network to the receiving part.嘿,我是 Gstreamer 的新手,想通过 a.network 将从摄像机捕获并使用 OpenCV 处理的视频发送到接收部分。 The receiving part then read it and displays it.然后接收部分读取它并显示它。 This shall be done in real-time.这应实时完成。 It basically works with the code/gstreamer settings below however as soon a frame is dropped (at least I think this is the reason) the video get corrupted in form of grey parts (attached picture).它基本上适用于下面的代码/gstreamer 设置,但是一旦帧丢失(至少我认为这是原因),视频就会以灰色部分的形式损坏(附图)。

OpenCV Sending Part: 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 Receiving part: OpenCV 接收部分:

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

It basically works but I often get grey parts in the video which then stay for a bit until the video is displayed correctly.它基本上可以工作,但我经常在视频中看到灰色部分,然后停留一段时间直到视频正确显示。 I guessed it happens always when a frame is dropped due to the transmission.我猜它总是在由于传输而丢失帧时发生。 However, how can I get rid of these grey/corrupted frames?但是,我怎样才能摆脱这些灰色/损坏的框架? Any Hints?任何提示? Any Gstreamer parameters I need to set to tune result?我需要设置任何 Gstreamer 参数来调整结果吗? Is there a better way to stream a video with opencv over.network?有没有更好的方法来 stream 与 opencv over.network 的视频?

Any help is appreciated!任何帮助表示赞赏!

No, there isn't any mechanism in Gstreamer to detect corrupted frames, because this doesn't make sense.不,Gstreamer 中没有任何机制来检测损坏的帧,因为这没有意义。

In most modern video codec, frame aren't sent in full anymore, but split in slices (meaning only a small part of the frame).在大多数现代视频编解码器中,帧不再完整发送,而是分成几片(意味着只有帧的一小部分)。 It can takes multiple intra packets (each containing multiple slices) to build a complete frame, and this is a good thing, because it makes your stream more resilient to errors, and allow multithreaded decoding of the slices (for example).它可以采用多个内部数据包(每个数据包包含多个切片)来构建一个完整的帧,这是一件好事,因为它使您的 stream 对错误更具弹性,并允许对切片进行多线程解码(例如)。

In order to achieve what you want, you have multiple solutions:为了实现你想要的,你有多种解决方案:

  1. Use RTP/RTCP instead of RTP over UDP only .仅在 UDP 上使用 RTP/RTCP 而不是 RTP At least RTP contains a sequence number and "end of frame" markers so it possible to detect some packet drops.至少 RTP 包含一个序列号和“帧结束”标记,因此可以检测到一些数据包丢失。 Gstreamer doesn't care about those by default unless you have started a RTP/RTCP session. If you set up a session with RTCP, you can have reports when some packets were dropped.默认情况下,Gstreamer 不关心这些,除非您启动了 RTP/RTCP session。如果您使用 RTCP 设置 session,您可以在某些数据包丢失时收到报告。 I'm not sure there is a pipeline way to be informed when a packet is dropped, so you might still have to write an appsink in your gstreamer pipeline to add some code for detecting this event.我不确定是否有一种管道方式可以在丢弃数据包时得到通知,因此您可能仍需要在 gstreamer 管道中编写一个 appsink 来添加一些代码来检测此事件。 However, this will tell you something is wrong, but not when it's ok to resume or how much wrong it is.但是,这会告诉您出了什么问题,但不会告诉您什么时候可以恢复或错误有多大。 In Gstreamer speak, it's called RTPSession, and you're interested in the stats::XXX_nack_count properties ,在 Gstreamer 中,它称为 RTPSession,您对stats::XXX_nack_count 属性感兴趣,
  2. Add some additional protocol to compute the checksum of the encoder's output frame/NAL/packet and transmit out of band.添加一些附加协议来计算编码器的 output 帧/NAL/数据包的校验和并进行带外传输。 Make sure the decoder also compute the checksum of incoming frame/NAL/packet and if doesn't match, you'll know it'll fail decoding.确保解码器还计算传入帧/NAL/数据包的校验和,如果不匹配,您就会知道解码失败。 Beware of packet/frame reordering (typically B frames will be re-ordered after their dependencies) that could disturb your algorithm.当心可能会干扰您的算法的数据包/帧重新排序(通常 B 帧将在它们的依赖关系之后重新排序)。 Again, you have no way to know when to resume upon an error.同样,您无法知道何时在出现错误时恢复。 Using TCP instead of UDP might be enough to fix it if you only have partial packet drop, but it'll fail to resume if it's a bandwidth issue (if the video bandwidth >.network bandwidth, it'll collapse, since TCP can't drop packets to adapt)如果您只有部分数据包丢失,使用 TCP 而不是 UDP 可能足以修复它,但如果它是带宽问题,它将无法恢复(如果视频带宽>.网络带宽,它会崩溃,因为 TCP不能' t丢弃数据包以适应)
  3. Use intra only video codec (like APNG, or JPEG) .仅使用内部视频编解码器(如 APNG 或 JPEG) JPEG can also partially decode, but gstreamer's default software jpeg decoder doesn't output a partial JPEG frame. JPEG 也可以部分解码,但 gstreamer 的默认软件 jpeg 解码器不会 output 部分 JPEG 帧。
  4. Set a closed and shorter GOP in your encoder .在编码器中设置一个封闭且更短的 GOP Many encoder have a pseudo "gop = group of picture" parameter and count the frames in your decoder when decoding after an error.许多编码器都有一个伪“gop = 图片组”参数,并在错误后解码时计算解码器中的帧数。 A GOP ensure that whatever the state of the encoding, after GOP frames, the encoder will emit an non-dependent group of frames (likely enough intra frame/slices to rebuild the complete frame). GOP 确保无论编码的 state 是什么,在 GOP 帧之后,编码器将发出一组非依赖帧(可能有足够的内部帧/切片来重建完整的帧)。 This will allow resuming after an error by dropping GOP - 1 frames (you must decode them, but you can't use them, they might be corrupted), you'll need a way to detect the error, see point 1 or 2 above.这将允许在错误后通过丢弃GOP - 1帧来恢复(你必须解码它们,但你不能使用它们,它们可能已损坏),你需要一种检测错误的方法,请参见上面的第 1 点或第 2 点. For x264enc the parameter is called key-int-max .对于x264enc ,该参数称为key-int-max You might want to try also intra-refresh=true so the broken frame effect upon error will be shorter.您可能还想尝试intra-refresh=true ,这样错误时的破帧效果会更短。 The downside is an increase in bandwidth for the same video quality.缺点是相同视频质量的带宽增加。
  5. Use a video codec with scalable video coding (SVC instead of AVC for exemple).使用具有可缩放视频编码的视频编解码器(例如,SVC 而不是 AVC)。 In that case, in case of decoding error, you'll get a lower quality instead of corrupted frame.在这种情况下,如果出现解码错误,您将获得质量较低的帧而不是损坏的帧。 There isn't any free SVC encoder I'm aware of in Gstreamer.据我所知,Gstreamer 中没有任何免费的 SVC 编码器。
  6. Deal with it .处理它 Compute a saturation map of the picture with OpenCV and compute its deviation & mean.用 OpenCV 计算图片的饱和度 map 并计算其偏差和均值。 If it's very different from the previous picture, stop computation until the GOP has elapsed and the saturation is back to expected levels.如果它与之前的图片有很大不同,则停止计算,直到 GOP 过去并且饱和度回到预期水平。

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

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