[FFmpeg-devel,19/25] avcodec/v4l2_m2m_dec: fix dropped packets while decoding

Submitted by Aman Gupta on Sept. 3, 2019, 1:02 a.m.

Details

Message ID 20190903010230.96236-20-ffmpeg@tmm1.net
State New
Headers show

Commit Message

Aman Gupta Sept. 3, 2019, 1:02 a.m.
From: Maxime Jourdan <mjourdan@baylibre.com>

* FFmpeg retrieves a packet from the bitstream
* It attempts to get an input buffer (from its own list or by dequeuing one from the driver)
* If no input buffer is found, the bitstream packet is dropped instead of scheduled for trying again later

It's an issue that showed especially at high speeds (like using `-f null -` as output parameters).

Signed-off-by: Aman Gupta <aman@tmm1.net>
---
 libavcodec/v4l2_m2m.h     |  1 +
 libavcodec/v4l2_m2m_dec.c | 21 ++++++++++++++++-----
 2 files changed, 17 insertions(+), 5 deletions(-)

Patch hide | download patch | download mbox

diff --git a/libavcodec/v4l2_m2m.h b/libavcodec/v4l2_m2m.h
index 97848363ef..662e682aa5 100644
--- a/libavcodec/v4l2_m2m.h
+++ b/libavcodec/v4l2_m2m.h
@@ -56,6 +56,7 @@  typedef struct V4L2m2mContext {
 
     /* null frame/packet received */
     int draining;
+    AVPacket buf_pkt;
 
     /* Reference to self; only valid while codec is active. */
     AVBufferRef *self_ref;
diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c
index b37b6ac7d9..71b2211594 100644
--- a/libavcodec/v4l2_m2m_dec.c
+++ b/libavcodec/v4l2_m2m_dec.c
@@ -143,9 +143,14 @@  static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame)
     AVPacket avpkt = {0};
     int ret;
 
-    ret = ff_decode_get_packet(avctx, &avpkt);
-    if (ret < 0 && ret != AVERROR_EOF)
-        return ret;
+    if (s->buf_pkt.size) {
+        avpkt = s->buf_pkt;
+        memset(&s->buf_pkt, 0, sizeof(AVPacket));
+    } else {
+        ret = ff_decode_get_packet(avctx, &avpkt);
+        if (ret < 0 && ret != AVERROR_EOF)
+            return ret;
+    }
 
     if (s->draining)
         goto dequeue;
@@ -154,6 +159,8 @@  static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame)
     if (ret < 0) {
         if (ret != AVERROR(EAGAIN))
            return ret;
+
+        s->buf_pkt = avpkt;
         /* no input buffers available, continue dequeing */
     }
 
@@ -171,7 +178,8 @@  static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame)
     }
 
 dequeue:
-    av_packet_unref(&avpkt);
+    if (!s->buf_pkt.size)
+        av_packet_unref(&avpkt);
     return ff_v4l2_context_dequeue_frame(capture, frame, -1);
 }
 
@@ -244,7 +252,10 @@  static av_cold int v4l2_decode_init(AVCodecContext *avctx)
 
 static av_cold int v4l2_decode_close(AVCodecContext *avctx)
 {
-    return ff_v4l2_m2m_codec_end(avctx->priv_data);
+    V4L2m2mPriv *priv = avctx->priv_data;
+    V4L2m2mContext* s = priv->context;
+    av_packet_unref(&s->buf_pkt);
+    return ff_v4l2_m2m_codec_end(priv);
 }
 
 static void v4l2_flush(AVCodecContext *avctx)