From ff0dfff3fa4af98ae908edc18249293aacbc50a2 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 4 Mar 2025 19:09:24 +0100
Subject: [PATCH 34/77] avcodec/mpegvideo_enc: Use func ptr for encoding
 macroblocks

It gets rid of a switch (with accompanying CONFIG_*_ENCODER checks);
for MJPEG, it even lets one perform the check for whether one is
really encoding or only recording the macroblock once during init.

Furthermore, the switch actually contained lots of dead code --
it is compiled three times (for different pixel formats: 420, 422, 444),
yet most encoders only support 420. The approach used here automatically
fixes this.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/h261enc.c       |  5 ++--
 libavcodec/h261enc.h       |  2 --
 libavcodec/h263enc.h       |  3 ---
 libavcodec/ituh263enc.c    |  8 ++++---
 libavcodec/mjpegenc.c      | 19 +++++++++++----
 libavcodec/mjpegenc.h      |  1 -
 libavcodec/mpeg12enc.c     |  5 ++--
 libavcodec/mpeg12enc.h     |  2 --
 libavcodec/mpeg4videoenc.c |  5 ++--
 libavcodec/mpeg4videoenc.h |  3 ---
 libavcodec/mpegvideo.h     |  4 ++++
 libavcodec/mpegvideo_enc.c | 48 +-------------------------------------
 libavcodec/msmpeg4enc.c    | 10 ++++----
 libavcodec/msmpeg4enc.h    |  2 --
 libavcodec/speedhqenc.c    |  4 +++-
 libavcodec/speedhqenc.h    |  2 --
 libavcodec/wmv2enc.c       |  6 ++---
 libavcodec/wmv2enc.h       | 30 ------------------------
 18 files changed, 45 insertions(+), 114 deletions(-)
 delete mode 100644 libavcodec/wmv2enc.h

diff --git a/libavcodec/h261enc.c b/libavcodec/h261enc.c
index bfe805bcdf..81711b3a16 100644
--- a/libavcodec/h261enc.c
+++ b/libavcodec/h261enc.c
@@ -228,8 +228,8 @@ static void h261_encode_block(H261EncContext *h, int16_t *block, int n)
         put_bits(&s->pb, 2, 0x2); // EOB
 }
 
-void ff_h261_encode_mb(MpegEncContext *s, int16_t block[6][64],
-                       int motion_x, int motion_y)
+static void h261_encode_mb(MpegEncContext *const s, int16_t block[6][64],
+                           int motion_x, int motion_y)
 {
     /* The following is only allowed because this encoder
      * does not use slice threading. */
@@ -374,6 +374,7 @@ static av_cold int h261_encode_init(AVCodecContext *avctx)
     }
     s->private_ctx = &h->common;
     h->s.encode_picture_header = h261_encode_picture_header;
+    s->encode_mb               = h261_encode_mb;
 
     s->min_qcoeff       = -127;
     s->max_qcoeff       = 127;
diff --git a/libavcodec/h261enc.h b/libavcodec/h261enc.h
index 092363b6f3..79cdd31c2f 100644
--- a/libavcodec/h261enc.h
+++ b/libavcodec/h261enc.h
@@ -31,7 +31,5 @@
 #include "mpegvideo.h"
 
 void ff_h261_reorder_mb_index(MpegEncContext *s);
-void ff_h261_encode_mb(MpegEncContext *s, int16_t block[6][64],
-                       int motion_x, int motion_y);
 
 #endif
diff --git a/libavcodec/h263enc.h b/libavcodec/h263enc.h
index 29a785dfeb..dd9caa7969 100644
--- a/libavcodec/h263enc.h
+++ b/libavcodec/h263enc.h
@@ -28,9 +28,6 @@ const uint8_t (*ff_h263_get_mv_penalty(void))[MAX_DMV*2+1];
 
 void ff_h263_encode_init(MPVMainEncContext *m);
 void ff_h263_encode_gob_header(MpegEncContext * s, int mb_line);
-void ff_h263_encode_mb(MpegEncContext *s,
-                       int16_t block[6][64],
-                       int motion_x, int motion_y);
 void ff_h263_encode_mba(MpegEncContext *s);
 
 void ff_clean_h263_qscales(MpegEncContext *s);
diff --git a/libavcodec/ituh263enc.c b/libavcodec/ituh263enc.c
index 739f959e40..deaf7dc5c6 100644
--- a/libavcodec/ituh263enc.c
+++ b/libavcodec/ituh263enc.c
@@ -608,9 +608,9 @@ static int h263_pred_dc(MpegEncContext * s, int n, int16_t **dc_val_ptr)
     return pred_dc;
 }
 
-void ff_h263_encode_mb(MpegEncContext * s,
-                       int16_t block[6][64],
-                       int motion_x, int motion_y)
+static void h263_encode_mb(MpegEncContext *const s,
+                           int16_t block[][64],
+                           int motion_x, int motion_y)
 {
     int cbpc, cbpy, i, cbp, pred_x, pred_y;
     int16_t pred_dc;
@@ -875,6 +875,8 @@ av_cold void ff_h263_encode_init(MPVMainEncContext *const m)
     // H.263, H.263+; will be overwritten for MSMPEG-4 later
     if (!m->encode_picture_header)
         m->encode_picture_header = h263_encode_picture_header;
+    if (!s->encode_mb)
+        s->encode_mb = h263_encode_mb;
 
     ff_h263dsp_init(&s->h263dsp);
 }
diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c
index 4c7a25832b..6c58c04892 100644
--- a/libavcodec/mjpegenc.c
+++ b/libavcodec/mjpegenc.c
@@ -463,10 +463,10 @@ static void encode_block(MpegEncContext *s, int16_t *block, int n)
         put_bits(&s->pb, huff_size_ac[0], huff_code_ac[0]);
 }
 
-void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[12][64])
+static void mjpeg_record_mb(MpegEncContext *const s, int16_t block[][64],
+                            int unused_x, int unused_y)
 {
     int i;
-    if (s->mjpeg_ctx->huffman == HUFFMAN_TABLE_OPTIMAL) {
         if (s->chroma_format == CHROMA_444) {
             record_block(s, block[0], 0);
             record_block(s, block[2], 2);
@@ -495,7 +495,12 @@ void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[12][64])
                 record_block(s, block[7], 7);
             }
         }
-    } else {
+}
+
+static void mjpeg_encode_mb(MpegEncContext *const s, int16_t block[][64],
+                            int unused_x, int unused_y)
+{
+    int i;
         if (s->chroma_format == CHROMA_444) {
             encode_block(s, block[0], 0);
             encode_block(s, block[2], 2);
@@ -526,7 +531,6 @@ void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[12][64])
         }
 
         s->i_tex_bits += get_bits_diff(s);
-    }
 }
 
 static av_cold int mjpeg_encode_init(AVCodecContext *avctx)
@@ -538,6 +542,8 @@ static av_cold int mjpeg_encode_init(AVCodecContext *avctx)
 
     s->mjpeg_ctx = m;
     m2->mpeg.encode_picture_header = mjpeg_amv_encode_picture_header;
+    // May be overridden below
+    s->encode_mb                   = mjpeg_encode_mb;
 
     if (s->mpv_flags & FF_MPV_FLAG_QP_RD) {
         // Used to produce garbage with MJPEG.
@@ -598,8 +604,11 @@ static av_cold int mjpeg_encode_init(AVCodecContext *avctx)
     if (s->slice_context_count > 1)
         m->huffman = HUFFMAN_TABLE_DEFAULT;
 
-    if (m->huffman == HUFFMAN_TABLE_OPTIMAL)
+    if (m->huffman == HUFFMAN_TABLE_OPTIMAL) {
+        // If we are here, we have only one slice_context. So no loop necessary.
+        s->encode_mb = mjpeg_record_mb;
         return alloc_huffman(m2);
+    }
 
     return 0;
 }
diff --git a/libavcodec/mjpegenc.h b/libavcodec/mjpegenc.h
index 9610656aaa..ceacba9893 100644
--- a/libavcodec/mjpegenc.h
+++ b/libavcodec/mjpegenc.h
@@ -94,7 +94,6 @@ static inline void put_marker(PutBitContext *p, enum JpegMarker code)
 
 typedef struct MpegEncContext MpegEncContext;
 
-void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[12][64]);
 int  ff_mjpeg_encode_stuffing(MpegEncContext *s);
 
 #endif /* AVCODEC_MJPEGENC_H */
diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c
index b67f70c5cd..1ef88d23b8 100644
--- a/libavcodec/mpeg12enc.c
+++ b/libavcodec/mpeg12enc.c
@@ -929,8 +929,8 @@ static av_always_inline void mpeg1_encode_mb_internal(MpegEncContext *s,
     }
 }
 
-void ff_mpeg1_encode_mb(MpegEncContext *s, int16_t block[8][64],
-                        int motion_x, int motion_y)
+static void mpeg12_encode_mb(MpegEncContext *s, int16_t block[][64],
+                             int motion_x, int motion_y)
 {
     if (!s->mb_intra)
         s->last_dc[0] = s->last_dc[1] = s->last_dc[2] = 128 << s->intra_dc_precision;
@@ -1111,6 +1111,7 @@ static av_cold int encode_init(AVCodecContext *avctx)
     }
 
     m->encode_picture_header = mpeg1_encode_picture_header;
+    s->encode_mb             = mpeg12_encode_mb;
 
     s->me.mv_penalty = mv_penalty;
     m->fcode_tab     = fcode_tab + MAX_MV;
diff --git a/libavcodec/mpeg12enc.h b/libavcodec/mpeg12enc.h
index 6c3709bbff..8ffa471a63 100644
--- a/libavcodec/mpeg12enc.h
+++ b/libavcodec/mpeg12enc.h
@@ -27,8 +27,6 @@
 #include "mpegvideo.h"
 #include "mpegvideodata.h"
 
-void ff_mpeg1_encode_mb(MpegEncContext *s, int16_t block[8][64],
-                        int motion_x, int motion_y);
 void ff_mpeg1_encode_slice_header(MpegEncContext *s);
 
 // Must not be called before intra_dc_precision has been sanitized in ff_mpv_encode_init()
diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c
index cc3c676e18..4f97199eba 100644
--- a/libavcodec/mpeg4videoenc.c
+++ b/libavcodec/mpeg4videoenc.c
@@ -499,8 +499,8 @@ static inline int get_b_cbp(MpegEncContext *s, int16_t block[6][64],
 // FIXME this is duplicated to h263.c
 static const int dquant_code[5] = { 1, 0, 9, 2, 3 };
 
-void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64],
-                        int motion_x, int motion_y)
+static void mpeg4_encode_mb(MpegEncContext *const s, int16_t block[][64],
+                            int motion_x, int motion_y)
 {
     int cbpc, cbpy, pred_x, pred_y;
     PutBitContext *const pb2    = s->data_partitioning ? &s->pb2 : &s->pb;
@@ -1301,6 +1301,7 @@ static av_cold int encode_init(AVCodecContext *avctx)
     }
 
     m->encode_picture_header = mpeg4_encode_picture_header;
+    s->encode_mb             = mpeg4_encode_mb;
 
     ff_qpeldsp_init(&s->qdsp);
     if ((ret = ff_mpv_encode_init(avctx)) < 0)
diff --git a/libavcodec/mpeg4videoenc.h b/libavcodec/mpeg4videoenc.h
index 4565a518b2..0727be6750 100644
--- a/libavcodec/mpeg4videoenc.h
+++ b/libavcodec/mpeg4videoenc.h
@@ -29,9 +29,6 @@
 
 typedef struct MpegEncContext MpegEncContext;
 
-void ff_mpeg4_encode_mb(MpegEncContext *s,
-                        int16_t block[6][64],
-                        int motion_x, int motion_y);
 void ff_set_mpeg4_time(MpegEncContext *s);
 
 void ff_mpeg4_encode_video_packet_header(MpegEncContext *s);
diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h
index 49e8159769..bdab782b29 100644
--- a/libavcodec/mpegvideo.h
+++ b/libavcodec/mpegvideo.h
@@ -438,7 +438,11 @@ typedef struct MpegEncContext {
 
     int16_t (*block)[64]; ///< points to one of the following blocks
     int16_t (*blocks)[12][64]; // for HQ mode we need to keep the best block
+    union {
     int (*decode_mb)(struct MpegEncContext *s, int16_t block[12][64]); // used by some codecs to avoid a switch()
+        void (*encode_mb)(struct MpegEncContext *s, int16_t block[][64],
+                          int motion_x, int motion_y);
+    };
 
 #define SLICE_OK         0
 #define SLICE_ERROR     -1
diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c
index 08fc72edb4..6650e5b35d 100644
--- a/libavcodec/mpegvideo_enc.c
+++ b/libavcodec/mpegvideo_enc.c
@@ -71,7 +71,6 @@
 #include "mpeg4videoenc.h"
 #include "internal.h"
 #include "bytestream.h"
-#include "wmv2enc.h"
 #include "rv10enc.h"
 #include "packet_internal.h"
 #include "libavutil/refstruct.h"
@@ -2562,52 +2561,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s,
         }
     }
 
-    /* huffman encode */
-    switch(s->codec_id){ //FIXME funct ptr could be slightly faster
-    case AV_CODEC_ID_MPEG1VIDEO:
-    case AV_CODEC_ID_MPEG2VIDEO:
-        if (CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER)
-            ff_mpeg1_encode_mb(s, s->block, motion_x, motion_y);
-        break;
-    case AV_CODEC_ID_MPEG4:
-        if (CONFIG_MPEG4_ENCODER)
-            ff_mpeg4_encode_mb(s, s->block, motion_x, motion_y);
-        break;
-    case AV_CODEC_ID_MSMPEG4V2:
-    case AV_CODEC_ID_MSMPEG4V3:
-    case AV_CODEC_ID_WMV1:
-        if (CONFIG_MSMPEG4ENC)
-            ff_msmpeg4_encode_mb(s, s->block, motion_x, motion_y);
-        break;
-    case AV_CODEC_ID_WMV2:
-        if (CONFIG_WMV2_ENCODER)
-            ff_wmv2_encode_mb(s, s->block, motion_x, motion_y);
-        break;
-    case AV_CODEC_ID_H261:
-        if (CONFIG_H261_ENCODER)
-            ff_h261_encode_mb(s, s->block, motion_x, motion_y);
-        break;
-    case AV_CODEC_ID_H263:
-    case AV_CODEC_ID_H263P:
-    case AV_CODEC_ID_FLV1:
-    case AV_CODEC_ID_RV10:
-    case AV_CODEC_ID_RV20:
-        if (CONFIG_H263_ENCODER)
-            ff_h263_encode_mb(s, s->block, motion_x, motion_y);
-        break;
-#if CONFIG_MJPEG_ENCODER || CONFIG_AMV_ENCODER
-    case AV_CODEC_ID_MJPEG:
-    case AV_CODEC_ID_AMV:
-        ff_mjpeg_encode_mb(s, s->block);
-        break;
-#endif
-    case AV_CODEC_ID_SPEEDHQ:
-        if (CONFIG_SPEEDHQ_ENCODER)
-            ff_speedhq_encode_mb(s, s->block);
-        break;
-    default:
-        av_assert1(0);
-    }
+    s->encode_mb(s, s->block, motion_x, motion_y);
 }
 
 static void encode_mb(MpegEncContext *s, int motion_x, int motion_y)
diff --git a/libavcodec/msmpeg4enc.c b/libavcodec/msmpeg4enc.c
index 01d5707370..9e58a91a80 100644
--- a/libavcodec/msmpeg4enc.c
+++ b/libavcodec/msmpeg4enc.c
@@ -370,9 +370,9 @@ static void msmpeg4v2_encode_motion(MpegEncContext * s, int val)
     }
 }
 
-void ff_msmpeg4_encode_mb(MpegEncContext * s,
-                          int16_t block[6][64],
-                          int motion_x, int motion_y)
+static void msmpeg4_encode_mb(MpegEncContext *const s,
+                              int16_t block[][64],
+                              int motion_x, int motion_y)
 {
     int cbp, coded_cbp, i;
     int pred_x, pred_y;
@@ -670,8 +670,10 @@ av_cold void ff_msmpeg4_encode_init(MPVMainEncContext *const m)
 
     ff_msmpeg4_common_init(s);
 
-    if (s->msmpeg4_version <= MSMP4_WMV1)
+    if (s->msmpeg4_version <= MSMP4_WMV1) {
         m->encode_picture_header = msmpeg4_encode_picture_header;
+        s->encode_mb             = msmpeg4_encode_mb;
+    }
 
     if (s->msmpeg4_version >= MSMP4_WMV1) {
         s->min_qcoeff = -255;
diff --git a/libavcodec/msmpeg4enc.h b/libavcodec/msmpeg4enc.h
index 5511e01283..dde1fb6b93 100644
--- a/libavcodec/msmpeg4enc.h
+++ b/libavcodec/msmpeg4enc.h
@@ -35,8 +35,6 @@ typedef struct MSMPEG4EncContext {
 
 void ff_msmpeg4_encode_init(MPVMainEncContext *m);
 void ff_msmpeg4_encode_ext_header(MpegEncContext *s);
-void ff_msmpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64],
-                          int motion_x, int motion_y);
 void ff_msmpeg4_encode_block(MpegEncContext * s, int16_t * block, int n);
 void ff_msmpeg4_handle_slices(MpegEncContext *s);
 void ff_msmpeg4_encode_motion(MpegEncContext * s, int mx, int my);
diff --git a/libavcodec/speedhqenc.c b/libavcodec/speedhqenc.c
index 1ba5dcc68f..1e28702f18 100644
--- a/libavcodec/speedhqenc.c
+++ b/libavcodec/speedhqenc.c
@@ -207,7 +207,8 @@ static void encode_block(MpegEncContext *s, int16_t *block, int n)
     put_bits_le(&s->pb, 4, 6);
 }
 
-void ff_speedhq_encode_mb(MpegEncContext *s, int16_t block[12][64])
+static void speedhq_encode_mb(MpegEncContext *const s, int16_t block[12][64],
+                              int unused_x, int unused_y)
 {
     int i;
     for(i=0;i<6;i++) {
@@ -263,6 +264,7 @@ static av_cold int speedhq_encode_init(AVCodecContext *avctx)
     }
 
     m->encode_picture_header = speedhq_encode_picture_header;
+    s->encode_mb             = speedhq_encode_mb;
 
     s->min_qcoeff = -2048;
     s->max_qcoeff = 2047;
diff --git a/libavcodec/speedhqenc.h b/libavcodec/speedhqenc.h
index f02fa1f51a..e804ce714a 100644
--- a/libavcodec/speedhqenc.h
+++ b/libavcodec/speedhqenc.h
@@ -33,8 +33,6 @@
 
 #include "mpegvideo.h"
 
-void ff_speedhq_encode_mb(MpegEncContext *s, int16_t block[12][64]);
-
 void ff_speedhq_end_slice(MpegEncContext *s);
 
 static inline int ff_speedhq_mb_rows_in_slice(int slice_num, int mb_height)
diff --git a/libavcodec/wmv2enc.c b/libavcodec/wmv2enc.c
index d70a680fb3..3ab3e75722 100644
--- a/libavcodec/wmv2enc.c
+++ b/libavcodec/wmv2enc.c
@@ -29,7 +29,6 @@
 #include "msmpeg4data.h"
 #include "msmpeg4_vc1_data.h"
 #include "wmv2.h"
-#include "wmv2enc.h"
 
 #define WMV2_EXTRADATA_SIZE 4
 
@@ -147,8 +146,8 @@ static int wmv2_encode_picture_header(MPVMainEncContext *const m)
 /* Nearly identical to wmv1 but that is just because we do not use the
  * useless M$ crap features. It is duplicated here in case someone wants
  * to add support for these crap features. */
-void ff_wmv2_encode_mb(MpegEncContext *s, int16_t block[6][64],
-                       int motion_x, int motion_y)
+static void wmv2_encode_mb(MpegEncContext *const s, int16_t block[][64],
+                           int motion_x, int motion_y)
 {
     WMV2EncContext *const w = (WMV2EncContext *) s;
     int cbp, coded_cbp, i;
@@ -224,6 +223,7 @@ static av_cold int wmv2_encode_init(AVCodecContext *avctx)
     int ret;
 
     w->msmpeg4.m.encode_picture_header = wmv2_encode_picture_header;
+    s->encode_mb                       = wmv2_encode_mb;
     s->private_ctx = &w->common;
     ret = ff_mpv_encode_init(avctx);
     if (ret < 0)
diff --git a/libavcodec/wmv2enc.h b/libavcodec/wmv2enc.h
deleted file mode 100644
index 59046c6a07..0000000000
--- a/libavcodec/wmv2enc.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2002 The FFmpeg Project
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef AVCODEC_WMV2ENC_H
-#define AVCODEC_WMV2ENC_H
-
-#include "mpegvideo.h"
-
-void ff_wmv2_encode_mb(MpegEncContext * s, int16_t block[6][64],
-                       int motion_x, int motion_y);
-
-
-#endif
-- 
2.45.2