Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
Subject: [FFmpeg-devel] [PATCH 01/44] avcodec/{x86, mips}/xvididct_init: Remove redundant checks
Date: Fri, 2 May 2025 02:12:28 +0200
Message-ID: <GV1P250MB0737B773C8A292FCEB12BF598F8D2@GV1P250MB0737.EURP250.PROD.OUTLOOK.COM> (raw)

[-- Attachment #1: Type: text/plain, Size: 29 bytes --]

Patches attached.

- Andreas

[-- Attachment #2: 0001-avcodec-x86-mips-xvididct_init-Remove-redundant-chec.patch --]
[-- Type: text/x-patch, Size: 3752 bytes --]

From 82a8c908080b2e308e0f6abf92aa0ed374f29aea Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Thu, 27 Mar 2025 02:57:20 +0100
Subject: [PATCH 01/44] avcodec/{x86,mips}/xvididct_init: Remove redundant
 checks

ff_xvid_idct_init() already checks in case of high_bit_depth,
lowres or an incompatible idct_algo.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mips/xvididct_init_mips.c | 16 +++++-----------
 libavcodec/x86/xvididct_init.c       |  8 +-------
 libavcodec/xvididct.c                |  4 ++--
 libavcodec/xvididct.h                |  6 ++----
 4 files changed, 10 insertions(+), 24 deletions(-)

diff --git a/libavcodec/mips/xvididct_init_mips.c b/libavcodec/mips/xvididct_init_mips.c
index 658a5792e0..524cf8dcdf 100644
--- a/libavcodec/mips/xvididct_init_mips.c
+++ b/libavcodec/mips/xvididct_init_mips.c
@@ -22,20 +22,14 @@
 #include "libavutil/mips/cpu.h"
 #include "xvididct_mips.h"
 
-av_cold void ff_xvid_idct_init_mips(IDCTDSPContext *c, AVCodecContext *avctx,
-        unsigned high_bit_depth)
+av_cold void ff_xvid_idct_init_mips(IDCTDSPContext *c)
 {
     int cpu_flags = av_get_cpu_flags();
 
     if (have_mmi(cpu_flags)) {
-        if (!high_bit_depth) {
-            if (avctx->idct_algo == FF_IDCT_AUTO ||
-                    avctx->idct_algo == FF_IDCT_XVID) {
-                c->idct_put = ff_xvid_idct_put_mmi;
-                c->idct_add = ff_xvid_idct_add_mmi;
-                c->idct = ff_xvid_idct_mmi;
-                c->perm_type = FF_IDCT_PERM_NONE;
-            }
-        }
+        c->idct_put  = ff_xvid_idct_put_mmi;
+        c->idct_add  = ff_xvid_idct_add_mmi;
+        c->idct      = ff_xvid_idct_mmi;
+        c->perm_type = FF_IDCT_PERM_NONE;
     }
 }
diff --git a/libavcodec/x86/xvididct_init.c b/libavcodec/x86/xvididct_init.c
index fda34cc638..c6c87b0c90 100644
--- a/libavcodec/x86/xvididct_init.c
+++ b/libavcodec/x86/xvididct_init.c
@@ -25,17 +25,11 @@
 
 #include "xvididct.h"
 
-av_cold void ff_xvid_idct_init_x86(IDCTDSPContext *c, AVCodecContext *avctx,
-                                   unsigned high_bit_depth)
+av_cold void ff_xvid_idct_init_x86(IDCTDSPContext *c)
 {
 #if HAVE_X86ASM
     int cpu_flags = av_get_cpu_flags();
 
-    if (high_bit_depth ||
-        !(avctx->idct_algo == FF_IDCT_AUTO ||
-          avctx->idct_algo == FF_IDCT_XVID))
-        return;
-
     if (EXTERNAL_SSE2(cpu_flags)) {
         c->idct_put  = ff_xvid_idct_put_sse2;
         c->idct_add  = ff_xvid_idct_add_sse2;
diff --git a/libavcodec/xvididct.c b/libavcodec/xvididct.c
index 01072d80ab..2eddc5978c 100644
--- a/libavcodec/xvididct.c
+++ b/libavcodec/xvididct.c
@@ -347,9 +347,9 @@ av_cold void ff_xvid_idct_init(IDCTDSPContext *c, AVCodecContext *avctx)
     }
 
 #if ARCH_X86
-    ff_xvid_idct_init_x86(c, avctx, high_bit_depth);
+    ff_xvid_idct_init_x86(c);
 #elif ARCH_MIPS
-    ff_xvid_idct_init_mips(c, avctx, high_bit_depth);
+    ff_xvid_idct_init_mips(c);
 #endif
 
     ff_init_scantable_permutation(c->idct_permutation, c->perm_type);
diff --git a/libavcodec/xvididct.h b/libavcodec/xvididct.h
index e0bc1a2b91..1395cfd8e1 100644
--- a/libavcodec/xvididct.h
+++ b/libavcodec/xvididct.h
@@ -28,9 +28,7 @@ void ff_xvid_idct(int16_t *const in);
 
 void ff_xvid_idct_init(IDCTDSPContext *c, AVCodecContext *avctx);
 
-void ff_xvid_idct_init_x86(IDCTDSPContext *c, AVCodecContext *avctx,
-                           unsigned high_bit_depth);
-void ff_xvid_idct_init_mips(IDCTDSPContext *c, AVCodecContext *avctx,
-                            unsigned high_bit_depth);
+void ff_xvid_idct_init_x86(IDCTDSPContext *c);
+void ff_xvid_idct_init_mips(IDCTDSPContext *c);
 
 #endif /* AVCODEC_XVIDIDCT_H */
-- 
2.45.2


[-- Attachment #3: 0002-avcodec-mpeg_er-Don-t-zero-ThreadFrame-unnecessarily.patch --]
[-- Type: text/x-patch, Size: 1023 bytes --]

From d766d790e62e5dfc8afa22a89e1837c71fbab53f Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Thu, 27 Mar 2025 15:14:02 +0100
Subject: [PATCH 02/44] avcodec/mpeg_er: Don't zero ThreadFrame* unnecessarily

We never set the ThreadFrame*, because mpegvideo uses
ThreadProgress instead of ThreadFrames. Furthermore,
it is unnecessary because the ERPicture has just been zeroed.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpeg_er.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/libavcodec/mpeg_er.c b/libavcodec/mpeg_er.c
index 3cbdeeebec..4b171354c7 100644
--- a/libavcodec/mpeg_er.c
+++ b/libavcodec/mpeg_er.c
@@ -28,11 +28,8 @@ static void set_erpic(ERPicture *dst, const MPVPicture *src)
     int i;
 
     memset(dst, 0, sizeof(*dst));
-    if (!src) {
-        dst->f  = NULL;
-        dst->tf = NULL;
+    if (!src)
         return;
-    }
 
     dst->f = src->f;
     dst->progress = &src->progress;
-- 
2.45.2


[-- Attachment #4: 0003-avcodec-mpeg4videodec-Avoid-redundant-assignments.patch --]
[-- Type: text/x-patch, Size: 1630 bytes --]

From d43ca46969cd7d30cd945d37d50a8cf32b12bca3 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 25 Mar 2025 12:25:20 +0100
Subject: [PATCH 03/44] avcodec/mpeg4videodec: Avoid redundant assignments

ff_h263_decode_frame() already checks for changing dimensions
and automatically reinits the context in this case.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpeg4videodec.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
index e21f1d24a2..51a2cd0a73 100644
--- a/libavcodec/mpeg4videodec.c
+++ b/libavcodec/mpeg4videodec.c
@@ -2556,9 +2556,6 @@ static int decode_studio_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb)
 
         /* Do the same check as non-studio profile */
         if (width && height) {
-            if (s->width && s->height &&
-                (s->width != width || s->height != height))
-                s->context_reinit = 1;
             s->width  = width;
             s->height = height;
         }
@@ -2702,9 +2699,6 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb)
             check_marker(s->avctx, gb, "after height");
             if (width && height &&  /* they should be non zero but who knows */
                 !(s->width && s->codec_tag == AV_RL32("MP4S"))) {
-                if (s->width && s->height &&
-                    (s->width != width || s->height != height))
-                    s->context_reinit = 1;
                 s->width  = width;
                 s->height = height;
             }
-- 
2.45.2


[-- Attachment #5: 0004-avcodec-mpeg4videodec-Set-yd-c_scale_table-during-in.patch --]
[-- Type: text/x-patch, Size: 2020 bytes --]

From a9408c2e1a13149e3787633be8f6b57b4065ef72 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Wed, 30 Apr 2025 12:11:31 +0200
Subject: [PATCH 04/44] avcodec/mpeg4videodec: Set [yd]c_scale_table during
 init

It does not change lateron.
(If we were to add short header support later, it would involve
a branch in mpeg4_decode_block() anyway and we would then
hardcode the dc_scaler value of eight there; the *_scale_tables
would stay the same.)

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpeg4videodec.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
index 51a2cd0a73..7764da7da7 100644
--- a/libavcodec/mpeg4videodec.c
+++ b/libavcodec/mpeg4videodec.c
@@ -1344,6 +1344,7 @@ static inline int mpeg4_decode_block(Mpeg4DecContext *ctx, int16_t *block,
     // Note intra & rvlc should be optimized away if this is inlined
 
     if (intra) {
+        // FIXME add short header support
         if (use_intra_dc_vlc) {
             /* DC coef */
             if (s->partitioned_frame) {
@@ -3401,10 +3402,6 @@ end:
 
     s->picture_number++;  // better than pic number==0 always ;)
 
-    // FIXME add short header support
-    s->y_dc_scale_table = ff_mpeg4_y_dc_scale_table;
-    s->c_dc_scale_table = ff_mpeg4_c_dc_scale_table;
-
     if (s->workaround_bugs & FF_BUG_EDGE) {
         s->h_edge_pos = s->width;
         s->v_edge_pos = s->height;
@@ -3878,6 +3875,9 @@ static av_cold int decode_init(AVCodecContext *avctx)
     // so we can already set dct_unquantize_inter here once and for all.
     s->dct_unquantize_inter = unquant_dsp_ctx.dct_unquantize_mpeg2_inter;
 
+    s->y_dc_scale_table = ff_mpeg4_y_dc_scale_table;
+    s->c_dc_scale_table = ff_mpeg4_c_dc_scale_table;
+
     s->h263_pred = 1;
     s->low_delay = 0; /* default, might be overridden in the vol header during header parsing */
     s->decode_mb = mpeg4_decode_mb;
-- 
2.45.2


[-- Attachment #6: 0005-avcodec-mpeg4videodec-Permute-quant-matrices-directl.patch --]
[-- Type: text/x-patch, Size: 5275 bytes --]

From 8163b73b71ab646bac466556b8ae90d5e7bdb56d Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Fri, 2 May 2025 00:57:46 +0200
Subject: [PATCH 05/44] avcodec/mpeg4videodec: Permute quant matrices directly
 upon IDCT reinit

When switching to the XviD IDCT, the IDCT permutation can change.
Given that we already permute the quant matrices when parsing
them, they need to be permuted, too. Up until now this has not been
done; instead the header has been parsed again in the expectation
that the currently active quant matrix is contained in this header.

This expectation is wrong; it is for example wrong when the VOL
header is only available via extradata (such a file can be easily
created from xvid_vlc_trac7411.h263 (in the FATE suite) via the
remove_extra BSF). It could also be wrong if the XviD user data
is only available in a subsequent packet.

This commit therefore switches to permuting the relevant matrices
directly. It also stops parsing the header a second time
when switching to the XviD IDCT.

(I wonder whether ff_mpv_idct_init() should take alternate_scan
into account when initializing permutated_intra_h_scantable
as the decoder does. Does the MPEG-4 encoder use a wrong scantable
in this case?)

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/h263dec.c       |  4 +---
 libavcodec/mpeg4videodec.c | 39 +++++++++++++++++++++++++++++++-------
 libavcodec/mpeg4videodec.h |  2 +-
 3 files changed, 34 insertions(+), 11 deletions(-)

diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c
index ddbada9841..fd1e36b68a 100644
--- a/libavcodec/h263dec.c
+++ b/libavcodec/h263dec.c
@@ -449,7 +449,6 @@ int ff_h263_decode_frame(AVCodecContext *avctx, AVFrame *pict,
         return 0;
     }
 
-retry:
     // s->gb might be overridden in ff_mpeg4_decode_picture_header() below.
     ret = init_get_bits8(&s->gb, buf, buf_size);
     if (ret < 0)
@@ -505,8 +504,7 @@ retry:
     if (CONFIG_MPEG4_DECODER && avctx->codec_id == AV_CODEC_ID_MPEG4) {
         if (s->pict_type != AV_PICTURE_TYPE_B && s->mb_num/2 > get_bits_left(&s->gb))
             return AVERROR_INVALIDDATA;
-        if (ff_mpeg4_workaround_bugs(avctx) == 1)
-            goto retry;
+        ff_mpeg4_workaround_bugs(avctx);
         if (s->studio_profile != (s->idsp.idct == NULL))
             ff_mpv_idct_init(s);
     }
diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
index 7764da7da7..bf90fba875 100644
--- a/libavcodec/mpeg4videodec.c
+++ b/libavcodec/mpeg4videodec.c
@@ -3015,7 +3015,36 @@ static int decode_user_data(Mpeg4DecContext *ctx, GetBitContext *gb)
     return 0;
 }
 
-int ff_mpeg4_workaround_bugs(AVCodecContext *avctx)
+static av_cold void permute_quant_matrix(uint16_t matrix[64],
+                                         const uint8_t new_perm[64],
+                                         const uint8_t old_perm[64])
+{
+    uint16_t tmp[64];
+
+    memcpy(tmp, matrix, sizeof(tmp));
+    for (int i = 0; i < 64; ++i)
+        matrix[new_perm[i]] = tmp[old_perm[i]];
+}
+
+static av_cold void switch_to_xvid_idct(AVCodecContext *const avctx,
+                                        MpegEncContext *const s)
+{
+    uint8_t old_permutation[64];
+
+    memcpy(old_permutation, s->idsp.idct_permutation, sizeof(old_permutation));
+
+    avctx->idct_algo = FF_IDCT_XVID;
+    ff_mpv_idct_init(s);
+    ff_permute_scantable(s->permutated_intra_h_scantable,
+                         s->alternate_scan ? ff_alternate_vertical_scan : ff_alternate_horizontal_scan,
+                         s->idsp.idct_permutation);
+
+    // Normal (i.e. non-studio) MPEG-4 does not use the chroma matrices.
+    permute_quant_matrix(s->inter_matrix, s->idsp.idct_permutation, old_permutation);
+    permute_quant_matrix(s->intra_matrix, s->idsp.idct_permutation, old_permutation);
+}
+
+void ff_mpeg4_workaround_bugs(AVCodecContext *avctx)
 {
     Mpeg4DecContext *ctx = avctx->priv_data;
     MpegEncContext *s = &ctx->m;
@@ -3123,13 +3152,9 @@ int ff_mpeg4_workaround_bugs(AVCodecContext *avctx)
                ctx->divx_version, ctx->divx_build, s->divx_packed ? "p" : "");
 
     if (CONFIG_MPEG4_DECODER && ctx->xvid_build >= 0 &&
-        avctx->idct_algo == FF_IDCT_AUTO) {
-        avctx->idct_algo = FF_IDCT_XVID;
-        ff_mpv_idct_init(s);
-        return 1;
+        avctx->idct_algo == FF_IDCT_AUTO && !s->studio_profile) {
+        switch_to_xvid_idct(avctx, s);
     }
-
-    return 0;
 }
 
 static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb,
diff --git a/libavcodec/mpeg4videodec.h b/libavcodec/mpeg4videodec.h
index d3de81c5a9..59a7251ce2 100644
--- a/libavcodec/mpeg4videodec.h
+++ b/libavcodec/mpeg4videodec.h
@@ -111,7 +111,7 @@ void ff_mpeg4_mcsel_motion(MpegEncContext *s,
 int ff_mpeg4_decode_partitions(Mpeg4DecContext *ctx);
 int ff_mpeg4_decode_video_packet_header(Mpeg4DecContext *ctx);
 int ff_mpeg4_decode_studio_slice_header(Mpeg4DecContext *ctx);
-int ff_mpeg4_workaround_bugs(AVCodecContext *avctx);
+void ff_mpeg4_workaround_bugs(AVCodecContext *avctx);
 void ff_mpeg4_pred_ac(MpegEncContext *s, int16_t *block, int n,
                       int dir);
 int ff_mpeg4_frame_end(AVCodecContext *avctx, const AVPacket *pkt);
-- 
2.45.2


[-- Attachment #7: 0006-avcodec-vc1-Remove-write-only-qs_last.patch --]
[-- Type: text/x-patch, Size: 4490 bytes --]

From 1bccf9e839acb3271925b353dafc3d19977bd72b Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Wed, 30 Apr 2025 13:10:23 +0200
Subject: [PATCH 06/44] avcodec/vc1: Remove write-only qs_last

Write-only since 9cc74c9f6e8b645e67d45b2070db004caca09af7.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/vc1.c | 7 -------
 libavcodec/vc1.h | 1 -
 2 files changed, 8 deletions(-)

diff --git a/libavcodec/vc1.c b/libavcodec/vc1.c
index 93c155dc2d..076127a1be 100644
--- a/libavcodec/vc1.c
+++ b/libavcodec/vc1.c
@@ -724,7 +724,6 @@ int ff_vc1_parse_frame_header(VC1Context *v, GetBitContext* gb)
             INIT_LUT(v->lumscale, v->lumshift, v->last_luty[0], v->last_lutuv[0], 1);
             INIT_LUT(v->lumscale, v->lumshift, v->last_luty[1], v->last_lutuv[1], 1);
         }
-        v->qs_last = v->s.quarter_sample;
         if (v->mv_mode == MV_PMODE_INTENSITY_COMP) {
             v->s.quarter_sample = (v->mv_mode2 != MV_PMODE_1MV_HPEL &&
                                    v->mv_mode2 != MV_PMODE_1MV_HPEL_BILIN);
@@ -781,7 +780,6 @@ int ff_vc1_parse_frame_header(VC1Context *v, GetBitContext* gb)
         v->tt_index = (v->pq > 4) + (v->pq > 12);
 
         v->mv_mode          = get_bits1(gb) ? MV_PMODE_1MV : MV_PMODE_1MV_HPEL_BILIN;
-        v->qs_last          = v->s.quarter_sample;
         v->s.quarter_sample = (v->mv_mode == MV_PMODE_1MV);
         v->s.mspel          = v->s.quarter_sample;
 
@@ -1119,7 +1117,6 @@ int ff_vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb)
                 }
                 v->last_use_ic = 1;
             }
-            v->qs_last = v->s.quarter_sample;
             if (v->mv_mode == MV_PMODE_INTENSITY_COMP) {
                 v->s.quarter_sample = (v->mv_mode2 != MV_PMODE_1MV_HPEL &&
                                        v->mv_mode2 != MV_PMODE_1MV_HPEL_BILIN);
@@ -1154,7 +1151,6 @@ int ff_vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb)
             v->cbptab           = get_bits(gb, 2);
             v->cbpcy_vlc        = ff_vc1_cbpcy_p_vlc[v->cbptab];
         } else if (v->fcm == ILACE_FRAME) { // frame interlaced
-            v->qs_last          = v->s.quarter_sample;
             v->s.quarter_sample = 1;
             v->s.mspel          = 1;
         } else {    // field interlaced
@@ -1218,7 +1214,6 @@ int ff_vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb)
             mvmode = get_unary(gb, 1, 3);
             lowquant = (v->pq > 12) ? 0 : 1;
             v->mv_mode          = ff_vc1_mv_pmode_table2[lowquant][mvmode];
-            v->qs_last          = v->s.quarter_sample;
             v->s.quarter_sample = (v->mv_mode == MV_PMODE_1MV || v->mv_mode == MV_PMODE_MIXED_MV);
             v->s.mspel          = (v->mv_mode != MV_PMODE_1MV_HPEL_BILIN);
             status = bitplane_decoding(v->forward_mb_plane, &v->fmb_is_raw, v);
@@ -1248,7 +1243,6 @@ int ff_vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb)
             v->intcomp          = 0;
             v->mv_mode          = MV_PMODE_1MV;
             v->fourmvswitch     = 0;
-            v->qs_last          = v->s.quarter_sample;
             v->s.quarter_sample = 1;
             v->s.mspel          = 1;
             status              = bitplane_decoding(v->direct_mb_plane, &v->dmb_is_raw, v);
@@ -1274,7 +1268,6 @@ int ff_vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb)
             v->fourmvbp_vlc = ff_vc1_4mv_block_pattern_vlc[v->fourmvbptab];
         } else {
             v->mv_mode          = get_bits1(gb) ? MV_PMODE_1MV : MV_PMODE_1MV_HPEL_BILIN;
-            v->qs_last          = v->s.quarter_sample;
             v->s.quarter_sample = (v->mv_mode == MV_PMODE_1MV);
             v->s.mspel          = v->s.quarter_sample;
             status              = bitplane_decoding(v->direct_mb_plane, &v->dmb_is_raw, v);
diff --git a/libavcodec/vc1.h b/libavcodec/vc1.h
index e8762350a2..94e0a9b2de 100644
--- a/libavcodec/vc1.h
+++ b/libavcodec/vc1.h
@@ -365,7 +365,6 @@ typedef struct VC1Context{
     int cur_field_type;     ///< 0: top, 1: bottom
     int ref_field_type[2];  ///< forward and backward reference field type (top or bottom)
     int blocks_off, mb_off;
-    int qs_last;            ///< if qpel has been used in the previous (tr.) picture
     int bmvtype;
     int frfd, brfd;         ///< reference frame distance (forward or backward)
     int first_pic_header_flag;
-- 
2.45.2


[-- Attachment #8: 0007-avcodec-vc1-Remove-unused-topleft-bottomright-fields.patch --]
[-- Type: text/x-patch, Size: 827 bytes --]

From 6001f4b6a5b918fc52c2e9826e94be36f66f4824 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Wed, 30 Apr 2025 13:41:21 +0200
Subject: [PATCH 07/44] avcodec/vc1: Remove unused topleft,bottomright fields

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/vc1.h | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/libavcodec/vc1.h b/libavcodec/vc1.h
index 94e0a9b2de..da82124a5e 100644
--- a/libavcodec/vc1.h
+++ b/libavcodec/vc1.h
@@ -314,10 +314,6 @@ typedef struct VC1Context{
     uint8_t numpanscanwin;
     uint8_t tfcntr;
     uint8_t rptfrm, tff, rff;
-    uint16_t topleftx;
-    uint16_t toplefty;
-    uint16_t bottomrightx;
-    uint16_t bottomrighty;
     uint8_t uvsamp;
     uint8_t postproc;
     int hrd_num_leaky_buckets;
-- 
2.45.2


[-- Attachment #9: 0008-avcodec-mpeg4video-Pass-parameters-directly.patch --]
[-- Type: text/x-patch, Size: 3554 bytes --]

From 8df7e7d44a7966d2218a98c87407d7c4edc8bd0e Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 25 Mar 2025 04:52:06 +0100
Subject: [PATCH 08/44] avcodec/mpeg4video: Pass parameters directly

Namely in ff_mpeg4_get_video_packet_prefix_length().
This will allow to move [fb]_code from MpegEncContext.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpeg4video.c    | 9 +++++----
 libavcodec/mpeg4video.h    | 3 ++-
 libavcodec/mpeg4videodec.c | 4 ++--
 libavcodec/mpeg4videoenc.c | 2 +-
 4 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/libavcodec/mpeg4video.c b/libavcodec/mpeg4video.c
index 3133cc22c4..2c0c1044f2 100644
--- a/libavcodec/mpeg4video.c
+++ b/libavcodec/mpeg4video.c
@@ -39,16 +39,17 @@ av_cold void ff_mpeg4_init_rl_intra(void)
     ff_thread_once(&init_static_once, mpeg4_init_rl_intra);
 }
 
-int ff_mpeg4_get_video_packet_prefix_length(MpegEncContext *s)
+int ff_mpeg4_get_video_packet_prefix_length(enum AVPictureType pict_type,
+                                            int f_code, int b_code)
 {
-    switch (s->pict_type) {
+    switch (pict_type) {
     case AV_PICTURE_TYPE_I:
         return 16;
     case AV_PICTURE_TYPE_P:
     case AV_PICTURE_TYPE_S:
-        return s->f_code + 15;
+        return f_code + 15;
     case AV_PICTURE_TYPE_B:
-        return FFMAX3(s->f_code, s->b_code, 2) + 15;
+        return FFMAX3(f_code, b_code, 2) + 15;
     default:
         return -1;
     }
diff --git a/libavcodec/mpeg4video.h b/libavcodec/mpeg4video.h
index cfc6dcb684..dc0bf31922 100644
--- a/libavcodec/mpeg4video.h
+++ b/libavcodec/mpeg4video.h
@@ -28,7 +28,8 @@
 #include "mpegvideo.h"
 
 void ff_mpeg4_clean_buffers(MpegEncContext *s);
-int ff_mpeg4_get_video_packet_prefix_length(MpegEncContext *s);
+int ff_mpeg4_get_video_packet_prefix_length(enum AVPictureType pict_type,
+                                            int f_code, int b_code);
 void ff_mpeg4_init_direct_mv(MpegEncContext *s);
 
 /**
diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
index bf90fba875..1954641198 100644
--- a/libavcodec/mpeg4videodec.c
+++ b/libavcodec/mpeg4videodec.c
@@ -421,7 +421,7 @@ static inline int mpeg4_is_resync(Mpeg4DecContext *ctx)
 
             s->gb = gb;
 
-            if (len >= ff_mpeg4_get_video_packet_prefix_length(s))
+            if (len >= ff_mpeg4_get_video_packet_prefix_length(s->pict_type, s->f_code, s->b_code))
                 return mb_num;
         }
     }
@@ -714,7 +714,7 @@ int ff_mpeg4_decode_video_packet_header(Mpeg4DecContext *ctx)
         if (get_bits1(&s->gb))
             break;
 
-    if (len != ff_mpeg4_get_video_packet_prefix_length(s)) {
+    if (len != ff_mpeg4_get_video_packet_prefix_length(s->pict_type, s->f_code, s->b_code)) {
         av_log(s->avctx, AV_LOG_ERROR, "marker does not match f_code\n");
         return AVERROR_INVALIDDATA;
     }
diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c
index 775dab0d4a..0998af663f 100644
--- a/libavcodec/mpeg4videoenc.c
+++ b/libavcodec/mpeg4videoenc.c
@@ -1393,7 +1393,7 @@ void ff_mpeg4_encode_video_packet_header(MPVEncContext *const s)
 {
     int mb_num_bits = av_log2(s->c.mb_num - 1) + 1;
 
-    put_bits(&s->pb, ff_mpeg4_get_video_packet_prefix_length(&s->c), 0);
+    put_bits(&s->pb, ff_mpeg4_get_video_packet_prefix_length(s->c.pict_type, s->c.f_code, s->c.b_code), 0);
     put_bits(&s->pb, 1, 1);
 
     put_bits(&s->pb, mb_num_bits, s->c.mb_x + s->c.mb_y * s->c.mb_width);
-- 
2.45.2


[-- Attachment #10: 0009-avcodec-mpegvideo-Move-fb-_code-to-Mpeg4Dec-and-MPVE.patch --]
[-- Type: text/x-patch, Size: 42054 bytes --]

From 5aacb03969f5e7e44092666ea3fae2c358ebe1b0 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 25 Mar 2025 05:05:04 +0100
Subject: [PATCH 09/44] avcodec/mpegvideo: Move [fb]_code to Mpeg4Dec and
 MPVEncContext

It is only used by the MPEG-4 decoder and the encoders.
Notice that this field is a per-frame property and therefore
does not need to by synced in mpeg4_update_thread_context().

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/motion_est.c    | 18 ++++++------
 libavcodec/mpeg12enc.c     | 40 ++++++++++++-------------
 libavcodec/mpeg4videodec.c | 60 +++++++++++++++++++-------------------
 libavcodec/mpeg4videodec.h |  3 ++
 libavcodec/mpeg4videoenc.c | 22 +++++++-------
 libavcodec/mpegvideo.h     |  2 --
 libavcodec/mpegvideo_enc.c | 30 +++++++++----------
 libavcodec/mpegvideoenc.h  |  3 ++
 libavcodec/msmpeg4enc.c    |  2 +-
 libavcodec/nvdec_mpeg4.c   |  4 +--
 libavcodec/ratecontrol.c   | 12 ++++----
 libavcodec/rv20enc.c       |  2 +-
 libavcodec/snowenc.c       |  4 +--
 libavcodec/svq1enc.c       |  4 +--
 libavcodec/vaapi_mpeg4.c   |  4 +--
 libavcodec/vdpau_mpeg4.c   |  4 +--
 16 files changed, 109 insertions(+), 105 deletions(-)

diff --git a/libavcodec/motion_est.c b/libavcodec/motion_est.c
index fd3cf04cd8..93aa909fb5 100644
--- a/libavcodec/motion_est.c
+++ b/libavcodec/motion_est.c
@@ -910,7 +910,7 @@ void ff_estimate_p_frame_motion(MPVEncContext *const s,
     c->penalty_factor     = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_cmp);
     c->sub_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_sub_cmp);
     c->mb_penalty_factor  = get_penalty_factor(s->lambda, s->lambda2, c->avctx->mb_cmp);
-    c->current_mv_penalty = c->mv_penalty[s->c.f_code] + MAX_DMV;
+    c->current_mv_penalty = c->mv_penalty[s->f_code] + MAX_DMV;
 
     get_limits(s, 16*mb_x, 16*mb_y, 0);
     c->skip=0;
@@ -1077,7 +1077,7 @@ int ff_pre_estimate_p_frame_motion(MPVEncContext *const s,
     av_assert0(s->c.quarter_sample == 0 || s->c.quarter_sample == 1);
 
     c->pre_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_pre_cmp);
-    c->current_mv_penalty = c->mv_penalty[s->c.f_code] + MAX_DMV;
+    c->current_mv_penalty = c->mv_penalty[s->f_code] + MAX_DMV;
 
     get_limits(s, 16*mb_x, 16*mb_y, 0);
     c->skip=0;
@@ -1187,8 +1187,8 @@ static inline int check_bidir_mv(MPVEncContext *const s,
     //FIXME better f_code prediction (max mv & distance)
     //FIXME pointers
     MotionEstContext *const c = &s->me;
-    const uint8_t * const mv_penalty_f = c->mv_penalty[s->c.f_code] + MAX_DMV; // f_code of the prev frame
-    const uint8_t * const mv_penalty_b = c->mv_penalty[s->c.b_code] + MAX_DMV; // f_code of the prev frame
+    const uint8_t * const mv_penalty_f = c->mv_penalty[s->f_code] + MAX_DMV; // f_code of the prev frame
+    const uint8_t * const mv_penalty_b = c->mv_penalty[s->b_code] + MAX_DMV; // f_code of the prev frame
     int stride= c->stride;
     uint8_t *dest_y = c->scratchpad;
     const uint8_t *ptr;
@@ -1526,11 +1526,11 @@ void ff_estimate_b_frame_motion(MPVEncContext *const s,
 
 // FIXME penalty stuff for non-MPEG-4
     c->skip=0;
-    fmin = estimate_motion_b(s, mb_x, mb_y, s->b_forw_mv_table, 0, s->c.f_code) +
+    fmin = estimate_motion_b(s, mb_x, mb_y, s->b_forw_mv_table, 0, s->f_code) +
            3 * c->mb_penalty_factor;
 
     c->skip=0;
-    bmin = estimate_motion_b(s, mb_x, mb_y, s->b_back_mv_table, 2, s->c.b_code) +
+    bmin = estimate_motion_b(s, mb_x, mb_y, s->b_back_mv_table, 2, s->b_code) +
            2 * c->mb_penalty_factor;
     ff_dlog(c->avctx, " %d %d ", s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1]);
 
@@ -1541,11 +1541,11 @@ void ff_estimate_b_frame_motion(MPVEncContext *const s,
     if (c->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) {
 //FIXME mb type penalty
         c->skip=0;
-        c->current_mv_penalty= c->mv_penalty[s->c.f_code] + MAX_DMV;
+        c->current_mv_penalty = c->mv_penalty[s->f_code] + MAX_DMV;
         fimin= interlaced_search(s, 0,
                                  s->b_field_mv_table[0], s->b_field_select_table[0],
                                  s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1], 0);
-        c->current_mv_penalty= c->mv_penalty[s->c.b_code] + MAX_DMV;
+        c->current_mv_penalty = c->mv_penalty[s->b_code] + MAX_DMV;
         bimin= interlaced_search(s, 2,
                                  s->b_field_mv_table[1], s->b_field_select_table[1],
                                  s->b_back_mv_table[xy][0], s->b_back_mv_table[xy][1], 0);
@@ -1661,7 +1661,7 @@ int ff_get_best_fcode(MPVMainEncContext *const m, const int16_t (*mv_table)[2],
 void ff_fix_long_p_mvs(MPVEncContext *const s, int type)
 {
     MotionEstContext *const c = &s->me;
-    const int f_code= s->c.f_code;
+    const int f_code= s->f_code;
     int y, range;
     av_assert0(s->c.pict_type == AV_PICTURE_TYPE_P);
 
diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c
index 8364368fde..b89619312e 100644
--- a/libavcodec/mpeg12enc.c
+++ b/libavcodec/mpeg12enc.c
@@ -358,7 +358,7 @@ static int mpeg1_encode_picture_header(MPVMainEncContext *const m)
         s->c.pict_type == AV_PICTURE_TYPE_B) {
         put_bits(&s->pb, 1, 0);                 /* half pel coordinates */
         if (s->c.codec_id == AV_CODEC_ID_MPEG1VIDEO)
-            put_bits(&s->pb, 3, s->c.f_code);   /* forward_f_code */
+            put_bits(&s->pb, 3, s->f_code);     /* forward_f_code */
         else
             put_bits(&s->pb, 3, 7);             /* forward_f_code */
     }
@@ -367,7 +367,7 @@ static int mpeg1_encode_picture_header(MPVMainEncContext *const m)
     if (s->c.pict_type == AV_PICTURE_TYPE_B) {
         put_bits(&s->pb, 1, 0);                 /* half pel coordinates */
         if (s->c.codec_id == AV_CODEC_ID_MPEG1VIDEO)
-            put_bits(&s->pb, 3, s->c.b_code);   /* backward_f_code */
+            put_bits(&s->pb, 3, s->b_code);     /* backward_f_code */
         else
             put_bits(&s->pb, 3, 7);             /* backward_f_code */
     }
@@ -380,14 +380,14 @@ static int mpeg1_encode_picture_header(MPVMainEncContext *const m)
         put_bits(&s->pb, 4, 8);                 /* pic ext */
         if (s->c.pict_type == AV_PICTURE_TYPE_P ||
             s->c.pict_type == AV_PICTURE_TYPE_B) {
-            put_bits(&s->pb, 4, s->c.f_code);
-            put_bits(&s->pb, 4, s->c.f_code);
+            put_bits(&s->pb, 4, s->f_code);
+            put_bits(&s->pb, 4, s->f_code);
         } else {
             put_bits(&s->pb, 8, 255);
         }
         if (s->c.pict_type == AV_PICTURE_TYPE_B) {
-            put_bits(&s->pb, 4, s->c.b_code);
-            put_bits(&s->pb, 4, s->c.b_code);
+            put_bits(&s->pb, 4, s->b_code);
+            put_bits(&s->pb, 4, s->b_code);
         } else {
             put_bits(&s->pb, 8, 255);
         }
@@ -748,11 +748,11 @@ static av_always_inline void mpeg1_encode_mb_internal(MPVEncContext *const s,
                         // RAL: f_code parameter added
                         mpeg1_encode_motion(s,
                                             motion_x - s->c.last_mv[0][0][0],
-                                            s->c.f_code);
+                                            s->f_code);
                         // RAL: f_code parameter added
                         mpeg1_encode_motion(s,
                                             motion_y - s->c.last_mv[0][0][1],
-                                            s->c.f_code);
+                                            s->f_code);
                         s->mv_bits += get_bits_diff(s);
                     }
                 } else {
@@ -763,11 +763,11 @@ static av_always_inline void mpeg1_encode_mb_internal(MPVEncContext *const s,
                     // RAL: f_code parameter added
                     mpeg1_encode_motion(s,
                                         motion_x - s->c.last_mv[0][0][0],
-                                        s->c.f_code);
+                                        s->f_code);
                     // RAL: f_code parameter added
                     mpeg1_encode_motion(s,
                                         motion_y - s->c.last_mv[0][0][1],
-                                        s->c.f_code);
+                                        s->f_code);
                     s->c.qscale  -= s->dquant;
                     s->mv_bits += get_bits_diff(s);
                 }
@@ -793,10 +793,10 @@ static av_always_inline void mpeg1_encode_mb_internal(MPVEncContext *const s,
                     put_bits(&s->pb, 1, s->c.field_select[0][i]);
                     mpeg1_encode_motion(s,
                                         s->c.mv[0][i][0] - s->c.last_mv[0][i][0],
-                                        s->c.f_code);
+                                        s->f_code);
                     mpeg1_encode_motion(s,
                                         s->c.mv[0][i][1] - (s->c.last_mv[0][i][1] >> 1),
-                                        s->c.f_code);
+                                        s->f_code);
                     s->c.last_mv[0][i][0] = s->c.mv[0][i][0];
                     s->c.last_mv[0][i][1] = 2 * s->c.mv[0][i][1];
                 }
@@ -836,10 +836,10 @@ static av_always_inline void mpeg1_encode_mb_internal(MPVEncContext *const s,
                 if (s->c.mv_dir & MV_DIR_FORWARD) {
                     mpeg1_encode_motion(s,
                                         s->c.mv[0][0][0] - s->c.last_mv[0][0][0],
-                                        s->c.f_code);
+                                        s->f_code);
                     mpeg1_encode_motion(s,
                                         s->c.mv[0][0][1] - s->c.last_mv[0][0][1],
-                                        s->c.f_code);
+                                        s->f_code);
                     s->c.last_mv[0][0][0] =
                     s->c.last_mv[0][1][0] = s->c.mv[0][0][0];
                     s->c.last_mv[0][0][1] =
@@ -848,10 +848,10 @@ static av_always_inline void mpeg1_encode_mb_internal(MPVEncContext *const s,
                 if (s->c.mv_dir & MV_DIR_BACKWARD) {
                     mpeg1_encode_motion(s,
                                         s->c.mv[1][0][0] - s->c.last_mv[1][0][0],
-                                        s->c.b_code);
+                                        s->b_code);
                     mpeg1_encode_motion(s,
                                         s->c.mv[1][0][1] - s->c.last_mv[1][0][1],
-                                        s->c.b_code);
+                                        s->b_code);
                     s->c.last_mv[1][0][0] =
                     s->c.last_mv[1][1][0] = s->c.mv[1][0][0];
                     s->c.last_mv[1][0][1] =
@@ -881,10 +881,10 @@ static av_always_inline void mpeg1_encode_mb_internal(MPVEncContext *const s,
                         put_bits(&s->pb, 1, s->c.field_select[0][i]);
                         mpeg1_encode_motion(s,
                                             s->c.mv[0][i][0] - s->c.last_mv[0][i][0],
-                                            s->c.f_code);
+                                            s->f_code);
                         mpeg1_encode_motion(s,
                                             s->c.mv[0][i][1] - (s->c.last_mv[0][i][1] >> 1),
-                                            s->c.f_code);
+                                            s->f_code);
                         s->c.last_mv[0][i][0] = s->c.mv[0][i][0];
                         s->c.last_mv[0][i][1] = s->c.mv[0][i][1] * 2;
                     }
@@ -894,10 +894,10 @@ static av_always_inline void mpeg1_encode_mb_internal(MPVEncContext *const s,
                         put_bits(&s->pb, 1, s->c.field_select[1][i]);
                         mpeg1_encode_motion(s,
                                             s->c.mv[1][i][0] - s->c.last_mv[1][i][0],
-                                            s->c.b_code);
+                                            s->b_code);
                         mpeg1_encode_motion(s,
                                             s->c.mv[1][i][1] - (s->c.last_mv[1][i][1] >> 1),
-                                            s->c.b_code);
+                                            s->b_code);
                         s->c.last_mv[1][i][0] = s->c.mv[1][i][0];
                         s->c.last_mv[1][i][1] = s->c.mv[1][i][1] * 2;
                     }
diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
index 1954641198..51af95720f 100644
--- a/libavcodec/mpeg4videodec.c
+++ b/libavcodec/mpeg4videodec.c
@@ -421,7 +421,7 @@ static inline int mpeg4_is_resync(Mpeg4DecContext *ctx)
 
             s->gb = gb;
 
-            if (len >= ff_mpeg4_get_video_packet_prefix_length(s->pict_type, s->f_code, s->b_code))
+            if (len >= ff_mpeg4_get_video_packet_prefix_length(s->pict_type, ctx->f_code, ctx->b_code))
                 return mb_num;
         }
     }
@@ -714,7 +714,7 @@ int ff_mpeg4_decode_video_packet_header(Mpeg4DecContext *ctx)
         if (get_bits1(&s->gb))
             break;
 
-    if (len != ff_mpeg4_get_video_packet_prefix_length(s->pict_type, s->f_code, s->b_code)) {
+    if (len != ff_mpeg4_get_video_packet_prefix_length(s->pict_type, ctx->f_code, ctx->b_code)) {
         av_log(s->avctx, AV_LOG_ERROR, "marker does not match f_code\n");
         return AVERROR_INVALIDDATA;
     }
@@ -844,7 +844,7 @@ static inline int get_amv(Mpeg4DecContext *ctx, int n)
 {
     MpegEncContext *s = &ctx->m;
     int x, y, mb_v, sum, dx, dy, shift;
-    int len     = 1 << (s->f_code + 4);
+    int len     = 1 << (ctx->f_code + 4);
     const int a = ctx->sprite_warping_accuracy;
 
     if (s->workaround_bugs & FF_BUG_AMV)
@@ -1117,11 +1117,11 @@ try_again:
 
                         ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y);
                         if (!s->mcsel) {
-                            mx = ff_h263_decode_motion(s, pred_x, s->f_code);
+                            mx = ff_h263_decode_motion(s, pred_x, ctx->f_code);
                             if (mx >= 0xffff)
                                 return AVERROR_INVALIDDATA;
 
-                            my = ff_h263_decode_motion(s, pred_y, s->f_code);
+                            my = ff_h263_decode_motion(s, pred_y, ctx->f_code);
                             if (my >= 0xffff)
                                 return AVERROR_INVALIDDATA;
                             s->cur_pic.mb_type[xy] = MB_TYPE_16x16 |
@@ -1148,11 +1148,11 @@ try_again:
                                                          MB_TYPE_FORWARD_MV;
                         for (i = 0; i < 4; i++) {
                             int16_t *mot_val = ff_h263_pred_motion(s, i, 0, &pred_x, &pred_y);
-                            mx = ff_h263_decode_motion(s, pred_x, s->f_code);
+                            mx = ff_h263_decode_motion(s, pred_x, ctx->f_code);
                             if (mx >= 0xffff)
                                 return AVERROR_INVALIDDATA;
 
-                            my = ff_h263_decode_motion(s, pred_y, s->f_code);
+                            my = ff_h263_decode_motion(s, pred_y, ctx->f_code);
                             if (my >= 0xffff)
                                 return AVERROR_INVALIDDATA;
                             mot_val[0] = mx;
@@ -1792,11 +1792,11 @@ static int mpeg4_decode_mb(MpegEncContext *s, int16_t block[6][64])
                 ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y);
 
                 for (i = 0; i < 2; i++) {
-                    mx = ff_h263_decode_motion(s, pred_x, s->f_code);
+                    mx = ff_h263_decode_motion(s, pred_x, ctx->f_code);
                     if (mx >= 0xffff)
                         return AVERROR_INVALIDDATA;
 
-                    my = ff_h263_decode_motion(s, pred_y / 2, s->f_code);
+                    my = ff_h263_decode_motion(s, pred_y / 2, ctx->f_code);
                     if (my >= 0xffff)
                         return AVERROR_INVALIDDATA;
 
@@ -1808,12 +1808,12 @@ static int mpeg4_decode_mb(MpegEncContext *s, int16_t block[6][64])
                 /* 16x16 motion prediction */
                 s->mv_type = MV_TYPE_16X16;
                 ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y);
-                mx = ff_h263_decode_motion(s, pred_x, s->f_code);
+                mx = ff_h263_decode_motion(s, pred_x, ctx->f_code);
 
                 if (mx >= 0xffff)
                     return AVERROR_INVALIDDATA;
 
-                my = ff_h263_decode_motion(s, pred_y, s->f_code);
+                my = ff_h263_decode_motion(s, pred_y, ctx->f_code);
 
                 if (my >= 0xffff)
                     return AVERROR_INVALIDDATA;
@@ -1825,11 +1825,11 @@ static int mpeg4_decode_mb(MpegEncContext *s, int16_t block[6][64])
             s->mv_type                     = MV_TYPE_8X8;
             for (i = 0; i < 4; i++) {
                 int16_t *mot_val = ff_h263_pred_motion(s, i, 0, &pred_x, &pred_y);
-                mx      = ff_h263_decode_motion(s, pred_x, s->f_code);
+                mx      = ff_h263_decode_motion(s, pred_x, ctx->f_code);
                 if (mx >= 0xffff)
                     return AVERROR_INVALIDDATA;
 
-                my = ff_h263_decode_motion(s, pred_y, s->f_code);
+                my = ff_h263_decode_motion(s, pred_y, ctx->f_code);
                 if (my >= 0xffff)
                     return AVERROR_INVALIDDATA;
                 s->mv[0][i][0] = mx;
@@ -1927,8 +1927,8 @@ static int mpeg4_decode_mb(MpegEncContext *s, int16_t block[6][64])
                 if (HAS_FORWARD_MV(mb_type)) {
                     s->mv_dir = MV_DIR_FORWARD;
 
-                    mx = ff_h263_decode_motion(s, s->last_mv[0][0][0], s->f_code);
-                    my = ff_h263_decode_motion(s, s->last_mv[0][0][1], s->f_code);
+                    mx = ff_h263_decode_motion(s, s->last_mv[0][0][0], ctx->f_code);
+                    my = ff_h263_decode_motion(s, s->last_mv[0][0][1], ctx->f_code);
                     s->last_mv[0][1][0] =
                     s->last_mv[0][0][0] =
                     s->mv[0][0][0]      = mx;
@@ -1940,8 +1940,8 @@ static int mpeg4_decode_mb(MpegEncContext *s, int16_t block[6][64])
                 if (HAS_BACKWARD_MV(mb_type)) {
                     s->mv_dir |= MV_DIR_BACKWARD;
 
-                    mx = ff_h263_decode_motion(s, s->last_mv[1][0][0], s->b_code);
-                    my = ff_h263_decode_motion(s, s->last_mv[1][0][1], s->b_code);
+                    mx = ff_h263_decode_motion(s, s->last_mv[1][0][0], ctx->b_code);
+                    my = ff_h263_decode_motion(s, s->last_mv[1][0][1], ctx->b_code);
                     s->last_mv[1][1][0] =
                     s->last_mv[1][0][0] =
                     s->mv[1][0][0]      = mx;
@@ -1956,8 +1956,8 @@ static int mpeg4_decode_mb(MpegEncContext *s, int16_t block[6][64])
                     s->mv_dir = MV_DIR_FORWARD;
 
                     for (i = 0; i < 2; i++) {
-                        mx = ff_h263_decode_motion(s, s->last_mv[0][i][0], s->f_code);
-                        my = ff_h263_decode_motion(s, s->last_mv[0][i][1] / 2, s->f_code);
+                        mx = ff_h263_decode_motion(s, s->last_mv[0][i][0], ctx->f_code);
+                        my = ff_h263_decode_motion(s, s->last_mv[0][i][1] / 2, ctx->f_code);
                         s->last_mv[0][i][0] =
                         s->mv[0][i][0]      = mx;
                         s->last_mv[0][i][1] = (s->mv[0][i][1] = my) * 2;
@@ -1968,8 +1968,8 @@ static int mpeg4_decode_mb(MpegEncContext *s, int16_t block[6][64])
                     s->mv_dir |= MV_DIR_BACKWARD;
 
                     for (i = 0; i < 2; i++) {
-                        mx = ff_h263_decode_motion(s, s->last_mv[1][i][0], s->b_code);
-                        my = ff_h263_decode_motion(s, s->last_mv[1][i][1] / 2, s->b_code);
+                        mx = ff_h263_decode_motion(s, s->last_mv[1][i][0], ctx->b_code);
+                        my = ff_h263_decode_motion(s, s->last_mv[1][i][1] / 2, ctx->b_code);
                         s->last_mv[1][i][0] =
                         s->mv[1][i][0]      = mx;
                         s->last_mv[1][i][1] = (s->mv[1][i][1] = my) * 2;
@@ -3349,8 +3349,8 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb,
         }
     }
 
-    s->f_code = 1;
-    s->b_code = 1;
+    ctx->f_code = 1;
+    ctx->b_code = 1;
     if (ctx->shape != BIN_ONLY_SHAPE) {
         s->chroma_qscale = s->qscale = get_bits(gb, ctx->quant_precision);
         if (s->qscale == 0) {
@@ -3360,21 +3360,21 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb,
         }
 
         if (s->pict_type != AV_PICTURE_TYPE_I) {
-            s->f_code = get_bits(gb, 3);        /* fcode_for */
-            if (s->f_code == 0) {
+            ctx->f_code = get_bits(gb, 3);        /* fcode_for */
+            if (ctx->f_code == 0) {
                 av_log(s->avctx, AV_LOG_ERROR,
                        "Error, header damaged or not MPEG-4 header (f_code=0)\n");
-                s->f_code = 1;
+                ctx->f_code = 1;
                 return AVERROR_INVALIDDATA;  // makes no sense to continue, as there is nothing left from the image then
             }
         }
 
         if (s->pict_type == AV_PICTURE_TYPE_B) {
-            s->b_code = get_bits(gb, 3);
-            if (s->b_code == 0) {
+            ctx->b_code = get_bits(gb, 3);
+            if (ctx->b_code == 0) {
                 av_log(s->avctx, AV_LOG_ERROR,
                        "Error, header damaged or not MPEG4 header (b_code=0)\n");
-                s->b_code=1;
+                ctx->b_code=1;
                 return AVERROR_INVALIDDATA; // makes no sense to continue, as the MV decoding will break very quickly
             }
         }
@@ -3382,7 +3382,7 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb,
         if (s->avctx->debug & FF_DEBUG_PICT_INFO) {
             av_log(s->avctx, AV_LOG_DEBUG,
                    "qp:%d fc:%d,%d %c size:%d pro:%d alt:%d top:%d %cpel part:%d resync:%d w:%d a:%d rnd:%d vot:%d%s dc:%d ce:%d/%d/%d time:%"PRId64" tincr:%d\n",
-                   s->qscale, s->f_code, s->b_code,
+                   s->qscale, ctx->f_code, ctx->b_code,
                    s->pict_type == AV_PICTURE_TYPE_I ? 'I' : (s->pict_type == AV_PICTURE_TYPE_P ? 'P' : (s->pict_type == AV_PICTURE_TYPE_B ? 'B' : 'S')),
                    gb->size_in_bits,s->progressive_sequence, s->alternate_scan,
                    s->top_field_first, s->quarter_sample ? 'q' : 'h',
diff --git a/libavcodec/mpeg4videodec.h b/libavcodec/mpeg4videodec.h
index 59a7251ce2..57a2f81816 100644
--- a/libavcodec/mpeg4videodec.h
+++ b/libavcodec/mpeg4videodec.h
@@ -34,6 +34,9 @@
 typedef struct Mpeg4DecContext {
     MpegEncContext m;
 
+    int f_code;                 ///< forward MV resolution
+    int b_code;                 ///< backward MV resolution for B-frames
+
     /// number of bits to represent the fractional part of time
     int time_increment_bits;
     int shape;
diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c
index 0998af663f..01d5076547 100644
--- a/libavcodec/mpeg4videoenc.c
+++ b/libavcodec/mpeg4videoenc.c
@@ -589,7 +589,7 @@ static void mpeg4_encode_mb(MPVEncContext *const s, int16_t block[][64],
                         ff_h263_encode_motion_vector(s,
                                                      s->c.mv[0][0][0] - s->c.last_mv[0][0][0],
                                                      s->c.mv[0][0][1] - s->c.last_mv[0][0][1],
-                                                     s->c.f_code);
+                                                     s->f_code);
                         s->c.last_mv[0][0][0] =
                         s->c.last_mv[0][1][0] = s->c.mv[0][0][0];
                         s->c.last_mv[0][0][1] =
@@ -599,7 +599,7 @@ static void mpeg4_encode_mb(MPVEncContext *const s, int16_t block[][64],
                         ff_h263_encode_motion_vector(s,
                                                      s->c.mv[1][0][0] - s->c.last_mv[1][0][0],
                                                      s->c.mv[1][0][1] - s->c.last_mv[1][0][1],
-                                                     s->c.b_code);
+                                                     s->b_code);
                         s->c.last_mv[1][0][0] =
                         s->c.last_mv[1][1][0] = s->c.mv[1][0][0];
                         s->c.last_mv[1][0][1] =
@@ -619,7 +619,7 @@ static void mpeg4_encode_mb(MPVEncContext *const s, int16_t block[][64],
                             ff_h263_encode_motion_vector(s,
                                                          s->c.mv[0][i][0] - s->c.last_mv[0][i][0],
                                                          s->c.mv[0][i][1] - s->c.last_mv[0][i][1] / 2,
-                                                         s->c.f_code);
+                                                         s->f_code);
                             s->c.last_mv[0][i][0] = s->c.mv[0][i][0];
                             s->c.last_mv[0][i][1] = s->c.mv[0][i][1] * 2;
                         }
@@ -629,7 +629,7 @@ static void mpeg4_encode_mb(MPVEncContext *const s, int16_t block[][64],
                             ff_h263_encode_motion_vector(s,
                                                          s->c.mv[1][i][0] - s->c.last_mv[1][i][0],
                                                          s->c.mv[1][i][1] - s->c.last_mv[1][i][1] / 2,
-                                                         s->c.b_code);
+                                                         s->b_code);
                             s->c.last_mv[1][i][0] = s->c.mv[1][i][0];
                             s->c.last_mv[1][i][1] = s->c.mv[1][i][1] * 2;
                         }
@@ -741,7 +741,7 @@ static void mpeg4_encode_mb(MPVEncContext *const s, int16_t block[][64],
                 ff_h263_encode_motion_vector(s,
                                              motion_x - pred_x,
                                              motion_y - pred_y,
-                                             s->c.f_code);
+                                             s->f_code);
             } else if (s->c.mv_type == MV_TYPE_FIELD) {
                 if (s->dquant)
                     cbpc += 8;
@@ -771,11 +771,11 @@ static void mpeg4_encode_mb(MPVEncContext *const s, int16_t block[][64],
                 ff_h263_encode_motion_vector(s,
                                              s->c.mv[0][0][0] - pred_x,
                                              s->c.mv[0][0][1] - pred_y,
-                                             s->c.f_code);
+                                             s->f_code);
                 ff_h263_encode_motion_vector(s,
                                              s->c.mv[0][1][0] - pred_x,
                                              s->c.mv[0][1][1] - pred_y,
-                                             s->c.f_code);
+                                             s->f_code);
             } else {
                 av_assert2(s->c.mv_type == MV_TYPE_8X8);
                 put_bits(&s->pb,
@@ -796,7 +796,7 @@ static void mpeg4_encode_mb(MPVEncContext *const s, int16_t block[][64],
                     ff_h263_encode_motion_vector(s,
                                                  s->c.cur_pic.motion_val[0][s->c.block_index[i]][0] - pred_x,
                                                  s->c.cur_pic.motion_val[0][s->c.block_index[i]][1] - pred_y,
-                                                 s->c.f_code);
+                                                 s->f_code);
                 }
             }
 
@@ -1116,9 +1116,9 @@ static int mpeg4_encode_picture_header(MPVMainEncContext *const m)
     put_bits(&s->pb, 5, s->c.qscale);
 
     if (s->c.pict_type != AV_PICTURE_TYPE_I)
-        put_bits(&s->pb, 3, s->c.f_code);  /* fcode_for */
+        put_bits(&s->pb, 3, s->f_code);  /* fcode_for */
     if (s->c.pict_type == AV_PICTURE_TYPE_B)
-        put_bits(&s->pb, 3, s->c.b_code);  /* fcode_back */
+        put_bits(&s->pb, 3, s->b_code);  /* fcode_back */
 
     return 0;
 }
@@ -1393,7 +1393,7 @@ void ff_mpeg4_encode_video_packet_header(MPVEncContext *const s)
 {
     int mb_num_bits = av_log2(s->c.mb_num - 1) + 1;
 
-    put_bits(&s->pb, ff_mpeg4_get_video_packet_prefix_length(s->c.pict_type, s->c.f_code, s->c.b_code), 0);
+    put_bits(&s->pb, ff_mpeg4_get_video_packet_prefix_length(s->c.pict_type, s->f_code, s->b_code), 0);
     put_bits(&s->pb, 1, 1);
 
     put_bits(&s->pb, mb_num_bits, s->c.mb_x + s->c.mb_y * s->c.mb_width);
diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h
index 2d60c9ddf0..de3ebd5ed2 100644
--- a/libavcodec/mpegvideo.h
+++ b/libavcodec/mpegvideo.h
@@ -179,8 +179,6 @@ typedef struct MpegEncContext {
     QpelDSPContext qdsp;
     VideoDSPContext vdsp;
     H263DSPContext h263dsp;
-    int f_code;                 ///< forward MV resolution
-    int b_code;                 ///< backward MV resolution for B-frames (MPEG-4)
     int16_t (*p_field_mv_table_base)[2];
     int16_t (*p_field_mv_table[2][2])[2];   ///< MV table (2MV per MB) interlaced P-frame encoding
 
diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c
index 02255fdaed..ce9315c1b8 100644
--- a/libavcodec/mpegvideo_enc.c
+++ b/libavcodec/mpegvideo_enc.c
@@ -258,8 +258,8 @@ static void update_duplicate_context_after_me(MPVEncContext *const dst,
 {
 #define COPY(a) dst->a = src->a
     COPY(c.pict_type);
-    COPY(c.f_code);
-    COPY(c.b_code);
+    COPY(f_code);
+    COPY(b_code);
     COPY(c.qscale);
     COPY(lambda);
     COPY(lambda2);
@@ -285,8 +285,8 @@ static av_cold void mpv_encode_defaults(MPVMainEncContext *const m)
 
     ff_mpv_common_defaults(&s->c);
 
-    s->c.f_code = 1;
-    s->c.b_code = 1;
+    s->f_code = 1;
+    s->b_code = 1;
 
     if (!m->fcode_tab) {
         m->fcode_tab = default_fcode_tab + MAX_MV;
@@ -3794,23 +3794,23 @@ static int encode_picture(MPVMainEncContext *const m, const AVPacket *pkt)
 
     if (!s->c.umvplus) {
         if (s->c.pict_type == AV_PICTURE_TYPE_P || s->c.pict_type == AV_PICTURE_TYPE_S) {
-            s->c.f_code = ff_get_best_fcode(m, s->p_mv_table, CANDIDATE_MB_TYPE_INTER);
+            s->f_code = ff_get_best_fcode(m, s->p_mv_table, CANDIDATE_MB_TYPE_INTER);
 
             if (s->c.avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) {
                 int a,b;
                 a = ff_get_best_fcode(m, s->c.p_field_mv_table[0][0], CANDIDATE_MB_TYPE_INTER_I); //FIXME field_select
                 b = ff_get_best_fcode(m, s->c.p_field_mv_table[1][1], CANDIDATE_MB_TYPE_INTER_I);
-                s->c.f_code = FFMAX3(s->c.f_code, a, b);
+                s->f_code = FFMAX3(s->f_code, a, b);
             }
 
             ff_fix_long_p_mvs(s, s->intra_penalty ? CANDIDATE_MB_TYPE_INTER : CANDIDATE_MB_TYPE_INTRA);
-            ff_fix_long_mvs(s, NULL, 0, s->p_mv_table, s->c.f_code, CANDIDATE_MB_TYPE_INTER, !!s->intra_penalty);
+            ff_fix_long_mvs(s, NULL, 0, s->p_mv_table, s->f_code, CANDIDATE_MB_TYPE_INTER, !!s->intra_penalty);
             if (s->c.avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) {
                 int j;
                 for(i=0; i<2; i++){
                     for(j=0; j<2; j++)
                         ff_fix_long_mvs(s, s->p_field_select_table[i], j,
-                                        s->c.p_field_mv_table[i][j], s->c.f_code, CANDIDATE_MB_TYPE_INTER_I, !!s->intra_penalty);
+                                        s->c.p_field_mv_table[i][j], s->f_code, CANDIDATE_MB_TYPE_INTER_I, !!s->intra_penalty);
                 }
             }
         } else if (s->c.pict_type == AV_PICTURE_TYPE_B) {
@@ -3818,16 +3818,16 @@ static int encode_picture(MPVMainEncContext *const m, const AVPacket *pkt)
 
             a = ff_get_best_fcode(m, s->b_forw_mv_table, CANDIDATE_MB_TYPE_FORWARD);
             b = ff_get_best_fcode(m, s->b_bidir_forw_mv_table, CANDIDATE_MB_TYPE_BIDIR);
-            s->c.f_code = FFMAX(a, b);
+            s->f_code = FFMAX(a, b);
 
             a = ff_get_best_fcode(m, s->b_back_mv_table, CANDIDATE_MB_TYPE_BACKWARD);
             b = ff_get_best_fcode(m, s->b_bidir_back_mv_table, CANDIDATE_MB_TYPE_BIDIR);
-            s->c.b_code = FFMAX(a, b);
+            s->b_code = FFMAX(a, b);
 
-            ff_fix_long_mvs(s, NULL, 0, s->b_forw_mv_table, s->c.f_code, CANDIDATE_MB_TYPE_FORWARD, 1);
-            ff_fix_long_mvs(s, NULL, 0, s->b_back_mv_table, s->c.b_code, CANDIDATE_MB_TYPE_BACKWARD, 1);
-            ff_fix_long_mvs(s, NULL, 0, s->b_bidir_forw_mv_table, s->c.f_code, CANDIDATE_MB_TYPE_BIDIR, 1);
-            ff_fix_long_mvs(s, NULL, 0, s->b_bidir_back_mv_table, s->c.b_code, CANDIDATE_MB_TYPE_BIDIR, 1);
+            ff_fix_long_mvs(s, NULL, 0, s->b_forw_mv_table, s->f_code, CANDIDATE_MB_TYPE_FORWARD, 1);
+            ff_fix_long_mvs(s, NULL, 0, s->b_back_mv_table, s->b_code, CANDIDATE_MB_TYPE_BACKWARD, 1);
+            ff_fix_long_mvs(s, NULL, 0, s->b_bidir_forw_mv_table, s->f_code, CANDIDATE_MB_TYPE_BIDIR, 1);
+            ff_fix_long_mvs(s, NULL, 0, s->b_bidir_back_mv_table, s->b_code, CANDIDATE_MB_TYPE_BIDIR, 1);
             if (s->c.avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) {
                 int dir, j;
                 for(dir=0; dir<2; dir++){
@@ -3836,7 +3836,7 @@ static int encode_picture(MPVMainEncContext *const m, const AVPacket *pkt)
                             int type= dir ? (CANDIDATE_MB_TYPE_BACKWARD_I|CANDIDATE_MB_TYPE_BIDIR_I)
                                           : (CANDIDATE_MB_TYPE_FORWARD_I |CANDIDATE_MB_TYPE_BIDIR_I);
                             ff_fix_long_mvs(s, s->b_field_select_table[dir][i], j,
-                                            s->b_field_mv_table[dir][i][j], dir ? s->c.b_code : s->c.f_code, type, 1);
+                                            s->b_field_mv_table[dir][i][j], dir ? s->b_code : s->f_code, type, 1);
                         }
                     }
                 }
diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h
index 787cfef11b..76e3780923 100644
--- a/libavcodec/mpegvideoenc.h
+++ b/libavcodec/mpegvideoenc.h
@@ -74,6 +74,9 @@ typedef struct MPVEncContext {
     PixblockDSPContext pdsp;
     MotionEstContext me;
 
+    int f_code;                 ///< forward MV resolution
+    int b_code;                 ///< backward MV resolution for B-frames
+
     int16_t (*p_mv_table)[2];            ///< MV table (1MV per MB) P-frame
     int16_t (*b_forw_mv_table)[2];       ///< MV table (1MV per MB) forward mode B-frame
     int16_t (*b_back_mv_table)[2];       ///< MV table (1MV per MB) backward mode B-frame
diff --git a/libavcodec/msmpeg4enc.c b/libavcodec/msmpeg4enc.c
index 4b03a7c10b..795db6e4de 100644
--- a/libavcodec/msmpeg4enc.c
+++ b/libavcodec/msmpeg4enc.c
@@ -349,7 +349,7 @@ static void msmpeg4v2_encode_motion(MPVEncContext *const s, int val)
         /* zero vector; corresponds to ff_mvtab[0] */
         put_bits(&s->pb, 1, 0x1);
     } else {
-        bit_size = s->c.f_code - 1;
+        bit_size = s->f_code - 1;
         range = 1 << bit_size;
         if (val <= -64)
             val += 64;
diff --git a/libavcodec/nvdec_mpeg4.c b/libavcodec/nvdec_mpeg4.c
index 14ce352512..7d158321ae 100644
--- a/libavcodec/nvdec_mpeg4.c
+++ b/libavcodec/nvdec_mpeg4.c
@@ -80,8 +80,8 @@ static int nvdec_mpeg4_start_frame(AVCodecContext *avctx,
             .vop_rounding_type            = s->no_rounding,
             .alternate_vertical_scan_flag = s->alternate_scan,
             .interlaced                   = !s->progressive_sequence,
-            .vop_fcode_forward            = s->f_code,
-            .vop_fcode_backward           = s->b_code,
+            .vop_fcode_forward            = m->f_code,
+            .vop_fcode_backward           = m->b_code,
             .trd                          = { s->pp_time, s->pp_field_time >> 1 },
             .trb                          = { s->pb_time, s->pb_field_time >> 1 },
 
diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c
index 13b1fb77df..06d998efcb 100644
--- a/libavcodec/ratecontrol.c
+++ b/libavcodec/ratecontrol.c
@@ -49,8 +49,8 @@ void ff_write_pass1_stats(MPVMainEncContext *const m)
              s->p_tex_bits,
              s->mv_bits,
              s->misc_bits,
-             s->c.f_code,
-             s->c.b_code,
+             s->f_code,
+             s->b_code,
              m->mc_mb_var_sum,
              m->mb_var_sum,
              s->i_count,
@@ -903,8 +903,8 @@ void ff_get_2pass_fcode(MPVMainEncContext *const m)
     const RateControlContext *rcc = &m->rc_context;
     const RateControlEntry   *rce = &rcc->entry[s->c.picture_number];
 
-    s->c.f_code = rce->f_code;
-    s->c.b_code = rce->b_code;
+    s->f_code = rce->f_code;
+    s->b_code = rce->b_code;
 }
 
 // FIXME rd or at least approx for dquant
@@ -997,8 +997,8 @@ float ff_rate_estimate_qscale(MPVMainEncContext *const m, int dry_run)
         rce->mc_mb_var_sum = m->mc_mb_var_sum;
         rce->mb_var_sum    = m->mb_var_sum;
         rce->qscale        = FF_QP2LAMBDA * 2;
-        rce->f_code        = s->c.f_code;
-        rce->b_code        = s->c.b_code;
+        rce->f_code        = s->f_code;
+        rce->b_code        = s->b_code;
         rce->misc_bits     = 1;
 
         bits = predict_size(&rcc->pred[pict_type], rce->qscale, sqrt(var));
diff --git a/libavcodec/rv20enc.c b/libavcodec/rv20enc.c
index 3211700f76..ce0d435dcb 100644
--- a/libavcodec/rv20enc.c
+++ b/libavcodec/rv20enc.c
@@ -48,7 +48,7 @@ int ff_rv20_encode_picture_header(MPVMainEncContext *const m)
 
     put_bits(&s->pb, 1, s->c.no_rounding);
 
-    av_assert0(s->c.f_code == 1);
+    av_assert0(s->f_code == 1);
     av_assert0(!s->c.unrestricted_mv);
     av_assert0(!s->c.alt_inter_vlc);
     av_assert0(!s->c.umvplus);
diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c
index 8e7712fe5f..661c6b3c07 100644
--- a/libavcodec/snowenc.c
+++ b/libavcodec/snowenc.c
@@ -445,7 +445,7 @@ static int encode_q_branch(SnowEncContext *enc, int level, int x, int y)
     c->penalty_factor    = get_penalty_factor(enc->lambda, enc->lambda2, c->avctx->me_cmp);
     c->sub_penalty_factor= get_penalty_factor(enc->lambda, enc->lambda2, c->avctx->me_sub_cmp);
     c->mb_penalty_factor = get_penalty_factor(enc->lambda, enc->lambda2, c->avctx->mb_cmp);
-    c->current_mv_penalty = c->mv_penalty[enc->m.s.c.f_code=1] + MAX_DMV;
+    c->current_mv_penalty = c->mv_penalty[enc->m.s.f_code=1] + MAX_DMV;
 
     c->xmin = - x*block_w - 16+3;
     c->ymin = - y*block_w - 16+3;
@@ -1863,7 +1863,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
         mpv->c.mb_height  = block_height;
         mpv->c.mb_stride  =     mpv->c.mb_width + 1;
         mpv->c.b8_stride  = 2 * mpv->c.mb_width + 1;
-        mpv->c.f_code     = 1;
+        mpv->f_code       = 1;
         mpv->c.pict_type  = pic->pict_type;
         mpv->me.motion_est = enc->motion_est;
         mpv->me.dia_size = avctx->dia_size;
diff --git a/libavcodec/svq1enc.c b/libavcodec/svq1enc.c
index 0a92c5607c..c1662da5ec 100644
--- a/libavcodec/svq1enc.c
+++ b/libavcodec/svq1enc.c
@@ -337,7 +337,7 @@ static int svq1_encode_plane(SVQ1EncContext *s, int plane,
         s2->mb_height                     = block_height;
         s2->mb_stride                     = s2->mb_width + 1;
         s2->b8_stride                     = 2 * s2->mb_width + 1;
-        s2->f_code                        = 1;
+        s->m.f_code                       = 1;
         s2->pict_type                     = s->pict_type;
         s->m.me.scene_change_score        = 0;
         // s2->out_format                    = FMT_H263;
@@ -400,7 +400,7 @@ static int svq1_encode_plane(SVQ1EncContext *s, int plane,
         }
 
         ff_fix_long_p_mvs(&s->m, CANDIDATE_MB_TYPE_INTRA);
-        ff_fix_long_mvs(&s->m, NULL, 0, s->m.p_mv_table, s2->f_code,
+        ff_fix_long_mvs(&s->m, NULL, 0, s->m.p_mv_table, s->m.f_code,
                         CANDIDATE_MB_TYPE_INTER, 0);
     }
 
diff --git a/libavcodec/vaapi_mpeg4.c b/libavcodec/vaapi_mpeg4.c
index 12bc9bc86a..8338c0732d 100644
--- a/libavcodec/vaapi_mpeg4.c
+++ b/libavcodec/vaapi_mpeg4.c
@@ -87,8 +87,8 @@ static int vaapi_mpeg4_start_frame(AVCodecContext *avctx,
             .top_field_first              = s->top_field_first,
             .alternate_vertical_scan_flag = s->alternate_scan,
         },
-        .vop_fcode_forward                = s->f_code,
-        .vop_fcode_backward               = s->b_code,
+        .vop_fcode_forward                = ctx->f_code,
+        .vop_fcode_backward               = ctx->b_code,
         .vop_time_increment_resolution    = avctx->framerate.num,
         .num_macroblocks_in_gob           = s->mb_width * H263_GOB_HEIGHT(s->height),
         .num_gobs_in_vop                  =
diff --git a/libavcodec/vdpau_mpeg4.c b/libavcodec/vdpau_mpeg4.c
index 24ae10b3c3..91981935f5 100644
--- a/libavcodec/vdpau_mpeg4.c
+++ b/libavcodec/vdpau_mpeg4.c
@@ -64,8 +64,8 @@ static int vdpau_mpeg4_start_frame(AVCodecContext *avctx,
     info->trd[1]                            = s->pp_field_time >> 1;
     info->trb[1]                            = s->pb_field_time >> 1;
     info->vop_time_increment_resolution     = s->avctx->framerate.num;
-    info->vop_fcode_forward                 = s->f_code;
-    info->vop_fcode_backward                = s->b_code;
+    info->vop_fcode_forward                 = ctx->f_code;
+    info->vop_fcode_backward                = ctx->b_code;
     info->resync_marker_disable             = !ctx->resync_marker;
     info->interlaced                        = !s->progressive_sequence;
     info->quant_type                        = s->mpeg_quant;
-- 
2.45.2


[-- Attachment #11: 0010-avcodec-mpegvideo_dec-Add-ff_mpv_decode_reinit.patch --]
[-- Type: text/x-patch, Size: 2178 bytes --]

From 23b72a64cc044216380b0f815ef5b752aceb63ed Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 25 Mar 2025 05:56:33 +0100
Subject: [PATCH 10/44] avcodec/mpegvideo_dec: Add ff_mpv_decode_reinit()

The rationale for adding ff_mpv_common_frame_size_change()
instead of a simple ff_mpv_common_end()+ff_mpv_common_init()
was that it would avoid freeing the "Picture" array and the
AVFrames contained in it. Yet this is obsolete because said
array no longer exists since 9ce56f91c0e74b7cc34985fdb15050aa98aeded6.

This commit therefore adds a simple end+init function
designed to replace ff_mpv_common_frame_size_change()
and also ff_mpv_common_init() for decoders. It also calls
ff_set_dimensions(), so that it does not allow 0x0 dimensions.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpegvideo_dec.c | 13 +++++++++++++
 libavcodec/mpegvideodec.h  |  5 +++++
 2 files changed, 18 insertions(+)

diff --git a/libavcodec/mpegvideo_dec.c b/libavcodec/mpegvideo_dec.c
index 4019b4f0da..089c50dcca 100644
--- a/libavcodec/mpegvideo_dec.c
+++ b/libavcodec/mpegvideo_dec.c
@@ -142,6 +142,19 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst,
     return 0;
 }
 
+av_cold int ff_mpv_decode_reinit(MpegEncContext *const s)
+{
+    int ret;
+
+    if (s->context_initialized)
+        ff_mpv_common_end(s);
+
+    ret = ff_set_dimensions(s->avctx, s->width, s->height);
+    if (ret < 0)
+        return ret;
+    return ff_mpv_common_init(s);
+}
+
 av_cold int ff_mpv_decode_close(AVCodecContext *avctx)
 {
     MpegEncContext *s = avctx->priv_data;
diff --git a/libavcodec/mpegvideodec.h b/libavcodec/mpegvideodec.h
index 6100364715..19b9587600 100644
--- a/libavcodec/mpegvideodec.h
+++ b/libavcodec/mpegvideodec.h
@@ -48,6 +48,11 @@
  * Also initialize the picture pool.
  */
 int ff_mpv_decode_init(MpegEncContext *s, AVCodecContext *avctx);
+/**
+ * Close the MpegEncContext (if initialized) and initialize it for decoding.
+ * Also set the AVCodecContext's dimensions.
+ */
+int ff_mpv_decode_reinit(MpegEncContext *s);
 
 int ff_mpv_common_frame_size_change(MpegEncContext *s);
 
-- 
2.45.2


[-- Attachment #12: 0011-avcodec-h261dec-Use-ff_mpv_decode_reinit.patch --]
[-- Type: text/x-patch, Size: 1366 bytes --]

From e31dc4f234326f711a486a7f73611ff9d1bafd21 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 25 Mar 2025 06:09:50 +0100
Subject: [PATCH 11/44] avcodec/h261dec: Use ff_mpv_decode_reinit()

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/h261dec.c | 13 +++----------
 1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/libavcodec/h261dec.c b/libavcodec/h261dec.c
index 146f979a5e..853a94a25a 100644
--- a/libavcodec/h261dec.c
+++ b/libavcodec/h261dec.c
@@ -28,7 +28,6 @@
 #include "libavutil/thread.h"
 #include "avcodec.h"
 #include "codec_internal.h"
-#include "decode.h"
 #include "mpeg_er.h"
 #include "mpegutils.h"
 #include "mpegvideo.h"
@@ -562,15 +561,9 @@ static int h261_decode_frame(AVCodecContext *avctx, AVFrame *pict,
         return -1;
     }
 
-    if (s->width != avctx->coded_width || s->height != avctx->coded_height) {
-        ff_mpv_common_end(s);
-    }
-
-    if (!s->context_initialized) {
-        if ((ret = ff_mpv_common_init(s)) < 0)
-            return ret;
-
-        ret = ff_set_dimensions(avctx, s->width, s->height);
+    if (s->width != avctx->coded_width || s->height != avctx->coded_height ||
+        !s->context_initialized) {
+        ret = ff_mpv_decode_reinit(s);
         if (ret < 0)
             return ret;
     }
-- 
2.45.2


[-- Attachment #13: 0012-avcodec-vc1dec-Use-ff_mpv_decode_reinit.patch --]
[-- Type: text/x-patch, Size: 1479 bytes --]

From 5e1456f2e11672f25f83d5bab7a989866ee40c48 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 25 Mar 2025 06:15:46 +0100
Subject: [PATCH 12/44] avcodec/vc1dec: Use ff_mpv_decode_reinit()

Given that it is stricter wrt invalid dimensions
we can avoid checking the dimensions manually here.
(Notice that due to the ff_mpv_decode_init()
call before ff_mpv_common_init() the MpegEncContext
and AVCodecContext dimensions already coincide.)

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/vc1dec.c | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c
index 7ee014d4b6..b9da1b25dc 100644
--- a/libavcodec/vc1dec.c
+++ b/libavcodec/vc1dec.c
@@ -47,7 +47,6 @@
 #include "vc1_vlc_data.h"
 #include "libavutil/attributes.h"
 #include "libavutil/avassert.h"
-#include "libavutil/imgutils.h"
 #include "libavutil/mem.h"
 #include "libavutil/thread.h"
 
@@ -456,17 +455,13 @@ av_cold int ff_vc1_decode_init(AVCodecContext *avctx)
     MpegEncContext *const s = &v->s;
     int ret;
 
-    ret = av_image_check_size(avctx->width, avctx->height, 0, avctx);
-    if (ret < 0)
-        return ret;
-
     ret = ff_mpv_decode_init(s, avctx);
     if (ret < 0)
         return ret;
 
     avctx->pix_fmt = vc1_get_format(avctx);
 
-    ret = ff_mpv_common_init(s);
+    ret = ff_mpv_decode_reinit(s);
     if (ret < 0)
         return ret;
 
-- 
2.45.2


[-- Attachment #14: 0013-avcodec-rv10-Use-ff_mpv_decode_reinit.patch --]
[-- Type: text/x-patch, Size: 1717 bytes --]

From 8685c1ae10130f46773382459f6b5850ef891e3d Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 25 Mar 2025 06:26:12 +0100
Subject: [PATCH 13/44] avcodec/rv10: Use ff_mpv_decode_reinit()

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/rv10.c | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/libavcodec/rv10.c b/libavcodec/rv10.c
index 482af8e52a..4431bff929 100644
--- a/libavcodec/rv10.c
+++ b/libavcodec/rv10.c
@@ -32,7 +32,6 @@
 
 #include "avcodec.h"
 #include "codec_internal.h"
-#include "decode.h"
 #include "error_resilience.h"
 #include "h263.h"
 #include "h263data.h"
@@ -222,8 +221,6 @@ static int rv20_decode_picture_header(RVDecContext *rv, int whole_size)
             if (whole_size < (new_w + 15)/16 * ((new_h + 15)/16) / 8)
                 return AVERROR_INVALIDDATA;
 
-            ff_mpv_common_end(s);
-
             // attempt to keep aspect during typical resolution switches
             if (!old_aspect.num)
                 old_aspect = (AVRational){1, 1};
@@ -232,13 +229,10 @@ static int rv20_decode_picture_header(RVDecContext *rv, int whole_size)
             if ((int64_t)new_w * s->height == 2 * (int64_t)new_h * s->width)
                 s->avctx->sample_aspect_ratio = av_mul_q(old_aspect, (AVRational){1, 2});
 
-            ret = ff_set_dimensions(s->avctx, new_w, new_h);
-            if (ret < 0)
-                return ret;
-
             s->width  = new_w;
             s->height = new_h;
-            if ((ret = ff_mpv_common_init(s)) < 0)
+            ret = ff_mpv_decode_reinit(s);
+            if (ret < 0)
                 return ret;
         }
 
-- 
2.45.2


[-- Attachment #15: 0014-avcodec-mpeg12dec-Use-ff_mpv_decode_reinit.patch --]
[-- Type: text/x-patch, Size: 3098 bytes --]

From a4eb056f7ec28fa3a86038879678a283262ade3b Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 25 Mar 2025 06:34:33 +0100
Subject: [PATCH 14/44] avcodec/mpeg12dec: Use ff_mpv_decode_reinit()

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpeg12dec.c | 26 ++++++++++----------------
 1 file changed, 10 insertions(+), 16 deletions(-)

diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
index 609af30523..9297c65029 100644
--- a/libavcodec/mpeg12dec.c
+++ b/libavcodec/mpeg12dec.c
@@ -944,13 +944,6 @@ static int mpeg_decode_postinit(AVCodecContext *avctx)
         av_cmp_q(s1->save_aspect, s->avctx->sample_aspect_ratio) ||
         (s1->save_progressive_seq != s->progressive_sequence && FFALIGN(s->height, 16) != FFALIGN(s->height, 32)) ||
         0) {
-        if (s->context_initialized)
-            ff_mpv_common_end(s);
-
-        ret = ff_set_dimensions(avctx, s->width, s->height);
-        if (ret < 0)
-            return ret;
-
         if (avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO && s1->bit_rate &&
             (s1->bit_rate != 0x3FFFF*400)) {
             avctx->rc_max_rate = s1->bit_rate;
@@ -958,10 +951,6 @@ static int mpeg_decode_postinit(AVCodecContext *avctx)
                    (s1->bit_rate != 0x3FFFF*400 || s1->vbv_delay != 0xFFFF)) {
             avctx->bit_rate = s1->bit_rate;
         }
-        s1->save_aspect          = s->avctx->sample_aspect_ratio;
-        s1->save_width           = s->width;
-        s1->save_height          = s->height;
-        s1->save_progressive_seq = s->progressive_sequence;
 
         /* low_delay may be forced, in this case we will have B-frames
          * that behave like P-frames. */
@@ -989,8 +978,15 @@ static int mpeg_decode_postinit(AVCodecContext *avctx)
 
         avctx->pix_fmt = mpeg_get_pixelformat(avctx);
 
-        if ((ret = ff_mpv_common_init(s)) < 0)
+        ret = ff_mpv_decode_reinit(s);
+        if (ret < 0)
             return ret;
+
+        s1->save_aspect          = s->avctx->sample_aspect_ratio;
+        s1->save_width           = s->width;
+        s1->save_height          = s->height;
+        s1->save_progressive_seq = s->progressive_sequence;
+
         if (!s->avctx->lowres)
             for (int i = 0; i < s->slice_context_count; i++)
                 ff_mpv_framesize_disable(&s->thread_context[i]->sc);
@@ -1853,9 +1849,6 @@ static int vcr2_init_sequence(AVCodecContext *avctx)
     int i, v, ret;
 
     /* start new MPEG-1 context decoding */
-    if (s->context_initialized)
-        ff_mpv_common_end(s);
-
     s->width            = avctx->coded_width;
     s->height           = avctx->coded_height;
     avctx->has_b_frames = 0; // true?
@@ -1863,7 +1856,8 @@ static int vcr2_init_sequence(AVCodecContext *avctx)
 
     avctx->pix_fmt = mpeg_get_pixelformat(avctx);
 
-    if ((ret = ff_mpv_common_init(s)) < 0)
+    ret = ff_mpv_decode_reinit(s);
+    if (ret < 0)
         return ret;
     if (!s->avctx->lowres)
         for (int i = 0; i < s->slice_context_count; i++)
-- 
2.45.2


[-- Attachment #16: 0015-avcodec-ituh263dec-Fix-indentation.patch --]
[-- Type: text/x-patch, Size: 2285 bytes --]

From ad26dd843a300f2423fe440e3804e5985d50b8df Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 25 Mar 2025 07:29:55 +0100
Subject: [PATCH 15/44] avcodec/ituh263dec: Fix indentation

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/ituh263dec.c | 29 ++++++++++++++---------------
 1 file changed, 14 insertions(+), 15 deletions(-)

diff --git a/libavcodec/ituh263dec.c b/libavcodec/ituh263dec.c
index 6c9c2583e3..d19bdc4dab 100644
--- a/libavcodec/ituh263dec.c
+++ b/libavcodec/ituh263dec.c
@@ -554,25 +554,24 @@ static int h263_decode_block(MpegEncContext * s, int16_t * block,
     } else if (s->mb_intra) {
         /* DC coef */
         if (CONFIG_RV10_DECODER && s->codec_id == AV_CODEC_ID_RV10) {
-          if (s->rv10_version == 3 && s->pict_type == AV_PICTURE_TYPE_I) {
-            int component, diff;
-            component = (n <= 3 ? 0 : n - 4 + 1);
-            level = s->last_dc[component];
-            if (s->rv10_first_dc_coded[component]) {
-                diff = ff_rv_decode_dc(s, n);
-                if (diff < 0)
-                    return -1;
-                level += diff;
-                level = level & 0xff; /* handle wrap round */
-                s->last_dc[component] = level;
+            if (s->rv10_version == 3 && s->pict_type == AV_PICTURE_TYPE_I) {
+                int component = (n <= 3 ? 0 : n - 4 + 1);
+                level = s->last_dc[component];
+                if (s->rv10_first_dc_coded[component]) {
+                    int diff = ff_rv_decode_dc(s, n);
+                    if (diff < 0)
+                        return -1;
+                    level += diff;
+                    level = level & 0xff; /* handle wrap round */
+                    s->last_dc[component] = level;
+                } else {
+                    s->rv10_first_dc_coded[component] = 1;
+                }
             } else {
-                s->rv10_first_dc_coded[component] = 1;
-            }
-          } else {
                 level = get_bits(&s->gb, 8);
                 if (level == 255)
                     level = 128;
-          }
+            }
         }else{
             level = get_bits(&s->gb, 8);
             if((level&0x7F) == 0){
-- 
2.45.2


[-- Attachment #17: 0016-avcodec-h263dec-Defer-initializing-FLV-H263I-context.patch --]
[-- Type: text/x-patch, Size: 3102 bytes --]

From 6efa820818470d33d32899f24c9924f2deac872c Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 25 Mar 2025 07:31:22 +0100
Subject: [PATCH 16/44] avcodec/h263dec: Defer initializing FLV, H263I contexts

These codec's frame headers can contain new dimensions,
so defer initializing the MpegEncContext and rely on the
existing check for uninitialized MpegEncContexts
in ff_h263_decode_frame().

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/h263dec.c | 24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c
index fd1e36b68a..19029e8d97 100644
--- a/libavcodec/h263dec.c
+++ b/libavcodec/h263dec.c
@@ -92,6 +92,7 @@ av_cold int ff_h263_decode_init(AVCodecContext *avctx)
 {
     MpegEncContext *s = avctx->priv_data;
     MPVUnquantDSPContext unquant_dsp_ctx;
+    int init_now = 0;
     int ret;
 
     s->out_format      = FMT_H263;
@@ -125,26 +126,33 @@ av_cold int ff_h263_decode_init(AVCodecContext *avctx)
     case AV_CODEC_ID_MSMPEG4V1:
         s->h263_pred       = 1;
         s->msmpeg4_version = MSMP4_V1;
+        init_now           = 1;
         break;
     case AV_CODEC_ID_MSMPEG4V2:
         s->h263_pred       = 1;
         s->msmpeg4_version = MSMP4_V2;
+        init_now           = 1;
         break;
     case AV_CODEC_ID_MSMPEG4V3:
         s->h263_pred       = 1;
         s->msmpeg4_version = MSMP4_V3;
+        init_now           = 1;
         break;
     case AV_CODEC_ID_WMV1:
         s->h263_pred       = 1;
         s->msmpeg4_version = MSMP4_WMV1;
+        init_now           = 1;
         break;
     case AV_CODEC_ID_WMV2:
         s->h263_pred       = 1;
         s->msmpeg4_version = MSMP4_WMV2;
+        init_now           = 1;
         break;
-    case AV_CODEC_ID_H263I:
     case AV_CODEC_ID_RV10:
     case AV_CODEC_ID_RV20:
+        init_now           = 1;
+        break;
+    case AV_CODEC_ID_H263I:
         break;
     case AV_CODEC_ID_FLV1:
         s->h263_flv = 1;
@@ -155,19 +163,17 @@ av_cold int ff_h263_decode_init(AVCodecContext *avctx)
         return AVERROR(ENOSYS);
     }
 
-    if (avctx->codec_tag == AV_RL32("L263") || avctx->codec_tag == AV_RL32("S263"))
-        if (avctx->extradata_size == 56 && avctx->extradata[0] == 1)
-            s->ehc_mode = 1;
-
-    /* for H.263, we allocate the images after having read the header */
-    if (avctx->codec->id != AV_CODEC_ID_H263 &&
-        avctx->codec->id != AV_CODEC_ID_H263P &&
-        avctx->codec->id != AV_CODEC_ID_MPEG4) {
+    /* Defer initializing the context for codecs with in-band dimensions. */
+    if (init_now) {
         avctx->pix_fmt = h263_get_format(avctx);
         if ((ret = ff_mpv_common_init(s)) < 0)
             return ret;
     }
 
+    if (avctx->codec_tag == AV_RL32("L263") || avctx->codec_tag == AV_RL32("S263"))
+        if (avctx->extradata_size == 56 && avctx->extradata[0] == 1)
+            s->ehc_mode = 1;
+
     ff_h263dsp_init(&s->h263dsp);
     ff_h263_decode_init_vlc();
 
-- 
2.45.2


[-- Attachment #18: 0017-avcodec-h263dec-Simplify-setting-pix_fmt.patch --]
[-- Type: text/x-patch, Size: 1265 bytes --]

From 940b56a5c68bb9bb888f352b19ba68f1a92db52b Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 25 Mar 2025 07:39:26 +0100
Subject: [PATCH 17/44] avcodec/h263dec: Simplify setting pix_fmt

There is no reason to check AVCodecContext.bits_per_raw_sample
here, as h263_get_format() does implicitly.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/h263dec.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c
index 19029e8d97..28e1cc2101 100644
--- a/libavcodec/h263dec.c
+++ b/libavcodec/h263dec.c
@@ -165,7 +165,13 @@ av_cold int ff_h263_decode_init(AVCodecContext *avctx)
 
     /* Defer initializing the context for codecs with in-band dimensions. */
     if (init_now) {
-        avctx->pix_fmt = h263_get_format(avctx);
+        if (CONFIG_GRAY && (avctx->flags & AV_CODEC_FLAG_GRAY)) {
+            if (avctx->color_range == AVCOL_RANGE_UNSPECIFIED)
+                avctx->color_range = AVCOL_RANGE_MPEG;
+            avctx->pix_fmt = AV_PIX_FMT_GRAY8;
+        } else
+            avctx->pix_fmt = AV_PIX_FMT_YUV420P;
+
         if ((ret = ff_mpv_common_init(s)) < 0)
             return ret;
     }
-- 
2.45.2


[-- Attachment #19: 0018-avcodec-h263dec-Don-t-overwrite-pix_fmt-prematurely.patch --]
[-- Type: text/x-patch, Size: 1309 bytes --]

From c551a2c62e173195598c7cbc54c182ec52b843ef Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 25 Mar 2025 07:44:24 +0100
Subject: [PATCH 18/44] avcodec/h263dec: Don't overwrite pix_fmt prematurely

h263_get_format() did this (on one exit of the function):

return avctx->pix_fmt = ff_get_format();

and ff_h263_decode_frame() calls it as follows:

if (avctx->pix_fmt != h263_get_format(avctx))

It is not defined whether avctx->pix_fmt on the left
is the old or the new value. Fix this by removing
the assignment from h263_get_format().

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/h263dec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c
index 28e1cc2101..189016e143 100644
--- a/libavcodec/h263dec.c
+++ b/libavcodec/h263dec.c
@@ -83,7 +83,7 @@ static enum AVPixelFormat h263_get_format(AVCodecContext *avctx)
     if (avctx->codec_id == AV_CODEC_ID_H263  ||
         avctx->codec_id == AV_CODEC_ID_H263P ||
         avctx->codec_id == AV_CODEC_ID_MPEG4)
-        return avctx->pix_fmt = ff_get_format(avctx, h263_hwaccel_pixfmt_list_420);
+        return ff_get_format(avctx, h263_hwaccel_pixfmt_list_420);
 
     return AV_PIX_FMT_YUV420P;
 }
-- 
2.45.2


[-- Attachment #20: 0019-avcodec-h263dec-Use-ff_mpv_decode_reinit.patch --]
[-- Type: text/x-patch, Size: 2380 bytes --]

From c79114346417fab1c09c3ca6d61fafae86aa3f0e Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 25 Mar 2025 08:19:22 +0100
Subject: [PATCH 19/44] avcodec/h263dec: Use ff_mpv_decode_reinit()

It allows to combine the uninitialized case (for which
ff_mpv_common_init() was called) and the frame size change
case.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/h263dec.c | 24 +++++-------------------
 1 file changed, 5 insertions(+), 19 deletions(-)

diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c
index 189016e143..cbcd719859 100644
--- a/libavcodec/h263dec.c
+++ b/libavcodec/h263dec.c
@@ -172,7 +172,8 @@ av_cold int ff_h263_decode_init(AVCodecContext *avctx)
         } else
             avctx->pix_fmt = AV_PIX_FMT_YUV420P;
 
-        if ((ret = ff_mpv_common_init(s)) < 0)
+        ret = ff_mpv_decode_reinit(s);
+        if (ret < 0)
             return ret;
     }
 
@@ -505,12 +506,6 @@ int ff_h263_decode_frame(AVCodecContext *avctx, AVFrame *pict,
         return ret;
     }
 
-    if (!s->context_initialized) {
-        avctx->pix_fmt = h263_get_format(avctx);
-        if ((ret = ff_mpv_common_init(s)) < 0)
-            return ret;
-    }
-
     avctx->has_b_frames = !s->low_delay;
 
     if (CONFIG_MPEG4_DECODER && avctx->codec_id == AV_CODEC_ID_MPEG4) {
@@ -527,24 +522,15 @@ int ff_h263_decode_frame(AVCodecContext *avctx, AVFrame *pict,
      * an H263EncContext */
     if (s->width  != avctx->coded_width  ||
         s->height != avctx->coded_height ||
-        s->context_reinit) {
+        s->context_reinit || !s->context_initialized) {
         /* H.263 could change picture size any time */
         s->context_reinit = 0;
-
-        ret = ff_set_dimensions(avctx, s->width, s->height);
+        avctx->pix_fmt = h263_get_format(avctx);
+        ret = ff_mpv_decode_reinit(s);
         if (ret < 0)
             return ret;
 
         ff_set_sar(avctx, avctx->sample_aspect_ratio);
-
-        if ((ret = ff_mpv_common_frame_size_change(s)))
-            return ret;
-
-        if (avctx->pix_fmt != h263_get_format(avctx)) {
-            av_log(avctx, AV_LOG_ERROR, "format change not supported\n");
-            avctx->pix_fmt = AV_PIX_FMT_NONE;
-            return AVERROR_UNKNOWN;
-        }
     }
 
     if (s->codec_id == AV_CODEC_ID_H263  ||
-- 
2.45.2


[-- Attachment #21: 0020-avcodec-mpegvideo_dec-Notify-users-of-reinit.patch --]
[-- Type: text/x-patch, Size: 2768 bytes --]

From 130b7d34ab4652e140c240e63355bad0a09bcd64 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 25 Mar 2025 09:08:50 +0100
Subject: [PATCH 20/44] avcodec/mpegvideo_dec: Notify users of reinit

Namely of reinititialization performed by
ff_mpeg_update_thread_context(), so that they can simply
update their own dimension-based buffers accordingly.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpegvideo_dec.c | 6 ++++--
 libavcodec/mpegvideodec.h  | 9 +++++++++
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/libavcodec/mpegvideo_dec.c b/libavcodec/mpegvideo_dec.c
index 089c50dcca..5e445d0d83 100644
--- a/libavcodec/mpegvideo_dec.c
+++ b/libavcodec/mpegvideo_dec.c
@@ -80,7 +80,7 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst,
 {
     MpegEncContext *const s1 = src->priv_data;
     MpegEncContext *const s  = dst->priv_data;
-    int ret;
+    int ret = 0;
 
     if (dst == src)
         return 0;
@@ -102,6 +102,7 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst,
         if (s1->context_initialized) {
             if ((err = ff_mpv_common_init(s)) < 0)
                 return err;
+            ret = 1;
         }
     }
 
@@ -110,6 +111,7 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst,
         s->width  = s1->width;
         if ((ret = ff_mpv_common_frame_size_change(s)) < 0)
             return ret;
+        ret = 1;
     }
 
     s->quarter_sample       = s1->quarter_sample;
@@ -139,7 +141,7 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst,
     memcpy(&s->progressive_sequence, &s1->progressive_sequence,
            (char *) &s1->first_field + sizeof(s1->first_field) - (char *) &s1->progressive_sequence);
 
-    return 0;
+    return ret;
 }
 
 av_cold int ff_mpv_decode_reinit(MpegEncContext *const s)
diff --git a/libavcodec/mpegvideodec.h b/libavcodec/mpegvideodec.h
index 19b9587600..ef6e657c0b 100644
--- a/libavcodec/mpegvideodec.h
+++ b/libavcodec/mpegvideodec.h
@@ -67,6 +67,15 @@ void ff_mpv_frame_end(MpegEncContext *s);
 
 int ff_mpv_export_qp_table(const MpegEncContext *s, AVFrame *f,
                            const MPVPicture *p, int qp_type);
+/**
+ * update_thread_context for mpegvideo-based decoders. It updates
+ * the MPVPictures and generic stream-level parameters. If necessary
+ * (on dimension changes), it also performs reinitialization.
+ *
+ * @retval 1 if a reinitialization happened
+ * @retval 0 on success if no reinitialization happened
+ * @retval "<0" error code
+ */
 int ff_mpeg_update_thread_context(AVCodecContext *dst, const AVCodecContext *src);
 void ff_mpeg_draw_horiz_band(MpegEncContext *s, int y, int h);
 void ff_mpeg_flush(AVCodecContext *avctx);
-- 
2.45.2


[-- Attachment #22: 0021-avcodec-rv34-Simplify-updating-thread-context.patch --]
[-- Type: text/x-patch, Size: 2189 bytes --]

From 402db1f0dc7e28784a2e8e3a4768c4a94fd2cfd5 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 25 Mar 2025 09:32:59 +0100
Subject: [PATCH 21/44] avcodec/rv34: Simplify updating thread context

Call ff_mpeg_update_thread_context() first and
update the RV34 buffers if it indicates a reinitialization.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/rv34.c | 27 ++++++++++++---------------
 1 file changed, 12 insertions(+), 15 deletions(-)

diff --git a/libavcodec/rv34.c b/libavcodec/rv34.c
index ddc95c3a78..5dcbe9a222 100644
--- a/libavcodec/rv34.c
+++ b/libavcodec/rv34.c
@@ -1538,19 +1538,21 @@ av_cold int ff_rv34_decode_init(AVCodecContext *avctx)
 int ff_rv34_decode_update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
 {
     RV34DecContext *r = dst->priv_data, *r1 = src->priv_data;
-    MpegEncContext * const s = &r->s, * const s1 = &r1->s;
-    int err;
+    MpegEncContext *const s1 = &r1->s;
+    int ret;
 
     if (dst == src || !s1->context_initialized)
         return 0;
 
-    if (s->height != s1->height || s->width != s1->width || s->context_reinit) {
-        s->height = s1->height;
-        s->width  = s1->width;
-        if ((err = ff_mpv_common_frame_size_change(s)) < 0)
-            return err;
-        if ((err = rv34_decoder_realloc(r)) < 0)
-            return err;
+    ret = ff_mpeg_update_thread_context(dst, src);
+    if (ret < 0)
+        return ret;
+
+    // Did ff_mpeg_update_thread_context reinit?
+    if (ret > 0) {
+        ret = rv34_decoder_realloc(r);
+        if (ret < 0)
+            return ret;
     }
 
     r->cur_pts  = r1->cur_pts;
@@ -1559,12 +1561,7 @@ int ff_rv34_decode_update_thread_context(AVCodecContext *dst, const AVCodecConte
 
     memset(&r->si, 0, sizeof(r->si));
 
-    // Do no call ff_mpeg_update_thread_context on a partially initialized
-    // decoder context.
-    if (!s1->context_initialized)
-        return 0;
-
-    return ff_mpeg_update_thread_context(dst, src);
+    return 0;
 }
 
 static int get_slice_offset(AVCodecContext *avctx, const uint8_t *buf, int n, int slice_count, int buf_size)
-- 
2.45.2


[-- Attachment #23: 0022-avcodec-mpeg12dec-Remove-disabled-frame-threading-co.patch --]
[-- Type: text/x-patch, Size: 4531 bytes --]

From 8d5184e668ce8c74e769a8dfb8ef29206babcf62 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 29 Apr 2025 19:09:16 +0200
Subject: [PATCH 22/44] avcodec/mpeg12dec: Remove disabled frame-threading code

The MPEG-1 decoder has an update_thread_context function set,
yet it was never enabled (missing AV_CODEC_CAP_FRAME_THREADS
flag). So remove it and also the ff_thread_finish_setup() call
as well as the progress reporting.

(Simply setting the flag would not be enough. The main problems
are:
a) The update_thread_context function relies on memcpy'ing
the whole context instead of only copying the necessary fields.
This leads to data races which is undefined behaviour.
(Btw: The check for whether the non-MpegEncContext fields
of Mpeg1Context should be copied has been broken in
7f0efe232475d7a704924a3cb308281973e8add3.)
b) Even an AVBufferRef* is simply copied, without creating a new
reference.
c) Copying the whole context happens only during init; when parameters
change lateron, the change is not propagated to the next thread.
This affects at least the quant matrix (for MPEG-1).
d) The MPEG-1/2 decoders are made to decode both MPEG-1 and MPEG-2.
When MPEG-2 is decoded, another complication arises: In case of
coded fields, both fields can be in one AVPacket or they can be
in separate AVPackets. One would need to parse enough of the data
to be able to determine whether the next thread needs to start
a new frame or decode the second field of the current frame;
for this one would need to either postpone calling
ff_thread_finish_setup() for coded slices altogether or implement
some form of ff_h2645_packet_split().
One would also need a second ThreadProgress to signal progress
of each field.
e) One would need to reenable waiting in ff_mpv_reconstruct_mb()
for MPEG-1/2 (and H.261).
f) Probably lots of other stuff for invalid input that I am currently
not thinking about.
If this were done, nothing from the current update_thread_context
would remain, so one can just nuke it altogether.)

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpeg12dec.c | 28 ----------------------------
 1 file changed, 28 deletions(-)

diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
index 9297c65029..910eed4932 100644
--- a/libavcodec/mpeg12dec.c
+++ b/libavcodec/mpeg12dec.c
@@ -58,7 +58,6 @@
 #include "mpegvideodec.h"
 #include "profiles.h"
 #include "startcode.h"
-#include "thread.h"
 
 #define A53_MAX_CC_COUNT 2000
 
@@ -786,28 +785,6 @@ static av_cold int mpeg_decode_init(AVCodecContext *avctx)
     return 0;
 }
 
-#if HAVE_THREADS
-static int mpeg_decode_update_thread_context(AVCodecContext *avctx,
-                                             const AVCodecContext *avctx_from)
-{
-    Mpeg1Context *ctx = avctx->priv_data, *ctx_from = avctx_from->priv_data;
-    MpegEncContext *s = &ctx->mpeg_enc_ctx, *s1 = &ctx_from->mpeg_enc_ctx;
-    int err;
-
-    if (avctx == avctx_from || !s1->context_initialized)
-        return 0;
-
-    err = ff_mpeg_update_thread_context(avctx, avctx_from);
-    if (err)
-        return err;
-
-    if (!s->context_initialized)
-        memcpy(s + 1, s1 + 1, sizeof(Mpeg1Context) - sizeof(MpegEncContext));
-
-    return 0;
-}
-#endif
-
 static const enum AVPixelFormat mpeg1_hwaccel_pixfmt_list_420[] = {
 #if CONFIG_MPEG1_NVDEC_HWACCEL
     AV_PIX_FMT_CUDA,
@@ -1317,9 +1294,6 @@ static int mpeg_field_start(Mpeg1Context *s1, const uint8_t *buf, int buf_size)
                 *sd->data = s1->afd;
             s1->has_afd = 0;
         }
-
-        if (HAVE_THREADS && (avctx->active_thread_type & FF_THREAD_FRAME))
-            ff_thread_finish_setup(avctx);
     } else { // second field
         second_field = 1;
         if (!s->cur_pic.ptr) {
@@ -1524,7 +1498,6 @@ static int mpeg_decode_slice(MpegEncContext *s, int mb_y,
             int left;
 
             ff_mpeg_draw_horiz_band(s, mb_size * (s->mb_y >> field_pic), mb_size);
-            ff_mpv_report_decode_progress(s);
 
             s->mb_x  = 0;
             s->mb_y += 1 << field_pic;
@@ -2661,7 +2634,6 @@ const FFCodec ff_mpeg1video_decoder = {
     .caps_internal         = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
     .flush                 = flush,
     .p.max_lowres          = 3,
-    UPDATE_THREAD_CONTEXT(mpeg_decode_update_thread_context),
     .hw_configs            = (const AVCodecHWConfigInternal *const []) {
 #if CONFIG_MPEG1_NVDEC_HWACCEL
                                HWACCEL_NVDEC(mpeg1),
-- 
2.45.2


[-- Attachment #24: 0023-avcodec-mpegvideo_dec-Move-memcpy-ing-ctx-to-mpeg4vi.patch --]
[-- Type: text/x-patch, Size: 3531 bytes --]

From cb8a184c0057a3b79d212b39c10fa97ecbe15208 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 29 Apr 2025 23:20:49 +0200
Subject: [PATCH 23/44] avcodec/mpegvideo_dec: Move memcpy'ing ctx to
 mpeg4videodec.c

When the destination MpegEncContext in ff_mpeg_update_thread_context()
is not initialized, the source MpegEncContext is simply copied
over it before (potentially) calling ff_mpv_common_init().
This leads to data races when this code is executed which is why
it should be replaced with only copying the necessary fields
(this is for future commits).

Given that the RV30 and RV40 decoders always call said function
with an already initialized MpegEncContext (they use context_reinit
in case of frame size changes), they don't need this ugly
initialization (and are therefore race-free). This means that
this code can be moved to the only decoder that actually needs it:
MPEG-4. This commit does so.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpeg4videodec.c | 27 ++++++++++++++++++++++++++-
 libavcodec/mpegvideo_dec.c | 19 -------------------
 2 files changed, 26 insertions(+), 20 deletions(-)

diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
index 51af95720f..ed33a056a4 100644
--- a/libavcodec/mpeg4videodec.c
+++ b/libavcodec/mpeg4videodec.c
@@ -3768,15 +3768,40 @@ int ff_mpeg4_frame_end(AVCodecContext *avctx, const AVPacket *pkt)
 
 #if CONFIG_MPEG4_DECODER
 #if HAVE_THREADS
+static int update_mpvctx(MpegEncContext *s, const MpegEncContext *s1)
+{
+    AVCodecContext *avctx = s->avctx;
+    // FIXME the following leads to a data race; instead copy only
+    // the necessary fields.
+    memcpy(s, s1, sizeof(*s));
+
+    s->context_initialized = 0;
+    s->context_reinit      = 0;
+    s->avctx = avctx;
+
+    if (s1->context_initialized) {
+        int err = ff_mpv_common_init(s);
+        if (err < 0)
+            return err;
+    }
+    return 0;
+}
+
 static int mpeg4_update_thread_context(AVCodecContext *dst,
                                        const AVCodecContext *src)
 {
     Mpeg4DecContext *s = dst->priv_data;
     const Mpeg4DecContext *s1 = src->priv_data;
     int init = s->m.context_initialized;
+    int ret;
 
-    int ret = ff_mpeg_update_thread_context(dst, src);
+    if (!init) {
+        ret = update_mpvctx(&s->m, &s1->m);
+        if (ret < 0)
+            return ret;
+    }
 
+    ret = ff_mpeg_update_thread_context(dst, src);
     if (ret < 0)
         return ret;
 
diff --git a/libavcodec/mpegvideo_dec.c b/libavcodec/mpegvideo_dec.c
index 5e445d0d83..54987a19df 100644
--- a/libavcodec/mpegvideo_dec.c
+++ b/libavcodec/mpegvideo_dec.c
@@ -87,25 +87,6 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst,
 
     av_assert0(s != s1);
 
-    // FIXME can parameters change on I-frames?
-    // in that case dst may need a reinit
-    if (!s->context_initialized) {
-        void *private_ctx = s->private_ctx;
-        int err;
-        memcpy(s, s1, sizeof(*s));
-
-        s->context_initialized   = 0;
-        s->context_reinit        = 0;
-        s->avctx                 = dst;
-        s->private_ctx           = private_ctx;
-
-        if (s1->context_initialized) {
-            if ((err = ff_mpv_common_init(s)) < 0)
-                return err;
-            ret = 1;
-        }
-    }
-
     if (s->height != s1->height || s->width != s1->width || s->context_reinit) {
         s->height = s1->height;
         s->width  = s1->width;
-- 
2.45.2


[-- Attachment #25: 0024-avcodec-mpegvideo_dec-rv34-Avoid-ff_mpv_common_frame.patch --]
[-- Type: text/x-patch, Size: 4254 bytes --]

From 319914ee082f7646dfba5346aac62a8298847007 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 25 Mar 2025 11:56:42 +0100
Subject: [PATCH 24/44] avcodec/mpegvideo_dec, rv34: Avoid
 ff_mpv_common_frame_size_change()

Replace the function by ff_mpv_decode_reinit(). This avoids having
to track two variables to see whether the context is properly
initialized.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpegvideo_dec.c | 13 +++++++++----
 libavcodec/rv34.c          | 16 ++++++----------
 2 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/libavcodec/mpegvideo_dec.c b/libavcodec/mpegvideo_dec.c
index 54987a19df..eb9e69871f 100644
--- a/libavcodec/mpegvideo_dec.c
+++ b/libavcodec/mpegvideo_dec.c
@@ -87,12 +87,17 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst,
 
     av_assert0(s != s1);
 
-    if (s->height != s1->height || s->width != s1->width || s->context_reinit) {
+    if (s->height != s1->height || s->width != s1->width || !s1->context_initialized) {
         s->height = s1->height;
         s->width  = s1->width;
-        if ((ret = ff_mpv_common_frame_size_change(s)) < 0)
-            return ret;
-        ret = 1;
+        if (s1->context_initialized) {
+            ret = ff_mpv_decode_reinit(s);
+            if (ret < 0)
+                return ret;
+            ret = 1;
+        } else {
+            ff_mpv_common_end(s);
+        }
     }
 
     s->quarter_sample       = s1->quarter_sample;
diff --git a/libavcodec/rv34.c b/libavcodec/rv34.c
index 5dcbe9a222..0545f77b44 100644
--- a/libavcodec/rv34.c
+++ b/libavcodec/rv34.c
@@ -32,7 +32,6 @@
 #include "libavutil/thread.h"
 
 #include "avcodec.h"
-#include "decode.h"
 #include "error_resilience.h"
 #include "mpegutils.h"
 #include "mpegvideo.h"
@@ -1403,7 +1402,7 @@ static int rv34_decoder_alloc(RV34DecContext *r)
 
     if (!(r->cbp_chroma       && r->cbp_luma && r->deblock_coefs &&
           r->intra_types_hist && r->mb_type)) {
-        r->s.context_reinit = 1;
+        ff_mpv_common_end(&r->s);
         rv34_decoder_free(r);
         return AVERROR(ENOMEM);
     }
@@ -1538,10 +1537,9 @@ av_cold int ff_rv34_decode_init(AVCodecContext *avctx)
 int ff_rv34_decode_update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
 {
     RV34DecContext *r = dst->priv_data, *r1 = src->priv_data;
-    MpegEncContext *const s1 = &r1->s;
     int ret;
 
-    if (dst == src || !s1->context_initialized)
+    if (dst == src)
         return 0;
 
     ret = ff_mpeg_update_thread_context(dst, src);
@@ -1671,12 +1669,12 @@ int ff_rv34_decode_frame(AVCodecContext *avctx, AVFrame *pict,
         if (s->mb_num_left > 0 && s->cur_pic.ptr) {
             av_log(avctx, AV_LOG_ERROR, "New frame but still %d MB left.\n",
                    s->mb_num_left);
-            if (!s->context_reinit)
+            if (s->context_initialized)
                 ff_er_frame_end(&s->er, NULL);
             ff_mpv_frame_end(s);
         }
 
-        if (s->width != si.width || s->height != si.height || s->context_reinit) {
+        if (!s->context_initialized || s->width != si.width || s->height != si.height) {
             int err;
 
             av_log(s->avctx, AV_LOG_WARNING, "Changing dimensions to %dx%d\n",
@@ -1691,11 +1689,9 @@ int ff_rv34_decode_frame(AVCodecContext *avctx, AVFrame *pict,
             s->width  = si.width;
             s->height = si.height;
 
-            err = ff_set_dimensions(s->avctx, s->width, s->height);
+            err = ff_mpv_decode_reinit(s);
             if (err < 0)
                 return err;
-            if ((err = ff_mpv_common_frame_size_change(s)) < 0)
-                return err;
             if ((err = rv34_decoder_realloc(r)) < 0)
                 return err;
         }
@@ -1750,7 +1746,7 @@ int ff_rv34_decode_frame(AVCodecContext *avctx, AVFrame *pict,
         }
         s->mb_x = s->mb_y = 0;
         ff_thread_finish_setup(s->avctx);
-    } else if (s->context_reinit) {
+    } else if (!s->context_initialized) {
         av_log(s->avctx, AV_LOG_ERROR, "Decoder needs full frames to "
                "reinitialize (start MB is %d).\n", si.start);
         return AVERROR_INVALIDDATA;
-- 
2.45.2


[-- Attachment #26: 0025-avcodec-mpegvideo_dec-Remove-ff_mpv_common_frame_siz.patch --]
[-- Type: text/x-patch, Size: 2831 bytes --]

From 9de2595e2b5fd03d427fa72b586540e356b05311 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 25 Mar 2025 12:12:59 +0100
Subject: [PATCH 25/44] avcodec/mpegvideo_dec: Remove
 ff_mpv_common_frame_size_change()

No longer used anywhere.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpegvideo_dec.c | 46 +-------------------------------------
 libavcodec/mpegvideodec.h  |  2 --
 2 files changed, 1 insertion(+), 47 deletions(-)

diff --git a/libavcodec/mpegvideo_dec.c b/libavcodec/mpegvideo_dec.c
index eb9e69871f..7e300bcdc2 100644
--- a/libavcodec/mpegvideo_dec.c
+++ b/libavcodec/mpegvideo_dec.c
@@ -26,8 +26,8 @@
 
 #include "libavutil/avassert.h"
 #include "libavutil/emms.h"
-#include "libavutil/imgutils.h"
 #include "libavutil/internal.h"
+#include "libavutil/pixdesc.h"
 #include "libavutil/video_enc_params.h"
 
 #include "avcodec.h"
@@ -152,50 +152,6 @@ av_cold int ff_mpv_decode_close(AVCodecContext *avctx)
     return 0;
 }
 
-av_cold int ff_mpv_common_frame_size_change(MpegEncContext *s)
-{
-    int err = 0;
-
-    if (!s->context_initialized)
-        return AVERROR(EINVAL);
-
-    ff_mpv_free_context_frame(s);
-
-    ff_mpv_unref_picture(&s->last_pic);
-    ff_mpv_unref_picture(&s->next_pic);
-    ff_mpv_unref_picture(&s->cur_pic);
-
-    if ((s->width || s->height) &&
-        (err = av_image_check_size(s->width, s->height, 0, s->avctx)) < 0)
-        goto fail;
-
-    /* set chroma shifts */
-    err = av_pix_fmt_get_chroma_sub_sample(s->avctx->pix_fmt,
-                                           &s->chroma_x_shift,
-                                           &s->chroma_y_shift);
-    if (err < 0)
-        goto fail;
-
-    if ((err = ff_mpv_init_context_frame(s)))
-        goto fail;
-
-    memset(s->thread_context, 0, sizeof(s->thread_context));
-    s->thread_context[0]   = s;
-
-    if (s->width && s->height) {
-        err = ff_mpv_init_duplicate_contexts(s);
-        if (err < 0)
-            goto fail;
-    }
-    s->context_reinit = 0;
-
-    return 0;
- fail:
-    ff_mpv_free_context_frame(s);
-    s->context_reinit = 1;
-    return err;
-}
-
 static int alloc_picture(MpegEncContext *s, MPVWorkPicture *dst, int reference)
 {
     AVCodecContext *avctx = s->avctx;
diff --git a/libavcodec/mpegvideodec.h b/libavcodec/mpegvideodec.h
index ef6e657c0b..df587732fe 100644
--- a/libavcodec/mpegvideodec.h
+++ b/libavcodec/mpegvideodec.h
@@ -54,8 +54,6 @@ int ff_mpv_decode_init(MpegEncContext *s, AVCodecContext *avctx);
  */
 int ff_mpv_decode_reinit(MpegEncContext *s);
 
-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.
-- 
2.45.2


[-- Attachment #27: 0026-avcodec-mpegvideo-Make-ff_mpv_-free-init-_context_fr.patch --]
[-- Type: text/x-patch, Size: 2951 bytes --]

From 9ce74a101c7ba9b5872378555f6901b32a089ff6 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 25 Mar 2025 12:17:25 +0100
Subject: [PATCH 26/44] avcodec/mpegvideo: Make
 ff_mpv_{free,init}_context_frame() static

Possible now that ff_mpv_common_framesize_change() no longer
exists.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpegvideo.c | 16 +++++-----------
 libavcodec/mpegvideo.h | 11 -----------
 2 files changed, 5 insertions(+), 22 deletions(-)

diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
index d09eb1211d..dfa3930f83 100644
--- a/libavcodec/mpegvideo.c
+++ b/libavcodec/mpegvideo.c
@@ -249,7 +249,7 @@ static av_cold void free_buffer_pools(BufferPoolContext *pools)
     pools->alloc_mb_height = pools->alloc_mb_width = pools->alloc_mb_stride = 0;
 }
 
-av_cold int ff_mpv_init_context_frame(MpegEncContext *s)
+static av_cold int mpv_init_context_frame(MpegEncContext *s)
 {
     BufferPoolContext *const pools = &s->buffer_pools;
     int y_size, c_size, yc_size, i, mb_array_size, mv_table_size, x, y;
@@ -450,7 +450,8 @@ av_cold int ff_mpv_common_init(MpegEncContext *s)
     if (ret)
         return ret;
 
-    if ((ret = ff_mpv_init_context_frame(s)))
+    ret = mpv_init_context_frame(s);
+    if (ret < 0)
         goto fail;
 
     if (nb_slices > MAX_THREADS || (nb_slices > s->mb_height && s->mb_height)) {
@@ -481,7 +482,7 @@ av_cold int ff_mpv_common_init(MpegEncContext *s)
     return ret;
 }
 
-av_cold void ff_mpv_free_context_frame(MpegEncContext *s)
+av_cold void ff_mpv_common_end(MpegEncContext *s)
 {
     free_duplicate_contexts(s);
 
@@ -503,14 +504,7 @@ av_cold void ff_mpv_free_context_frame(MpegEncContext *s)
     av_freep(&s->er.er_temp_buffer);
     av_freep(&s->mb_index2xy);
 
-    s->linesize = s->uvlinesize = 0;
-}
-
-av_cold void ff_mpv_common_end(MpegEncContext *s)
-{
-    ff_mpv_free_context_frame(s);
-    if (s->slice_context_count > 1)
-        s->slice_context_count = 1;
+    s->slice_context_count = 1;
 
     ff_mpv_unref_picture(&s->last_pic);
     ff_mpv_unref_picture(&s->cur_pic);
diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h
index de3ebd5ed2..3a769db569 100644
--- a/libavcodec/mpegvideo.h
+++ b/libavcodec/mpegvideo.h
@@ -354,17 +354,6 @@ int ff_mpv_common_init(MpegEncContext *s);
  * that are freed/reset in free_duplicate_context() are NULL.
  */
 int ff_mpv_init_duplicate_contexts(MpegEncContext *s);
-/**
- * Initialize and allocates MpegEncContext fields dependent on the resolution.
- */
-int ff_mpv_init_context_frame(MpegEncContext *s);
-/**
- * Frees and resets MpegEncContext fields depending on the resolution
- * as well as the slice thread contexts.
- * Is used during resolution changes to avoid a full reinitialization of the
- * codec.
- */
-void ff_mpv_free_context_frame(MpegEncContext *s);
 
 void ff_mpv_common_end(MpegEncContext *s);
 
-- 
2.45.2


[-- Attachment #28: 0027-avcodec-mpegvideo-Move-clear_context-to-mpeg4videode.patch --]
[-- Type: text/x-patch, Size: 4153 bytes --]

From 124b54752bad326953051473baca41dfda376dfa Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 25 Mar 2025 12:42:45 +0100
Subject: [PATCH 27/44] avcodec/mpegvideo: Move clear_context() to
 mpeg4videodec.c

There is only one source of dirty MpegEncContexts:
update_mpvctx() (which copies an MpegEncContext
over another one in order to initialize it). So only clear
these contexts.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpeg4videodec.c | 44 +++++++++++++++++++++++++++++++++++---
 libavcodec/mpegvideo.c     | 38 --------------------------------
 2 files changed, 41 insertions(+), 41 deletions(-)

diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
index ed33a056a4..39c05859d3 100644
--- a/libavcodec/mpeg4videodec.c
+++ b/libavcodec/mpeg4videodec.c
@@ -3768,15 +3768,53 @@ int ff_mpeg4_frame_end(AVCodecContext *avctx, const AVPacket *pkt)
 
 #if CONFIG_MPEG4_DECODER
 #if HAVE_THREADS
-static int update_mpvctx(MpegEncContext *s, const MpegEncContext *s1)
+static av_cold void clear_context(MpegEncContext *s)
+{
+    memset(&s->buffer_pools, 0, sizeof(s->buffer_pools));
+    memset(&s->next_pic, 0, sizeof(s->next_pic));
+    memset(&s->last_pic, 0, sizeof(s->last_pic));
+    memset(&s->cur_pic,  0, sizeof(s->cur_pic));
+
+    memset(s->thread_context, 0, sizeof(s->thread_context));
+
+    s->block = NULL;
+    s->blocks = NULL;
+    s->ac_val_base = NULL;
+    s->ac_val[0] =
+    s->ac_val[1] =
+    s->ac_val[2] =NULL;
+    memset(&s->sc, 0, sizeof(s->sc));
+
+
+    s->p_field_mv_table_base = NULL;
+    for (int i = 0; i < 2; i++)
+        for (int j = 0; j < 2; j++)
+            s->p_field_mv_table[i][j] = NULL;
+
+    s->dc_val_base = NULL;
+    s->coded_block_base = NULL;
+    s->mbintra_table = NULL;
+    s->cbp_table = NULL;
+    s->pred_dir_table = NULL;
+
+    s->mbskip_table = NULL;
+
+    s->er.error_status_table = NULL;
+    s->er.er_temp_buffer = NULL;
+    s->mb_index2xy = NULL;
+
+    s->context_initialized   = 0;
+    s->context_reinit        = 0;
+}
+
+static av_cold int update_mpvctx(MpegEncContext *s, const MpegEncContext *s1)
 {
     AVCodecContext *avctx = s->avctx;
     // FIXME the following leads to a data race; instead copy only
     // the necessary fields.
     memcpy(s, s1, sizeof(*s));
+    clear_context(s);
 
-    s->context_initialized = 0;
-    s->context_reinit      = 0;
     s->avctx = avctx;
 
     if (s1->context_initialized) {
diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
index dfa3930f83..de1901d53d 100644
--- a/libavcodec/mpegvideo.c
+++ b/libavcodec/mpegvideo.c
@@ -379,42 +379,6 @@ static av_cold int mpv_init_context_frame(MpegEncContext *s)
     return !CONFIG_MPEGVIDEODEC || s->encoding ? 0 : ff_mpeg_er_init(s);
 }
 
-static void clear_context(MpegEncContext *s)
-{
-    memset(&s->buffer_pools, 0, sizeof(s->buffer_pools));
-    memset(&s->next_pic, 0, sizeof(s->next_pic));
-    memset(&s->last_pic, 0, sizeof(s->last_pic));
-    memset(&s->cur_pic,  0, sizeof(s->cur_pic));
-
-    memset(s->thread_context, 0, sizeof(s->thread_context));
-
-    s->block = NULL;
-    s->blocks = NULL;
-    s->ac_val_base = NULL;
-    s->ac_val[0] =
-    s->ac_val[1] =
-    s->ac_val[2] =NULL;
-    memset(&s->sc, 0, sizeof(s->sc));
-
-
-    s->p_field_mv_table_base = NULL;
-    for (int i = 0; i < 2; i++)
-        for (int j = 0; j < 2; j++)
-            s->p_field_mv_table[i][j] = NULL;
-
-    s->dc_val_base = NULL;
-    s->coded_block_base = NULL;
-    s->mbintra_table = NULL;
-    s->cbp_table = NULL;
-    s->pred_dir_table = NULL;
-
-    s->mbskip_table = NULL;
-
-    s->er.error_status_table = NULL;
-    s->er.er_temp_buffer = NULL;
-    s->mb_index2xy = NULL;
-}
-
 /**
  * init common structure for both encoder and decoder.
  * this assumes that some variables like width/height are already set
@@ -426,8 +390,6 @@ av_cold int ff_mpv_common_init(MpegEncContext *s)
                     s->avctx->thread_count : 1;
     int ret;
 
-    clear_context(s);
-
     if (s->encoding && s->avctx->slices)
         nb_slices = s->avctx->slices;
 
-- 
2.45.2


[-- Attachment #29: 0028-avcodec-mpeg4videodec-Avoid-redundant-ff_mpv_common_.patch --]
[-- Type: text/x-patch, Size: 1800 bytes --]

From 6e75823015ea7c724185642e5f2380a5d52ae456 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Wed, 30 Apr 2025 01:00:59 +0200
Subject: [PATCH 28/44] avcodec/mpeg4videodec: Avoid redundant
 ff_mpv_common_init()

ff_mpeg_update_thread_context() will initialize it for us.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpeg4videodec.c | 16 +++-------------
 1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
index 39c05859d3..4e1c4e31d8 100644
--- a/libavcodec/mpeg4videodec.c
+++ b/libavcodec/mpeg4videodec.c
@@ -3807,7 +3807,7 @@ static av_cold void clear_context(MpegEncContext *s)
     s->context_reinit        = 0;
 }
 
-static av_cold int update_mpvctx(MpegEncContext *s, const MpegEncContext *s1)
+static av_cold void update_mpvctx(MpegEncContext *s, const MpegEncContext *s1)
 {
     AVCodecContext *avctx = s->avctx;
     // FIXME the following leads to a data race; instead copy only
@@ -3816,13 +3816,6 @@ static av_cold int update_mpvctx(MpegEncContext *s, const MpegEncContext *s1)
     clear_context(s);
 
     s->avctx = avctx;
-
-    if (s1->context_initialized) {
-        int err = ff_mpv_common_init(s);
-        if (err < 0)
-            return err;
-    }
-    return 0;
 }
 
 static int mpeg4_update_thread_context(AVCodecContext *dst,
@@ -3833,11 +3826,8 @@ static int mpeg4_update_thread_context(AVCodecContext *dst,
     int init = s->m.context_initialized;
     int ret;
 
-    if (!init) {
-        ret = update_mpvctx(&s->m, &s1->m);
-        if (ret < 0)
-            return ret;
-    }
+    if (!init)
+        update_mpvctx(&s->m, &s1->m);
 
     ret = ff_mpeg_update_thread_context(dst, src);
     if (ret < 0)
-- 
2.45.2


[-- Attachment #30: 0029-avcodec-rv34-Defer-initializing-MpegEncContext.patch --]
[-- Type: text/x-patch, Size: 2356 bytes --]

From fedd0ae5f88d6691a7c19b75719451961e32bdd6 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Wed, 30 Apr 2025 01:45:03 +0200
Subject: [PATCH 29/44] avcodec/rv34: Defer initializing MpegEncContext

Now that the RV30 and RV40 decoders use ff_mpv_decode_reinit()
upon frame size changes, they need not be initialized during init;
instead one can use the ordinary resizing code to also perform
the initial initilization.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/rv34.c | 23 +++++++++--------------
 1 file changed, 9 insertions(+), 14 deletions(-)

diff --git a/libavcodec/rv34.c b/libavcodec/rv34.c
index 0545f77b44..3ebb92f563 100644
--- a/libavcodec/rv34.c
+++ b/libavcodec/rv34.c
@@ -1520,15 +1520,8 @@ av_cold int ff_rv34_decode_init(AVCodecContext *avctx)
     avctx->has_b_frames = 1;
     s->low_delay = 0;
 
-    if ((ret = ff_mpv_common_init(s)) < 0)
-        return ret;
-
     ff_h264_pred_init(&r->h, AV_CODEC_ID_RV40, 8, 1);
 
-    ret = rv34_decoder_alloc(r);
-    if (ret < 0)
-        return ret;
-
     ff_thread_once(&init_static_once, rv34_init_tables);
 
     return 0;
@@ -1677,15 +1670,17 @@ int ff_rv34_decode_frame(AVCodecContext *avctx, AVFrame *pict,
         if (!s->context_initialized || s->width != si.width || s->height != si.height) {
             int err;
 
-            av_log(s->avctx, AV_LOG_WARNING, "Changing dimensions to %dx%d\n",
-                   si.width, si.height);
+            if (s->context_initialized) {
+                av_log(s->avctx, AV_LOG_WARNING, "Changing dimensions to %dx%d\n",
+                       si.width, si.height);
 
-            if (av_image_check_size(si.width, si.height, 0, s->avctx))
-                return AVERROR_INVALIDDATA;
+                if (av_image_check_size(si.width, si.height, 0, s->avctx))
+                    return AVERROR_INVALIDDATA;
 
-            s->avctx->sample_aspect_ratio = update_sar(
-                s->width, s->height, s->avctx->sample_aspect_ratio,
-                si.width, si.height);
+                s->avctx->sample_aspect_ratio = update_sar(
+                    s->width, s->height, s->avctx->sample_aspect_ratio,
+                    si.width, si.height);
+            }
             s->width  = si.width;
             s->height = si.height;
 
-- 
2.45.2


[-- Attachment #31: 0030-avcodec-mpegvideo-Move-decoding-initializing-code-to.patch --]
[-- Type: text/x-patch, Size: 2439 bytes --]

From 25a92b896ce6d682e4fb2fdaff8288b20ece0fb3 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Wed, 30 Apr 2025 02:04:24 +0200
Subject: [PATCH 30/44] avcodec/mpegvideo: Move decoding initializing code to
 mpegvideo_dec.c

Now that the decoders all use ff_mpv_decode_reinit(), we can move
the pixel format check to it; and we can also remove the size check,
as ff_mpv_decode_reinit() performs this on its own (and disallows
0x0 resolutions).

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpegvideo.c     | 13 +------------
 libavcodec/mpegvideo_dec.c |  6 ++++++
 2 files changed, 7 insertions(+), 12 deletions(-)

diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
index de1901d53d..c804205745 100644
--- a/libavcodec/mpegvideo.c
+++ b/libavcodec/mpegvideo.c
@@ -29,9 +29,9 @@
 
 #include "libavutil/attributes.h"
 #include "libavutil/avassert.h"
-#include "libavutil/imgutils.h"
 #include "libavutil/internal.h"
 #include "libavutil/mem.h"
+#include "libavutil/pixdesc.h"
 
 #include "avcodec.h"
 #include "blockdsp.h"
@@ -41,7 +41,6 @@
 #include "mpegutils.h"
 #include "mpegvideo.h"
 #include "mpegvideodata.h"
-#include "mpegvideo_unquantize.h"
 #include "libavutil/refstruct.h"
 
 
@@ -393,16 +392,6 @@ av_cold int ff_mpv_common_init(MpegEncContext *s)
     if (s->encoding && s->avctx->slices)
         nb_slices = s->avctx->slices;
 
-    if (s->avctx->pix_fmt == AV_PIX_FMT_NONE) {
-        av_log(s->avctx, AV_LOG_ERROR,
-               "decoding to AV_PIX_FMT_NONE is not supported.\n");
-        return AVERROR(EINVAL);
-    }
-
-    if ((s->width || s->height) &&
-        av_image_check_size(s->width, s->height, 0, s->avctx))
-        return AVERROR(EINVAL);
-
     dsp_init(s);
 
     /* set chroma shifts */
diff --git a/libavcodec/mpegvideo_dec.c b/libavcodec/mpegvideo_dec.c
index 7e300bcdc2..fe5d5bcadd 100644
--- a/libavcodec/mpegvideo_dec.c
+++ b/libavcodec/mpegvideo_dec.c
@@ -137,6 +137,12 @@ av_cold int ff_mpv_decode_reinit(MpegEncContext *const s)
     if (s->context_initialized)
         ff_mpv_common_end(s);
 
+    if (s->avctx->pix_fmt == AV_PIX_FMT_NONE) {
+        av_log(s->avctx, AV_LOG_ERROR,
+               "decoding to AV_PIX_FMT_NONE is not supported.\n");
+        return AVERROR(EINVAL);
+    }
+
     ret = ff_set_dimensions(s->avctx, s->width, s->height);
     if (ret < 0)
         return ret;
-- 
2.45.2


[-- Attachment #32: 0031-avcodec-mpegvideo-Remove-dead-checks.patch --]
[-- Type: text/x-patch, Size: 1423 bytes --]

From bf2f9e5985ffce952d1e3d8adf45e48a9cdc9c59 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Wed, 30 Apr 2025 02:12:53 +0200
Subject: [PATCH 31/44] avcodec/mpegvideo: Remove dead checks

ff_mpv_common_init() is no longer called with 0x0 dimensions
at all, so s->mb_height is never zero.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpegvideo.c | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
index c804205745..9c96e25e03 100644
--- a/libavcodec/mpegvideo.c
+++ b/libavcodec/mpegvideo.c
@@ -405,15 +405,10 @@ av_cold int ff_mpv_common_init(MpegEncContext *s)
     if (ret < 0)
         goto fail;
 
-    if (nb_slices > MAX_THREADS || (nb_slices > s->mb_height && s->mb_height)) {
-        int max_slices;
-        if (s->mb_height)
-            max_slices = FFMIN(MAX_THREADS, s->mb_height);
-        else
-            max_slices = MAX_THREADS;
+    if (nb_slices > FFMIN(MAX_THREADS, s->mb_height)) {
         av_log(s->avctx, AV_LOG_WARNING, "too many threads/slices (%d),"
-               " reducing to %d\n", nb_slices, max_slices);
-        nb_slices = max_slices;
+               " reducing to %d\n", nb_slices, FFMIN(MAX_THREADS, s->mb_height));
+        nb_slices = FFMIN(MAX_THREADS, s->mb_height);
     }
 
     s->context_initialized = 1;
-- 
2.45.2


[-- Attachment #33: 0032-avcodec-mpegvideo-Defer-init-of-slice-contexts-in-ff.patch --]
[-- Type: text/x-patch, Size: 3763 bytes --]

From 0138d80319982b29201c8e31dfd3db76a5680d6c Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Wed, 30 Apr 2025 02:47:42 +0200
Subject: [PATCH 32/44] avcodec/mpegvideo: Defer init of slice contexts in
 ff_mpv_common_init

This will allow the callers to do something between ff_mpv_common_init()
and ff_mpv_init_duplicate_contexts().

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpegvideo.c     | 11 +----------
 libavcodec/mpegvideo_dec.c | 11 ++++++++++-
 libavcodec/mpegvideo_enc.c |  9 ++++++---
 libavcodec/svq1enc.c       |  4 ++++
 4 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
index 9c96e25e03..b51d9ef00d 100644
--- a/libavcodec/mpegvideo.c
+++ b/libavcodec/mpegvideo.c
@@ -403,7 +403,7 @@ av_cold int ff_mpv_common_init(MpegEncContext *s)
 
     ret = mpv_init_context_frame(s);
     if (ret < 0)
-        goto fail;
+        return ret;
 
     if (nb_slices > FFMIN(MAX_THREADS, s->mb_height)) {
         av_log(s->avctx, AV_LOG_WARNING, "too many threads/slices (%d),"
@@ -416,16 +416,7 @@ av_cold int ff_mpv_common_init(MpegEncContext *s)
     s->thread_context[0]   = s;
     s->slice_context_count = nb_slices;
 
-//     if (s->width && s->height) {
-    ret = ff_mpv_init_duplicate_contexts(s);
-    if (ret < 0)
-        goto fail;
-//     }
-
     return 0;
- fail:
-    ff_mpv_common_end(s);
-    return ret;
 }
 
 av_cold void ff_mpv_common_end(MpegEncContext *s)
diff --git a/libavcodec/mpegvideo_dec.c b/libavcodec/mpegvideo_dec.c
index fe5d5bcadd..0d545e5b86 100644
--- a/libavcodec/mpegvideo_dec.c
+++ b/libavcodec/mpegvideo_dec.c
@@ -146,7 +146,16 @@ av_cold int ff_mpv_decode_reinit(MpegEncContext *const s)
     ret = ff_set_dimensions(s->avctx, s->width, s->height);
     if (ret < 0)
         return ret;
-    return ff_mpv_common_init(s);
+    ret = ff_mpv_common_init(s);
+    if (ret < 0)
+        goto fail;
+    ret = ff_mpv_init_duplicate_contexts(s);
+    if (ret < 0)
+        goto fail;
+    return 0;
+fail:
+    ff_mpv_common_end(s);
+    return ret;
 }
 
 av_cold int ff_mpv_decode_close(AVCodecContext *avctx)
diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c
index ce9315c1b8..031647fa53 100644
--- a/libavcodec/mpegvideo_enc.c
+++ b/libavcodec/mpegvideo_enc.c
@@ -1021,9 +1021,9 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx)
         m->lmin = m->lmax;
     }
 
-    /* ff_mpv_common_init() will copy (memdup) the contents of the main slice
-     * to the slice contexts, so we initialize various fields of it
-     * before calling ff_mpv_common_init(). */
+    /* ff_mpv_init_duplicate_contexts() will copy (memdup) the contents of the
+     * main slice to the slice contexts, so we initialize various fields of it
+     * before calling ff_mpv_init_duplicate_contexts(). */
     ff_mpv_idct_init(&s->c);
     init_unquantize(&s->c, avctx);
     ff_fdctdsp_init(&s->fdsp, avctx);
@@ -1054,6 +1054,9 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx)
 
     s->c.slice_ctx_size = sizeof(*s);
     ret = ff_mpv_common_init(&s->c);
+    if (ret < 0)
+        return ret;
+    ret = ff_mpv_init_duplicate_contexts(&s->c);
     if (ret < 0)
         return ret;
 
diff --git a/libavcodec/svq1enc.c b/libavcodec/svq1enc.c
index c1662da5ec..ad6cae6237 100644
--- a/libavcodec/svq1enc.c
+++ b/libavcodec/svq1enc.c
@@ -608,6 +608,10 @@ static av_cold int svq1_encode_init(AVCodecContext *avctx)
     s->m.c.avctx           = avctx;
 
     ret = ff_mpv_common_init(&s->m.c);
+    if (ret < 0)
+        return ret;
+    // Not really needed
+    ret = ff_mpv_init_duplicate_contexts(&s->m.c);
     if (ret < 0)
         return ret;
 
-- 
2.45.2


[-- Attachment #34: 0033-avcodec-mpegvideo-Move-initializing-error-resilience.patch --]
[-- Type: text/x-patch, Size: 1845 bytes --]

From 0d713b7dc3ab9ecb72914cd209333ff8200e5558 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Wed, 30 Apr 2025 02:53:22 +0200
Subject: [PATCH 33/44] avcodec/mpegvideo: Move initializing error resilience
 ctx to decoders

Possible now that ff_mpv_decode_reinit() calls
ff_mpv_init_duplicate_contexts() on its own.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpegvideo.c     | 3 +--
 libavcodec/mpegvideo_dec.c | 4 ++++
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
index b51d9ef00d..6d6f126fd3 100644
--- a/libavcodec/mpegvideo.c
+++ b/libavcodec/mpegvideo.c
@@ -37,7 +37,6 @@
 #include "blockdsp.h"
 #include "idctdsp.h"
 #include "mathops.h"
-#include "mpeg_er.h"
 #include "mpegutils.h"
 #include "mpegvideo.h"
 #include "mpegvideodata.h"
@@ -375,7 +374,7 @@ static av_cold int mpv_init_context_frame(MpegEncContext *s)
     pools->alloc_mb_height = mb_height;
     pools->alloc_mb_stride = s->mb_stride;
 
-    return !CONFIG_MPEGVIDEODEC || s->encoding ? 0 : ff_mpeg_er_init(s);
+    return 0;
 }
 
 /**
diff --git a/libavcodec/mpegvideo_dec.c b/libavcodec/mpegvideo_dec.c
index 0d545e5b86..f46f3a9945 100644
--- a/libavcodec/mpegvideo_dec.c
+++ b/libavcodec/mpegvideo_dec.c
@@ -39,6 +39,7 @@
 #include "mpegvideo.h"
 #include "mpegvideodec.h"
 #include "mpeg4videodec.h"
+#include "mpeg_er.h"
 #include "libavutil/refstruct.h"
 #include "thread.h"
 #include "threadprogress.h"
@@ -147,6 +148,9 @@ av_cold int ff_mpv_decode_reinit(MpegEncContext *const s)
     if (ret < 0)
         return ret;
     ret = ff_mpv_common_init(s);
+    if (ret < 0)
+        goto fail;
+    ret = ff_mpeg_er_init(s);
     if (ret < 0)
         goto fail;
     ret = ff_mpv_init_duplicate_contexts(s);
-- 
2.45.2


[-- Attachment #35: 0034-avcodec-mpegvideo_enc-Simplify-allocating-non-slice-.patch --]
[-- Type: text/x-patch, Size: 8610 bytes --]

From b4f66dad3b5357968963a73559c4033a702f2814 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Wed, 30 Apr 2025 03:23:01 +0200
Subject: [PATCH 34/44] avcodec/mpegvideo_enc: Simplify allocating non-slice
 buffers

Allocate them before the slice contexts, so that they are automatically
copied to the slice contexts. This avoids having to set them in a loop.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpegvideo_enc.c | 142 ++++++++++++++++++-------------------
 1 file changed, 70 insertions(+), 72 deletions(-)

diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c
index 031647fa53..f1de7f6ff6 100644
--- a/libavcodec/mpegvideo_enc.c
+++ b/libavcodec/mpegvideo_enc.c
@@ -443,41 +443,22 @@ static av_cold int init_matrices(MPVMainEncContext *const m, AVCodecContext *avc
     return 0;
 }
 
-static av_cold int init_buffers(MPVMainEncContext *const m, AVCodecContext *avctx)
+static av_cold int init_buffers(MPVMainEncContext *const m)
 {
     MPVEncContext *const s = &m->s;
-    // Align the following per-thread buffers to avoid false sharing.
-    enum {
-#ifndef _MSC_VER
-        /// The number is supposed to match/exceed the cache-line size.
-        ALIGN = FFMAX(128, _Alignof(max_align_t)),
-#else
-        ALIGN = 128,
-#endif
-        DCT_ERROR_SIZE    = FFALIGN(2 * sizeof(*s->dct_error_sum), ALIGN),
-    };
-    static_assert(DCT_ERROR_SIZE * MAX_THREADS + ALIGN - 1 <= SIZE_MAX,
-                  "Need checks for potential overflow.");
-    unsigned nb_slices = s->c.slice_context_count, mv_table_size, mb_array_size;
-    char *dct_error = NULL;
+    unsigned mv_table_size, mb_array_size;
     int has_b_frames = !!m->max_b_frames, nb_mv_tables = 1 + 5 * has_b_frames;
     int16_t (*mv_table)[2];
 
-    if (m->noise_reduction) {
-        if (!FF_ALLOCZ_TYPED_ARRAY(s->dct_offset, 2))
-            return AVERROR(ENOMEM);
-        dct_error = av_mallocz(ALIGN - 1 + nb_slices * DCT_ERROR_SIZE);
-        if (!dct_error)
-            return AVERROR(ENOMEM);
-        m->dct_error_sum_base = dct_error;
-        dct_error += FFALIGN((uintptr_t)dct_error, ALIGN) - (uintptr_t)dct_error;
-    }
-
     /* Allocate MB type table */
     mb_array_size = s->c.mb_stride * s->c.mb_height;
     s->mb_type = av_calloc(mb_array_size, 3 * sizeof(*s->mb_type) + sizeof(*s->mb_mean));
     if (!s->mb_type)
         return AVERROR(ENOMEM);
+    s->mc_mb_var    = s->mb_type   + mb_array_size;
+    s->mb_var       = s->mc_mb_var + mb_array_size;
+    s->mb_mean      = (uint8_t*)(s->mb_var + mb_array_size);
+
     if (!FF_ALLOCZ_TYPED_ARRAY(s->lambda_table, mb_array_size))
         return AVERROR(ENOMEM);
 
@@ -485,8 +466,10 @@ static av_cold int init_buffers(MPVMainEncContext *const m, AVCodecContext *avct
     if (s->c.codec_id == AV_CODEC_ID_MPEG4 ||
         (s->c.avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)) {
         nb_mv_tables += 8 * has_b_frames;
-        if (!ALLOCZ_ARRAYS(s->p_field_select_table[0], 2 * (2 + 4 * has_b_frames), mv_table_size))
+        s->p_field_select_table[0] = av_calloc(mv_table_size, 2 * (2 + 4 * has_b_frames));
+        if (!s->p_field_select_table[0])
             return AVERROR(ENOMEM);
+        s->p_field_select_table[1] = s->p_field_select_table[0] + 2 * mv_table_size;
     }
 
     mv_table = av_calloc(mv_table_size, nb_mv_tables * sizeof(*mv_table));
@@ -495,43 +478,21 @@ static av_cold int init_buffers(MPVMainEncContext *const m, AVCodecContext *avct
     m->mv_table_base = mv_table;
     mv_table += s->c.mb_stride + 1;
 
-    for (unsigned i = 0; i < nb_slices; ++i) {
-        MPVEncContext *const s2 = s->c.enc_contexts[i];
-        int16_t (*tmp_mv_table)[2] = mv_table;
-
-        if (dct_error) {
-            s2->dct_offset    = s->dct_offset;
-            s2->dct_error_sum = (void*)dct_error;
-            dct_error        += DCT_ERROR_SIZE;
-        }
-
-        s2->mb_type      = s->mb_type;
-        s2->mc_mb_var    = s2->mb_type   + mb_array_size;
-        s2->mb_var       = s2->mc_mb_var + mb_array_size;
-        s2->mb_mean      = (uint8_t*)(s2->mb_var + mb_array_size);
-        s2->lambda_table = s->lambda_table;
-
-        s2->p_mv_table            = tmp_mv_table;
-        if (has_b_frames) {
-            s2->b_forw_mv_table       = tmp_mv_table += mv_table_size;
-            s2->b_back_mv_table       = tmp_mv_table += mv_table_size;
-            s2->b_bidir_forw_mv_table = tmp_mv_table += mv_table_size;
-            s2->b_bidir_back_mv_table = tmp_mv_table += mv_table_size;
-            s2->b_direct_mv_table     = tmp_mv_table += mv_table_size;
-        }
-
-        if (s->p_field_select_table[0]) { // MPEG-4 or INTERLACED_ME above
-            uint8_t *field_select = s->p_field_select_table[0];
-            s2->p_field_select_table[0] = field_select;
-            s2->p_field_select_table[1] = field_select += 2 * mv_table_size;
-
-            if (has_b_frames) {
-                for (int j = 0; j < 2; j++) {
-                    for (int k = 0; k < 2; k++) {
-                        for (int l = 0; l < 2; l++)
-                            s2->b_field_mv_table[j][k][l] = tmp_mv_table += mv_table_size;
-                        s2->b_field_select_table[j][k] = field_select += 2 * mv_table_size;
-                    }
+    s->p_mv_table            = mv_table;
+    if (has_b_frames) {
+        s->b_forw_mv_table       = mv_table += mv_table_size;
+        s->b_back_mv_table       = mv_table += mv_table_size;
+        s->b_bidir_forw_mv_table = mv_table += mv_table_size;
+        s->b_bidir_back_mv_table = mv_table += mv_table_size;
+        s->b_direct_mv_table     = mv_table += mv_table_size;
+
+        if (s->p_field_select_table[1]) { // MPEG-4 or INTERLACED_ME above
+            uint8_t *field_select = s->p_field_select_table[1];
+            for (int j = 0; j < 2; j++) {
+                for (int k = 0; k < 2; k++) {
+                    for (int l = 0; l < 2; l++)
+                        s->b_field_mv_table[j][k][l] = mv_table += mv_table_size;
+                    s->b_field_select_table[j][k] = field_select += 2 * mv_table_size;
                 }
             }
         }
@@ -540,6 +501,44 @@ static av_cold int init_buffers(MPVMainEncContext *const m, AVCodecContext *avct
     return 0;
 }
 
+static av_cold int init_slice_buffers(MPVMainEncContext *const m)
+{
+    MPVEncContext *const s = &m->s;
+    // Align the following per-thread buffers to avoid false sharing.
+    enum {
+#ifndef _MSC_VER
+        /// The number is supposed to match/exceed the cache-line size.
+        ALIGN = FFMAX(128, _Alignof(max_align_t)),
+#else
+        ALIGN = 128,
+#endif
+        DCT_ERROR_SIZE    = FFALIGN(2 * sizeof(*s->dct_error_sum), ALIGN),
+    };
+    static_assert(DCT_ERROR_SIZE * MAX_THREADS + ALIGN - 1 <= SIZE_MAX,
+                  "Need checks for potential overflow.");
+    unsigned nb_slices = s->c.slice_context_count;
+
+    if (!m->noise_reduction)
+        return 0;
+
+    if (!FF_ALLOCZ_TYPED_ARRAY(s->dct_offset, 2))
+        return AVERROR(ENOMEM);
+    char *dct_error = av_mallocz(ALIGN - 1 + nb_slices * DCT_ERROR_SIZE);
+    if (!dct_error)
+        return AVERROR(ENOMEM);
+    m->dct_error_sum_base = dct_error;
+    dct_error += FFALIGN((uintptr_t)dct_error, ALIGN) - (uintptr_t)dct_error;
+
+    for (unsigned i = 0; i < nb_slices; ++i) {
+        MPVEncContext *const s2 = s->c.enc_contexts[i];
+
+        s2->dct_offset    = s->dct_offset;
+        s2->dct_error_sum = (void*)dct_error;
+        dct_error        += DCT_ERROR_SIZE;
+    }
+    return 0;
+}
+
 /* init video encoder */
 av_cold int ff_mpv_encode_init(AVCodecContext *avctx)
 {
@@ -1056,20 +1055,19 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx)
     ret = ff_mpv_common_init(&s->c);
     if (ret < 0)
         return ret;
-    ret = ff_mpv_init_duplicate_contexts(&s->c);
+    ret = init_buffers(m);
     if (ret < 0)
         return ret;
-
     if (s->c.slice_context_count > 1) {
-        for (int i = 0; i < s->c.slice_context_count; ++i) {
-            s->c.enc_contexts[i]->rtp_mode = 1;
-
-            if (avctx->codec_id == AV_CODEC_ID_H263P)
-                s->c.enc_contexts[i]->c.h263_slice_structured = 1;
-        }
+        s->rtp_mode = 1;
+        if (avctx->codec_id == AV_CODEC_ID_H263P)
+            s->c.h263_slice_structured = 1;
     }
+    ret = ff_mpv_init_duplicate_contexts(&s->c);
+    if (ret < 0)
+        return ret;
 
-    ret = init_buffers(m, avctx);
+    ret = init_slice_buffers(m);
     if (ret < 0)
         return ret;
 
-- 
2.45.2


[-- Attachment #36: 0035-avcodec-svq1enc-Remove-always-false-check.patch --]
[-- Type: text/x-patch, Size: 1021 bytes --]

From 9604bcf96c976d9a8e8cdf19e161886c9875e3a9 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Wed, 30 Apr 2025 03:34:08 +0200
Subject: [PATCH 35/44] avcodec/svq1enc: Remove always-false check

The pixel format has already been checked generically
via CODEC_PIXFMTS.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/svq1enc.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/libavcodec/svq1enc.c b/libavcodec/svq1enc.c
index ad6cae6237..abb1dc9863 100644
--- a/libavcodec/svq1enc.c
+++ b/libavcodec/svq1enc.c
@@ -648,11 +648,6 @@ static int svq1_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
     if (ret < 0)
         return ret;
 
-    if (avctx->pix_fmt != AV_PIX_FMT_YUV410P) {
-        av_log(avctx, AV_LOG_ERROR, "unsupported pixel format\n");
-        return -1;
-    }
-
     if (!s->current_picture->data[0]) {
         if ((ret = ff_encode_alloc_frame(avctx, s->current_picture)) < 0) {
             return ret;
-- 
2.45.2


[-- Attachment #37: 0036-avcodec-svq1enc-Allocate-buffers-during-init.patch --]
[-- Type: text/x-patch, Size: 1911 bytes --]

From 1d7342e943f780f489afd6382cb8b3e81335e5c5 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Wed, 30 Apr 2025 03:48:38 +0200
Subject: [PATCH 36/44] avcodec/svq1enc: Allocate buffers during init

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/svq1enc.c | 25 +++++++++----------------
 1 file changed, 9 insertions(+), 16 deletions(-)

diff --git a/libavcodec/svq1enc.c b/libavcodec/svq1enc.c
index abb1dc9863..6dc7839a1b 100644
--- a/libavcodec/svq1enc.c
+++ b/libavcodec/svq1enc.c
@@ -594,6 +594,15 @@ static av_cold int svq1_encode_init(AVCodecContext *avctx)
     if (!s->current_picture || !s->last_picture) {
         return AVERROR(ENOMEM);
     }
+    ret = ff_encode_alloc_frame(avctx, s->current_picture);
+    if (ret < 0)
+        return ret;
+    ret = ff_encode_alloc_frame(avctx, s->last_picture);
+    if (ret < 0)
+        return ret;
+    s->scratchbuf = av_malloc_array(s->current_picture->linesize[0], 16 * 3);
+    if (!s->scratchbuf)
+        return AVERROR(ENOMEM);
 
     s->frame_width  = avctx->width;
     s->frame_height = avctx->height;
@@ -648,22 +657,6 @@ static int svq1_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
     if (ret < 0)
         return ret;
 
-    if (!s->current_picture->data[0]) {
-        if ((ret = ff_encode_alloc_frame(avctx, s->current_picture)) < 0) {
-            return ret;
-        }
-    }
-    if (!s->last_picture->data[0]) {
-        ret = ff_encode_alloc_frame(avctx, s->last_picture);
-        if (ret < 0)
-            return ret;
-    }
-    if (!s->scratchbuf) {
-        s->scratchbuf = av_malloc_array(s->current_picture->linesize[0], 16 * 3);
-        if (!s->scratchbuf)
-            return AVERROR(ENOMEM);
-    }
-
     FFSWAP(AVFrame*, s->current_picture, s->last_picture);
 
     if (avctx->gop_size && (avctx->frame_num % avctx->gop_size))
-- 
2.45.2


[-- Attachment #38: 0037-avcodec-mpeg4videodec-Don-t-set-chroma-matrices-unne.patch --]
[-- Type: text/x-patch, Size: 2091 bytes --]

From 1bb29b373f590b62191353b390fe2e83f15c71d9 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Wed, 30 Apr 2025 15:54:50 +0200
Subject: [PATCH 37/44] avcodec/mpeg4videodec: Don't set chroma matrices
 unnecessarily

Only the studio profile uses chroma_inter/intra matrices;
the ordinary profile has only inter/intra matrices.
And our code (namely the MPEG-2 unquantize functions)
only use these two matrices (the MPEG-2 decoder unquantizes
on its own while parsing).

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpeg4videodec.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
index 4e1c4e31d8..b4a1e2ffba 100644
--- a/libavcodec/mpeg4videodec.c
+++ b/libavcodec/mpeg4videodec.c
@@ -2781,14 +2781,12 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb)
                     last = v;
                     j = s->idsp.idct_permutation[ff_zigzag_direct[i]];
                     s->intra_matrix[j]        = last;
-                    s->chroma_intra_matrix[j] = last;
                 }
 
                 /* replicate last value */
                 for (; i < 64; i++) {
                     int j = s->idsp.idct_permutation[ff_zigzag_direct[i]];
                     s->intra_matrix[j]        = last;
-                    s->chroma_intra_matrix[j] = last;
                 }
             }
 
@@ -2808,14 +2806,12 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb)
                     last = v;
                     j = s->idsp.idct_permutation[ff_zigzag_direct[i]];
                     s->inter_matrix[j]        = v;
-                    s->chroma_inter_matrix[j] = v;
                 }
 
                 /* replicate last value */
                 for (; i < 64; i++) {
                     int j = s->idsp.idct_permutation[ff_zigzag_direct[i]];
                     s->inter_matrix[j]        = last;
-                    s->chroma_inter_matrix[j] = last;
                 }
             }
 
-- 
2.45.2


[-- Attachment #39: 0038-avcodec-mpeg12dec-Don-t-reinit-upon-aspect-ratio-cha.patch --]
[-- Type: text/x-patch, Size: 2215 bytes --]

From 81bee9417cd5b6ccae2db7bc5cb935a967de1434 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Wed, 30 Apr 2025 18:20:51 +0200
Subject: [PATCH 38/44] avcodec/mpeg12dec: Don't reinit upon aspect ratio
 change

The spec indeed does not allow the aspect ratio to change
within a video sequence, but this does not imply that we
must reinitialize the decoder if only the aspect ratio changes,
as this value does not affect the decoding process at all.
Moreover, our reinitialization is a bit buggy: If there is
frame reordering, then the not yet output next P-frame is
simply discarded upon reinit. With this patch this no longer
happens when only the aspect ratio changes.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpeg12dec.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
index 910eed4932..3f387de0fd 100644
--- a/libavcodec/mpeg12dec.c
+++ b/libavcodec/mpeg12dec.c
@@ -80,7 +80,6 @@ typedef struct Mpeg1Context {
     int has_afd;
     int slice_count;
     unsigned aspect_ratio_info;
-    AVRational save_aspect;
     int save_width, save_height, save_progressive_seq;
     AVRational frame_rate_ext;  /* MPEG-2 specific framerate modificator */
     unsigned frame_rate_index;
@@ -918,7 +917,6 @@ static int mpeg_decode_postinit(AVCodecContext *avctx)
         avctx->coded_height      != s->height               ||
         s1->save_width           != s->width                ||
         s1->save_height          != s->height               ||
-        av_cmp_q(s1->save_aspect, s->avctx->sample_aspect_ratio) ||
         (s1->save_progressive_seq != s->progressive_sequence && FFALIGN(s->height, 16) != FFALIGN(s->height, 32)) ||
         0) {
         if (avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO && s1->bit_rate &&
@@ -959,7 +957,6 @@ static int mpeg_decode_postinit(AVCodecContext *avctx)
         if (ret < 0)
             return ret;
 
-        s1->save_aspect          = s->avctx->sample_aspect_ratio;
         s1->save_width           = s->width;
         s1->save_height          = s->height;
         s1->save_progressive_seq = s->progressive_sequence;
-- 
2.45.2


[-- Attachment #40: 0039-avcodec-mpeg12dec-Reinit-upon-chroma_format-change.patch --]
[-- Type: text/x-patch, Size: 1931 bytes --]

From 9c483feffdc5059e17d8236d78416dae677d5551 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Wed, 30 Apr 2025 18:42:43 +0200
Subject: [PATCH 39/44] avcodec/mpeg12dec: Reinit upon chroma_format change

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpeg12dec.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
index 3f387de0fd..a06cacb87a 100644
--- a/libavcodec/mpeg12dec.c
+++ b/libavcodec/mpeg12dec.c
@@ -80,7 +80,7 @@ typedef struct Mpeg1Context {
     int has_afd;
     int slice_count;
     unsigned aspect_ratio_info;
-    int save_width, save_height, save_progressive_seq;
+    int save_width, save_height, save_progressive_seq, save_chroma_format;
     AVRational frame_rate_ext;  /* MPEG-2 specific framerate modificator */
     unsigned frame_rate_index;
     int sync;                   /* Did we reach a sync point like a GOP/SEQ/KEYFrame? */
@@ -917,6 +917,7 @@ static int mpeg_decode_postinit(AVCodecContext *avctx)
         avctx->coded_height      != s->height               ||
         s1->save_width           != s->width                ||
         s1->save_height          != s->height               ||
+        s1->save_chroma_format   != s->chroma_format        ||
         (s1->save_progressive_seq != s->progressive_sequence && FFALIGN(s->height, 16) != FFALIGN(s->height, 32)) ||
         0) {
         if (avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO && s1->bit_rate &&
@@ -960,6 +961,7 @@ static int mpeg_decode_postinit(AVCodecContext *avctx)
         s1->save_width           = s->width;
         s1->save_height          = s->height;
         s1->save_progressive_seq = s->progressive_sequence;
+        s1->save_chroma_format   = s->chroma_format;
 
         if (!s->avctx->lowres)
             for (int i = 0; i < s->slice_context_count; i++)
-- 
2.45.2


[-- Attachment #41: 0040-avcodec-mpeg4videodec-Keep-skipped_last_frame-in-syn.patch --]
[-- Type: text/x-patch, Size: 1123 bytes --]

From a7b660ce8aed5bb031617df95170ba34265190e0 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Thu, 1 May 2025 21:06:45 +0200
Subject: [PATCH 40/44] avcodec/mpeg4videodec: Keep skipped_last_frame in sync
 between threads

Otherwise the output may depend upon the number of frame threads used.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpeg4videodec.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
index b4a1e2ffba..d6740c8872 100644
--- a/libavcodec/mpeg4videodec.c
+++ b/libavcodec/mpeg4videodec.c
@@ -3856,6 +3856,7 @@ static int mpeg4_update_thread_context(AVCodecContext *dst,
     s->cplx_estimation_trash_p   = s1->cplx_estimation_trash_p;
     s->cplx_estimation_trash_b   = s1->cplx_estimation_trash_b;
     s->rgb                       = s1->rgb;
+    s->m.skipped_last_frame      = s1->m.skipped_last_frame;
 
     memcpy(s->sprite_shift, s1->sprite_shift, sizeof(s1->sprite_shift));
     memcpy(s->sprite_traj,  s1->sprite_traj,  sizeof(s1->sprite_traj));
-- 
2.45.2


[-- Attachment #42: 0041-avcodec-h263dec-Always-output-next-not-current-pic-w.patch --]
[-- Type: text/x-patch, Size: 2179 bytes --]

From dcd7c01b2eb05da1fe1081097f481e33f0324046 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Thu, 1 May 2025 21:51:07 +0200
Subject: [PATCH 41/44] avcodec/h263dec: Always output next, not current pic
 when flushing

It is the last picture in display order.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/h263dec.c | 23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)

diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c
index cbcd719859..33dccfad2c 100644
--- a/libavcodec/h263dec.c
+++ b/libavcodec/h263dec.c
@@ -439,22 +439,19 @@ int ff_h263_decode_frame(AVCodecContext *avctx, AVFrame *pict,
     /* no supplementary picture */
     if (buf_size == 0) {
         /* special case for last picture */
-        if (s->low_delay == 0 && s->next_pic.ptr) {
+        if ((!s->low_delay || s->skipped_last_frame) && s->next_pic.ptr) {
             if ((ret = av_frame_ref(pict, s->next_pic.ptr->f)) < 0)
                 return ret;
-            ff_mpv_unref_picture(&s->next_pic);
+            if (s->skipped_last_frame) {
+                /* If the stream ended with an NVOP, we output the last frame
+                 * in display order, but with the props from the last input
+                 * packet so that the stream's end time is correct. */
+                ret = ff_decode_frame_props(avctx, pict);
+                if (ret < 0)
+                    return ret;
+            }
 
-            *got_frame = 1;
-        } else if (s->skipped_last_frame && s->cur_pic.ptr) {
-            /* Output the last picture we decoded again if the stream ended with
-             * an NVOP */
-            if ((ret = av_frame_ref(pict, s->cur_pic.ptr->f)) < 0)
-                return ret;
-            /* Copy props from the last input packet. Otherwise, props from the last
-             * returned picture would be reused */
-            if ((ret = ff_decode_frame_props(avctx, pict)) < 0)
-                return ret;
-            ff_mpv_unref_picture(&s->cur_pic);
+            ff_mpv_unref_picture(&s->next_pic);
 
             *got_frame = 1;
         }
-- 
2.45.2


[-- Attachment #43: 0042-avcodec-mpeg4videodec-h263dec-Only-set-skipped_last_.patch --]
[-- Type: text/x-patch, Size: 1963 bytes --]

From b9005093a317e0398d63b31de63112589d336b59 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Thu, 1 May 2025 22:31:36 +0200
Subject: [PATCH 42/44] avcodec/mpeg4videodec,h263dec: Only set
 skipped_last_frame for !vop_coded

This is more in line with the spec and avoids a branch.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/h263dec.c       | 1 -
 libavcodec/mpeg4videodec.c | 3 +++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c
index 33dccfad2c..cfeaf1520f 100644
--- a/libavcodec/h263dec.c
+++ b/libavcodec/h263dec.c
@@ -476,7 +476,6 @@ int ff_h263_decode_frame(AVCodecContext *avctx, AVFrame *pict,
 #endif
     } else if (CONFIG_MPEG4_DECODER && avctx->codec_id == AV_CODEC_ID_MPEG4) {
         ret = ff_mpeg4_decode_picture_header(s);
-        s->skipped_last_frame = (ret == FRAME_SKIPPED);
     } else if (CONFIG_H263I_DECODER && s->codec_id == AV_CODEC_ID_H263I) {
         ret = ff_intel_h263_decode_picture_header(s);
     } else if (CONFIG_FLV_DECODER && s->h263_flv) {
diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
index d6740c8872..6d26eb6c8e 100644
--- a/libavcodec/mpeg4videodec.c
+++ b/libavcodec/mpeg4videodec.c
@@ -3259,6 +3259,7 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb,
     if (get_bits1(gb) != 1) {
         if (s->avctx->debug & FF_DEBUG_PICT_INFO)
             av_log(s->avctx, AV_LOG_ERROR, "vop not coded\n");
+        s->skipped_last_frame = 1;
         return FRAME_SKIPPED;
     }
     if (ctx->new_pred)
@@ -3685,6 +3686,8 @@ int ff_mpeg4_decode_picture_header(MpegEncContext *s)
 {
     Mpeg4DecContext *const ctx = (Mpeg4DecContext*)s;
 
+    s->skipped_last_frame = 0;
+
     if (ctx->bitstream_buffer) {
         int buf_size = get_bits_left(&s->gb) / 8U;
         int bitstream_buffer_size = ctx->bitstream_buffer->size;
-- 
2.45.2


[-- Attachment #44: 0043-avcodec-mpeg4videodec-Move-setting-has_b_frames-to-m.patch --]
[-- Type: text/x-patch, Size: 1639 bytes --]

From fe879aa298208de4235a11952d7c1881c6147ea8 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Thu, 1 May 2025 22:50:00 +0200
Subject: [PATCH 43/44] avcodec/mpeg4videodec: Move setting has_b_frames to
 mpeg4video_parser.c

ff_h263_decode_frame() already does it generically for the decoder.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpeg4video_parser.c | 1 +
 libavcodec/mpeg4videodec.c     | 1 -
 2 files changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/mpeg4video_parser.c b/libavcodec/mpeg4video_parser.c
index ef9ea923f6..de92f1b1dc 100644
--- a/libavcodec/mpeg4video_parser.c
+++ b/libavcodec/mpeg4video_parser.c
@@ -99,6 +99,7 @@ static int mpeg4_decode_header(AVCodecParserContext *s1, AVCodecContext *avctx,
 
     init_get_bits(gb, buf, 8 * buf_size);
     ret = ff_mpeg4_parse_picture_header(dec_ctx, gb, 0, 1);
+    avctx->has_b_frames = !s->low_delay;
     if (s->width && (!avctx->width || !avctx->height ||
                      !avctx->coded_width || !avctx->coded_height)) {
         ret = ff_set_dimensions(avctx, s->width, s->height);
diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
index 6d26eb6c8e..707b12dd7b 100644
--- a/libavcodec/mpeg4videodec.c
+++ b/libavcodec/mpeg4videodec.c
@@ -3670,7 +3670,6 @@ int ff_mpeg4_parse_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb,
 end:
     if (s->avctx->flags & AV_CODEC_FLAG_LOW_DELAY)
         s->low_delay = 1;
-    s->avctx->has_b_frames = !s->low_delay;
 
     if (s->studio_profile) {
         if (!s->avctx->bits_per_raw_sample) {
-- 
2.45.2


[-- Attachment #45: 0044-avcodec-mpegvideo-Move-parent-to-MPVEncContext.patch --]
[-- Type: text/x-patch, Size: 3029 bytes --]

From 93aea509729e4bf740669aa79fba5b4340c65817 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Wed, 30 Apr 2025 04:09:11 +0200
Subject: [PATCH 44/44] avcodec/mpegvideo: Move parent to MPVEncContext

This is more type-safe and avoids having parent contexts
when unnecessary.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpegvideo.c     | 2 --
 libavcodec/mpegvideo.h     | 4 ----
 libavcodec/mpegvideo_enc.c | 1 +
 libavcodec/mpegvideoenc.h  | 4 +++-
 4 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
index 6d6f126fd3..1297c584f2 100644
--- a/libavcodec/mpegvideo.c
+++ b/libavcodec/mpegvideo.c
@@ -140,8 +140,6 @@ av_cold int ff_mpv_init_duplicate_contexts(MpegEncContext *s)
     int nb_slices = s->slice_context_count, ret;
     size_t slice_size = s->slice_ctx_size ? s->slice_ctx_size : sizeof(*s);
 
-    s->parent = s;
-
     /* We initialize the copies before the original so that
      * fields allocated in init_duplicate_context are NULL after
      * copying. This prevents double-frees upon allocation error. */
diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h
index 3a769db569..e79d93c48b 100644
--- a/libavcodec/mpegvideo.h
+++ b/libavcodec/mpegvideo.h
@@ -80,10 +80,6 @@ typedef struct MpegEncContext {
     uint8_t permutated_intra_v_scantable[64];
 
     struct AVCodecContext *avctx;
-    union {
-        const struct MpegEncContext *parent;
-        const struct MPVMainEncContext *encparent;
-    };
     /* The following pointer is intended for codecs sharing code
      * between decoder and encoder and in need of a common context to do so. */
     void *private_ctx;
diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c
index f1de7f6ff6..503906efeb 100644
--- a/libavcodec/mpegvideo_enc.c
+++ b/libavcodec/mpegvideo_enc.c
@@ -1023,6 +1023,7 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx)
     /* ff_mpv_init_duplicate_contexts() will copy (memdup) the contents of the
      * main slice to the slice contexts, so we initialize various fields of it
      * before calling ff_mpv_init_duplicate_contexts(). */
+    s->parent = m;
     ff_mpv_idct_init(&s->c);
     init_unquantize(&s->c, avctx);
     ff_fdctdsp_init(&s->fdsp, avctx);
diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h
index 76e3780923..ec0304c4a0 100644
--- a/libavcodec/mpegvideoenc.h
+++ b/libavcodec/mpegvideoenc.h
@@ -69,6 +69,8 @@ typedef struct MPVEncContext {
      */
     AVFrame *new_pic;
 
+    struct MPVMainEncContext *parent;
+
     FDCTDSPContext fdsp;
     MpegvideoEncDSPContext mpvencdsp;
     PixblockDSPContext pdsp;
@@ -254,7 +256,7 @@ static inline const MPVMainEncContext *slice_to_mainenc(const MPVEncContext *s)
                !(s->c.avctx->codec->capabilities & AV_CODEC_CAP_SLICE_THREADS));
     return (const MPVMainEncContext*)s;
 #else
-    return s->c.encparent;
+    return s->parent;
 #endif
 }
 
-- 
2.45.2


[-- Attachment #46: Type: text/plain, Size: 251 bytes --]

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

                 reply	other threads:[~2025-05-02  0:12 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=GV1P250MB0737B773C8A292FCEB12BF598F8D2@GV1P250MB0737.EURP250.PROD.OUTLOOK.COM \
    --to=andreas.rheinhardt@outlook.com \
    --cc=ffmpeg-devel@ffmpeg.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git