Patches attached; mostly about MPEG-4. - Andreas
From 1a73463508298d6683658e86a5e0e5453c75e0d7 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Sat, 17 May 2025 19:30:02 +0200 Subject: [PATCH 01/19] avcodec/mpegvideo_enc: Set gob_index once during init
Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/ituh263enc.c | 3 +++ libavcodec/mpegvideo_enc.c | 16 +++------------- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/libavcodec/ituh263enc.c b/libavcodec/ituh263enc.c index b9d903a220..9a6d5dc201 100644 --- a/libavcodec/ituh263enc.c +++ b/libavcodec/ituh263enc.c @@ -842,6 +842,9 @@ av_cold void ff_h263_encode_init(MPVMainEncContext *const m) if (s->c.modified_quant) s->c.chroma_qscale_table = ff_h263_chroma_qscale_table; + // Only used for H.263 and H.263+ + s->c.gob_index = H263_GOB_HEIGHT(s->c.height); + // use fcodes >1 only for MPEG-4 & H.263 & H.263+ FIXME switch(s->c.codec_id){ case AV_CODEC_ID_H263P: diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 6e9533ebc9..62a3a82ff3 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -3006,25 +3006,15 @@ static int encode_thread(AVCodecContext *c, void *arg){ s->c.last_dc[0] = 128 * 8 / 13; s->c.last_dc[1] = 128 * 8 / 14; s->c.last_dc[2] = 128 * 8 / 14; + } else if (CONFIG_MPEG4_ENCODER && s->c.codec_id == AV_CODEC_ID_MPEG4 && + s->c.partitioned_frame) { + ff_mpeg4_init_partitions(s); } s->c.mb_skip_run = 0; memset(s->c.last_mv, 0, sizeof(s->c.last_mv)); s->last_mv_dir = 0; - switch (s->c.codec_id) { - case AV_CODEC_ID_H263: - case AV_CODEC_ID_H263P: - case AV_CODEC_ID_FLV1: - if (CONFIG_H263_ENCODER) - s->c.gob_index = H263_GOB_HEIGHT(s->c.height); - break; - case AV_CODEC_ID_MPEG4: - if (CONFIG_MPEG4_ENCODER && s->c.partitioned_frame) - ff_mpeg4_init_partitions(s); - break; - } - s->c.resync_mb_x = 0; s->c.resync_mb_y = 0; s->c.first_slice_line = 1; -- 2.45.2
From 4527ee66d9fc5b13b6946ed3912de88b4d738a3f Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Sat, 17 May 2025 20:20:05 +0200 Subject: [PATCH 02/19] avcodec/h263dec: Move calculating gob_index to {intel,itu}h263dec.c This avoids checks for whether it should be calculated at all. Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/h263dec.c | 5 ----- libavcodec/intelh263dec.c | 3 +++ libavcodec/ituh263dec.c | 2 ++ 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c index c36070e23c..501b8b44ff 100644 --- a/libavcodec/h263dec.c +++ b/libavcodec/h263dec.c @@ -537,11 +537,6 @@ int ff_h263_decode_frame(AVCodecContext *avctx, AVFrame *pict, } } - if (s->codec_id == AV_CODEC_ID_H263 || - s->codec_id == AV_CODEC_ID_H263P || - s->codec_id == AV_CODEC_ID_H263I) - s->gob_index = H263_GOB_HEIGHT(s->height); - /* skip B-frames if we don't have reference frames */ if (!s->last_pic.ptr && (s->pict_type == AV_PICTURE_TYPE_B || s->droppable)) diff --git a/libavcodec/intelh263dec.c b/libavcodec/intelh263dec.c index 374dfdc0de..b2e7fa6c54 100644 --- a/libavcodec/intelh263dec.c +++ b/libavcodec/intelh263dec.c @@ -19,6 +19,7 @@ */ #include "codec_internal.h" +#include "h263.h" #include "mpegvideo.h" #include "mpegvideodec.h" #include "h263data.h" @@ -119,6 +120,8 @@ int ff_intel_h263_decode_picture_header(MpegEncContext *s) if (skip_1stop_8data_bits(&s->gb) < 0) return AVERROR_INVALIDDATA; + s->gob_index = H263_GOB_HEIGHT(s->height); + ff_h263_show_pict_info(s); return 0; diff --git a/libavcodec/ituh263dec.c b/libavcodec/ituh263dec.c index d19bdc4dab..7965b77ff3 100644 --- a/libavcodec/ituh263dec.c +++ b/libavcodec/ituh263dec.c @@ -1314,6 +1314,8 @@ int ff_h263_decode_picture_header(MpegEncContext *s) s->mb_height = (s->height + 15) / 16; s->mb_num = s->mb_width * s->mb_height; + s->gob_index = H263_GOB_HEIGHT(s->height); + if (s->pb_frame) { skip_bits(&s->gb, 3); /* Temporal reference for B-pictures */ if (s->custom_pcf) -- 2.45.2
From 5bc20ffb8881543dd3b22e713735bfca8a84368e Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Sun, 18 May 2025 01:01:28 +0200 Subject: [PATCH 03/19] avcodec/mpeg4videodec: Don't initialize unused parts of RLTables The reversible VLC tables use a simpler escaping method than the ordinary VLCs: It does not use max_run, max_level etc. and therefore one does not need to initialize these at all. Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/mpeg4videodec.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index b6bb21174e..4d09a58ffb 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -3901,7 +3901,6 @@ static int mpeg4_update_thread_context_for_user(AVCodecContext *dst, static av_cold void mpeg4_init_static(void) { - static uint8_t mpeg4_rvlc_rl_tables[2][2][2 * MAX_RUN + MAX_LEVEL + 3]; static VLCElem vlc_buf[6498]; VLCInitState state = VLC_INIT_STATE(vlc_buf); @@ -3924,8 +3923,6 @@ static av_cold void mpeg4_init_static(void) } ff_mpeg4_init_rl_intra(); - ff_rl_init(&ff_rvlc_rl_inter, mpeg4_rvlc_rl_tables[0]); - ff_rl_init(&ff_rvlc_rl_intra, mpeg4_rvlc_rl_tables[1]); INIT_FIRST_VLC_RL(ff_mpeg4_rl_intra, 554); VLC_INIT_RL(ff_rvlc_rl_inter, 1072); INIT_FIRST_VLC_RL(ff_rvlc_rl_intra, 1072); -- 2.45.2
From b6a3f5f9ddb8d38f6fddf18d0a0984537dc7704c Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Sun, 18 May 2025 04:56:21 +0200 Subject: [PATCH 04/19] avcodec/mpegvideo_enc: Reduce stack usage Multiple PutBitContexts are used when encoding partitioned frames. When there are multiple candidates for macroblock types, multiple states (namely the state before encoding the current MB, the best state among the ones already tried and the current one) need to be kept; duplicates of the PutBitContexts are among this state. The temporary buffers for them are kept on the stack in encode_thread() and their size is quite generous (MAX_MB_SIZE - 3000 bytes). This commit uses tighter bounds, bringing the size of the pb2 buffer down to 15 bytes. Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/mpeg4videoenc.h | 12 ++++++++++++ libavcodec/mpegvideo_enc.c | 9 +++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/libavcodec/mpeg4videoenc.h b/libavcodec/mpeg4videoenc.h index 815f16f073..4e20b8aaa0 100644 --- a/libavcodec/mpeg4videoenc.h +++ b/libavcodec/mpeg4videoenc.h @@ -27,6 +27,18 @@ #include "put_bits.h" +enum { + MAX_PB2_INTRA_SIZE = 1 /* ac_pred */ + 5 /* max cbpy len */ + + 2 /* dquant */ + 1 /* interlaced dct */ + + 4 * (8 /* longest luma dct_dc_size */ + + 9 /* longest dc diff */ + 1 /* marker */) + + 2 * (9 + 9 + 1), + MAX_PB2_INTER_SIZE = 5 /* max cbpy len */ + + 2 /* dquant */ + 1 /* interlaced_dct */ + 1, + MAX_PB2_MB_SIZE = (FFMAX(MAX_PB2_INTER_SIZE, MAX_PB2_INTRA_SIZE) + 7) / 8, + MAX_AC_TEX_MB_SIZE = 64 * 6 * 30 /* longest escape code */ / 8, +}; + typedef struct MPVEncContext MPVEncContext; void ff_set_mpeg4_time(MPVEncContext *s); diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 62a3a82ff3..8d3c003182 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -2978,14 +2978,15 @@ static int encode_thread(AVCodecContext *c, void *arg){ int i; MBBackup best_s = { 0 }, backup_s; uint8_t bit_buf[2][MAX_MB_BYTES]; - uint8_t bit_buf2[2][MAX_MB_BYTES]; - uint8_t bit_buf_tex[2][MAX_MB_BYTES]; + // + 2 because ff_copy_bits() overreads + uint8_t bit_buf2[2][MAX_PB2_MB_SIZE + 2]; + uint8_t bit_buf_tex[2][MAX_AC_TEX_MB_SIZE + 2]; PutBitContext pb[2], pb2[2], tex_pb[2]; for(i=0; i<2; i++){ init_put_bits(&pb [i], bit_buf [i], MAX_MB_BYTES); - init_put_bits(&pb2 [i], bit_buf2 [i], MAX_MB_BYTES); - init_put_bits(&tex_pb[i], bit_buf_tex[i], MAX_MB_BYTES); + init_put_bits(&pb2 [i], bit_buf2 [i], MAX_PB2_MB_SIZE); + init_put_bits(&tex_pb[i], bit_buf_tex[i], MAX_AC_TEX_MB_SIZE); } s->last_bits= put_bits_count(&s->pb); -- 2.45.2
From 5f897d6d747a8ab4871f7fdf2b959f3688f0f31e Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Sun, 18 May 2025 08:35:23 +0200 Subject: [PATCH 05/19] avcodec/mpeg4videoenc: Simplify creating LUT There four cases for the LUT entry: An ordinary entry or one of three escaping methods. Three of these methods are only rarely possible --they correspond to the 102 codes of the underlying VLC and so only 102 of 16384 entries are possible. The earlier code would nevertheless try them all for every LUT entry and use the best one; the new code meanwhile only uses one method (the fallback one (i.e. the worst)) for them all and only processes the 102 valid entries afterwards. The implementation used also means that index_run, max_level and max_run of the RLTable are no longer needed; the earlier code would initialize said static tables although they are only used for a short time to initialize something else. Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/mpeg4videoenc.c | 158 ++++++++++++++++--------------------- 1 file changed, 68 insertions(+), 90 deletions(-) diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c index cf4a1dfa63..229d5df8f1 100644 --- a/libavcodec/mpeg4videoenc.c +++ b/libavcodec/mpeg4videoenc.c @@ -1184,95 +1184,75 @@ static av_cold void init_uni_dc_tab(void) static av_cold void init_uni_mpeg4_rl_tab(RLTable *rl, uint32_t *bits_tab, uint8_t *len_tab) { - int slevel, run, last; - - av_assert0(MAX_LEVEL >= 64); - av_assert0(MAX_RUN >= 63); - - for (slevel = -64; slevel < 64; slevel++) { - if (slevel == 0) - continue; - for (run = 0; run < 64; run++) { - for (last = 0; last <= 1; last++) { - const int index = UNI_MPEG4_ENC_INDEX(last, run, slevel + 64); - int level = slevel < 0 ? -slevel : slevel; - int sign = slevel < 0 ? 1 : 0; - int bits, len, code; - int level1, run1; - - len_tab[index] = 100; - - /* ESC0 */ - code = get_rl_index(rl, last, run, level); - bits = rl->table_vlc[code][0]; - len = rl->table_vlc[code][1]; - bits = bits * 2 + sign; - len++; - - if (code != rl->n && len < len_tab[index]) { - bits_tab[index] = bits; - len_tab[index] = len; - } - /* ESC1 */ - bits = rl->table_vlc[rl->n][0]; - len = rl->table_vlc[rl->n][1]; - bits = bits * 2; - len++; // esc1 - level1 = level - rl->max_level[last][run]; - if (level1 > 0) { - code = get_rl_index(rl, last, run, level1); - bits <<= rl->table_vlc[code][1]; - len += rl->table_vlc[code][1]; - bits += rl->table_vlc[code][0]; - bits = bits * 2 + sign; - len++; - - if (code != rl->n && len < len_tab[index]) { - bits_tab[index] = bits; - len_tab[index] = len; - } - } - /* ESC2 */ - bits = rl->table_vlc[rl->n][0]; - len = rl->table_vlc[rl->n][1]; - bits = bits * 4 + 2; - len += 2; // esc2 - run1 = run - rl->max_run[last][level] - 1; - if (run1 >= 0) { - code = get_rl_index(rl, last, run1, level); - bits <<= rl->table_vlc[code][1]; - len += rl->table_vlc[code][1]; - bits += rl->table_vlc[code][0]; - bits = bits * 2 + sign; - len++; - - if (code != rl->n && len < len_tab[index]) { - bits_tab[index] = bits; - len_tab[index] = len; - } - } - /* ESC3 */ - bits = rl->table_vlc[rl->n][0]; - len = rl->table_vlc[rl->n][1]; - bits = bits * 4 + 3; - len += 2; // esc3 - bits = bits * 2 + last; - len++; - bits = bits * 64 + run; - len += 6; - bits = bits * 2 + 1; - len++; // marker - bits = bits * 4096 + (slevel & 0xfff); - len += 12; - bits = bits * 2 + 1; - len++; // marker - - if (len < len_tab[index]) { - bits_tab[index] = bits; - len_tab[index] = len; - } - } + // Type 3 escape method. The escape code is the same for both VLCs + // (0x3, seven bits), so it is hardcoded. + memset(len_tab, 30, 2 * 2 * 64 * 64); + len_tab += 64; + bits_tab += 64; + for (int run = 0; run < 64; ++run) { + for (int level = 1;; ++level) { + // Escape code type 3 not last run (6 bits) marker marker + unsigned code = (3 << 23) | (3 << 21) | (0 << 20) | (run << 14) | (1 << 13) | 1; + // first the negative levels + bits_tab[UNI_MPEG4_ENC_INDEX(0, run, -level)] = code | (-level & 0xfff) << 1; + bits_tab[UNI_MPEG4_ENC_INDEX(1, run, -level)] = + bits_tab[UNI_MPEG4_ENC_INDEX(0, run, -level)] | (1 << 20) /* last */; + + if (level == 64) // positive levels have a range of 1..63 + break; + bits_tab[UNI_MPEG4_ENC_INDEX(0, run, level)] = code | level << 1; + bits_tab[UNI_MPEG4_ENC_INDEX(1, run, level)] = + bits_tab[UNI_MPEG4_ENC_INDEX(0, run, level)] | (1 << 20) /* last */; + } + } + + uint8_t max_run[2][32] = { 0 }; + +#define VLC_NUM_CODES 102 // excluding the escape + av_assert2(rl->n == VLC_NUM_CODES); + for (int i = VLC_NUM_CODES - 1, max_level, cur_run = 0; i >= 0; --i) { + int run = rl->table_run[i], level = rl->table_level[i]; + int last = i >= rl->last; + unsigned code = rl->table_vlc[i][0] << 1; + int len = rl->table_vlc[i][1] + 1; + + bits_tab[UNI_MPEG4_ENC_INDEX(last, run, level)] = code; + len_tab [UNI_MPEG4_ENC_INDEX(last, run, level)] = len; + bits_tab[UNI_MPEG4_ENC_INDEX(last, run, -level)] = code | 1; + len_tab [UNI_MPEG4_ENC_INDEX(last, run, -level)] = len; + + if (!max_run[last][level]) + max_run[last][level] = run + 1; + av_assert2(run + 1 <= max_run[last][level]); + + int run3 = run + max_run[last][level]; + int len3 = len + 7 + 2; + + if (run3 < 64 && len3 < len_tab[UNI_MPEG4_ENC_INDEX(last, run3, level)]) { + unsigned code3 = code | (0x3 << 2 | 0x2) << len; + bits_tab[UNI_MPEG4_ENC_INDEX(last, run3, level)] = code3; + len_tab [UNI_MPEG4_ENC_INDEX(last, run3, level)] = len3; + bits_tab[UNI_MPEG4_ENC_INDEX(last, run3, -level)] = code3 | 1; + len_tab [UNI_MPEG4_ENC_INDEX(last, run3, -level)] = len3; } + // table_run and table_level are ordered so that all the entries + // with the same last and run are consecutive and level is ascending + // among these entries. By traversing downwards we therefore automatically + // encounter max_level of a given run first, needed for escape method 1. + if (run != cur_run) { + max_level = level; + cur_run = run; + } else + av_assert2(max_level > level); + + code |= 0x3 << (len + 1); + len += 7 + 1; + level += max_level; + av_assert2(len_tab [UNI_MPEG4_ENC_INDEX(last, run, level)] >= len); + bits_tab[UNI_MPEG4_ENC_INDEX(last, run, level)] = code; + len_tab [UNI_MPEG4_ENC_INDEX(last, run, level)] = len; + bits_tab[UNI_MPEG4_ENC_INDEX(last, run, -level)] = code | 1; + len_tab [UNI_MPEG4_ENC_INDEX(last, run, -level)] = len; } } @@ -1280,8 +1260,6 @@ static av_cold void mpeg4_encode_init_static(void) { init_uni_dc_tab(); - ff_mpeg4_init_rl_intra(); - init_uni_mpeg4_rl_tab(&ff_mpeg4_rl_intra, uni_mpeg4_intra_rl_bits, uni_mpeg4_intra_rl_len); init_uni_mpeg4_rl_tab(&ff_h263_rl_inter, uni_mpeg4_inter_rl_bits, uni_mpeg4_inter_rl_len); -- 2.45.2
From 07d8e19895243515e155024a8b0e01b13a14e512 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Sun, 18 May 2025 08:59:27 +0200 Subject: [PATCH 06/19] avcodec/mpeg4video: Nuke ff_mpeg4_init_rl_intra() The MPEG-4 decoder can now initialize ff_mpeg4_rl_intra directly given that the MPEG-4 encoder no longer wants it performed, too. Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/mpeg4video.c | 14 -------------- libavcodec/mpeg4videodata.h | 1 - libavcodec/mpeg4videodec.c | 4 +++- 3 files changed, 3 insertions(+), 16 deletions(-) diff --git a/libavcodec/mpeg4video.c b/libavcodec/mpeg4video.c index 2c0c1044f2..3980a39305 100644 --- a/libavcodec/mpeg4video.c +++ b/libavcodec/mpeg4video.c @@ -20,25 +20,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/thread.h" - #include "mpegutils.h" #include "mpegvideo.h" #include "mpeg4video.h" #include "mpeg4data.h" -static av_cold void mpeg4_init_rl_intra(void) -{ - static uint8_t mpeg4_rl_intra_table[2][2 * MAX_RUN + MAX_LEVEL + 3]; - ff_rl_init(&ff_mpeg4_rl_intra, mpeg4_rl_intra_table); -} - -av_cold void ff_mpeg4_init_rl_intra(void) -{ - static AVOnce init_static_once = AV_ONCE_INIT; - ff_thread_once(&init_static_once, mpeg4_init_rl_intra); -} - int ff_mpeg4_get_video_packet_prefix_length(enum AVPictureType pict_type, int f_code, int b_code) { diff --git a/libavcodec/mpeg4videodata.h b/libavcodec/mpeg4videodata.h index 8aac8a2255..baca8a0b9a 100644 --- a/libavcodec/mpeg4videodata.h +++ b/libavcodec/mpeg4videodata.h @@ -35,7 +35,6 @@ extern const int8_t ff_mpeg4_intra_level[102]; extern const int8_t ff_mpeg4_intra_run[102]; extern RLTable ff_mpeg4_rl_intra; -void ff_mpeg4_init_rl_intra(void); /* Note this is identical to the intra rvlc except that it is reordered. */ extern RLTable ff_rvlc_rl_inter; diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index 4d09a58ffb..82b552356a 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -3922,7 +3922,9 @@ static av_cold void mpeg4_init_static(void) 0, 0); } - ff_mpeg4_init_rl_intra(); + static uint8_t mpeg4_rl_intra_table[2][2 * MAX_RUN + MAX_LEVEL + 3]; + ff_rl_init(&ff_mpeg4_rl_intra, mpeg4_rl_intra_table); + INIT_FIRST_VLC_RL(ff_mpeg4_rl_intra, 554); VLC_INIT_RL(ff_rvlc_rl_inter, 1072); INIT_FIRST_VLC_RL(ff_rvlc_rl_intra, 1072); -- 2.45.2
From 0d74a6b377426c574ea5dea3461a658ed7c1a5c4 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Sun, 18 May 2025 18:33:55 +0200 Subject: [PATCH 07/19] avcodec/mpeg4videoenc: Remove no-output code While it offers modest speedups compared to the ordinary code, removing it completely offers even bigger speedups; and given that these speedups also exist in the ordinary mode, they are even more important. The no-output code has a 7.8% performance improvement (based on benchmarking mpeg4_encode_mb()), yet removing the no-output code resulted in a 9.4% improvement. Furthermore, the no-output code was broken for the majority of its existence (until 9207dc3b0db368bb9cf5eb295cbc1129c2975e31) and no one complained, so it is likely no used at all. Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/mpeg4videoenc.c | 76 -------------------------------------- 1 file changed, 76 deletions(-) diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c index 229d5df8f1..f5e93f8b8f 100644 --- a/libavcodec/mpeg4videoenc.c +++ b/libavcodec/mpeg4videoenc.c @@ -292,14 +292,6 @@ static inline void mpeg4_encode_dc(PutBitContext *s, int level, int n) } } -static inline int mpeg4_get_dc_length(int level, int n) -{ - if (n < 4) - return uni_DCtab_lum_len[level + 256]; - else - return uni_DCtab_chrom_len[level + 256]; -} - /** * Encode an 8x8 block. * @param n block index (0-3 are luma, 4-5 are chroma) @@ -365,60 +357,6 @@ static inline void mpeg4_encode_block(const MPVEncContext *const s, } } -static int mpeg4_get_block_length(MPVEncContext *const s, - const int16_t *block, int n, - int intra_dc, const uint8_t *scan_table) -{ - int i, last_non_zero; - const uint8_t *len_tab; - const int last_index = s->c.block_last_index[n]; - int len = 0; - - if (s->c.mb_intra) { // Note gcc (3.2.1 at least) will optimize this away - /* MPEG-4 based DC predictor */ - len += mpeg4_get_dc_length(intra_dc, n); - if (last_index < 1) - return len; - i = 1; - len_tab = uni_mpeg4_intra_rl_len; - } else { - if (last_index < 0) - return 0; - i = 0; - len_tab = uni_mpeg4_inter_rl_len; - } - - /* AC coefs */ - last_non_zero = i - 1; - for (; i < last_index; i++) { - int level = block[scan_table[i]]; - if (level) { - int run = i - last_non_zero - 1; - level += 64; - if ((level & (~127)) == 0) { - const int index = UNI_MPEG4_ENC_INDEX(0, run, level); - len += len_tab[index]; - } else { // ESC3 - len += 7 + 2 + 1 + 6 + 1 + 12 + 1; - } - last_non_zero = i; - } - } - /* if (i <= last_index) */ { - int level = block[scan_table[i]]; - int run = i - last_non_zero - 1; - level += 64; - if ((level & (~127)) == 0) { - const int index = UNI_MPEG4_ENC_INDEX(1, run, level); - len += len_tab[index]; - } else { // ESC3 - len += 7 + 2 + 1 + 6 + 1 + 12 + 1; - } - } - - return len; -} - static inline void mpeg4_encode_blocks(MPVEncContext *const s, const int16_t block[6][64], const int intra_dc[6], @@ -429,29 +367,15 @@ static inline void mpeg4_encode_blocks(MPVEncContext *const s, int i; if (scan_table) { - if (s->c.avctx->flags2 & AV_CODEC_FLAG2_NO_OUTPUT) { - for (i = 0; i < 6; i++) - skip_put_bits(&s->pb, - mpeg4_get_block_length(s, block[i], i, - intra_dc[i], scan_table[i])); - } else { /* encode each block */ for (i = 0; i < 6; i++) mpeg4_encode_block(s, block[i], i, intra_dc[i], scan_table[i], dc_pb, ac_pb); - } } else { - if (s->c.avctx->flags2 & AV_CODEC_FLAG2_NO_OUTPUT) { - for (i = 0; i < 6; i++) - skip_put_bits(&s->pb, - mpeg4_get_block_length(s, block[i], i, 0, - s->c.intra_scantable.permutated)); - } else { /* encode each block */ for (i = 0; i < 6; i++) mpeg4_encode_block(s, block[i], i, 0, s->c.intra_scantable.permutated, dc_pb, ac_pb); - } } } -- 2.45.2
From ecc15131ac5bb6fda9dbf5d543f8e7b78e63b025 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Sun, 18 May 2025 21:14:54 +0200 Subject: [PATCH 08/19] avcodec/mpeg4videoenc: Split writing blocks into intra and inter These are sufficiently different to warrant their own functions; in particular, the earlier code had two callsites for the actual "write block" function, one for intra and one for inter, yet the "write block" function nevertheless performed a check (that the compiler can't optimize away) for whether the current MB is intra or not. Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/mpeg4videoenc.c | 90 ++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 47 deletions(-) diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c index f5e93f8b8f..c0b1c3512c 100644 --- a/libavcodec/mpeg4videoenc.c +++ b/libavcodec/mpeg4videoenc.c @@ -293,37 +293,18 @@ static inline void mpeg4_encode_dc(PutBitContext *s, int level, int n) } /** - * Encode an 8x8 block. - * @param n block index (0-3 are luma, 4-5 are chroma) + * Encode the AC coefficients of an 8x8 block. */ -static inline void mpeg4_encode_block(const MPVEncContext *const s, - const int16_t *block, int n, int intra_dc, - const uint8_t *scan_table, PutBitContext *dc_pb, - PutBitContext *ac_pb) +static inline void mpeg4_encode_ac_coeffs(const int16_t block[64], + const int last_index, int i, + const uint8_t *const scan_table, + PutBitContext *const ac_pb, + const uint32_t *const bits_tab, + const uint8_t *const len_tab) { - int i, last_non_zero; - const uint32_t *bits_tab; - const uint8_t *len_tab; - const int last_index = s->c.block_last_index[n]; - - if (s->c.mb_intra) { // Note gcc (3.2.1 at least) will optimize this away - /* MPEG-4 based DC predictor */ - mpeg4_encode_dc(dc_pb, intra_dc, n); - if (last_index < 1) - return; - i = 1; - bits_tab = uni_mpeg4_intra_rl_bits; - len_tab = uni_mpeg4_intra_rl_len; - } else { - if (last_index < 0) - return; - i = 0; - bits_tab = uni_mpeg4_inter_rl_bits; - len_tab = uni_mpeg4_inter_rl_len; - } + int last_non_zero = i - 1; /* AC coefs */ - last_non_zero = i - 1; for (; i < last_index; i++) { int level = block[scan_table[i]]; if (level) { @@ -357,25 +338,40 @@ static inline void mpeg4_encode_block(const MPVEncContext *const s, } } -static inline void mpeg4_encode_blocks(MPVEncContext *const s, - const int16_t block[6][64], - const int intra_dc[6], - const uint8_t * const *scan_table, - PutBitContext *dc_pb, - PutBitContext *ac_pb) +static void mpeg4_encode_blocks_inter(MPVEncContext *const s, + const int16_t block[6][64], + PutBitContext *ac_pb) { - int i; + /* encode each block */ + for (int n = 0; n < 6; ++n) { + const int last_index = s->c.block_last_index[n]; + if (last_index < 0) + continue; - if (scan_table) { - /* encode each block */ - for (i = 0; i < 6; i++) - mpeg4_encode_block(s, block[i], i, - intra_dc[i], scan_table[i], dc_pb, ac_pb); - } else { - /* encode each block */ - for (i = 0; i < 6; i++) - mpeg4_encode_block(s, block[i], i, 0, - s->c.intra_scantable.permutated, dc_pb, ac_pb); + mpeg4_encode_ac_coeffs(block[n], last_index, 0, + s->c.intra_scantable.permutated, ac_pb, + uni_mpeg4_inter_rl_bits, uni_mpeg4_inter_rl_len); + } +} + +static void mpeg4_encode_blocks_intra(MPVEncContext *const s, + const int16_t block[6][64], + const int intra_dc[6], + const uint8_t * const *scan_table, + PutBitContext *dc_pb, + PutBitContext *ac_pb) +{ + /* encode each block */ + for (int n = 0; n < 6; ++n) { + mpeg4_encode_dc(dc_pb, intra_dc[n], n); + + const int last_index = s->c.block_last_index[n]; + if (last_index <= 0) + continue; + + mpeg4_encode_ac_coeffs(block[n], last_index, 1, + scan_table[n], ac_pb, + uni_mpeg4_intra_rl_bits, uni_mpeg4_intra_rl_len); } } @@ -565,7 +561,7 @@ static void mpeg4_encode_mb(MPVEncContext *const s, int16_t block[][64], if (interleaved_stats) s->mv_bits += get_bits_diff(s); - mpeg4_encode_blocks(s, block, NULL, NULL, NULL, &s->pb); + mpeg4_encode_blocks_inter(s, block, &s->pb); if (interleaved_stats) s->p_tex_bits += get_bits_diff(s); @@ -728,7 +724,7 @@ static void mpeg4_encode_mb(MPVEncContext *const s, int16_t block[][64], if (interleaved_stats) s->mv_bits += get_bits_diff(s); - mpeg4_encode_blocks(s, block, NULL, NULL, NULL, tex_pb); + mpeg4_encode_blocks_inter(s, block, tex_pb); if (interleaved_stats) s->p_tex_bits += get_bits_diff(s); @@ -790,7 +786,7 @@ static void mpeg4_encode_mb(MPVEncContext *const s, int16_t block[][64], if (interleaved_stats) s->misc_bits += get_bits_diff(s); - mpeg4_encode_blocks(s, block, dc_diff, scan_table, dc_pb, tex_pb); + mpeg4_encode_blocks_intra(s, block, dc_diff, scan_table, dc_pb, tex_pb); if (interleaved_stats) s->i_tex_bits += get_bits_diff(s); -- 2.45.2
From a79cac74eb11517142b514b66b8cf812570dee44 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Sun, 18 May 2025 21:22:04 +0200 Subject: [PATCH 09/19] avcodec/mpeg4videoenc: Use smaller scope for variable Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/mpeg4videoenc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c index c0b1c3512c..1cfd64128d 100644 --- a/libavcodec/mpeg4videoenc.c +++ b/libavcodec/mpeg4videoenc.c @@ -238,11 +238,10 @@ static inline int decide_ac_pred(MPVEncContext *const s, int16_t block[6][64], */ void ff_clean_mpeg4_qscales(MPVEncContext *const s) { - int8_t *const qscale_table = s->c.cur_pic.qscale_table; - ff_clean_h263_qscales(s); if (s->c.pict_type == AV_PICTURE_TYPE_B) { + int8_t *const qscale_table = s->c.cur_pic.qscale_table; int odd = 0; /* ok, come on, this isn't funny anymore, there's more code for * handling this MPEG-4 mess than for the actual adaptive quantization */ -- 2.45.2
From 73c3e1c408c3d758c440afa0975795e44aae504e Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Mon, 19 May 2025 17:18:38 +0200 Subject: [PATCH 10/19] avcodec/mpeg4videodec: Remove unnecessary ff_xvid_idct_init() It is unnecessary: If the dst context is not already initialized, then it will be initialized by memcpy(dst, src, sizeof(*dst), which already initializes the IDCT to the desired one, potentially followed by ff_mpv_common_init(), which does not touch the IDCT. (This call has been added in f89d76c10355242c39b08f253c1d1524f45ef778; the aforementioned copying took place back then, too, but ff_mpv_common_init() reinitialized the IDCT to a non-xvid one, therefore the initialization here has been added to fix multithreaded decoding.) Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/mpeg4videodec.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index 82b552356a..c4eed9136a 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -48,7 +48,6 @@ #include "profiles.h" #include "qpeldsp.h" #include "threadprogress.h" -#include "xvididct.h" #include "unary.h" #if 0 //3IV1 is quite rare and it slows things down a tiny bit @@ -3880,9 +3879,6 @@ static int mpeg4_update_thread_context(AVCodecContext *dst, memcpy(s->sprite_shift, s1->sprite_shift, sizeof(s1->sprite_shift)); memcpy(s->sprite_traj, s1->sprite_traj, sizeof(s1->sprite_traj)); - if (!init && s1->xvid_build >= 0) - ff_xvid_idct_init(&s->m.idsp, dst); - return av_buffer_replace(&s->bitstream_buffer, s1->bitstream_buffer); } -- 2.45.2
From 88e923a48cfbea1f5ee1fda31c17366f1b18a6bc Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Tue, 20 May 2025 22:31:47 +0200 Subject: [PATCH 11/19] avcodec/xvididct: Remove always-true checks ff_xvid_idct_init() is now only called from ff_idctdsp_init() and only if idct_algo is FF_IDCT_XVID. This also implies that it is unnecessary to initalize the permutation on our own. Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/xvididct.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/libavcodec/xvididct.c b/libavcodec/xvididct.c index 2eddc5978c..f50d8b7695 100644 --- a/libavcodec/xvididct.c +++ b/libavcodec/xvididct.c @@ -334,23 +334,17 @@ av_cold void ff_xvid_idct_init(IDCTDSPContext *c, AVCodecContext *avctx) { const unsigned high_bit_depth = avctx->bits_per_raw_sample > 8; - if (high_bit_depth || avctx->lowres || - !(avctx->idct_algo == FF_IDCT_AUTO || - avctx->idct_algo == FF_IDCT_XVID)) + if (high_bit_depth || avctx->lowres) return; - if (avctx->idct_algo == FF_IDCT_XVID) { - c->idct_put = xvid_idct_put; - c->idct_add = xvid_idct_add; - c->idct = ff_xvid_idct; - c->perm_type = FF_IDCT_PERM_NONE; - } + c->idct_put = xvid_idct_put; + c->idct_add = xvid_idct_add; + c->idct = ff_xvid_idct; + c->perm_type = FF_IDCT_PERM_NONE; #if ARCH_X86 ff_xvid_idct_init_x86(c); #elif ARCH_MIPS ff_xvid_idct_init_mips(c); #endif - - ff_init_scantable_permutation(c->idct_permutation, c->perm_type); } -- 2.45.2
From 9ad84bb72230bb27483a66a0c56a2dd2de05019e Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Tue, 20 May 2025 22:55:53 +0200 Subject: [PATCH 12/19] avcodec/idctdsp: Only try to initialize xvid idct if it is used This allows to remove checks from ff_xvid_idct_init() (and also the AVCodecContext* parameter). Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/idctdsp.c | 7 ++++--- libavcodec/xvididct.c | 8 +------- libavcodec/xvididct.h | 3 +-- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/libavcodec/idctdsp.c b/libavcodec/idctdsp.c index 4259a117dc..8a71c7ef77 100644 --- a/libavcodec/idctdsp.c +++ b/libavcodec/idctdsp.c @@ -276,6 +276,10 @@ av_cold void ff_idctdsp_init(IDCTDSPContext *c, AVCodecContext *avctx) c->idct = ff_faanidct; c->perm_type = FF_IDCT_PERM_NONE; #endif /* CONFIG_FAANIDCT */ +#if CONFIG_MPEG4_DECODER + } else if (avctx->idct_algo == FF_IDCT_XVID) { + ff_xvid_idct_init(c); +#endif } else { // accurate/default c->idct_put = ff_simple_idct_put_int16_8bit; c->idct_add = ff_simple_idct_add_int16_8bit; @@ -289,9 +293,6 @@ av_cold void ff_idctdsp_init(IDCTDSPContext *c, AVCodecContext *avctx) c->put_signed_pixels_clamped = put_signed_pixels_clamped_c; c->add_pixels_clamped = ff_add_pixels_clamped_c; - if (CONFIG_MPEG4_DECODER && avctx->idct_algo == FF_IDCT_XVID) - ff_xvid_idct_init(c, avctx); - #if ARCH_AARCH64 ff_idctdsp_init_aarch64(c, avctx, high_bit_depth); #elif ARCH_ARM diff --git a/libavcodec/xvididct.c b/libavcodec/xvididct.c index f50d8b7695..317e4e82cd 100644 --- a/libavcodec/xvididct.c +++ b/libavcodec/xvididct.c @@ -32,7 +32,6 @@ #include "config.h" #include "libavutil/attributes.h" -#include "avcodec.h" #include "idctdsp.h" #include "xvididct.h" @@ -330,13 +329,8 @@ static void xvid_idct_add(uint8_t *dest, ptrdiff_t line_size, int16_t *block) ff_add_pixels_clamped_c(block, dest, line_size); } -av_cold void ff_xvid_idct_init(IDCTDSPContext *c, AVCodecContext *avctx) +av_cold void ff_xvid_idct_init(IDCTDSPContext *c) { - const unsigned high_bit_depth = avctx->bits_per_raw_sample > 8; - - if (high_bit_depth || avctx->lowres) - return; - c->idct_put = xvid_idct_put; c->idct_add = xvid_idct_add; c->idct = ff_xvid_idct; diff --git a/libavcodec/xvididct.h b/libavcodec/xvididct.h index 1395cfd8e1..496071a034 100644 --- a/libavcodec/xvididct.h +++ b/libavcodec/xvididct.h @@ -21,12 +21,11 @@ #include <stdint.h> -#include "avcodec.h" #include "idctdsp.h" void ff_xvid_idct(int16_t *const in); -void ff_xvid_idct_init(IDCTDSPContext *c, AVCodecContext *avctx); +void ff_xvid_idct_init(IDCTDSPContext *c); void ff_xvid_idct_init_x86(IDCTDSPContext *c); void ff_xvid_idct_init_mips(IDCTDSPContext *c); -- 2.45.2
From 8a5876d4acb54b74006ee1c741edadc68ed2773a Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Tue, 20 May 2025 23:40:48 +0200 Subject: [PATCH 13/19] avcodec/mpegvideo_dec: Document which codecs take which codepath Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/mpegvideo_dec.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavcodec/mpegvideo_dec.c b/libavcodec/mpegvideo_dec.c index 9cb3eab50d..c85c7db722 100644 --- a/libavcodec/mpegvideo_dec.c +++ b/libavcodec/mpegvideo_dec.c @@ -962,6 +962,9 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], /* add dct residue */ if (!(IS_MPEG12_H261(s) || s->msmpeg4_version != MSMP4_UNUSED || (s->codec_id == AV_CODEC_ID_MPEG4 && !s->mpeg_quant))) { + // H.263, H.263+, H.263I, FLV, RV10, RV20 and MPEG-4 with MPEG-2 quantization + // Also RV30, RV40 when performing error resilience, but + // all blocks are skipped in this case. add_dequant_dct(s, block[0], 0, dest_y , dct_linesize, s->qscale); add_dequant_dct(s, block[1], 1, dest_y + block_size, dct_linesize, s->qscale); add_dequant_dct(s, block[2], 2, dest_y + dct_offset , dct_linesize, s->qscale); @@ -973,6 +976,9 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], add_dequant_dct(s, block[5], 5, dest_cr, uvlinesize, s->chroma_qscale); } } else if (is_mpeg12 == DEFINITELY_MPEG12_H261 || lowres_flag || (s->codec_id != AV_CODEC_ID_WMV2)) { + // H.261, MPEG-1, MPEG-2, MPEG-4 with H.263 quantization, + // MSMP4V1-3 and WMV1. + // Also the VC-1 family when performing error resilience add_dct(s, block[0], 0, dest_y , dct_linesize); add_dct(s, block[1], 1, dest_y + block_size, dct_linesize); add_dct(s, block[2], 2, dest_y + dct_offset , dct_linesize); -- 2.45.2
From 71d5c05ea2e4560be99a5dbf9d36a65ea8443e2f Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Tue, 20 May 2025 23:58:34 +0200 Subject: [PATCH 14/19] avcodec/mpegvideo_dec: Simplify check for unquantizing inter blocks Just ensure that dct_unquantize_inter is set iff it is used and check for the function pointer instead. Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/h263dec.c | 3 ++- libavcodec/mpeg4videodec.c | 6 ++++-- libavcodec/mpeg4videodec.h | 2 ++ libavcodec/mpegvideo_dec.c | 8 +++----- libavcodec/msmpeg4dec.c | 3 +++ 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c index 501b8b44ff..c9515480f0 100644 --- a/libavcodec/h263dec.c +++ b/libavcodec/h263dec.c @@ -110,7 +110,8 @@ av_cold int ff_h263_decode_init(AVCodecContext *avctx) 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. + // they might change on a per-frame basis for MPEG-4; + // dct_unquantize_inter will be unset for MSMPEG4 codecs later. s->dct_unquantize_intra = unquant_dsp_ctx.dct_unquantize_h263_intra; s->dct_unquantize_inter = unquant_dsp_ctx.dct_unquantize_h263_inter; diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index c4eed9136a..936711d72e 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -3417,6 +3417,8 @@ 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; + // The following tells ff_mpv_reconstruct_mb() to unquantize iff mpeg_quant + s->dct_unquantize_inter = s->mpeg_quant ? ctx->dct_unquantize_mpeg2_inter : NULL; end: /* detect buggy encoders which don't set the low_delay flag @@ -3961,8 +3963,8 @@ static av_cold int decode_init(AVCodecContext *avctx) 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; + // so that is all we keep. + ctx->dct_unquantize_mpeg2_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; diff --git a/libavcodec/mpeg4videodec.h b/libavcodec/mpeg4videodec.h index 57a2f81816..111d60ba10 100644 --- a/libavcodec/mpeg4videodec.h +++ b/libavcodec/mpeg4videodec.h @@ -91,6 +91,8 @@ typedef struct Mpeg4DecContext { Mpeg4VideoDSPContext mdsp; + void (*dct_unquantize_mpeg2_inter)(MpegEncContext *s, + int16_t *block, int n, int qscale); void (*dct_unquantize_mpeg2_intra)(MpegEncContext *s, int16_t *block, int n, int qscale); void (*dct_unquantize_h263_intra)(MpegEncContext *s, diff --git a/libavcodec/mpegvideo_dec.c b/libavcodec/mpegvideo_dec.c index c85c7db722..f8551b93c8 100644 --- a/libavcodec/mpegvideo_dec.c +++ b/libavcodec/mpegvideo_dec.c @@ -960,11 +960,8 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], } /* add dct residue */ - if (!(IS_MPEG12_H261(s) || s->msmpeg4_version != MSMP4_UNUSED || - (s->codec_id == AV_CODEC_ID_MPEG4 && !s->mpeg_quant))) { + if (is_mpeg12 != DEFINITELY_MPEG12_H261 && s->dct_unquantize_inter) { // H.263, H.263+, H.263I, FLV, RV10, RV20 and MPEG-4 with MPEG-2 quantization - // Also RV30, RV40 when performing error resilience, but - // all blocks are skipped in this case. add_dequant_dct(s, block[0], 0, dest_y , dct_linesize, s->qscale); add_dequant_dct(s, block[1], 1, dest_y + block_size, dct_linesize, s->qscale); add_dequant_dct(s, block[2], 2, dest_y + dct_offset , dct_linesize, s->qscale); @@ -978,7 +975,8 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], } else if (is_mpeg12 == DEFINITELY_MPEG12_H261 || lowres_flag || (s->codec_id != AV_CODEC_ID_WMV2)) { // H.261, MPEG-1, MPEG-2, MPEG-4 with H.263 quantization, // MSMP4V1-3 and WMV1. - // Also the VC-1 family when performing error resilience + // Also RV30, RV40 and the VC-1 family when performing error resilience, + // but all blocks are skipped in this case. add_dct(s, block[0], 0, dest_y , dct_linesize); add_dct(s, block[1], 1, dest_y + block_size, dct_linesize); add_dct(s, block[2], 2, dest_y + dct_offset , dct_linesize); diff --git a/libavcodec/msmpeg4dec.c b/libavcodec/msmpeg4dec.c index df67d43542..bfd2ef0b02 100644 --- a/libavcodec/msmpeg4dec.c +++ b/libavcodec/msmpeg4dec.c @@ -366,6 +366,9 @@ av_cold int ff_msmpeg4_decode_init(AVCodecContext *avctx) if (ff_h263_decode_init(avctx) < 0) return -1; + // We unquantize inter blocks as we parse them. + s->dct_unquantize_inter = NULL; + ff_msmpeg4_common_init(s); switch (s->msmpeg4_version) { -- 2.45.2
From 8abbf55aab25db8ee8b48b312c08c37760a5cd80 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Wed, 21 May 2025 00:22:46 +0200 Subject: [PATCH 15/19] avcodec/mpegvideo: Move mpeg_quant to {Mpeg4Dec,MPVEnc}Context Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/mpeg12enc.c | 2 +- libavcodec/mpeg4videodec.c | 15 ++++++++------- libavcodec/mpeg4videodec.h | 1 + libavcodec/mpeg4videoenc.c | 10 +++++----- libavcodec/mpegvideo.h | 1 - libavcodec/mpegvideo_enc.c | 15 ++++++++------- libavcodec/mpegvideoenc.h | 1 + libavcodec/nvdec_mpeg4.c | 2 +- libavcodec/vaapi_mpeg4.c | 2 +- libavcodec/vdpau_mpeg4.c | 2 +- libavcodec/x86/mpegvideoenc_template.c | 2 +- 11 files changed, 28 insertions(+), 25 deletions(-) diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index d4791e8b33..96957235e9 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -1125,7 +1125,7 @@ static av_cold int encode_init(AVCodecContext *avctx) } else { s->min_qcoeff = -2047; s->max_qcoeff = 2047; - s->c.mpeg_quant = 1; + s->mpeg_quant = 1; } if (s->c.intra_vlc_format) { s->intra_ac_vlc_length = diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index 936711d72e..313d73157f 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -1399,7 +1399,7 @@ static inline int mpeg4_decode_block(Mpeg4DecContext *ctx, int16_t *block, scan_table = s->intra_scantable.permutated; - if (s->mpeg_quant) { + if (ctx->mpeg_quant) { qmul = 1; qadd = 0; if (rvlc) @@ -2155,7 +2155,7 @@ static int mpeg4_decode_studio_block(MpegEncContext *s, int32_t block[64], int n s->last_dc[cc] += dct_diff; - if (s->mpeg_quant) + if (ctx->mpeg_quant) block[0] = s->last_dc[cc] * (8 >> s->intra_dc_precision); else block[0] = s->last_dc[cc] * (8 >> s->intra_dc_precision) * (8 >> s->dct_precision); @@ -2585,7 +2585,7 @@ static int decode_studio_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb) skip_bits(gb, 15); /* latter_half_vbv_occupancy */ check_marker(s->avctx, gb, "after latter_half_vbv_occupancy"); s->low_delay = get_bits1(gb); - s->mpeg_quant = get_bits1(gb); /* mpeg2_stream */ + ctx->mpeg_quant = get_bits1(gb); /* mpeg2_stream */ next_start_code_studio(gb); extension_and_user_data(s, gb, 2); @@ -2767,7 +2767,7 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb) // FIXME a bunch of grayscale shape things - if ((s->mpeg_quant = get_bits1(gb))) { /* vol_quant_type */ + if ((ctx->mpeg_quant = get_bits1(gb))) { /* vol_quant_type */ int i, v; mpeg4_load_default_matrices(s); @@ -3415,10 +3415,10 @@ 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; + s->dct_unquantize_intra = ctx->mpeg_quant ? ctx->dct_unquantize_mpeg2_intra + : ctx->dct_unquantize_h263_intra; // The following tells ff_mpv_reconstruct_mb() to unquantize iff mpeg_quant - s->dct_unquantize_inter = s->mpeg_quant ? ctx->dct_unquantize_mpeg2_inter : NULL; + s->dct_unquantize_inter = ctx->mpeg_quant ? ctx->dct_unquantize_mpeg2_inter : NULL; end: /* detect buggy encoders which don't set the low_delay flag @@ -3857,6 +3857,7 @@ static int mpeg4_update_thread_context(AVCodecContext *dst, s->sprite_warping_accuracy = s1->sprite_warping_accuracy; s->num_sprite_warping_points = s1->num_sprite_warping_points; s->m.data_partitioning = s1->m.data_partitioning; + s->mpeg_quant = s1->mpeg_quant; s->rvlc = s1->rvlc; s->resync_marker = s1->resync_marker; s->t_frame = s1->t_frame; diff --git a/libavcodec/mpeg4videodec.h b/libavcodec/mpeg4videodec.h index 111d60ba10..593c8ab290 100644 --- a/libavcodec/mpeg4videodec.h +++ b/libavcodec/mpeg4videodec.h @@ -52,6 +52,7 @@ typedef struct Mpeg4DecContext { /// sprite shift [isChroma] int sprite_shift[2]; + int mpeg_quant; // reversible vlc int rvlc; /// could this stream contain resync markers diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c index 1cfd64128d..3107ee6230 100644 --- a/libavcodec/mpeg4videoenc.c +++ b/libavcodec/mpeg4videoenc.c @@ -952,9 +952,9 @@ static void mpeg4_encode_vol_header(Mpeg4EncContext *const m4, put_bits(&s->pb, 2, 0); /* sprite enable */ put_bits(&s->pb, 1, 0); /* not 8 bit == false */ - put_bits(&s->pb, 1, s->c.mpeg_quant); /* quant type = (0 = H.263 style) */ + put_bits(&s->pb, 1, s->mpeg_quant); /* quant type = (0 = H.263 style) */ - if (s->c.mpeg_quant) { + if (s->mpeg_quant) { ff_write_quant_matrix(&s->pb, s->c.avctx->intra_matrix); ff_write_quant_matrix(&s->pb, s->c.avctx->inter_matrix); } @@ -1301,11 +1301,11 @@ void ff_mpeg4_encode_video_packet_header(MPVEncContext *const s) put_bits(&s->pb, 1, 0); /* no HEC */ } -#define OFFSET(x) offsetof(MPVEncContext, c.x) +#define OFFSET(x) offsetof(MPVEncContext, x) #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { - { "data_partitioning", "Use data partitioning.", OFFSET(data_partitioning), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, - { "alternate_scan", "Enable alternate scantable.", OFFSET(alternate_scan), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + { "data_partitioning", "Use data partitioning.", OFFSET(c.data_partitioning), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + { "alternate_scan", "Enable alternate scantable.", OFFSET(c.alternate_scan), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, { "mpeg_quant", "Use MPEG quantizers instead of H.263", OFFSET(mpeg_quant), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, VE }, FF_MPV_COMMON_BFRAME_OPTS diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 20a5759958..239d026960 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -254,7 +254,6 @@ typedef struct MpegEncContext { int data_partitioning; ///< data partitioning flag from header int partitioned_frame; ///< is current frame partitioned int low_delay; ///< no reordering needed / has no B-frames - int mpeg_quant; int padding_bug_score; ///< used to detect the VERY common padding bug in MPEG-4 /* divx specific, used to workaround (many) bugs in divx5 */ diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 8d3c003182..6ce741c042 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -313,14 +313,15 @@ 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) +static av_cold void init_unquantize(MPVEncContext *const s2, AVCodecContext *avctx) { + MpegEncContext *const s = &s2->c; 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) { + if (s2->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) { @@ -403,7 +404,7 @@ static av_cold int init_matrices(MPVMainEncContext *const m, AVCodecContext *avc } if (CONFIG_MPEG4_ENCODER && s->c.codec_id == AV_CODEC_ID_MPEG4 && - s->c.mpeg_quant) { + s->mpeg_quant) { intra_matrix = ff_mpeg4_default_intra_matrix; inter_matrix = ff_mpeg4_default_non_intra_matrix; } else if (s->c.out_format == FMT_H263 || s->c.out_format == FMT_H261) { @@ -838,7 +839,7 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) //return -1; } - if (s->c.mpeg_quant || s->c.codec_id == AV_CODEC_ID_MPEG1VIDEO || s->c.codec_id == AV_CODEC_ID_MPEG2VIDEO || s->c.codec_id == AV_CODEC_ID_MJPEG || s->c.codec_id == AV_CODEC_ID_AMV || s->c.codec_id == AV_CODEC_ID_SPEEDHQ) { + if (s->mpeg_quant || s->c.codec_id == AV_CODEC_ID_MPEG1VIDEO || s->c.codec_id == AV_CODEC_ID_MPEG2VIDEO || s->c.codec_id == AV_CODEC_ID_MJPEG || s->c.codec_id == AV_CODEC_ID_AMV || s->c.codec_id == AV_CODEC_ID_SPEEDHQ) { // (a + x * 3 / 8) / x s->intra_quant_bias = 3 << (QUANT_BIAS_SHIFT - 3); s->inter_quant_bias = 0; @@ -1026,7 +1027,7 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) * before calling ff_mpv_common_init(). */ s->parent = m; ff_mpv_idct_init(&s->c); - init_unquantize(&s->c, avctx); + init_unquantize(s, avctx); ff_fdctdsp_init(&s->fdsp, avctx); ff_mpegvideoencdsp_init(&s->mpvencdsp, avctx); ff_pixblockdsp_init(&s->pdsp, avctx); @@ -4010,7 +4011,7 @@ static int dct_quantize_trellis_c(MPVEncContext *const s, last_non_zero = 0; qmat = n < 4 ? s->q_intra_matrix[qscale] : s->q_chroma_intra_matrix[qscale]; matrix = n < 4 ? s->c.intra_matrix : s->c.chroma_intra_matrix; - if (s->c.mpeg_quant || s->c.out_format == FMT_MPEG1 || s->c.out_format == FMT_MJPEG) + if (s->mpeg_quant || s->c.out_format == FMT_MPEG1 || s->c.out_format == FMT_MJPEG) bias= 1<<(QMAT_SHIFT-1); if (n > 3 && s->intra_chroma_ac_vlc_length) { @@ -4325,7 +4326,7 @@ static int dct_quantize_refine(MPVEncContext *const s, //FIXME breaks denoise? dc= block[0]*q; // block[0] = (block[0] + (q >> 1)) / q; start_i = 1; -// if (s->c.mpeg_quant || s->c.out_format == FMT_MPEG1) +// if (s->mpeg_quant || s->c.out_format == FMT_MPEG1) // bias= 1<<(QMAT_SHIFT-1); if (n > 3 && s->intra_chroma_ac_vlc_length) { length = s->intra_chroma_ac_vlc_length; diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h index ec0304c4a0..5510b43f86 100644 --- a/libavcodec/mpegvideoenc.h +++ b/libavcodec/mpegvideoenc.h @@ -147,6 +147,7 @@ typedef struct MPVEncContext { int last_mv_dir; ///< last mv_dir, used for B-frame encoding /* MPEG-4 specific */ + int mpeg_quant; PutBitContext tex_pb; ///< used for data partitioned VOPs PutBitContext pb2; ///< used for data partitioned VOPs diff --git a/libavcodec/nvdec_mpeg4.c b/libavcodec/nvdec_mpeg4.c index 7d158321ae..8272439031 100644 --- a/libavcodec/nvdec_mpeg4.c +++ b/libavcodec/nvdec_mpeg4.c @@ -70,7 +70,7 @@ static int nvdec_mpeg4_start_frame(AVCodecContext *avctx, .vop_time_increment_bitcount = m->time_increment_bits, .top_field_first = s->top_field_first, .resync_marker_disable = !m->resync_marker, - .quant_type = s->mpeg_quant, + .quant_type = m->mpeg_quant, .quarter_sample = s->quarter_sample, .short_video_header = avctx->codec->id == AV_CODEC_ID_H263, .divx_flags = s->divx_packed ? 5 : 0, diff --git a/libavcodec/vaapi_mpeg4.c b/libavcodec/vaapi_mpeg4.c index 8338c0732d..533e6750a1 100644 --- a/libavcodec/vaapi_mpeg4.c +++ b/libavcodec/vaapi_mpeg4.c @@ -70,7 +70,7 @@ static int vaapi_mpeg4_start_frame(AVCodecContext *avctx, .obmc_disable = 1, .sprite_enable = ctx->vol_sprite_usage, .sprite_warping_accuracy = ctx->sprite_warping_accuracy, - .quant_type = s->mpeg_quant, + .quant_type = ctx->mpeg_quant, .quarter_sample = s->quarter_sample, .data_partitioned = s->data_partitioning, .reversible_vlc = ctx->rvlc, diff --git a/libavcodec/vdpau_mpeg4.c b/libavcodec/vdpau_mpeg4.c index 91981935f5..7ec7a74ad1 100644 --- a/libavcodec/vdpau_mpeg4.c +++ b/libavcodec/vdpau_mpeg4.c @@ -68,7 +68,7 @@ static int vdpau_mpeg4_start_frame(AVCodecContext *avctx, 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; + info->quant_type = ctx->mpeg_quant; info->quarter_sample = s->quarter_sample; info->short_video_header = avctx->codec->id == AV_CODEC_ID_H263; info->rounding_control = s->no_rounding; diff --git a/libavcodec/x86/mpegvideoenc_template.c b/libavcodec/x86/mpegvideoenc_template.c index 85e9159f91..dbb2187121 100644 --- a/libavcodec/x86/mpegvideoenc_template.c +++ b/libavcodec/x86/mpegvideoenc_template.c @@ -109,7 +109,7 @@ static int RENAME(dct_quantize)(MPVEncContext *const s, qmat = s->q_inter_matrix16[qscale][0]; } - if ((s->c.out_format == FMT_H263 || s->c.out_format == FMT_H261) && !s->c.mpeg_quant) { + if ((s->c.out_format == FMT_H263 || s->c.out_format == FMT_H261) && !s->mpeg_quant) { __asm__ volatile( "movd %%"FF_REG_a", %%xmm3 \n\t" // last_non_zero_p1 SPREADW("%%xmm3") -- 2.45.2
From 5db20278314cb4abc94048c566442b11b5b99b56 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Wed, 21 May 2025 01:57:52 +0200 Subject: [PATCH 16/19] avcodec/mpegvideo: Check h263_aic, not h263_plus for allocating dc_val This means that these buffers won't be allocated any more for H.263+ with AIC disabled. Also remove setting h263_plus for the RV20 encoder, as it has only been done to force allocating dc_val. Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/mpegvideo.c | 4 +++- libavcodec/mpegvideo_enc.c | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 55f7178bed..f3e4d4c386 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -335,9 +335,11 @@ av_cold int ff_mpv_init_context_frame(MpegEncContext *s) s->coded_block = s->coded_block_base + s->b8_stride + 1; } - if (s->h263_pred || s->h263_plus || !s->encoding) { + if (s->h263_pred || s->h263_aic || !s->encoding) { /* dc values */ // MN: we need these for error resilience of intra-frames + // Allocating them unconditionally for decoders also means + // that we don't need to reinitialize when e.g. h263_aic changes. if (!FF_ALLOCZ_TYPED_ARRAY(s->dc_val_base, yc_size)) return AVERROR(ENOMEM); s->dc_val[0] = s->dc_val_base + s->b8_stride + 1; diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 6ce741c042..e0b7ea0846 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -943,8 +943,9 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) avctx->delay = 0; s->c.low_delay = 1; s->c.modified_quant = 1; + // Set here to force allocation of dc_val; + // will be set later on a per-frame basis. s->c.h263_aic = 1; - s->c.h263_plus = 1; s->c.loop_filter = 1; s->c.unrestricted_mv = 0; break; -- 2.45.2
From 4e9bf9aaf3858d0aac300b2d20d3d42c18a78950 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Wed, 21 May 2025 02:17:25 +0200 Subject: [PATCH 17/19] avcodec/ituh263enc: Don't use h263_plus field It is equal to codec_id == AV_CODEC_ID_H263P, check for that instead. Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/ituh263enc.c | 4 ++-- libavcodec/mpegvideo_enc.c | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/libavcodec/ituh263enc.c b/libavcodec/ituh263enc.c index 9a6d5dc201..4fdf9cf402 100644 --- a/libavcodec/ituh263enc.c +++ b/libavcodec/ituh263enc.c @@ -233,7 +233,7 @@ static int h263_encode_picture_header(MPVMainEncContext *const m) put_bits_assume_flushed(&s->pb); - if(s->c.h263_plus){ + if (s->c.codec_id == AV_CODEC_ID_H263P) { for(i=0; i<2; i++){ int div, error; div= (s->c.avctx->time_base.num*1800000LL + 500LL*s->c.avctx->time_base.den) / ((1000LL+i)*s->c.avctx->time_base.den); @@ -262,7 +262,7 @@ static int h263_encode_picture_header(MPVMainEncContext *const m) put_bits(&s->pb, 1, 0); /* freeze picture release off */ format = ff_match_2uint16(ff_h263_format, FF_ARRAY_ELEMS(ff_h263_format), s->c.width, s->c.height); - if (!s->c.h263_plus) { + if (s->c.codec_id != AV_CODEC_ID_H263P) { /* H.263v1 */ put_bits(&s->pb, 3, format); put_bits(&s->pb, 1, (s->c.pict_type == AV_PICTURE_TYPE_P)); diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index e0b7ea0846..75229dad73 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -907,7 +907,6 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) break; case AV_CODEC_ID_H263P: s->c.out_format = FMT_H263; - s->c.h263_plus = 1; /* Fx */ s->c.h263_aic = (avctx->flags & AV_CODEC_FLAG_AC_PRED) ? 1 : 0; s->c.modified_quant = s->c.h263_aic; -- 2.45.2
From 1fe9b4e8a955220065ea3d2fece4f9cd1ba5f3ed Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Wed, 21 May 2025 02:21:45 +0200 Subject: [PATCH 18/19] avcodec/mpegvideo: Remove h263_plus It is only used to indicate to ff_h263_show_pict_info() that we are decoding H.263+; pass this information via a function parameter instead. Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/flvdec.c | 2 -- libavcodec/h263dec.h | 2 +- libavcodec/intelh263dec.c | 3 +-- libavcodec/ituh263dec.c | 13 ++++++++----- libavcodec/mpegvideo.h | 1 - 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/libavcodec/flvdec.c b/libavcodec/flvdec.c index 627538ef83..e8c1595639 100644 --- a/libavcodec/flvdec.c +++ b/libavcodec/flvdec.c @@ -89,8 +89,6 @@ int ff_flv_decode_picture_header(MpegEncContext *s) skip_bits1(&s->gb); /* deblocking flag */ s->chroma_qscale = s->qscale = get_bits(&s->gb, 5); - s->h263_plus = 0; - s->h263_long_vectors = 0; /* PEI */ diff --git a/libavcodec/h263dec.h b/libavcodec/h263dec.h index 633d4aa577..c1306c7ec5 100644 --- a/libavcodec/h263dec.h +++ b/libavcodec/h263dec.h @@ -55,7 +55,7 @@ int ff_h263_decode_mba(MpegEncContext *s); /** * Print picture info if FF_DEBUG_PICT_INFO is set. */ -void ff_h263_show_pict_info(MpegEncContext *s); +void ff_h263_show_pict_info(MpegEncContext *s, int h263_plus); int ff_intel_h263_decode_picture_header(MpegEncContext *s); int ff_h263_decode_mb(MpegEncContext *s, diff --git a/libavcodec/intelh263dec.c b/libavcodec/intelh263dec.c index b2e7fa6c54..02016e93bf 100644 --- a/libavcodec/intelh263dec.c +++ b/libavcodec/intelh263dec.c @@ -57,7 +57,6 @@ int ff_intel_h263_decode_picture_header(MpegEncContext *s) av_log(s->avctx, AV_LOG_ERROR, "Intel H.263 free format not supported\n"); return -1; } - s->h263_plus = 0; s->pict_type = AV_PICTURE_TYPE_I + get_bits1(&s->gb); @@ -122,7 +121,7 @@ int ff_intel_h263_decode_picture_header(MpegEncContext *s) s->gob_index = H263_GOB_HEIGHT(s->height); - ff_h263_show_pict_info(s); + ff_h263_show_pict_info(s, 0); return 0; } diff --git a/libavcodec/ituh263dec.c b/libavcodec/ituh263dec.c index 7965b77ff3..21c78f3cb5 100644 --- a/libavcodec/ituh263dec.c +++ b/libavcodec/ituh263dec.c @@ -77,7 +77,8 @@ static const int16_t h263_mb_type_b_map[15]= { MB_TYPE_INTRA4x4 | MB_TYPE_CBP | MB_TYPE_QUANT, }; -void ff_h263_show_pict_info(MpegEncContext *s){ +void ff_h263_show_pict_info(MpegEncContext *s, int h263_plus) +{ if(s->avctx->debug&FF_DEBUG_PICT_INFO){ av_log(s->avctx, AV_LOG_DEBUG, "qp:%d %c size:%d rnd:%d%s%s%s%s%s%s%s%s%s %d/%d\n", s->qscale, av_get_picture_type_char(s->pict_type), @@ -85,7 +86,7 @@ void ff_h263_show_pict_info(MpegEncContext *s){ s->obmc ? " AP" : "", s->umvplus ? " UMV" : "", s->h263_long_vectors ? " LONG" : "", - s->h263_plus ? " +" : "", + h263_plus ? " +" : "", s->h263_aic ? " AIC" : "", s->alt_inter_vlc ? " AIV" : "", s->modified_quant ? " MQ" : "", @@ -1089,6 +1090,7 @@ int ff_h263_decode_picture_header(MpegEncContext *s) { int format, width, height, i, ret; uint32_t startcode; + int h263_plus; align_get_bits(&s->gb); @@ -1137,7 +1139,7 @@ int ff_h263_decode_picture_header(MpegEncContext *s) */ if (format != 7 && format != 6) { - s->h263_plus = 0; + h263_plus = 0; /* H.263v1 */ width = ff_h263_format[format][0]; height = ff_h263_format[format][1]; @@ -1166,7 +1168,7 @@ int ff_h263_decode_picture_header(MpegEncContext *s) int ufep; /* H.263v2 */ - s->h263_plus = 1; + h263_plus = 1; ufep = get_bits(&s->gb, 3); /* Update Full Extended PTYPE */ /* ufep other than 0 and 1 are reserved */ @@ -1366,7 +1368,8 @@ int ff_h263_decode_picture_header(MpegEncContext *s) s->c_dc_scale_table= ff_mpeg1_dc_scale_table; } - ff_h263_show_pict_info(s); + ff_h263_show_pict_info(s, h263_plus); + if (s->pict_type == AV_PICTURE_TYPE_I && s->codec_tag == AV_RL32("ZYGO") && get_bits_left(&s->gb) >= 85 + 13*3*16 + 50){ int i,j; for(i=0; i<85; i++) av_log(s->avctx, AV_LOG_DEBUG, "%d", get_bits1(&s->gb)); diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 239d026960..68d70cc0e3 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -90,7 +90,6 @@ typedef struct MpegEncContext { int pb_frame; ///< PB-frame mode (0 = none, 1 = base, 2 = improved) /* the following codec id fields are deprecated in favor of codec_id */ - int h263_plus; ///< H.263+ headers int h263_flv; ///< use flv H.263 header enum AVCodecID codec_id; /* see AV_CODEC_ID_xxx */ -- 2.45.2
From 9bd7c1908421485aa05f353242739d0e7871325f Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Wed, 21 May 2025 15:22:39 +0200 Subject: [PATCH 19/19] avcodec/mpeg4videodec: Use union to save space At most one of block32 and dpcm_macroblock is used at any given time. Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/mpeg4videodec.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavcodec/mpeg4videodec.h b/libavcodec/mpeg4videodec.h index 593c8ab290..ae8428fd2b 100644 --- a/libavcodec/mpeg4videodec.h +++ b/libavcodec/mpeg4videodec.h @@ -99,10 +99,12 @@ typedef struct Mpeg4DecContext { void (*dct_unquantize_h263_intra)(MpegEncContext *s, int16_t *block, int n, int qscale); - DECLARE_ALIGNED(8, int32_t, block32)[12][64]; + union { + DECLARE_ALIGNED(8, int32_t, block32)[12][64]; + int16_t dpcm_macroblock[3][256]; + }; // 0 = DCT, 1 = DPCM top to bottom scan, -1 = DPCM bottom to top scan int dpcm_direction; - int16_t dpcm_macroblock[3][256]; } Mpeg4DecContext; int ff_mpeg4_decode_picture_header(MpegEncContext *s); -- 2.45.2
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".