From 92dd0825800227c364fb2e5b0d7f9d23ddde6662 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Fri, 28 Jan 2022 20:24:18 +0100
Subject: [PATCH 03/77] avcodec/mpegvideoenc: Move tmp bframes to
 MPVMainEncContext

Also move b_frame_strategy and b_sensitivity and brd_scale;
they are all only used by an encoder's main thread when
b_frame_strategy == 2.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpegvideo.h     |   8 ---
 libavcodec/mpegvideo_enc.c | 114 ++++++++++++++++++++-----------------
 libavcodec/mpegvideoenc.h  |  15 ++++-
 3 files changed, 73 insertions(+), 64 deletions(-)

diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h
index afd18591c4..1091c93d95 100644
--- a/libavcodec/mpegvideo.h
+++ b/libavcodec/mpegvideo.h
@@ -48,8 +48,6 @@
 
 #define MAX_THREADS 32
 
-#define MAX_B_FRAMES 16
-
 /**
  * Scantable.
  */
@@ -446,7 +444,6 @@ typedef struct MpegEncContext {
     int top_field_first;
     int concealment_motion_vectors;
     int q_scale_type;
-    int brd_scale;
     int intra_vlc_format;
     int alternate_scan;
     int repeat_first_field;
@@ -518,11 +515,6 @@ typedef struct MpegEncContext {
 
     int error_rate;
 
-    /* temporary frames used by b_frame_strategy = 2 */
-    AVFrame *tmp_frames[MAX_B_FRAMES + 2];
-    int b_frame_strategy;
-    int b_sensitivity;
-
     /* frame skip options for encoding */
     int frame_skip_threshold;
     int frame_skip_factor;
diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c
index 720ded49c2..ffa9484669 100644
--- a/libavcodec/mpegvideo_enc.c
+++ b/libavcodec/mpegvideo_enc.c
@@ -419,7 +419,8 @@ static av_cold int init_matrices(MpegEncContext *s, AVCodecContext *avctx)
 /* init video encoder */
 av_cold int ff_mpv_encode_init(AVCodecContext *avctx)
 {
-    MpegEncContext *s = avctx->priv_data;
+    MPVMainEncContext *const m = avctx->priv_data;
+    MpegEncContext    *const s = &m->s;
     AVCPBProperties *cpb_props;
     int i, ret;
     int mb_array_size, mv_table_size;
@@ -456,10 +457,10 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx)
     }
     s->gop_size     = avctx->gop_size;
     s->avctx        = avctx;
-    if (avctx->max_b_frames > MAX_B_FRAMES) {
+    if (avctx->max_b_frames > MPVENC_MAX_B_FRAMES) {
         av_log(avctx, AV_LOG_ERROR, "Too many B-frames requested, maximum "
-               "is %d.\n", MAX_B_FRAMES);
-        avctx->max_b_frames = MAX_B_FRAMES;
+               "is " AV_STRINGIFY(MPVENC_MAX_B_FRAMES) ".\n");
+        avctx->max_b_frames = MPVENC_MAX_B_FRAMES;
     } else if (avctx->max_b_frames < 0) {
         av_log(avctx, AV_LOG_ERROR,
                "max b frames must be 0 or positive for mpegvideo based encoders\n");
@@ -700,10 +701,10 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx)
         return AVERROR(EINVAL);
     }
 
-    if (s->b_frame_strategy && (avctx->flags & AV_CODEC_FLAG_PASS2)) {
+    if (m->b_frame_strategy && (avctx->flags & AV_CODEC_FLAG_PASS2)) {
         av_log(avctx, AV_LOG_INFO,
                "notice: b_frame_strategy only affects the first pass\n");
-        s->b_frame_strategy = 0;
+        m->b_frame_strategy = 0;
     }
 
     i = av_gcd(avctx->time_base.den, avctx->time_base.num);
@@ -914,8 +915,8 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx)
         return ret;
 
     if (!(avctx->stats_out = av_mallocz(256))               ||
-        !FF_ALLOCZ_TYPED_ARRAY(s->input_picture,           MAX_B_FRAMES + 1) ||
-        !FF_ALLOCZ_TYPED_ARRAY(s->reordered_input_picture, MAX_B_FRAMES + 1) ||
+        !FF_ALLOCZ_TYPED_ARRAY(s->input_picture,           MPVENC_MAX_B_FRAMES + 1) ||
+        !FF_ALLOCZ_TYPED_ARRAY(s->reordered_input_picture, MPVENC_MAX_B_FRAMES + 1) ||
         !(s->new_pic = av_frame_alloc()) ||
         !(s->picture_pool = ff_mpv_alloc_pic_pool(0)))
         return AVERROR(ENOMEM);
@@ -1010,17 +1011,17 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx)
     if ((ret = ff_rate_control_init(s)) < 0)
         return ret;
 
-    if (s->b_frame_strategy == 2) {
+    if (m->b_frame_strategy == 2) {
         for (i = 0; i < s->max_b_frames + 2; i++) {
-            s->tmp_frames[i] = av_frame_alloc();
-            if (!s->tmp_frames[i])
+            m->tmp_frames[i] = av_frame_alloc();
+            if (!m->tmp_frames[i])
                 return AVERROR(ENOMEM);
 
-            s->tmp_frames[i]->format = AV_PIX_FMT_YUV420P;
-            s->tmp_frames[i]->width  = s->width  >> s->brd_scale;
-            s->tmp_frames[i]->height = s->height >> s->brd_scale;
+            m->tmp_frames[i]->format = AV_PIX_FMT_YUV420P;
+            m->tmp_frames[i]->width  = s->width  >> m->brd_scale;
+            m->tmp_frames[i]->height = s->height >> m->brd_scale;
 
-            ret = av_frame_get_buffer(s->tmp_frames[i], 0);
+            ret = av_frame_get_buffer(m->tmp_frames[i], 0);
             if (ret < 0)
                 return ret;
         }
@@ -1039,8 +1040,8 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx)
 
 av_cold int ff_mpv_encode_end(AVCodecContext *avctx)
 {
-    MpegEncContext *s = avctx->priv_data;
-    int i;
+    MPVMainEncContext *const m = avctx->priv_data;
+    MpegEncContext    *const s = &m->s;
 
     ff_rate_control_uninit(&s->rc_context);
 
@@ -1048,13 +1049,13 @@ av_cold int ff_mpv_encode_end(AVCodecContext *avctx)
     av_refstruct_pool_uninit(&s->picture_pool);
 
     if (s->input_picture && s->reordered_input_picture) {
-        for (int i = 0; i < MAX_B_FRAMES + 1; i++) {
+        for (int i = 0; i < MPVENC_MAX_B_FRAMES + 1; i++) {
             av_refstruct_unref(&s->input_picture[i]);
             av_refstruct_unref(&s->reordered_input_picture[i]);
         }
     }
-    for (i = 0; i < FF_ARRAY_ELEMS(s->tmp_frames); i++)
-        av_frame_free(&s->tmp_frames[i]);
+    for (int i = 0; i < FF_ARRAY_ELEMS(m->tmp_frames); i++)
+        av_frame_free(&m->tmp_frames[i]);
 
     av_frame_free(&s->new_pic);
 
@@ -1249,8 +1250,9 @@ static int prepare_picture(MpegEncContext *s, AVFrame *f, const AVFrame *props_f
     return 0;
 }
 
-static int load_input_picture(MpegEncContext *s, const AVFrame *pic_arg)
+static int load_input_picture(MPVMainEncContext *const m, const AVFrame *pic_arg)
 {
+    MpegEncContext *const s = &m->s;
     MPVPicture *pic = NULL;
     int64_t pts;
     int display_picture_number = 0, ret;
@@ -1376,9 +1378,9 @@ static int load_input_picture(MpegEncContext *s, const AVFrame *pic_arg)
     }
 
     /* shift buffer entries */
-    for (int i = flush_offset; i <= MAX_B_FRAMES; i++)
+    for (int i = flush_offset; i <= MPVENC_MAX_B_FRAMES; i++)
         s->input_picture[i - flush_offset] = s->input_picture[i];
-    for (int i = MAX_B_FRAMES + 1 - flush_offset; i <= MAX_B_FRAMES; i++)
+    for (int i = MPVENC_MAX_B_FRAMES + 1 - flush_offset; i <= MPVENC_MAX_B_FRAMES; i++)
         s->input_picture[i] = NULL;
 
     s->input_picture[encoding_delay] = pic;
@@ -1451,10 +1453,11 @@ static int encode_frame(AVCodecContext *c, const AVFrame *frame, AVPacket *pkt)
     return size;
 }
 
-static int estimate_best_b_count(MpegEncContext *s)
+static int estimate_best_b_count(MPVMainEncContext *const m)
 {
+    MpegEncContext *const s = &m->s;
     AVPacket *pkt;
-    const int scale = s->brd_scale;
+    const int scale = m->brd_scale;
     int width  = s->width  >> scale;
     int height = s->height >> scale;
     int i, j, out_size, p_lambda, b_lambda, lambda2;
@@ -1491,18 +1494,18 @@ static int estimate_best_b_count(MpegEncContext *s)
                 data[2] += INPLACE_OFFSET;
             }
 
-            s->mpvencdsp.shrink[scale](s->tmp_frames[i]->data[0],
-                                       s->tmp_frames[i]->linesize[0],
+            s->mpvencdsp.shrink[scale](m->tmp_frames[i]->data[0],
+                                       m->tmp_frames[i]->linesize[0],
                                        data[0],
                                        pre_input_ptr->f->linesize[0],
                                        width, height);
-            s->mpvencdsp.shrink[scale](s->tmp_frames[i]->data[1],
-                                       s->tmp_frames[i]->linesize[1],
+            s->mpvencdsp.shrink[scale](m->tmp_frames[i]->data[1],
+                                       m->tmp_frames[i]->linesize[1],
                                        data[1],
                                        pre_input_ptr->f->linesize[1],
                                        width >> 1, height >> 1);
-            s->mpvencdsp.shrink[scale](s->tmp_frames[i]->data[2],
-                                       s->tmp_frames[i]->linesize[2],
+            s->mpvencdsp.shrink[scale](m->tmp_frames[i]->data[2],
+                                       m->tmp_frames[i]->linesize[2],
                                        data[2],
                                        pre_input_ptr->f->linesize[2],
                                        width >> 1, height >> 1);
@@ -1539,10 +1542,10 @@ static int estimate_best_b_count(MpegEncContext *s)
             goto fail;
 
 
-        s->tmp_frames[0]->pict_type = AV_PICTURE_TYPE_I;
-        s->tmp_frames[0]->quality   = 1 * FF_QP2LAMBDA;
+        m->tmp_frames[0]->pict_type = AV_PICTURE_TYPE_I;
+        m->tmp_frames[0]->quality   = 1 * FF_QP2LAMBDA;
 
-        out_size = encode_frame(c, s->tmp_frames[0], pkt);
+        out_size = encode_frame(c, m->tmp_frames[0], pkt);
         if (out_size < 0) {
             ret = out_size;
             goto fail;
@@ -1553,11 +1556,11 @@ static int estimate_best_b_count(MpegEncContext *s)
         for (i = 0; i < s->max_b_frames + 1; i++) {
             int is_p = i % (j + 1) == j || i == s->max_b_frames;
 
-            s->tmp_frames[i + 1]->pict_type = is_p ?
+            m->tmp_frames[i + 1]->pict_type = is_p ?
                                      AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_B;
-            s->tmp_frames[i + 1]->quality   = is_p ? p_lambda : b_lambda;
+            m->tmp_frames[i + 1]->quality   = is_p ? p_lambda : b_lambda;
 
-            out_size = encode_frame(c, s->tmp_frames[i + 1], pkt);
+            out_size = encode_frame(c, m->tmp_frames[i + 1], pkt);
             if (out_size < 0) {
                 ret = out_size;
                 goto fail;
@@ -1603,8 +1606,10 @@ fail:
  * input_picture[0] is always NULL when exiting this function, even on error;
  * reordered_input_picture[0] is always NULL when exiting this function on error.
  */
-static int set_bframe_chain_length(MpegEncContext *s)
+static int set_bframe_chain_length(MPVMainEncContext *const m)
 {
+    MpegEncContext *const s = &m->s;
+
     /* Either nothing to do or can't do anything */
     if (s->reordered_input_picture[0] || !s->input_picture[0])
         return 0;
@@ -1649,11 +1654,11 @@ static int set_bframe_chain_length(MpegEncContext *s)
             }
         }
 
-        if (s->b_frame_strategy == 0) {
+        if (m->b_frame_strategy == 0) {
             b_frames = s->max_b_frames;
             while (b_frames && !s->input_picture[b_frames])
                 b_frames--;
-        } else if (s->b_frame_strategy == 1) {
+        } else if (m->b_frame_strategy == 1) {
             int i;
             for (i = 1; i < s->max_b_frames + 1; i++) {
                 if (s->input_picture[i] &&
@@ -1668,7 +1673,7 @@ static int set_bframe_chain_length(MpegEncContext *s)
             for (i = 0; i < s->max_b_frames + 1; i++) {
                 if (!s->input_picture[i] ||
                     s->input_picture[i]->b_frame_score - 1 >
-                        s->mb_num / s->b_sensitivity)
+                        s->mb_num / m->b_sensitivity)
                     break;
             }
 
@@ -1678,8 +1683,8 @@ static int set_bframe_chain_length(MpegEncContext *s)
             for (i = 0; i < b_frames + 1; i++) {
                 s->input_picture[i]->b_frame_score = 0;
             }
-        } else if (s->b_frame_strategy == 2) {
-            b_frames = estimate_best_b_count(s);
+        } else if (m->b_frame_strategy == 2) {
+            b_frames = estimate_best_b_count(m);
             if (b_frames < 0) {
                 av_refstruct_unref(&s->input_picture[0]);
                 return b_frames;
@@ -1733,17 +1738,18 @@ static int set_bframe_chain_length(MpegEncContext *s)
     return 0;
 }
 
-static int select_input_picture(MpegEncContext *s)
+static int select_input_picture(MPVMainEncContext *const m)
 {
+    MpegEncContext *const s = &m->s;
     int ret;
 
     av_assert1(!s->reordered_input_picture[0]);
 
-    for (int i = 1; i <= MAX_B_FRAMES; i++)
+    for (int i = 1; i <= MPVENC_MAX_B_FRAMES; i++)
         s->reordered_input_picture[i - 1] = s->reordered_input_picture[i];
-    s->reordered_input_picture[MAX_B_FRAMES] = NULL;
+    s->reordered_input_picture[MPVENC_MAX_B_FRAMES] = NULL;
 
-    ret = set_bframe_chain_length(s);
+    ret = set_bframe_chain_length(m);
     av_assert1(!s->input_picture[0]);
     if (ret < 0)
         return ret;
@@ -1867,7 +1873,8 @@ static void frame_start(MpegEncContext *s)
 int ff_mpv_encode_picture(AVCodecContext *avctx, AVPacket *pkt,
                           const AVFrame *pic_arg, int *got_packet)
 {
-    MpegEncContext *s = avctx->priv_data;
+    MPVMainEncContext *const m = avctx->priv_data;
+    MpegEncContext    *const s = &m->s;
     int stuffing_count, ret;
     int context_count = s->slice_context_count;
 
@@ -1877,12 +1884,13 @@ int ff_mpv_encode_picture(AVCodecContext *avctx, AVPacket *pkt,
 
     s->picture_in_gop_number++;
 
-    if (load_input_picture(s, pic_arg) < 0)
-        return -1;
+    ret = load_input_picture(m, pic_arg);
+    if (ret < 0)
+        return ret;
 
-    if (select_input_picture(s) < 0) {
-        return -1;
-    }
+    ret = select_input_picture(m);
+    if (ret < 0)
+        return ret;
 
     /* output? */
     if (s->new_pic->data[0]) {
diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h
index f7aad17650..7b5635e50e 100644
--- a/libavcodec/mpegvideoenc.h
+++ b/libavcodec/mpegvideoenc.h
@@ -33,8 +33,16 @@
 #include "libavutil/opt.h"
 #include "mpegvideo.h"
 
+#define MPVENC_MAX_B_FRAMES 16
+
 typedef struct MPVMainEncContext {
     MpegEncContext s;  ///< The main slicecontext
+
+    /// temporary frames used by b_frame_strategy = 2
+    AVFrame *tmp_frames[MPVENC_MAX_B_FRAMES + 2];
+    int b_frame_strategy;
+    int b_sensitivity;
+    int brd_scale;
 } MPVMainEncContext;
 
 #define MAX_FCODE        7
@@ -85,6 +93,7 @@ typedef struct MPVMainEncContext {
 { "msad",   "Sum of absolute differences, median predicted", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_MEDIAN_SAD }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, .unit = "cmp_func" }
 
 #define FF_MPV_OFFSET(x) offsetof(MpegEncContext, x)
+#define FF_MPV_MAIN_OFFSET(x) offsetof(MPVMainEncContext, x)
 #define FF_RC_OFFSET(x)  offsetof(MpegEncContext, rc_context.x)
 #define FF_MPV_OPT_FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
 #define FF_MPV_COMMON_OPTS \
@@ -126,9 +135,9 @@ FF_MPV_OPT_CMP_FUNC, \
 {"ps", "RTP payload size in bytes",                             FF_MPV_OFFSET(rtp_payload_size), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \
 
 #define FF_MPV_COMMON_BFRAME_OPTS \
-{"b_strategy", "Strategy to choose between I/P/B-frames",      FF_MPV_OFFSET(b_frame_strategy), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 2, FF_MPV_OPT_FLAGS }, \
-{"b_sensitivity", "Adjust sensitivity of b_frame_strategy 1",  FF_MPV_OFFSET(b_sensitivity), AV_OPT_TYPE_INT, {.i64 = 40 }, 1, INT_MAX, FF_MPV_OPT_FLAGS }, \
-{"brd_scale", "Downscale frames for dynamic B-frame decision", FF_MPV_OFFSET(brd_scale), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 3, FF_MPV_OPT_FLAGS },
+{"b_strategy", "Strategy to choose between I/P/B-frames",      FF_MPV_MAIN_OFFSET(b_frame_strategy), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 2, FF_MPV_OPT_FLAGS }, \
+{"b_sensitivity", "Adjust sensitivity of b_frame_strategy 1",  FF_MPV_MAIN_OFFSET(b_sensitivity), AV_OPT_TYPE_INT, {.i64 = 40 }, 1, INT_MAX, FF_MPV_OPT_FLAGS }, \
+{"brd_scale", "Downscale frames for dynamic B-frame decision", FF_MPV_MAIN_OFFSET(brd_scale), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 3, FF_MPV_OPT_FLAGS },
 
 #define FF_MPV_COMMON_MOTION_EST_OPTS \
 {"motion_est", "motion estimation algorithm",                       FF_MPV_OFFSET(motion_est), AV_OPT_TYPE_INT, {.i64 = FF_ME_EPZS }, FF_ME_ZERO, FF_ME_XONE, FF_MPV_OPT_FLAGS, .unit = "motion_est" },   \
-- 
2.45.2