diff mbox series

[FFmpeg-devel,04/14] avcodec/mpegvideo_dec: Factor allocating dummy frames out

Message ID GV1SPRMB00210ECAE0CD45BA8CBF728C8F1B2@GV1SPRMB0021.EURP250.PROD.OUTLOOK.COM
State New
Headers show
Series [FFmpeg-devel,01/14] avcodec/get_buffer: Remove redundant check | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished

Commit Message

Andreas Rheinhardt April 29, 2024, 12:35 a.m. UTC
This will allow to reuse it to allocate dummy frames for
the second field (which can be a P-field even if the first
field was an intra field).

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpegvideo_dec.c | 85 +++++++++++++++++++++++---------------
 libavcodec/mpegvideodec.h  |  4 ++
 2 files changed, 56 insertions(+), 33 deletions(-)
diff mbox series

Patch

diff --git a/libavcodec/mpegvideo_dec.c b/libavcodec/mpegvideo_dec.c
index 597ffde7f8..efc257d43e 100644
--- a/libavcodec/mpegvideo_dec.c
+++ b/libavcodec/mpegvideo_dec.c
@@ -281,14 +281,21 @@  fail:
     return ret;
 }
 
-static int av_cold alloc_dummy_frame(MpegEncContext *s, Picture **picp)
+static int av_cold alloc_dummy_frame(MpegEncContext *s, Picture **picp, Picture *wpic)
 {
     Picture *pic;
-    int ret = alloc_picture(s, picp, 1);
+    int ret = alloc_picture(s, &pic, 1);
     if (ret < 0)
         return ret;
 
-    pic = *picp;
+    ff_mpeg_unref_picture(wpic);
+    ret = ff_mpeg_ref_picture(wpic, pic);
+    if (ret < 0) {
+        ff_mpeg_unref_picture(pic);
+        return ret;
+    }
+
+    *picp = pic;
 
     ff_thread_report_progress(&pic->tf, INT_MAX, 0);
     ff_thread_report_progress(&pic->tf, INT_MAX, 1);
@@ -314,6 +321,45 @@  static void color_frame(AVFrame *frame, int luma)
     }
 }
 
+int ff_mpv_alloc_dummy_frames(MpegEncContext *s)
+{
+    AVCodecContext *avctx = s->avctx;
+    int ret;
+
+    if ((!s->last_picture_ptr || !s->last_picture_ptr->f->buf[0]) &&
+        (s->pict_type != AV_PICTURE_TYPE_I)) {
+        if (s->pict_type == AV_PICTURE_TYPE_B && s->next_picture_ptr && s->next_picture_ptr->f->buf[0])
+            av_log(avctx, AV_LOG_DEBUG,
+                   "allocating dummy last picture for B frame\n");
+        else if (s->codec_id != AV_CODEC_ID_H261 /* H.261 has no keyframes */ &&
+                 (s->picture_structure == PICT_FRAME || s->first_field))
+            av_log(avctx, AV_LOG_ERROR,
+                   "warning: first frame is no keyframe\n");
+
+        /* Allocate a dummy frame */
+        ret = alloc_dummy_frame(s, &s->last_picture_ptr, &s->last_picture);
+        if (ret < 0)
+            return ret;
+
+        if (!avctx->hwaccel) {
+            int luma_val = s->codec_id == AV_CODEC_ID_FLV1 || s->codec_id == AV_CODEC_ID_H263 ? 16 : 0x80;
+            color_frame(s->last_picture_ptr->f, luma_val);
+        }
+    }
+    if ((!s->next_picture_ptr || !s->next_picture_ptr->f->buf[0]) &&
+        s->pict_type == AV_PICTURE_TYPE_B) {
+        /* Allocate a dummy frame */
+        ret = alloc_dummy_frame(s, &s->next_picture_ptr, &s->next_picture);
+        if (ret < 0)
+            return ret;
+    }
+
+    av_assert0(s->pict_type == AV_PICTURE_TYPE_I || (s->last_picture_ptr &&
+                                                 s->last_picture_ptr->f->buf[0]));
+
+    return 0;
+}
+
 /**
  * generic function called after decoding
  * the header and before a frame is decoded.
@@ -382,34 +428,6 @@  int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx)
             s->current_picture_ptr ? s->current_picture_ptr->f->data[0] : NULL,
             s->pict_type, s->droppable);
 
-    if ((!s->last_picture_ptr || !s->last_picture_ptr->f->buf[0]) &&
-        (s->pict_type != AV_PICTURE_TYPE_I)) {
-        if (s->pict_type == AV_PICTURE_TYPE_B && s->next_picture_ptr && s->next_picture_ptr->f->buf[0])
-            av_log(avctx, AV_LOG_DEBUG,
-                   "allocating dummy last picture for B frame\n");
-        else if (s->codec_id != AV_CODEC_ID_H261)
-            av_log(avctx, AV_LOG_ERROR,
-                   "warning: first frame is no keyframe\n");
-
-        /* Allocate a dummy frame */
-        ret = alloc_dummy_frame(s, &s->last_picture_ptr);
-        if (ret < 0)
-            return ret;
-
-        if (!avctx->hwaccel) {
-            int luma_val = s->codec_id == AV_CODEC_ID_FLV1 || s->codec_id == AV_CODEC_ID_H263 ? 16 : 0x80;
-            color_frame(s->last_picture_ptr->f, luma_val);
-        }
-
-    }
-    if ((!s->next_picture_ptr || !s->next_picture_ptr->f->buf[0]) &&
-        s->pict_type == AV_PICTURE_TYPE_B) {
-        /* Allocate a dummy frame */
-        ret = alloc_dummy_frame(s, &s->next_picture_ptr);
-        if (ret < 0)
-            return ret;
-    }
-
     if (s->last_picture_ptr) {
         if (s->last_picture_ptr->f->buf[0] &&
             (ret = ff_mpeg_ref_picture(&s->last_picture,
@@ -423,8 +441,9 @@  int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx)
             return ret;
     }
 
-    av_assert0(s->pict_type == AV_PICTURE_TYPE_I || (s->last_picture_ptr &&
-                                                 s->last_picture_ptr->f->buf[0]));
+    ret = ff_mpv_alloc_dummy_frames(s);
+    if (ret < 0)
+        return ret;
 
     /* set dequantizer, we can't do it during init as
      * it might change for MPEG-4 and we can't do it in the header
diff --git a/libavcodec/mpegvideodec.h b/libavcodec/mpegvideodec.h
index 0b841bc1a1..42c2697749 100644
--- a/libavcodec/mpegvideodec.h
+++ b/libavcodec/mpegvideodec.h
@@ -50,6 +50,10 @@  void ff_mpv_decode_init(MpegEncContext *s, AVCodecContext *avctx);
 int ff_mpv_common_frame_size_change(MpegEncContext *s);
 
 int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx);
+/**
+ * Ensure that the dummy frames are allocated according to pict_type if necessary.
+ */
+int ff_mpv_alloc_dummy_frames(MpegEncContext *s);
 void ff_mpv_reconstruct_mb(MpegEncContext *s, int16_t block[12][64]);
 void ff_mpv_report_decode_progress(MpegEncContext *s);
 void ff_mpv_frame_end(MpegEncContext *s);