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-devel@ffmpeg.org
Subject: Re: [FFmpeg-devel] [PATCH 01/77] avcodec/mpegvideo(_enc)?: Mark init, close functions as, av_cold
Date: Sat, 22 Mar 2025 14:16:55 +0100
Message-ID: <GV1SPRMB003675F14FD6B01A4B42D87F8FDA2@GV1SPRMB0036.EURP250.PROD.OUTLOOK.COM> (raw)
In-Reply-To: <20250322003428.GK4991@pb2>

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

Michael Niedermayer:
> On Wed, Mar 19, 2025 at 10:18:38PM +0100, Andreas Rheinhardt wrote:
>> First part of a patchset; the second part will be sent separately
>> because the complete set crosses the ML thresholds ("Message body is too
>> big: 1731572 bytes with a limit of 1000 KB"). A complete branch can be
> 
>> found here: https://github.com/mkver/FFmpeg/tree/mpvenc
> 
> tested the branch on mips:
> 
> make -k
> CC	libavcodec/mpegvideo_unquantize.o
> src/libavcodec/mpegvideo_unquantize.c: In function ‘ff_mpv_unquantize_init’:
> src/libavcodec/mpegvideo_unquantize.c:272:34: error: ‘s’ is a pointer; did you mean to use ‘->’?
>      ff_mpv_unquantize_init_mips(s. avctx, q_scale_type);
>                                   ^
>                                   ->
> src/libavcodec/mpegvideo_unquantize.c:272:43: warning: passing argument 2 of ‘ff_mpv_unquantize_init_mips’ makes pointer from integer without a cast [-Wint-conversion]
>      ff_mpv_unquantize_init_mips(s. avctx, q_scale_type);
>                                            ^~~~~~~~~~~~
> In file included from src/libavcodec/mpegvideo_unquantize.c:34:0:
> src/libavcodec/mpegvideo_unquantize.h:60:6: note: expected ‘AVCodecContext * {aka struct AVCodecContext *}’ but argument is of type ‘int’
>  void ff_mpv_unquantize_init_mips(MPVUnquantDSPContext *s, AVCodecContext *avctx,
>       ^~~~~~~~~~~~~~~~~~~~~~~~~~~
> src/libavcodec/mpegvideo_unquantize.c:272:5: error: too few arguments to function ‘ff_mpv_unquantize_init_mips’
>      ff_mpv_unquantize_init_mips(s. avctx, q_scale_type);
>      ^~~~~~~~~~~~~~~~~~~~~~~~~~~
> In file included from src/libavcodec/mpegvideo_unquantize.c:34:0:
> src/libavcodec/mpegvideo_unquantize.h:60:6: note: declared here
>  void ff_mpv_unquantize_init_mips(MPVUnquantDSPContext *s, AVCodecContext *avctx,
>       ^~~~~~~~~~~~~~~~~~~~~~~~~~~
> make: *** [src/ffbuild/common.mak:81: libavcodec/mpegvideo_unquantize.o] Error 1
> make: Target 'all' not remade because of errors.
> 
> [...]

Thanks. I fixed this as well as a bug in the ppc/altivec unquantize
functions and force pushed my branch. Please replace the last two
patches with the ones attached here (or just look at the github branch).

- Andreas

PS: Both mips as well as arm (neon) always use the inter scantable. This
works because the derived raster_end for inter is always >= the
raster_end for intra. I didn't fix MIPS, because I can't seem to compile
MMI; and I didn't change ARM, because it would entail tinkering with
external assembly.

[-- Attachment #2: 0076-avcodec-mpegvideo-Move-unquantize-functions-into-a-f.patch --]
[-- Type: text/x-patch, Size: 22498 bytes --]

From 3c1a1e3d4fe0a2f58a9877be09da5634904d6111 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Sun, 2 Mar 2025 05:44:09 +0100
Subject: [PATCH 76/81] avcodec/mpegvideo: Move unquantize functions into a
 file of their own

This is in preparation for only keeping the actually used
unquantize functions in MpegEncContext.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/Makefile                   |   1 +
 libavcodec/arm/mpegvideo_arm.c        |   1 +
 libavcodec/mips/mpegvideo_init_mips.c |   1 +
 libavcodec/mpegvideo.c                | 237 +---------------------
 libavcodec/mpegvideo.h                |   5 -
 libavcodec/mpegvideo_unquantize.c     | 273 ++++++++++++++++++++++++++
 libavcodec/mpegvideo_unquantize.h     |  37 ++++
 libavcodec/neon/mpegvideo.c           |   1 +
 libavcodec/ppc/mpegvideo_altivec.c    |   1 +
 libavcodec/x86/mpegvideo.c            |   1 +
 10 files changed, 318 insertions(+), 240 deletions(-)
 create mode 100644 libavcodec/mpegvideo_unquantize.c
 create mode 100644 libavcodec/mpegvideo_unquantize.h

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 37b201ec4a..b2abb3b863 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -147,6 +147,7 @@ OBJS-$(CONFIG_MPEGAUDIOHEADER)         += mpegaudiodecheader.o mpegaudiotabs.o
 OBJS-$(CONFIG_MPEG4AUDIO)              += mpeg4audio.o mpeg4audio_sample_rates.o
 OBJS-$(CONFIG_MPEGVIDEO)               += mpegvideo.o rl.o \
                                           mpegvideo_motion.o \
+                                          mpegvideo_unquantize.o \
                                           mpegvideodata.o mpegpicture.o  \
                                           to_upper4.o
 OBJS-$(CONFIG_MPEGVIDEODEC)            += mpegvideo_dec.o mpegutils.o
diff --git a/libavcodec/arm/mpegvideo_arm.c b/libavcodec/arm/mpegvideo_arm.c
index 28a3f2cdd9..e32451b554 100644
--- a/libavcodec/arm/mpegvideo_arm.c
+++ b/libavcodec/arm/mpegvideo_arm.c
@@ -24,6 +24,7 @@
 #include "libavutil/arm/cpu.h"
 #include "libavcodec/avcodec.h"
 #include "libavcodec/mpegvideo.h"
+#include "libavcodec/mpegvideo_unquantize.h"
 #include "mpegvideo_arm.h"
 #include "asm-offsets.h"
 
diff --git a/libavcodec/mips/mpegvideo_init_mips.c b/libavcodec/mips/mpegvideo_init_mips.c
index 1d02b0c937..a9acae94ce 100644
--- a/libavcodec/mips/mpegvideo_init_mips.c
+++ b/libavcodec/mips/mpegvideo_init_mips.c
@@ -20,6 +20,7 @@
 
 #include "libavutil/attributes.h"
 #include "libavutil/mips/cpu.h"
+#include "libavcodec/mpegvideo_unquantize.h"
 #include "h263dsp_mips.h"
 #include "mpegvideo_mips.h"
 
diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
index efc9ee24d6..9a40937bbd 100644
--- a/libavcodec/mpegvideo.c
+++ b/libavcodec/mpegvideo.c
@@ -41,221 +41,9 @@
 #include "mpegutils.h"
 #include "mpegvideo.h"
 #include "mpegvideodata.h"
+#include "mpegvideo_unquantize.h"
 #include "libavutil/refstruct.h"
 
-static void dct_unquantize_mpeg1_intra_c(MpegEncContext *s,
-                                   int16_t *block, int n, int qscale)
-{
-    int i, level, nCoeffs;
-    const uint16_t *quant_matrix;
-
-    nCoeffs= s->block_last_index[n];
-
-    block[0] *= n < 4 ? s->y_dc_scale : s->c_dc_scale;
-    /* XXX: only MPEG-1 */
-    quant_matrix = s->intra_matrix;
-    for(i=1;i<=nCoeffs;i++) {
-        int j= s->intra_scantable.permutated[i];
-        level = block[j];
-        if (level) {
-            if (level < 0) {
-                level = -level;
-                level = (int)(level * qscale * quant_matrix[j]) >> 3;
-                level = (level - 1) | 1;
-                level = -level;
-            } else {
-                level = (int)(level * qscale * quant_matrix[j]) >> 3;
-                level = (level - 1) | 1;
-            }
-            block[j] = level;
-        }
-    }
-}
-
-static void dct_unquantize_mpeg1_inter_c(MpegEncContext *s,
-                                   int16_t *block, int n, int qscale)
-{
-    int i, level, nCoeffs;
-    const uint16_t *quant_matrix;
-
-    nCoeffs= s->block_last_index[n];
-
-    quant_matrix = s->inter_matrix;
-    for(i=0; i<=nCoeffs; i++) {
-        int j= s->intra_scantable.permutated[i];
-        level = block[j];
-        if (level) {
-            if (level < 0) {
-                level = -level;
-                level = (((level << 1) + 1) * qscale *
-                         ((int) (quant_matrix[j]))) >> 4;
-                level = (level - 1) | 1;
-                level = -level;
-            } else {
-                level = (((level << 1) + 1) * qscale *
-                         ((int) (quant_matrix[j]))) >> 4;
-                level = (level - 1) | 1;
-            }
-            block[j] = level;
-        }
-    }
-}
-
-static void dct_unquantize_mpeg2_intra_c(MpegEncContext *s,
-                                   int16_t *block, int n, int qscale)
-{
-    int i, level, nCoeffs;
-    const uint16_t *quant_matrix;
-
-    if (s->q_scale_type) qscale = ff_mpeg2_non_linear_qscale[qscale];
-    else                 qscale <<= 1;
-
-    nCoeffs= s->block_last_index[n];
-
-    block[0] *= n < 4 ? s->y_dc_scale : s->c_dc_scale;
-    quant_matrix = s->intra_matrix;
-    for(i=1;i<=nCoeffs;i++) {
-        int j= s->intra_scantable.permutated[i];
-        level = block[j];
-        if (level) {
-            if (level < 0) {
-                level = -level;
-                level = (int)(level * qscale * quant_matrix[j]) >> 4;
-                level = -level;
-            } else {
-                level = (int)(level * qscale * quant_matrix[j]) >> 4;
-            }
-            block[j] = level;
-        }
-    }
-}
-
-static void dct_unquantize_mpeg2_intra_bitexact(MpegEncContext *s,
-                                   int16_t *block, int n, int qscale)
-{
-    int i, level, nCoeffs;
-    const uint16_t *quant_matrix;
-    int sum=-1;
-
-    if (s->q_scale_type) qscale = ff_mpeg2_non_linear_qscale[qscale];
-    else                 qscale <<= 1;
-
-    nCoeffs= s->block_last_index[n];
-
-    block[0] *= n < 4 ? s->y_dc_scale : s->c_dc_scale;
-    sum += block[0];
-    quant_matrix = s->intra_matrix;
-    for(i=1;i<=nCoeffs;i++) {
-        int j= s->intra_scantable.permutated[i];
-        level = block[j];
-        if (level) {
-            if (level < 0) {
-                level = -level;
-                level = (int)(level * qscale * quant_matrix[j]) >> 4;
-                level = -level;
-            } else {
-                level = (int)(level * qscale * quant_matrix[j]) >> 4;
-            }
-            block[j] = level;
-            sum+=level;
-        }
-    }
-    block[63]^=sum&1;
-}
-
-static void dct_unquantize_mpeg2_inter_c(MpegEncContext *s,
-                                   int16_t *block, int n, int qscale)
-{
-    int i, level, nCoeffs;
-    const uint16_t *quant_matrix;
-    int sum=-1;
-
-    if (s->q_scale_type) qscale = ff_mpeg2_non_linear_qscale[qscale];
-    else                 qscale <<= 1;
-
-    nCoeffs= s->block_last_index[n];
-
-    quant_matrix = s->inter_matrix;
-    for(i=0; i<=nCoeffs; i++) {
-        int j= s->intra_scantable.permutated[i];
-        level = block[j];
-        if (level) {
-            if (level < 0) {
-                level = -level;
-                level = (((level << 1) + 1) * qscale *
-                         ((int) (quant_matrix[j]))) >> 5;
-                level = -level;
-            } else {
-                level = (((level << 1) + 1) * qscale *
-                         ((int) (quant_matrix[j]))) >> 5;
-            }
-            block[j] = level;
-            sum+=level;
-        }
-    }
-    block[63]^=sum&1;
-}
-
-static void dct_unquantize_h263_intra_c(MpegEncContext *s,
-                                  int16_t *block, int n, int qscale)
-{
-    int i, level, qmul, qadd;
-    int nCoeffs;
-
-    av_assert2(s->block_last_index[n]>=0 || s->h263_aic);
-
-    qmul = qscale << 1;
-
-    if (!s->h263_aic) {
-        block[0] *= n < 4 ? s->y_dc_scale : s->c_dc_scale;
-        qadd = (qscale - 1) | 1;
-    }else{
-        qadd = 0;
-    }
-    if(s->ac_pred)
-        nCoeffs=63;
-    else
-        nCoeffs= s->intra_scantable.raster_end[ s->block_last_index[n] ];
-
-    for(i=1; i<=nCoeffs; i++) {
-        level = block[i];
-        if (level) {
-            if (level < 0) {
-                level = level * qmul - qadd;
-            } else {
-                level = level * qmul + qadd;
-            }
-            block[i] = level;
-        }
-    }
-}
-
-static void dct_unquantize_h263_inter_c(MpegEncContext *s,
-                                  int16_t *block, int n, int qscale)
-{
-    int i, level, qmul, qadd;
-    int nCoeffs;
-
-    av_assert2(s->block_last_index[n]>=0);
-
-    qadd = (qscale - 1) | 1;
-    qmul = qscale << 1;
-
-    nCoeffs= s->inter_scantable.raster_end[ s->block_last_index[n] ];
-
-    for(i=0; i<=nCoeffs; i++) {
-        level = block[i];
-        if (level) {
-            if (level < 0) {
-                level = level * qmul - qadd;
-            } else {
-                level = level * qmul + qadd;
-            }
-            block[i] = level;
-        }
-    }
-}
-
 
 static void gray16(uint8_t *dst, const uint8_t *src, ptrdiff_t linesize, int h)
 {
@@ -325,28 +113,7 @@ av_cold void ff_mpv_idct_init(MpegEncContext *s)
     ff_permute_scantable(s->permutated_intra_v_scantable, ff_alternate_vertical_scan,
                          s->idsp.idct_permutation);
 
-    s->dct_unquantize_h263_intra  = dct_unquantize_h263_intra_c;
-    s->dct_unquantize_h263_inter  = dct_unquantize_h263_inter_c;
-    s->dct_unquantize_mpeg1_intra = dct_unquantize_mpeg1_intra_c;
-    s->dct_unquantize_mpeg1_inter = dct_unquantize_mpeg1_inter_c;
-    s->dct_unquantize_mpeg2_intra = dct_unquantize_mpeg2_intra_c;
-    if (s->avctx->flags & AV_CODEC_FLAG_BITEXACT)
-        s->dct_unquantize_mpeg2_intra = dct_unquantize_mpeg2_intra_bitexact;
-    s->dct_unquantize_mpeg2_inter = dct_unquantize_mpeg2_inter_c;
-
-#if HAVE_INTRINSICS_NEON
-    ff_mpv_common_init_neon(s);
-#endif
-
-#if ARCH_ARM
-    ff_mpv_common_init_arm(s);
-#elif ARCH_PPC
-    ff_mpv_common_init_ppc(s);
-#elif ARCH_X86
-    ff_mpv_common_init_x86(s);
-#elif ARCH_MIPS
-    ff_mpv_common_init_mips(s);
-#endif
+    ff_mpv_unquantize_init(s);
 }
 
 static av_cold int init_duplicate_context(MpegEncContext *s)
diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h
index 1dcfca6b03..7379160159 100644
--- a/libavcodec/mpegvideo.h
+++ b/libavcodec/mpegvideo.h
@@ -362,11 +362,6 @@ typedef struct MpegEncContext {
 void ff_mpv_common_defaults(MpegEncContext *s);
 
 int ff_mpv_common_init(MpegEncContext *s);
-void ff_mpv_common_init_arm(MpegEncContext *s);
-void ff_mpv_common_init_neon(MpegEncContext *s);
-void ff_mpv_common_init_ppc(MpegEncContext *s);
-void ff_mpv_common_init_x86(MpegEncContext *s);
-void ff_mpv_common_init_mips(MpegEncContext *s);
 /**
  * Initialize an MpegEncContext's thread contexts. Presumes that
  * slice_context_count is already set and that all the fields
diff --git a/libavcodec/mpegvideo_unquantize.c b/libavcodec/mpegvideo_unquantize.c
new file mode 100644
index 0000000000..12bacdf424
--- /dev/null
+++ b/libavcodec/mpegvideo_unquantize.c
@@ -0,0 +1,273 @@
+/*
+ * Unquantize functions for mpegvideo
+ * Copyright (c) 2000,2001 Fabrice Bellard
+ * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * 4MV & hq & B-frame encoding stuff by Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+
+#include "config.h"
+
+#include "libavutil/attributes.h"
+#include "libavutil/avassert.h"
+#include "avcodec.h"
+#include "mpegvideo.h"
+#include "mpegvideodata.h"
+#include "mpegvideo_unquantize.h"
+
+static void dct_unquantize_mpeg1_intra_c(MpegEncContext *s,
+                                   int16_t *block, int n, int qscale)
+{
+    int i, level, nCoeffs;
+    const uint16_t *quant_matrix;
+
+    nCoeffs= s->block_last_index[n];
+
+    block[0] *= n < 4 ? s->y_dc_scale : s->c_dc_scale;
+    /* XXX: only MPEG-1 */
+    quant_matrix = s->intra_matrix;
+    for(i=1;i<=nCoeffs;i++) {
+        int j= s->intra_scantable.permutated[i];
+        level = block[j];
+        if (level) {
+            if (level < 0) {
+                level = -level;
+                level = (int)(level * qscale * quant_matrix[j]) >> 3;
+                level = (level - 1) | 1;
+                level = -level;
+            } else {
+                level = (int)(level * qscale * quant_matrix[j]) >> 3;
+                level = (level - 1) | 1;
+            }
+            block[j] = level;
+        }
+    }
+}
+
+static void dct_unquantize_mpeg1_inter_c(MpegEncContext *s,
+                                   int16_t *block, int n, int qscale)
+{
+    int i, level, nCoeffs;
+    const uint16_t *quant_matrix;
+
+    nCoeffs= s->block_last_index[n];
+
+    quant_matrix = s->inter_matrix;
+    for(i=0; i<=nCoeffs; i++) {
+        int j= s->intra_scantable.permutated[i];
+        level = block[j];
+        if (level) {
+            if (level < 0) {
+                level = -level;
+                level = (((level << 1) + 1) * qscale *
+                         ((int) (quant_matrix[j]))) >> 4;
+                level = (level - 1) | 1;
+                level = -level;
+            } else {
+                level = (((level << 1) + 1) * qscale *
+                         ((int) (quant_matrix[j]))) >> 4;
+                level = (level - 1) | 1;
+            }
+            block[j] = level;
+        }
+    }
+}
+
+static void dct_unquantize_mpeg2_intra_c(MpegEncContext *s,
+                                   int16_t *block, int n, int qscale)
+{
+    int i, level, nCoeffs;
+    const uint16_t *quant_matrix;
+
+    if (s->q_scale_type) qscale = ff_mpeg2_non_linear_qscale[qscale];
+    else                 qscale <<= 1;
+
+    nCoeffs= s->block_last_index[n];
+
+    block[0] *= n < 4 ? s->y_dc_scale : s->c_dc_scale;
+    quant_matrix = s->intra_matrix;
+    for(i=1;i<=nCoeffs;i++) {
+        int j= s->intra_scantable.permutated[i];
+        level = block[j];
+        if (level) {
+            if (level < 0) {
+                level = -level;
+                level = (int)(level * qscale * quant_matrix[j]) >> 4;
+                level = -level;
+            } else {
+                level = (int)(level * qscale * quant_matrix[j]) >> 4;
+            }
+            block[j] = level;
+        }
+    }
+}
+
+static void dct_unquantize_mpeg2_intra_bitexact(MpegEncContext *s,
+                                   int16_t *block, int n, int qscale)
+{
+    int i, level, nCoeffs;
+    const uint16_t *quant_matrix;
+    int sum=-1;
+
+    if (s->q_scale_type) qscale = ff_mpeg2_non_linear_qscale[qscale];
+    else                 qscale <<= 1;
+
+    nCoeffs= s->block_last_index[n];
+
+    block[0] *= n < 4 ? s->y_dc_scale : s->c_dc_scale;
+    sum += block[0];
+    quant_matrix = s->intra_matrix;
+    for(i=1;i<=nCoeffs;i++) {
+        int j= s->intra_scantable.permutated[i];
+        level = block[j];
+        if (level) {
+            if (level < 0) {
+                level = -level;
+                level = (int)(level * qscale * quant_matrix[j]) >> 4;
+                level = -level;
+            } else {
+                level = (int)(level * qscale * quant_matrix[j]) >> 4;
+            }
+            block[j] = level;
+            sum+=level;
+        }
+    }
+    block[63]^=sum&1;
+}
+
+static void dct_unquantize_mpeg2_inter_c(MpegEncContext *s,
+                                   int16_t *block, int n, int qscale)
+{
+    int i, level, nCoeffs;
+    const uint16_t *quant_matrix;
+    int sum=-1;
+
+    if (s->q_scale_type) qscale = ff_mpeg2_non_linear_qscale[qscale];
+    else                 qscale <<= 1;
+
+    nCoeffs= s->block_last_index[n];
+
+    quant_matrix = s->inter_matrix;
+    for(i=0; i<=nCoeffs; i++) {
+        int j= s->intra_scantable.permutated[i];
+        level = block[j];
+        if (level) {
+            if (level < 0) {
+                level = -level;
+                level = (((level << 1) + 1) * qscale *
+                         ((int) (quant_matrix[j]))) >> 5;
+                level = -level;
+            } else {
+                level = (((level << 1) + 1) * qscale *
+                         ((int) (quant_matrix[j]))) >> 5;
+            }
+            block[j] = level;
+            sum+=level;
+        }
+    }
+    block[63]^=sum&1;
+}
+
+static void dct_unquantize_h263_intra_c(MpegEncContext *s,
+                                  int16_t *block, int n, int qscale)
+{
+    int i, level, qmul, qadd;
+    int nCoeffs;
+
+    av_assert2(s->block_last_index[n]>=0 || s->h263_aic);
+
+    qmul = qscale << 1;
+
+    if (!s->h263_aic) {
+        block[0] *= n < 4 ? s->y_dc_scale : s->c_dc_scale;
+        qadd = (qscale - 1) | 1;
+    }else{
+        qadd = 0;
+    }
+    if(s->ac_pred)
+        nCoeffs=63;
+    else
+        nCoeffs= s->intra_scantable.raster_end[ s->block_last_index[n] ];
+
+    for(i=1; i<=nCoeffs; i++) {
+        level = block[i];
+        if (level) {
+            if (level < 0) {
+                level = level * qmul - qadd;
+            } else {
+                level = level * qmul + qadd;
+            }
+            block[i] = level;
+        }
+    }
+}
+
+static void dct_unquantize_h263_inter_c(MpegEncContext *s,
+                                  int16_t *block, int n, int qscale)
+{
+    int i, level, qmul, qadd;
+    int nCoeffs;
+
+    av_assert2(s->block_last_index[n]>=0);
+
+    qadd = (qscale - 1) | 1;
+    qmul = qscale << 1;
+
+    nCoeffs= s->inter_scantable.raster_end[ s->block_last_index[n] ];
+
+    for(i=0; i<=nCoeffs; i++) {
+        level = block[i];
+        if (level) {
+            if (level < 0) {
+                level = level * qmul - qadd;
+            } else {
+                level = level * qmul + qadd;
+            }
+            block[i] = level;
+        }
+    }
+}
+
+av_cold void ff_mpv_unquantize_init(MpegEncContext *s)
+{
+    s->dct_unquantize_h263_intra  = dct_unquantize_h263_intra_c;
+    s->dct_unquantize_h263_inter  = dct_unquantize_h263_inter_c;
+    s->dct_unquantize_mpeg1_intra = dct_unquantize_mpeg1_intra_c;
+    s->dct_unquantize_mpeg1_inter = dct_unquantize_mpeg1_inter_c;
+    s->dct_unquantize_mpeg2_intra = dct_unquantize_mpeg2_intra_c;
+    if (s->avctx->flags & AV_CODEC_FLAG_BITEXACT)
+        s->dct_unquantize_mpeg2_intra = dct_unquantize_mpeg2_intra_bitexact;
+    s->dct_unquantize_mpeg2_inter = dct_unquantize_mpeg2_inter_c;
+
+#if HAVE_INTRINSICS_NEON
+    ff_mpv_common_init_neon(s);
+#endif
+
+#if ARCH_ARM
+    ff_mpv_common_init_arm(s);
+#elif ARCH_PPC
+    ff_mpv_common_init_ppc(s);
+#elif ARCH_X86
+    ff_mpv_common_init_x86(s);
+#elif ARCH_MIPS
+    ff_mpv_common_init_mips(s);
+#endif
+}
diff --git a/libavcodec/mpegvideo_unquantize.h b/libavcodec/mpegvideo_unquantize.h
new file mode 100644
index 0000000000..1e7590561c
--- /dev/null
+++ b/libavcodec/mpegvideo_unquantize.h
@@ -0,0 +1,37 @@
+/*
+ * Unquantize functions for mpegvideo
+ * Copyright (c) 2000,2001 Fabrice Bellard
+ * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * 4MV & hq & B-frame encoding stuff by Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_MPEGVIDEO_UNQUANTIZE_H
+#define AVCODEC_MPEGVIDEO_UNQUANTIZE_H
+
+typedef struct MpegEncContext MpegEncContext;
+
+void ff_mpv_unquantize_init(MpegEncContext *s);
+void ff_mpv_common_init_arm(MpegEncContext *s);
+void ff_mpv_common_init_neon(MpegEncContext *s);
+void ff_mpv_common_init_ppc(MpegEncContext *s);
+void ff_mpv_common_init_x86(MpegEncContext *s);
+void ff_mpv_common_init_mips(MpegEncContext *s);
+
+#endif /* AVCODEC_MPEGVIDEO_UNQUANTIZE_H */
diff --git a/libavcodec/neon/mpegvideo.c b/libavcodec/neon/mpegvideo.c
index 8f05d77a65..a8b2a0606d 100644
--- a/libavcodec/neon/mpegvideo.c
+++ b/libavcodec/neon/mpegvideo.c
@@ -32,6 +32,7 @@
 #endif
 
 #include "libavcodec/mpegvideo.h"
+#include "libavcodec/mpegvideo_unquantize.h"
 
 static void inline ff_dct_unquantize_h263_neon(int qscale, int qadd, int nCoeffs,
                                                int16_t *block)
diff --git a/libavcodec/ppc/mpegvideo_altivec.c b/libavcodec/ppc/mpegvideo_altivec.c
index bcb59ba845..c361ca7857 100644
--- a/libavcodec/ppc/mpegvideo_altivec.c
+++ b/libavcodec/ppc/mpegvideo_altivec.c
@@ -33,6 +33,7 @@
 #include "libavutil/ppc/util_altivec.h"
 
 #include "libavcodec/mpegvideo.h"
+#include "libavcodec/mpegvideo_unquantize.h"
 
 #if HAVE_ALTIVEC
 
diff --git a/libavcodec/x86/mpegvideo.c b/libavcodec/x86/mpegvideo.c
index 9878607a81..11a5ee474b 100644
--- a/libavcodec/x86/mpegvideo.c
+++ b/libavcodec/x86/mpegvideo.c
@@ -26,6 +26,7 @@
 #include "libavcodec/avcodec.h"
 #include "libavcodec/mpegvideo.h"
 #include "libavcodec/mpegvideodata.h"
+#include "libavcodec/mpegvideo_unquantize.h"
 
 #if HAVE_MMX_INLINE
 
-- 
2.45.2


[-- Attachment #3: 0077-avcodec-ppc-mpegvideo_altivec-Use-correct-inter-scan.patch --]
[-- Type: text/x-patch, Size: 1385 bytes --]

From bb2b8dd7c52bb85b289c0069cb70d21888602552 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Sat, 22 Mar 2025 06:51:28 +0100
Subject: [PATCH 77/81] avcodec/ppc/mpegvideo_altivec: Use correct inter
 scantable

This affected the WMV1/2 encoders (but not when running FATE because
the encoding part uses the fastint dct, so this code isn't used
then anyway).

It did not affect anything else, because a) only WMV1/2 use different
scantables, b) ff_msmpeg4_decode_block() (and therefore the WMV1
decoder) already unquantize inter macroblocks as they are parsed
c) the WMV2 decoder does not use the unquantize functions for inter
macroblocks at all.

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

diff --git a/libavcodec/ppc/mpegvideo_altivec.c b/libavcodec/ppc/mpegvideo_altivec.c
index c361ca7857..6006d0484d 100644
--- a/libavcodec/ppc/mpegvideo_altivec.c
+++ b/libavcodec/ppc/mpegvideo_altivec.c
@@ -61,7 +61,7 @@ static void dct_unquantize_h263_altivec(MpegEncContext *s,
     } else {
         i = 0;
         av_assert2(s->block_last_index[n]>=0);
-        nCoeffs= s->intra_scantable.raster_end[ s->block_last_index[n] ];
+        nCoeffs = s->inter_scantable.raster_end[s->block_last_index[n]];
     }
 
     {
-- 
2.45.2


[-- Attachment #4: 0078-avcodec-ppc-mpegvideo_altivec-Set-unquantize-functio.patch --]
[-- Type: text/x-patch, Size: 1422 bytes --]

From 18a6f8cc013216ce8e3de3b126e82e2182b1e20e Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Sat, 22 Mar 2025 04:20:14 +0100
Subject: [PATCH 78/81] avcodec/ppc/mpegvideo_altivec: Set unquantize functions
 unconditionally

Don't do it depending upon dct_algo, as this is not supposed
to influence the unquantize function selection.
(This check originated in 05c4072b45f3cde1185de6eccfe7febf91d9f8fd
where it was used for the dct_quantize function only.)

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

diff --git a/libavcodec/ppc/mpegvideo_altivec.c b/libavcodec/ppc/mpegvideo_altivec.c
index 6006d0484d..23b7701fd6 100644
--- a/libavcodec/ppc/mpegvideo_altivec.c
+++ b/libavcodec/ppc/mpegvideo_altivec.c
@@ -123,10 +123,7 @@ av_cold void ff_mpv_common_init_ppc(MpegEncContext *s)
     if (!PPC_ALTIVEC(av_get_cpu_flags()))
         return;
 
-    if ((s->avctx->dct_algo == FF_DCT_AUTO) ||
-        (s->avctx->dct_algo == FF_DCT_ALTIVEC)) {
-        s->dct_unquantize_h263_intra = dct_unquantize_h263_altivec;
-        s->dct_unquantize_h263_inter = dct_unquantize_h263_altivec;
-    }
+    s->dct_unquantize_h263_intra = dct_unquantize_h263_altivec;
+    s->dct_unquantize_h263_inter = dct_unquantize_h263_altivec;
 #endif /* HAVE_ALTIVEC */
 }
-- 
2.45.2


[-- Attachment #5: 0079-avcodec-ppc-mpegvideo_altivec-Don-t-process-unnecess.patch --]
[-- Type: text/x-patch, Size: 1094 bytes --]

From d6e005924133d679af1af08d16c64f8456bfc345 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Sat, 22 Mar 2025 07:31:30 +0100
Subject: [PATCH 79/81] avcodec/ppc/mpegvideo_altivec: Don't process
 unnecessarily many coeffs

Use the same number as the C version.

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

diff --git a/libavcodec/ppc/mpegvideo_altivec.c b/libavcodec/ppc/mpegvideo_altivec.c
index 23b7701fd6..7e3db6f76a 100644
--- a/libavcodec/ppc/mpegvideo_altivec.c
+++ b/libavcodec/ppc/mpegvideo_altivec.c
@@ -57,7 +57,10 @@ static void dct_unquantize_h263_altivec(MpegEncContext *s,
         }else
             qadd = 0;
         i = 1;
-        nCoeffs= 63; //does not always use zigzag table
+        if (s->ac_pred)
+            nCoeffs = 63;
+        else
+            nCoeffs = s->intra_scantable.raster_end[s->block_last_index[n]];
     } else {
         i = 0;
         av_assert2(s->block_last_index[n]>=0);
-- 
2.45.2


[-- Attachment #6: 0080-avcodec-ppc-mpegvideo_altivec-Don-t-process-coeffs-a.patch --]
[-- Type: text/x-patch, Size: 2842 bytes --]

From 6d39f2624ca780432d491cb9ec9dc9576e26beca Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Sat, 22 Mar 2025 07:53:34 +0100
Subject: [PATCH 80/81] avcodec/ppc/mpegvideo_altivec: Don't process coeffs as
 scalars

block_last_index and nCoeffs is an optimization designed
to avoid processing unnecessarily many coefficients; yet
it would be legal to always process all coefficients
(all coefficients beyond nCoeffs are zero anyway and
zeros are always unquantized to zeros). Therefore
one does not need a scalar tail.

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

diff --git a/libavcodec/ppc/mpegvideo_altivec.c b/libavcodec/ppc/mpegvideo_altivec.c
index 7e3db6f76a..a455cadc4b 100644
--- a/libavcodec/ppc/mpegvideo_altivec.c
+++ b/libavcodec/ppc/mpegvideo_altivec.c
@@ -42,7 +42,7 @@
 static void dct_unquantize_h263_altivec(MpegEncContext *s,
                                  int16_t *block, int n, int qscale)
 {
-    int i, level, qmul, qadd;
+    int i, qmul, qadd;
     int nCoeffs;
 
     qadd = (qscale - 1) | 1;
@@ -74,7 +74,6 @@ static void dct_unquantize_h263_altivec(MpegEncContext *s,
         register vector signed short blockv, qmulv, qaddv, nqaddv, temp1;
         register vector bool short blockv_null, blockv_neg;
         register short backup_0 = block[0];
-        register int j = 0;
 
         qmulv = vec_splat((vec_s16)vec_lde(0, &qmul8), 0);
         qaddv = vec_splat((vec_s16)vec_lde(0, &qadd8), 0);
@@ -82,7 +81,7 @@ static void dct_unquantize_h263_altivec(MpegEncContext *s,
 
         // vectorize all the 16 bytes-aligned blocks
         // of 8 elements
-        for(; (j + 7) <= nCoeffs ; j+=8) {
+        for (register int j = 0; j <= nCoeffs ; j += 8) {
             blockv = vec_ld(j << 1, block);
             blockv_neg = vec_cmplt(blockv, vczero);
             blockv_null = vec_cmpeq(blockv, vczero);
@@ -95,22 +94,6 @@ static void dct_unquantize_h263_altivec(MpegEncContext *s,
             vec_st(blockv, j << 1, block);
         }
 
-        // if nCoeffs isn't a multiple of 8, finish the job
-        // using good old scalar units.
-        // (we could do it using a truncated vector,
-        // but I'm not sure it's worth the hassle)
-        for(; j <= nCoeffs ; j++) {
-            level = block[j];
-            if (level) {
-                if (level < 0) {
-                    level = level * qmul - qadd;
-                } else {
-                    level = level * qmul + qadd;
-                }
-                block[j] = level;
-            }
-        }
-
         if (i == 1) {
             // cheat. this avoid special-casing the first iteration
             block[0] = backup_0;
-- 
2.45.2


[-- Attachment #7: 0081-avcodec-mpegvideo-Only-keep-the-actually-used-unquan.patch --]
[-- Type: text/x-patch, Size: 20352 bytes --]

From d9d282489fe262a629f59007e3c05f8525880958 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Wed, 19 Mar 2025 15:24:57 +0100
Subject: [PATCH 81/81] avcodec/mpegvideo: Only keep the actually used
 unquantize funcs

For all encoders and all decoders except MPEG-4 the unquantize
functions to use don't change at all and therefore needn't be
kept in the context. So discard them after setting them;
for MPEG-4, the functions get assigned on a per-frame basis.

Decoders not using any unquantize functions (H.261, MPEG-1/2)
as well as decoders that only call ff_mpv_reconstruct_mb()
through error resilience (RV30/40, the VC-1 family) don't have
the remaining pointers set at all.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/arm/mpegvideo_arm.c        |  4 +--
 libavcodec/arm/mpegvideo_arm.h        |  4 +--
 libavcodec/arm/mpegvideo_armv5te.c    |  2 +-
 libavcodec/h263dec.c                  | 16 +++++-------
 libavcodec/mips/mpegvideo_init_mips.c |  9 ++++---
 libavcodec/mpeg4videodec.c            | 14 ++++++++++
 libavcodec/mpeg4videodec.h            |  5 ++++
 libavcodec/mpegvideo.c                |  2 --
 libavcodec/mpegvideo.h                | 12 ---------
 libavcodec/mpegvideo_enc.c            | 32 +++++++++++++++--------
 libavcodec/mpegvideo_unquantize.c     | 15 ++++++-----
 libavcodec/mpegvideo_unquantize.h     | 37 ++++++++++++++++++++++-----
 libavcodec/neon/mpegvideo.c           |  2 +-
 libavcodec/ppc/mpegvideo_altivec.c    |  2 +-
 libavcodec/x86/mpegvideo.c            |  4 +--
 15 files changed, 99 insertions(+), 61 deletions(-)

diff --git a/libavcodec/arm/mpegvideo_arm.c b/libavcodec/arm/mpegvideo_arm.c
index e32451b554..5c96c9df2c 100644
--- a/libavcodec/arm/mpegvideo_arm.c
+++ b/libavcodec/arm/mpegvideo_arm.c
@@ -46,12 +46,12 @@ void ff_dct_unquantize_h263_inter_neon(MpegEncContext *s, int16_t *block,
 void ff_dct_unquantize_h263_intra_neon(MpegEncContext *s, int16_t *block,
                                        int n, int qscale);
 
-av_cold void ff_mpv_common_init_arm(MpegEncContext *s)
+av_cold void ff_mpv_unquantize_init_arm(MPVUnquantDSPContext *s, int bitexact)
 {
     int cpu_flags = av_get_cpu_flags();
 
     if (have_armv5te(cpu_flags))
-        ff_mpv_common_init_armv5te(s);
+        ff_mpv_unquantize_init_armv5te(s);
 
     if (have_neon(cpu_flags)) {
         s->dct_unquantize_h263_intra = ff_dct_unquantize_h263_intra_neon;
diff --git a/libavcodec/arm/mpegvideo_arm.h b/libavcodec/arm/mpegvideo_arm.h
index 709ae6b247..93da7a5664 100644
--- a/libavcodec/arm/mpegvideo_arm.h
+++ b/libavcodec/arm/mpegvideo_arm.h
@@ -19,8 +19,8 @@
 #ifndef AVCODEC_ARM_MPEGVIDEO_ARM_H
 #define AVCODEC_ARM_MPEGVIDEO_ARM_H
 
-#include "libavcodec/mpegvideo.h"
+#include "libavcodec/mpegvideo_unquantize.h"
 
-void ff_mpv_common_init_armv5te(MpegEncContext *s);
+void ff_mpv_unquantize_init_armv5te(MPVUnquantDSPContext *s);
 
 #endif /* AVCODEC_ARM_MPEGVIDEO_ARM_H */
diff --git a/libavcodec/arm/mpegvideo_armv5te.c b/libavcodec/arm/mpegvideo_armv5te.c
index e20bb4c645..2737f68643 100644
--- a/libavcodec/arm/mpegvideo_armv5te.c
+++ b/libavcodec/arm/mpegvideo_armv5te.c
@@ -95,7 +95,7 @@ static void dct_unquantize_h263_inter_armv5te(MpegEncContext *s,
     ff_dct_unquantize_h263_armv5te(block, qmul, qadd, nCoeffs + 1);
 }
 
-av_cold void ff_mpv_common_init_armv5te(MpegEncContext *s)
+av_cold void ff_mpv_unquantize_init_armv5te(MPVUnquantDSPContext *s)
 {
     s->dct_unquantize_h263_intra = dct_unquantize_h263_intra_armv5te;
     s->dct_unquantize_h263_inter = dct_unquantize_h263_inter_armv5te;
diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c
index 8434f6e7cf..ddbada9841 100644
--- a/libavcodec/h263dec.c
+++ b/libavcodec/h263dec.c
@@ -44,6 +44,7 @@
 #include "mpegvideo.h"
 #include "mpegvideodata.h"
 #include "mpegvideodec.h"
+#include "mpegvideo_unquantize.h"
 #include "msmpeg4dec.h"
 #include "thread.h"
 #include "wmv2dec.h"
@@ -90,6 +91,7 @@ static enum AVPixelFormat h263_get_format(AVCodecContext *avctx)
 av_cold int ff_h263_decode_init(AVCodecContext *avctx)
 {
     MpegEncContext *s = avctx->priv_data;
+    MPVUnquantDSPContext unquant_dsp_ctx;
     int ret;
 
     s->out_format      = FMT_H263;
@@ -105,10 +107,12 @@ av_cold int ff_h263_decode_init(AVCodecContext *avctx)
     s->y_dc_scale_table =
     s->c_dc_scale_table = ff_mpeg1_dc_scale_table;
 
+    ff_mpv_unquantize_init(&unquant_dsp_ctx,
+                           avctx->flags & AV_CODEC_FLAG_BITEXACT, 0);
     // dct_unquantize defaults for H.263;
     // they might change on a per-frame basis for MPEG-4.
-    s->dct_unquantize_intra = s->dct_unquantize_h263_intra;
-    s->dct_unquantize_inter = s->dct_unquantize_h263_inter;
+    s->dct_unquantize_intra = unquant_dsp_ctx.dct_unquantize_h263_intra;
+    s->dct_unquantize_inter = unquant_dsp_ctx.dct_unquantize_h263_inter;
 
     /* select sub codec */
     switch (avctx->codec->id) {
@@ -117,9 +121,6 @@ av_cold int ff_h263_decode_init(AVCodecContext *avctx)
         avctx->chroma_sample_location = AVCHROMA_LOC_CENTER;
         break;
     case AV_CODEC_ID_MPEG4:
-        // dct_unquantize_inter is only used with MPEG-2 quantizers,
-        // so we can already set dct_unquantize_inter here once and for all.
-        s->dct_unquantize_inter = s->dct_unquantize_mpeg2_inter;
         break;
     case AV_CODEC_ID_MSMPEG4V1:
         s->h263_pred       = 1;
@@ -508,11 +509,6 @@ retry:
             goto retry;
         if (s->studio_profile != (s->idsp.idct == NULL))
             ff_mpv_idct_init(s);
-        if (s->mpeg_quant) {
-            s->dct_unquantize_intra = s->dct_unquantize_mpeg2_intra;
-        } else {
-            s->dct_unquantize_intra = s->dct_unquantize_h263_intra;
-        }
     }
 
     /* After H.263 & MPEG-4 header decode we have the height, width,
diff --git a/libavcodec/mips/mpegvideo_init_mips.c b/libavcodec/mips/mpegvideo_init_mips.c
index a9acae94ce..75c88a1317 100644
--- a/libavcodec/mips/mpegvideo_init_mips.c
+++ b/libavcodec/mips/mpegvideo_init_mips.c
@@ -24,7 +24,8 @@
 #include "h263dsp_mips.h"
 #include "mpegvideo_mips.h"
 
-av_cold void ff_mpv_common_init_mips(MpegEncContext *s)
+av_cold void ff_mpv_unquantize_init_mips(MPVUnquantDSPContext *s,
+                                         int bitexact, int q_scale_type)
 {
     int cpu_flags = av_get_cpu_flags();
 
@@ -34,15 +35,15 @@ av_cold void ff_mpv_common_init_mips(MpegEncContext *s)
         s->dct_unquantize_mpeg1_intra = ff_dct_unquantize_mpeg1_intra_mmi;
         s->dct_unquantize_mpeg1_inter = ff_dct_unquantize_mpeg1_inter_mmi;
 
-        if (!(s->avctx->flags & AV_CODEC_FLAG_BITEXACT))
-            if (!s->q_scale_type)
+        if (!bitexact)
+            if (!q_scale_type)
                 s->dct_unquantize_mpeg2_intra = ff_dct_unquantize_mpeg2_intra_mmi;
     }
 
     if (have_msa(cpu_flags)) {
         s->dct_unquantize_h263_intra = ff_dct_unquantize_h263_intra_msa;
         s->dct_unquantize_h263_inter = ff_dct_unquantize_h263_inter_msa;
-        if (!s->q_scale_type)
+        if (!q_scale_type)
             s->dct_unquantize_mpeg2_inter = ff_dct_unquantize_mpeg2_inter_msa;
     }
 }
diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
index 139b6d4b08..7d5af9b877 100644
--- a/libavcodec/mpeg4videodec.c
+++ b/libavcodec/mpeg4videodec.c
@@ -35,6 +35,7 @@
 #include "mpegvideo.h"
 #include "mpegvideodata.h"
 #include "mpegvideodec.h"
+#include "mpegvideo_unquantize.h"
 #include "mpeg4video.h"
 #include "mpeg4videodata.h"
 #include "mpeg4videodec.h"
@@ -3390,6 +3391,9 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb,
         }
     }
 
+    s->dct_unquantize_intra = s->mpeg_quant ? ctx->dct_unquantize_mpeg2_intra
+                                            : ctx->dct_unquantize_h263_intra;
+
 end:
     /* detect buggy encoders which don't set the low_delay flag
      * (divx4/xvid/opendivx). Note we cannot detect divx5 without B-frames
@@ -3862,6 +3866,7 @@ static av_cold int decode_init(AVCodecContext *avctx)
     static AVOnce init_static_once = AV_ONCE_INIT;
     Mpeg4DecContext *ctx = avctx->priv_data;
     MpegEncContext *s = &ctx->m;
+    MPVUnquantDSPContext unquant_dsp_ctx;
     int ret;
 
     ctx->divx_version =
@@ -3872,6 +3877,15 @@ static av_cold int decode_init(AVCodecContext *avctx)
     if ((ret = ff_h263_decode_init(avctx)) < 0)
         return ret;
 
+    ff_mpv_unquantize_init(&unquant_dsp_ctx,
+                           avctx->flags & AV_CODEC_FLAG_BITEXACT, 0);
+
+    ctx->dct_unquantize_h263_intra  = unquant_dsp_ctx.dct_unquantize_h263_intra;
+    ctx->dct_unquantize_mpeg2_intra = unquant_dsp_ctx.dct_unquantize_mpeg2_intra;
+    // dct_unquantize_inter is only used with MPEG-2 quantizers,
+    // 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->h263_pred = 1;
     s->low_delay = 0; /* default, might be overridden in the vol header during header parsing */
     s->decode_mb = mpeg4_decode_mb;
diff --git a/libavcodec/mpeg4videodec.h b/libavcodec/mpeg4videodec.h
index bb14d24c88..d3de81c5a9 100644
--- a/libavcodec/mpeg4videodec.h
+++ b/libavcodec/mpeg4videodec.h
@@ -88,6 +88,11 @@ typedef struct Mpeg4DecContext {
 
     Mpeg4VideoDSPContext mdsp;
 
+    void (*dct_unquantize_mpeg2_intra)(MpegEncContext *s,
+                                       int16_t *block, int n, int qscale);
+    void (*dct_unquantize_h263_intra)(MpegEncContext *s,
+                                      int16_t *block, int n, int qscale);
+
     DECLARE_ALIGNED(8, int32_t, block32)[12][64];
     // 0 = DCT, 1 = DPCM top to bottom scan, -1 = DPCM bottom to top scan
     int dpcm_direction;
diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
index 9a40937bbd..794b2d0f66 100644
--- a/libavcodec/mpegvideo.c
+++ b/libavcodec/mpegvideo.c
@@ -112,8 +112,6 @@ av_cold void ff_mpv_idct_init(MpegEncContext *s)
                          s->idsp.idct_permutation);
     ff_permute_scantable(s->permutated_intra_v_scantable, ff_alternate_vertical_scan,
                          s->idsp.idct_permutation);
-
-    ff_mpv_unquantize_init(s);
 }
 
 static av_cold int init_duplicate_context(MpegEncContext *s)
diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h
index 7379160159..2d60c9ddf0 100644
--- a/libavcodec/mpegvideo.h
+++ b/libavcodec/mpegvideo.h
@@ -326,18 +326,6 @@ typedef struct MpegEncContext {
 #define SLICE_END       -2 ///<end marker found
 #define SLICE_NOEND     -3 ///<no end marker or error found but mb count exceeded
 
-    void (*dct_unquantize_mpeg1_intra)(struct MpegEncContext *s,
-                           int16_t *block/*align 16*/, int n, int qscale);
-    void (*dct_unquantize_mpeg1_inter)(struct MpegEncContext *s,
-                           int16_t *block/*align 16*/, int n, int qscale);
-    void (*dct_unquantize_mpeg2_intra)(struct MpegEncContext *s,
-                           int16_t *block/*align 16*/, int n, int qscale);
-    void (*dct_unquantize_mpeg2_inter)(struct MpegEncContext *s,
-                           int16_t *block/*align 16*/, int n, int qscale);
-    void (*dct_unquantize_h263_intra)(struct MpegEncContext *s,
-                           int16_t *block/*align 16*/, int n, int qscale);
-    void (*dct_unquantize_h263_inter)(struct MpegEncContext *s,
-                           int16_t *block/*align 16*/, int n, int qscale);
     void (*dct_unquantize_intra)(struct MpegEncContext *s, // unquantizer to use (MPEG-4 can use both)
                            int16_t *block/*align 16*/, int n, int qscale);
     void (*dct_unquantize_inter)(struct MpegEncContext *s, // unquantizer to use (MPEG-4 can use both)
diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c
index 95d774155a..e7945270f5 100644
--- a/libavcodec/mpegvideo_enc.c
+++ b/libavcodec/mpegvideo_enc.c
@@ -60,6 +60,7 @@
 #include "mjpegenc_common.h"
 #include "mathops.h"
 #include "mpegutils.h"
+#include "mpegvideo_unquantize.h"
 #include "mjpegenc.h"
 #include "speedhqenc.h"
 #include "msmpeg4enc.h"
@@ -310,6 +311,25 @@ av_cold void ff_dct_encode_init(MPVEncContext *const s)
         s->dct_quantize  = dct_quantize_trellis_c;
 }
 
+static av_cold void init_unquantize(MpegEncContext *const s, AVCodecContext *avctx)
+{
+    MPVUnquantDSPContext unquant_dsp_ctx;
+
+    ff_mpv_unquantize_init(&unquant_dsp_ctx,
+                           avctx->flags & AV_CODEC_FLAG_BITEXACT, s->q_scale_type);
+
+    if (s->mpeg_quant || s->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
+        s->dct_unquantize_intra = unquant_dsp_ctx.dct_unquantize_mpeg2_intra;
+        s->dct_unquantize_inter = unquant_dsp_ctx.dct_unquantize_mpeg2_inter;
+    } else if (s->out_format == FMT_H263 || s->out_format == FMT_H261) {
+        s->dct_unquantize_intra = unquant_dsp_ctx.dct_unquantize_h263_intra;
+        s->dct_unquantize_inter = unquant_dsp_ctx.dct_unquantize_h263_inter;
+    } else {
+        s->dct_unquantize_intra = unquant_dsp_ctx.dct_unquantize_mpeg1_intra;
+        s->dct_unquantize_inter = unquant_dsp_ctx.dct_unquantize_mpeg1_inter;
+    }
+}
+
 static av_cold int me_cmp_init(MPVMainEncContext *const m, AVCodecContext *avctx)
 {
     MPVEncContext *const s = &m->s;
@@ -1013,6 +1033,7 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx)
      * to the slice contexts, so we initialize various fields of it
      * before calling ff_mpv_common_init(). */
     ff_mpv_idct_init(&s->c);
+    init_unquantize(&s->c, avctx);
     ff_fdctdsp_init(&s->fdsp, avctx);
     ff_mpegvideoencdsp_init(&s->mpvencdsp, avctx);
     ff_pixblockdsp_init(&s->pdsp, avctx);
@@ -1031,17 +1052,6 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx)
 
     ff_dct_encode_init(s);
 
-    if (s->c.mpeg_quant || s->c.codec_id == AV_CODEC_ID_MPEG2VIDEO) {
-        s->c.dct_unquantize_intra = s->c.dct_unquantize_mpeg2_intra;
-        s->c.dct_unquantize_inter = s->c.dct_unquantize_mpeg2_inter;
-    } else if (s->c.out_format == FMT_H263 || s->c.out_format == FMT_H261) {
-        s->c.dct_unquantize_intra = s->c.dct_unquantize_h263_intra;
-        s->c.dct_unquantize_inter = s->c.dct_unquantize_h263_inter;
-    } else {
-        s->c.dct_unquantize_intra = s->c.dct_unquantize_mpeg1_intra;
-        s->c.dct_unquantize_inter = s->c.dct_unquantize_mpeg1_inter;
-    }
-
     if (CONFIG_H263_ENCODER && s->c.out_format == FMT_H263) {
         ff_h263_encode_init(m);
 #if CONFIG_MSMPEG4ENC
diff --git a/libavcodec/mpegvideo_unquantize.c b/libavcodec/mpegvideo_unquantize.c
index 12bacdf424..213e37a514 100644
--- a/libavcodec/mpegvideo_unquantize.c
+++ b/libavcodec/mpegvideo_unquantize.c
@@ -246,28 +246,29 @@ static void dct_unquantize_h263_inter_c(MpegEncContext *s,
     }
 }
 
-av_cold void ff_mpv_unquantize_init(MpegEncContext *s)
+av_cold void ff_mpv_unquantize_init(MPVUnquantDSPContext *s,
+                                    int bitexact, int q_scale_type)
 {
     s->dct_unquantize_h263_intra  = dct_unquantize_h263_intra_c;
     s->dct_unquantize_h263_inter  = dct_unquantize_h263_inter_c;
     s->dct_unquantize_mpeg1_intra = dct_unquantize_mpeg1_intra_c;
     s->dct_unquantize_mpeg1_inter = dct_unquantize_mpeg1_inter_c;
     s->dct_unquantize_mpeg2_intra = dct_unquantize_mpeg2_intra_c;
-    if (s->avctx->flags & AV_CODEC_FLAG_BITEXACT)
+    if (bitexact)
         s->dct_unquantize_mpeg2_intra = dct_unquantize_mpeg2_intra_bitexact;
     s->dct_unquantize_mpeg2_inter = dct_unquantize_mpeg2_inter_c;
 
 #if HAVE_INTRINSICS_NEON
-    ff_mpv_common_init_neon(s);
+    ff_mpv_unquantize_init_neon(s, bitexact);
 #endif
 
 #if ARCH_ARM
-    ff_mpv_common_init_arm(s);
+    ff_mpv_unquantize_init_arm(s, bitexact);
 #elif ARCH_PPC
-    ff_mpv_common_init_ppc(s);
+    ff_mpv_unquantize_init_ppc(s, bitexact);
 #elif ARCH_X86
-    ff_mpv_common_init_x86(s);
+    ff_mpv_unquantize_init_x86(s, bitexact);
 #elif ARCH_MIPS
-    ff_mpv_common_init_mips(s);
+    ff_mpv_unquantize_init_mips(s, bitexact, q_scale_type);
 #endif
 }
diff --git a/libavcodec/mpegvideo_unquantize.h b/libavcodec/mpegvideo_unquantize.h
index 1e7590561c..3e6d8aedf7 100644
--- a/libavcodec/mpegvideo_unquantize.h
+++ b/libavcodec/mpegvideo_unquantize.h
@@ -25,13 +25,38 @@
 #ifndef AVCODEC_MPEGVIDEO_UNQUANTIZE_H
 #define AVCODEC_MPEGVIDEO_UNQUANTIZE_H
 
+#include <stdint.h>
+
+#include "config.h"
+
 typedef struct MpegEncContext MpegEncContext;
 
-void ff_mpv_unquantize_init(MpegEncContext *s);
-void ff_mpv_common_init_arm(MpegEncContext *s);
-void ff_mpv_common_init_neon(MpegEncContext *s);
-void ff_mpv_common_init_ppc(MpegEncContext *s);
-void ff_mpv_common_init_x86(MpegEncContext *s);
-void ff_mpv_common_init_mips(MpegEncContext *s);
+typedef struct MPVUnquantDSPContext {
+    void (*dct_unquantize_mpeg1_intra)(struct MpegEncContext *s,
+                           int16_t *block/*align 16*/, int n, int qscale);
+    void (*dct_unquantize_mpeg1_inter)(struct MpegEncContext *s,
+                           int16_t *block/*align 16*/, int n, int qscale);
+    void (*dct_unquantize_mpeg2_intra)(struct MpegEncContext *s,
+                           int16_t *block/*align 16*/, int n, int qscale);
+    void (*dct_unquantize_mpeg2_inter)(struct MpegEncContext *s,
+                           int16_t *block/*align 16*/, int n, int qscale);
+    void (*dct_unquantize_h263_intra)(struct MpegEncContext *s,
+                           int16_t *block/*align 16*/, int n, int qscale);
+    void (*dct_unquantize_h263_inter)(struct MpegEncContext *s,
+                           int16_t *block/*align 16*/, int n, int qscale);
+} MPVUnquantDSPContext;
+
+#if !ARCH_MIPS
+#define ff_mpv_unquantize_init(s, bitexact, q_scale_type) ff_mpv_unquantize_init(s, bitexact)
+#endif
+
+void ff_mpv_unquantize_init(MPVUnquantDSPContext *s,
+                            int bitexact, int q_scale_type);
+void ff_mpv_unquantize_init_arm (MPVUnquantDSPContext *s, int bitexact);
+void ff_mpv_unquantize_init_neon(MPVUnquantDSPContext *s, int bitexact);
+void ff_mpv_unquantize_init_ppc (MPVUnquantDSPContext *s, int bitexact);
+void ff_mpv_unquantize_init_x86 (MPVUnquantDSPContext *s, int bitexact);
+void ff_mpv_unquantize_init_mips(MPVUnquantDSPContext *s, int bitexact,
+                                 int q_scale_type);
 
 #endif /* AVCODEC_MPEGVIDEO_UNQUANTIZE_H */
diff --git a/libavcodec/neon/mpegvideo.c b/libavcodec/neon/mpegvideo.c
index a8b2a0606d..a0276ad808 100644
--- a/libavcodec/neon/mpegvideo.c
+++ b/libavcodec/neon/mpegvideo.c
@@ -125,7 +125,7 @@ static void dct_unquantize_h263_intra_neon(MpegEncContext *s, int16_t *block,
 }
 
 
-av_cold void ff_mpv_common_init_neon(MpegEncContext *s)
+av_cold void ff_mpv_unquantize_init_neon(MPVUnquantDSPContext *s, int bitexact)
 {
     int cpu_flags = av_get_cpu_flags();
 
diff --git a/libavcodec/ppc/mpegvideo_altivec.c b/libavcodec/ppc/mpegvideo_altivec.c
index a455cadc4b..8cc213efe4 100644
--- a/libavcodec/ppc/mpegvideo_altivec.c
+++ b/libavcodec/ppc/mpegvideo_altivec.c
@@ -103,7 +103,7 @@ static void dct_unquantize_h263_altivec(MpegEncContext *s,
 
 #endif /* HAVE_ALTIVEC */
 
-av_cold void ff_mpv_common_init_ppc(MpegEncContext *s)
+av_cold void ff_mpv_unquantize_init_ppc(MPVUnquantDSPContext *s, int bitexact)
 {
 #if HAVE_ALTIVEC
     if (!PPC_ALTIVEC(av_get_cpu_flags()))
diff --git a/libavcodec/x86/mpegvideo.c b/libavcodec/x86/mpegvideo.c
index 11a5ee474b..24f1e14007 100644
--- a/libavcodec/x86/mpegvideo.c
+++ b/libavcodec/x86/mpegvideo.c
@@ -450,7 +450,7 @@ __asm__ volatile(
 
 #endif /* HAVE_MMX_INLINE */
 
-av_cold void ff_mpv_common_init_x86(MpegEncContext *s)
+av_cold void ff_mpv_unquantize_init_x86(MPVUnquantDSPContext *s, int bitexact)
 {
 #if HAVE_MMX_INLINE
     int cpu_flags = av_get_cpu_flags();
@@ -460,7 +460,7 @@ av_cold void ff_mpv_common_init_x86(MpegEncContext *s)
         s->dct_unquantize_h263_inter = dct_unquantize_h263_inter_mmx;
         s->dct_unquantize_mpeg1_intra = dct_unquantize_mpeg1_intra_mmx;
         s->dct_unquantize_mpeg1_inter = dct_unquantize_mpeg1_inter_mmx;
-        if (!(s->avctx->flags & AV_CODEC_FLAG_BITEXACT))
+        if (!bitexact)
             s->dct_unquantize_mpeg2_intra = dct_unquantize_mpeg2_intra_mmx;
         s->dct_unquantize_mpeg2_inter = dct_unquantize_mpeg2_inter_mmx;
     }
-- 
2.45.2


[-- Attachment #8: 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-03-22 13:17 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-03-19 21:18 Andreas Rheinhardt
2025-03-19 21:20 ` Andreas Rheinhardt
2025-03-22  0:34 ` Michael Niedermayer
2025-03-22 13:16   ` Andreas Rheinhardt [this message]

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=GV1SPRMB003675F14FD6B01A4B42D87F8FDA2@GV1SPRMB0036.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