From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org> Subject: [FFmpeg-devel] [PATCH 01/77] avcodec/mpegvideo(_enc)?: Mark init, close functions as, av_cold Date: Wed, 19 Mar 2025 22:18:38 +0100 Message-ID: <AS8P250MB0744A8DBC25ABEC4F82344B58FD92@AS8P250MB0744.EURP250.PROD.OUTLOOK.COM> (raw) [-- Attachment #1: Type: text/plain, Size: 277 bytes --] 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 - Andreas [-- Attachment #2: 0001-avcodec-mpegvideo-_enc-Mark-init-close-functions-as-.patch --] [-- Type: text/x-patch, Size: 3909 bytes --] From b232c37e21e7a8759546f821e198ef83cf548a2f Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sun, 16 Mar 2025 04:58:27 +0100 Subject: [PATCH 01/77] avcodec/mpegvideo(_enc)?: Mark init, close functions as av_cold Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpegvideo.c | 16 ++++++++-------- libavcodec/mpegvideo_enc.c | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index f114dd8c0c..4b69b5b65c 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -349,7 +349,7 @@ av_cold void ff_mpv_idct_init(MpegEncContext *s) #endif } -static int init_duplicate_context(MpegEncContext *s) +static av_cold int init_duplicate_context(MpegEncContext *s) { if (s->encoding) { s->me.map = av_mallocz(2 * ME_MAP_SIZE * sizeof(*s->me.map)); @@ -383,7 +383,7 @@ static int init_duplicate_context(MpegEncContext *s) return 0; } -int ff_mpv_init_duplicate_contexts(MpegEncContext *s) +av_cold int ff_mpv_init_duplicate_contexts(MpegEncContext *s) { int nb_slices = s->slice_context_count, ret; @@ -407,7 +407,7 @@ int ff_mpv_init_duplicate_contexts(MpegEncContext *s) return init_duplicate_context(s); } -static void free_duplicate_context(MpegEncContext *s) +static av_cold void free_duplicate_context(MpegEncContext *s) { if (!s) return; @@ -426,7 +426,7 @@ static void free_duplicate_context(MpegEncContext *s) s->block = NULL; } -static void free_duplicate_contexts(MpegEncContext *s) +static av_cold void free_duplicate_contexts(MpegEncContext *s) { for (int i = 1; i < s->slice_context_count; i++) { free_duplicate_context(s->thread_context[i]); @@ -497,7 +497,7 @@ av_cold void ff_mpv_common_defaults(MpegEncContext *s) s->slice_context_count = 1; } -static void free_buffer_pools(BufferPoolContext *pools) +static av_cold void free_buffer_pools(BufferPoolContext *pools) { av_refstruct_pool_uninit(&pools->mbskip_table_pool); av_refstruct_pool_uninit(&pools->qscale_table_pool); @@ -507,7 +507,7 @@ static void free_buffer_pools(BufferPoolContext *pools) pools->alloc_mb_height = pools->alloc_mb_width = pools->alloc_mb_stride = 0; } -int ff_mpv_init_context_frame(MpegEncContext *s) +av_cold int ff_mpv_init_context_frame(MpegEncContext *s) { BufferPoolContext *const pools = &s->buffer_pools; int y_size, c_size, yc_size, i, mb_array_size, mv_table_size, x, y; @@ -744,7 +744,7 @@ av_cold int ff_mpv_common_init(MpegEncContext *s) return ret; } -void ff_mpv_free_context_frame(MpegEncContext *s) +av_cold void ff_mpv_free_context_frame(MpegEncContext *s) { free_duplicate_contexts(s); @@ -769,7 +769,7 @@ void ff_mpv_free_context_frame(MpegEncContext *s) s->linesize = s->uvlinesize = 0; } -void ff_mpv_common_end(MpegEncContext *s) +av_cold void ff_mpv_common_end(MpegEncContext *s) { ff_mpv_free_context_frame(s); if (s->slice_context_count > 1) diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 493a3edde6..720ded49c2 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -268,7 +268,7 @@ static void update_duplicate_context_after_me(MpegEncContext *dst, #undef COPY } -static void mpv_encode_init_static(void) +static av_cold void mpv_encode_init_static(void) { for (int i = -16; i < 16; i++) default_fcode_tab[i + MAX_MV] = 1; @@ -278,7 +278,7 @@ static void mpv_encode_init_static(void) * Set the given MpegEncContext to defaults for encoding. * the changed fields will not depend upon the prior state of the MpegEncContext. */ -static void mpv_encode_defaults(MpegEncContext *s) +static av_cold void mpv_encode_defaults(MpegEncContext *s) { static AVOnce init_static_once = AV_ONCE_INIT; -- 2.45.2 [-- Attachment #3: 0002-avcodec-mpegvideoenc-Add-MPVMainEncContext.patch --] [-- Type: text/x-patch, Size: 8939 bytes --] From 05f52331882ac51b589bde5bb710d51219453a5f Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Fri, 28 Feb 2025 18:56:15 +0100 Subject: [PATCH 02/77] avcodec/mpegvideoenc: Add MPVMainEncContext This is in preparation for moving all the elements from MpegEncContext that are only used by the main encoder thread to MPVMainEncContext. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/flvenc.c | 2 +- libavcodec/h261enc.c | 4 ++-- libavcodec/ituh263enc.c | 4 ++-- libavcodec/mjpegenc.c | 2 +- libavcodec/mpeg12enc.c | 4 ++-- libavcodec/mpeg4videoenc.c | 2 +- libavcodec/mpegvideoenc.h | 4 ++++ libavcodec/msmpeg4enc.c | 2 +- libavcodec/msmpeg4enc.h | 4 ++-- libavcodec/rv10enc.c | 2 +- libavcodec/rv20enc.c | 2 +- libavcodec/speedhqenc.c | 2 +- libavcodec/wmv2enc.c | 4 ++-- 13 files changed, 21 insertions(+), 17 deletions(-) diff --git a/libavcodec/flvenc.c b/libavcodec/flvenc.c index b6f9d1c6db..0cd20f026d 100644 --- a/libavcodec/flvenc.c +++ b/libavcodec/flvenc.c @@ -89,7 +89,7 @@ const FFCodec ff_flv_encoder = { .p.id = AV_CODEC_ID_FLV1, .p.priv_class = &ff_mpv_enc_class, .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, - .priv_data_size = sizeof(MpegEncContext), + .priv_data_size = sizeof(MPVMainEncContext), .init = ff_mpv_encode_init, FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), .close = ff_mpv_encode_end, diff --git a/libavcodec/h261enc.c b/libavcodec/h261enc.c index 36436ee60f..264efb0aa3 100644 --- a/libavcodec/h261enc.c +++ b/libavcodec/h261enc.c @@ -55,7 +55,7 @@ static uint8_t uni_h261_rl_len_last[64 * 128]; static uint8_t h261_mv_codes[64][2]; typedef struct H261EncContext { - MpegEncContext s; + MPVMainEncContext s; H261Context common; @@ -167,7 +167,7 @@ static inline int get_cbp(MpegEncContext *s, int16_t block[6][64]) */ static void h261_encode_block(H261EncContext *h, int16_t *block, int n) { - MpegEncContext *const s = &h->s; + MpegEncContext *const s = &h->s.s; int level, run, i, j, last_index, last_non_zero; if (s->mb_intra) { diff --git a/libavcodec/ituh263enc.c b/libavcodec/ituh263enc.c index a81bfb7c79..825b398455 100644 --- a/libavcodec/ituh263enc.c +++ b/libavcodec/ituh263enc.c @@ -908,7 +908,7 @@ const FFCodec ff_h263_encoder = { .p.priv_class = &h263_class, .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, - .priv_data_size = sizeof(MpegEncContext), + .priv_data_size = sizeof(MPVMainEncContext), .init = ff_mpv_encode_init, FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), .close = ff_mpv_encode_end, @@ -941,7 +941,7 @@ const FFCodec ff_h263p_encoder = { .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, - .priv_data_size = sizeof(MpegEncContext), + .priv_data_size = sizeof(MPVMainEncContext), .init = ff_mpv_encode_init, FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), .close = ff_mpv_encode_end, diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c index 30f2c9900d..0a2d6eebd3 100644 --- a/libavcodec/mjpegenc.c +++ b/libavcodec/mjpegenc.c @@ -64,7 +64,7 @@ typedef struct MJpegHuffmanCode { * MpegEncContext is followed by a MjpegContext; the other threads * can access this shared context via MpegEncContext.mjpeg. */ typedef struct MJPEGEncContext { - MpegEncContext mpeg; + MPVMainEncContext mpeg; MJpegContext mjpeg; } MJPEGEncContext; diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index 1563cefd23..bb61b4f4fe 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -72,7 +72,7 @@ static uint32_t mpeg1_lum_dc_uni[512]; static uint32_t mpeg1_chr_dc_uni[512]; typedef struct MPEG12EncContext { - MpegEncContext mpeg; + MPVMainEncContext mpeg; AVRational frame_rate_ext; unsigned frame_rate_index; @@ -201,7 +201,7 @@ static av_cold int encode_init(AVCodecContext *avctx) } } - if (mpeg12->mpeg.q_scale_type == 1) { + if (mpeg12->mpeg.s.q_scale_type == 1) { if (avctx->qmax > 28) { av_log(avctx, AV_LOG_ERROR, "non linear quant only supports qmax <= 28 currently\n"); diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c index 3b312915b4..11872f29eb 100644 --- a/libavcodec/mpeg4videoenc.c +++ b/libavcodec/mpeg4videoenc.c @@ -1395,7 +1395,7 @@ const FFCodec ff_mpeg4_encoder = { CODEC_LONG_NAME("MPEG-4 part 2"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_MPEG4, - .priv_data_size = sizeof(MpegEncContext), + .priv_data_size = sizeof(MPVMainEncContext), .init = encode_init, FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), .close = ff_mpv_encode_end, diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h index 6dd382a3c6..f7aad17650 100644 --- a/libavcodec/mpegvideoenc.h +++ b/libavcodec/mpegvideoenc.h @@ -33,6 +33,10 @@ #include "libavutil/opt.h" #include "mpegvideo.h" +typedef struct MPVMainEncContext { + MpegEncContext s; ///< The main slicecontext +} MPVMainEncContext; + #define MAX_FCODE 7 #define UNI_AC_ENC_INDEX(run,level) ((run)*128 + (level)) #define INPLACE_OFFSET 16 diff --git a/libavcodec/msmpeg4enc.c b/libavcodec/msmpeg4enc.c index 8310e0a578..98b72e4d58 100644 --- a/libavcodec/msmpeg4enc.c +++ b/libavcodec/msmpeg4enc.c @@ -151,7 +151,7 @@ av_cold void ff_msmpeg4_encode_init(MpegEncContext *s) static void find_best_tables(MSMPEG4EncContext *ms) { - MpegEncContext *const s = &ms->s; + MpegEncContext *const s = &ms->m.s; int i; int best = 0, best_size = INT_MAX; int chroma_best = 0, best_chroma_size = INT_MAX; diff --git a/libavcodec/msmpeg4enc.h b/libavcodec/msmpeg4enc.h index da9a45b589..72992176de 100644 --- a/libavcodec/msmpeg4enc.h +++ b/libavcodec/msmpeg4enc.h @@ -22,12 +22,12 @@ #ifndef AVCODEC_MSMPEG4ENC_H #define AVCODEC_MSMPEG4ENC_H -#include "mpegvideo.h" +#include "mpegvideoenc.h" #include "put_bits.h" #include "rl.h" typedef struct MSMPEG4EncContext { - MpegEncContext s; + MPVMainEncContext m; /** [mb_intra][isChroma][level][run][last] */ unsigned ac_stats[2][2][MAX_LEVEL + 1][MAX_RUN + 1][2]; diff --git a/libavcodec/rv10enc.c b/libavcodec/rv10enc.c index 53463dd068..d55fa7c2b0 100644 --- a/libavcodec/rv10enc.c +++ b/libavcodec/rv10enc.c @@ -72,7 +72,7 @@ const FFCodec ff_rv10_encoder = { .p.id = AV_CODEC_ID_RV10, .p.priv_class = &ff_mpv_enc_class, .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, - .priv_data_size = sizeof(MpegEncContext), + .priv_data_size = sizeof(MPVMainEncContext), .init = ff_mpv_encode_init, FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), .close = ff_mpv_encode_end, diff --git a/libavcodec/rv20enc.c b/libavcodec/rv20enc.c index cf27ff04ea..cacda6fdda 100644 --- a/libavcodec/rv20enc.c +++ b/libavcodec/rv20enc.c @@ -69,7 +69,7 @@ const FFCodec ff_rv20_encoder = { .p.id = AV_CODEC_ID_RV20, .p.priv_class = &ff_mpv_enc_class, .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, - .priv_data_size = sizeof(MpegEncContext), + .priv_data_size = sizeof(MPVMainEncContext), .init = ff_mpv_encode_init, FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), .close = ff_mpv_encode_end, diff --git a/libavcodec/speedhqenc.c b/libavcodec/speedhqenc.c index 536ddc0bf1..a0baa869cc 100644 --- a/libavcodec/speedhqenc.c +++ b/libavcodec/speedhqenc.c @@ -59,7 +59,7 @@ static uint32_t speedhq_chr_dc_uni[512]; static uint8_t uni_speedhq_ac_vlc_len[64 * 64 * 2]; typedef struct SpeedHQEncContext { - MpegEncContext m; + MPVMainEncContext m; int slice_start; } SpeedHQEncContext; diff --git a/libavcodec/wmv2enc.c b/libavcodec/wmv2enc.c index 825ab91a05..33569a6d39 100644 --- a/libavcodec/wmv2enc.c +++ b/libavcodec/wmv2enc.c @@ -49,7 +49,7 @@ typedef struct WMV2EncContext { static int encode_ext_header(WMV2EncContext *w) { - MpegEncContext *const s = &w->msmpeg4.s; + MpegEncContext *const s = &w->msmpeg4.m.s; PutBitContext pb; int code; @@ -76,7 +76,7 @@ static int encode_ext_header(WMV2EncContext *w) static av_cold int wmv2_encode_init(AVCodecContext *avctx) { WMV2EncContext *const w = avctx->priv_data; - MpegEncContext *const s = &w->msmpeg4.s; + MpegEncContext *const s = &w->msmpeg4.m.s; s->private_ctx = &w->common; if (ff_mpv_encode_init(avctx) < 0) -- 2.45.2 [-- Attachment #4: 0003-avcodec-mpegvideoenc-Move-tmp-bframes-to-MPVMainEncC.patch --] [-- Type: text/x-patch, Size: 16445 bytes --] From 92dd0825800227c364fb2e5b0d7f9d23ddde6662 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Fri, 28 Jan 2022 20:24:18 +0100 Subject: [PATCH 03/77] avcodec/mpegvideoenc: Move tmp bframes to MPVMainEncContext Also move b_frame_strategy and b_sensitivity and brd_scale; they are all only used by an encoder's main thread when b_frame_strategy == 2. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpegvideo.h | 8 --- libavcodec/mpegvideo_enc.c | 114 ++++++++++++++++++++----------------- libavcodec/mpegvideoenc.h | 15 ++++- 3 files changed, 73 insertions(+), 64 deletions(-) diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index afd18591c4..1091c93d95 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -48,8 +48,6 @@ #define MAX_THREADS 32 -#define MAX_B_FRAMES 16 - /** * Scantable. */ @@ -446,7 +444,6 @@ typedef struct MpegEncContext { int top_field_first; int concealment_motion_vectors; int q_scale_type; - int brd_scale; int intra_vlc_format; int alternate_scan; int repeat_first_field; @@ -518,11 +515,6 @@ typedef struct MpegEncContext { int error_rate; - /* temporary frames used by b_frame_strategy = 2 */ - AVFrame *tmp_frames[MAX_B_FRAMES + 2]; - int b_frame_strategy; - int b_sensitivity; - /* frame skip options for encoding */ int frame_skip_threshold; int frame_skip_factor; diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 720ded49c2..ffa9484669 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -419,7 +419,8 @@ static av_cold int init_matrices(MpegEncContext *s, AVCodecContext *avctx) /* init video encoder */ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) { - MpegEncContext *s = avctx->priv_data; + MPVMainEncContext *const m = avctx->priv_data; + MpegEncContext *const s = &m->s; AVCPBProperties *cpb_props; int i, ret; int mb_array_size, mv_table_size; @@ -456,10 +457,10 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) } s->gop_size = avctx->gop_size; s->avctx = avctx; - if (avctx->max_b_frames > MAX_B_FRAMES) { + if (avctx->max_b_frames > MPVENC_MAX_B_FRAMES) { av_log(avctx, AV_LOG_ERROR, "Too many B-frames requested, maximum " - "is %d.\n", MAX_B_FRAMES); - avctx->max_b_frames = MAX_B_FRAMES; + "is " AV_STRINGIFY(MPVENC_MAX_B_FRAMES) ".\n"); + avctx->max_b_frames = MPVENC_MAX_B_FRAMES; } else if (avctx->max_b_frames < 0) { av_log(avctx, AV_LOG_ERROR, "max b frames must be 0 or positive for mpegvideo based encoders\n"); @@ -700,10 +701,10 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } - if (s->b_frame_strategy && (avctx->flags & AV_CODEC_FLAG_PASS2)) { + if (m->b_frame_strategy && (avctx->flags & AV_CODEC_FLAG_PASS2)) { av_log(avctx, AV_LOG_INFO, "notice: b_frame_strategy only affects the first pass\n"); - s->b_frame_strategy = 0; + m->b_frame_strategy = 0; } i = av_gcd(avctx->time_base.den, avctx->time_base.num); @@ -914,8 +915,8 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) return ret; if (!(avctx->stats_out = av_mallocz(256)) || - !FF_ALLOCZ_TYPED_ARRAY(s->input_picture, MAX_B_FRAMES + 1) || - !FF_ALLOCZ_TYPED_ARRAY(s->reordered_input_picture, MAX_B_FRAMES + 1) || + !FF_ALLOCZ_TYPED_ARRAY(s->input_picture, MPVENC_MAX_B_FRAMES + 1) || + !FF_ALLOCZ_TYPED_ARRAY(s->reordered_input_picture, MPVENC_MAX_B_FRAMES + 1) || !(s->new_pic = av_frame_alloc()) || !(s->picture_pool = ff_mpv_alloc_pic_pool(0))) return AVERROR(ENOMEM); @@ -1010,17 +1011,17 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) if ((ret = ff_rate_control_init(s)) < 0) return ret; - if (s->b_frame_strategy == 2) { + if (m->b_frame_strategy == 2) { for (i = 0; i < s->max_b_frames + 2; i++) { - s->tmp_frames[i] = av_frame_alloc(); - if (!s->tmp_frames[i]) + m->tmp_frames[i] = av_frame_alloc(); + if (!m->tmp_frames[i]) return AVERROR(ENOMEM); - s->tmp_frames[i]->format = AV_PIX_FMT_YUV420P; - s->tmp_frames[i]->width = s->width >> s->brd_scale; - s->tmp_frames[i]->height = s->height >> s->brd_scale; + m->tmp_frames[i]->format = AV_PIX_FMT_YUV420P; + m->tmp_frames[i]->width = s->width >> m->brd_scale; + m->tmp_frames[i]->height = s->height >> m->brd_scale; - ret = av_frame_get_buffer(s->tmp_frames[i], 0); + ret = av_frame_get_buffer(m->tmp_frames[i], 0); if (ret < 0) return ret; } @@ -1039,8 +1040,8 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) av_cold int ff_mpv_encode_end(AVCodecContext *avctx) { - MpegEncContext *s = avctx->priv_data; - int i; + MPVMainEncContext *const m = avctx->priv_data; + MpegEncContext *const s = &m->s; ff_rate_control_uninit(&s->rc_context); @@ -1048,13 +1049,13 @@ av_cold int ff_mpv_encode_end(AVCodecContext *avctx) av_refstruct_pool_uninit(&s->picture_pool); if (s->input_picture && s->reordered_input_picture) { - for (int i = 0; i < MAX_B_FRAMES + 1; i++) { + for (int i = 0; i < MPVENC_MAX_B_FRAMES + 1; i++) { av_refstruct_unref(&s->input_picture[i]); av_refstruct_unref(&s->reordered_input_picture[i]); } } - for (i = 0; i < FF_ARRAY_ELEMS(s->tmp_frames); i++) - av_frame_free(&s->tmp_frames[i]); + for (int i = 0; i < FF_ARRAY_ELEMS(m->tmp_frames); i++) + av_frame_free(&m->tmp_frames[i]); av_frame_free(&s->new_pic); @@ -1249,8 +1250,9 @@ static int prepare_picture(MpegEncContext *s, AVFrame *f, const AVFrame *props_f return 0; } -static int load_input_picture(MpegEncContext *s, const AVFrame *pic_arg) +static int load_input_picture(MPVMainEncContext *const m, const AVFrame *pic_arg) { + MpegEncContext *const s = &m->s; MPVPicture *pic = NULL; int64_t pts; int display_picture_number = 0, ret; @@ -1376,9 +1378,9 @@ static int load_input_picture(MpegEncContext *s, const AVFrame *pic_arg) } /* shift buffer entries */ - for (int i = flush_offset; i <= MAX_B_FRAMES; i++) + for (int i = flush_offset; i <= MPVENC_MAX_B_FRAMES; i++) s->input_picture[i - flush_offset] = s->input_picture[i]; - for (int i = MAX_B_FRAMES + 1 - flush_offset; i <= MAX_B_FRAMES; i++) + for (int i = MPVENC_MAX_B_FRAMES + 1 - flush_offset; i <= MPVENC_MAX_B_FRAMES; i++) s->input_picture[i] = NULL; s->input_picture[encoding_delay] = pic; @@ -1451,10 +1453,11 @@ static int encode_frame(AVCodecContext *c, const AVFrame *frame, AVPacket *pkt) return size; } -static int estimate_best_b_count(MpegEncContext *s) +static int estimate_best_b_count(MPVMainEncContext *const m) { + MpegEncContext *const s = &m->s; AVPacket *pkt; - const int scale = s->brd_scale; + const int scale = m->brd_scale; int width = s->width >> scale; int height = s->height >> scale; int i, j, out_size, p_lambda, b_lambda, lambda2; @@ -1491,18 +1494,18 @@ static int estimate_best_b_count(MpegEncContext *s) data[2] += INPLACE_OFFSET; } - s->mpvencdsp.shrink[scale](s->tmp_frames[i]->data[0], - s->tmp_frames[i]->linesize[0], + s->mpvencdsp.shrink[scale](m->tmp_frames[i]->data[0], + m->tmp_frames[i]->linesize[0], data[0], pre_input_ptr->f->linesize[0], width, height); - s->mpvencdsp.shrink[scale](s->tmp_frames[i]->data[1], - s->tmp_frames[i]->linesize[1], + s->mpvencdsp.shrink[scale](m->tmp_frames[i]->data[1], + m->tmp_frames[i]->linesize[1], data[1], pre_input_ptr->f->linesize[1], width >> 1, height >> 1); - s->mpvencdsp.shrink[scale](s->tmp_frames[i]->data[2], - s->tmp_frames[i]->linesize[2], + s->mpvencdsp.shrink[scale](m->tmp_frames[i]->data[2], + m->tmp_frames[i]->linesize[2], data[2], pre_input_ptr->f->linesize[2], width >> 1, height >> 1); @@ -1539,10 +1542,10 @@ static int estimate_best_b_count(MpegEncContext *s) goto fail; - s->tmp_frames[0]->pict_type = AV_PICTURE_TYPE_I; - s->tmp_frames[0]->quality = 1 * FF_QP2LAMBDA; + m->tmp_frames[0]->pict_type = AV_PICTURE_TYPE_I; + m->tmp_frames[0]->quality = 1 * FF_QP2LAMBDA; - out_size = encode_frame(c, s->tmp_frames[0], pkt); + out_size = encode_frame(c, m->tmp_frames[0], pkt); if (out_size < 0) { ret = out_size; goto fail; @@ -1553,11 +1556,11 @@ static int estimate_best_b_count(MpegEncContext *s) for (i = 0; i < s->max_b_frames + 1; i++) { int is_p = i % (j + 1) == j || i == s->max_b_frames; - s->tmp_frames[i + 1]->pict_type = is_p ? + m->tmp_frames[i + 1]->pict_type = is_p ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_B; - s->tmp_frames[i + 1]->quality = is_p ? p_lambda : b_lambda; + m->tmp_frames[i + 1]->quality = is_p ? p_lambda : b_lambda; - out_size = encode_frame(c, s->tmp_frames[i + 1], pkt); + out_size = encode_frame(c, m->tmp_frames[i + 1], pkt); if (out_size < 0) { ret = out_size; goto fail; @@ -1603,8 +1606,10 @@ fail: * input_picture[0] is always NULL when exiting this function, even on error; * reordered_input_picture[0] is always NULL when exiting this function on error. */ -static int set_bframe_chain_length(MpegEncContext *s) +static int set_bframe_chain_length(MPVMainEncContext *const m) { + MpegEncContext *const s = &m->s; + /* Either nothing to do or can't do anything */ if (s->reordered_input_picture[0] || !s->input_picture[0]) return 0; @@ -1649,11 +1654,11 @@ static int set_bframe_chain_length(MpegEncContext *s) } } - if (s->b_frame_strategy == 0) { + if (m->b_frame_strategy == 0) { b_frames = s->max_b_frames; while (b_frames && !s->input_picture[b_frames]) b_frames--; - } else if (s->b_frame_strategy == 1) { + } else if (m->b_frame_strategy == 1) { int i; for (i = 1; i < s->max_b_frames + 1; i++) { if (s->input_picture[i] && @@ -1668,7 +1673,7 @@ static int set_bframe_chain_length(MpegEncContext *s) for (i = 0; i < s->max_b_frames + 1; i++) { if (!s->input_picture[i] || s->input_picture[i]->b_frame_score - 1 > - s->mb_num / s->b_sensitivity) + s->mb_num / m->b_sensitivity) break; } @@ -1678,8 +1683,8 @@ static int set_bframe_chain_length(MpegEncContext *s) for (i = 0; i < b_frames + 1; i++) { s->input_picture[i]->b_frame_score = 0; } - } else if (s->b_frame_strategy == 2) { - b_frames = estimate_best_b_count(s); + } else if (m->b_frame_strategy == 2) { + b_frames = estimate_best_b_count(m); if (b_frames < 0) { av_refstruct_unref(&s->input_picture[0]); return b_frames; @@ -1733,17 +1738,18 @@ static int set_bframe_chain_length(MpegEncContext *s) return 0; } -static int select_input_picture(MpegEncContext *s) +static int select_input_picture(MPVMainEncContext *const m) { + MpegEncContext *const s = &m->s; int ret; av_assert1(!s->reordered_input_picture[0]); - for (int i = 1; i <= MAX_B_FRAMES; i++) + for (int i = 1; i <= MPVENC_MAX_B_FRAMES; i++) s->reordered_input_picture[i - 1] = s->reordered_input_picture[i]; - s->reordered_input_picture[MAX_B_FRAMES] = NULL; + s->reordered_input_picture[MPVENC_MAX_B_FRAMES] = NULL; - ret = set_bframe_chain_length(s); + ret = set_bframe_chain_length(m); av_assert1(!s->input_picture[0]); if (ret < 0) return ret; @@ -1867,7 +1873,8 @@ static void frame_start(MpegEncContext *s) int ff_mpv_encode_picture(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pic_arg, int *got_packet) { - MpegEncContext *s = avctx->priv_data; + MPVMainEncContext *const m = avctx->priv_data; + MpegEncContext *const s = &m->s; int stuffing_count, ret; int context_count = s->slice_context_count; @@ -1877,12 +1884,13 @@ int ff_mpv_encode_picture(AVCodecContext *avctx, AVPacket *pkt, s->picture_in_gop_number++; - if (load_input_picture(s, pic_arg) < 0) - return -1; + ret = load_input_picture(m, pic_arg); + if (ret < 0) + return ret; - if (select_input_picture(s) < 0) { - return -1; - } + ret = select_input_picture(m); + if (ret < 0) + return ret; /* output? */ if (s->new_pic->data[0]) { diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h index f7aad17650..7b5635e50e 100644 --- a/libavcodec/mpegvideoenc.h +++ b/libavcodec/mpegvideoenc.h @@ -33,8 +33,16 @@ #include "libavutil/opt.h" #include "mpegvideo.h" +#define MPVENC_MAX_B_FRAMES 16 + typedef struct MPVMainEncContext { MpegEncContext s; ///< The main slicecontext + + /// temporary frames used by b_frame_strategy = 2 + AVFrame *tmp_frames[MPVENC_MAX_B_FRAMES + 2]; + int b_frame_strategy; + int b_sensitivity; + int brd_scale; } MPVMainEncContext; #define MAX_FCODE 7 @@ -85,6 +93,7 @@ typedef struct MPVMainEncContext { { "msad", "Sum of absolute differences, median predicted", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_MEDIAN_SAD }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, .unit = "cmp_func" } #define FF_MPV_OFFSET(x) offsetof(MpegEncContext, x) +#define FF_MPV_MAIN_OFFSET(x) offsetof(MPVMainEncContext, x) #define FF_RC_OFFSET(x) offsetof(MpegEncContext, rc_context.x) #define FF_MPV_OPT_FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM) #define FF_MPV_COMMON_OPTS \ @@ -126,9 +135,9 @@ FF_MPV_OPT_CMP_FUNC, \ {"ps", "RTP payload size in bytes", FF_MPV_OFFSET(rtp_payload_size), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ #define FF_MPV_COMMON_BFRAME_OPTS \ -{"b_strategy", "Strategy to choose between I/P/B-frames", FF_MPV_OFFSET(b_frame_strategy), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 2, FF_MPV_OPT_FLAGS }, \ -{"b_sensitivity", "Adjust sensitivity of b_frame_strategy 1", FF_MPV_OFFSET(b_sensitivity), AV_OPT_TYPE_INT, {.i64 = 40 }, 1, INT_MAX, FF_MPV_OPT_FLAGS }, \ -{"brd_scale", "Downscale frames for dynamic B-frame decision", FF_MPV_OFFSET(brd_scale), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 3, FF_MPV_OPT_FLAGS }, +{"b_strategy", "Strategy to choose between I/P/B-frames", FF_MPV_MAIN_OFFSET(b_frame_strategy), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 2, FF_MPV_OPT_FLAGS }, \ +{"b_sensitivity", "Adjust sensitivity of b_frame_strategy 1", FF_MPV_MAIN_OFFSET(b_sensitivity), AV_OPT_TYPE_INT, {.i64 = 40 }, 1, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"brd_scale", "Downscale frames for dynamic B-frame decision", FF_MPV_MAIN_OFFSET(brd_scale), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 3, FF_MPV_OPT_FLAGS }, #define FF_MPV_COMMON_MOTION_EST_OPTS \ {"motion_est", "motion estimation algorithm", FF_MPV_OFFSET(motion_est), AV_OPT_TYPE_INT, {.i64 = FF_ME_EPZS }, FF_ME_ZERO, FF_ME_XONE, FF_MPV_OPT_FLAGS, .unit = "motion_est" }, \ -- 2.45.2 [-- Attachment #5: 0004-avcodec-mpegvideoenc-Move-ratecontrol-to-MPVMainEncC.patch --] [-- Type: text/x-patch, Size: 34411 bytes --] From 0bbf4604f747b894efcd7adfd2149edbfb58d97f Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Fri, 28 Jan 2022 20:43:54 +0100 Subject: [PATCH 04/77] avcodec/mpegvideoenc: Move ratecontrol to MPVMainEncContext Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpegvideo.h | 8 ---- libavcodec/mpegvideo_enc.c | 73 ++++++++++++++++++--------------- libavcodec/mpegvideoenc.h | 10 ++++- libavcodec/ratecontrol.c | 75 +++++++++++++++++++--------------- libavcodec/ratecontrol.h | 12 +++--- libavcodec/snowenc.c | 82 ++++++++++++++++++++------------------ 6 files changed, 140 insertions(+), 120 deletions(-) diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 1091c93d95..75b1fff245 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -42,7 +42,6 @@ #include "mpegvideoencdsp.h" #include "pixblockdsp.h" #include "put_bits.h" -#include "ratecontrol.h" #include "qpeldsp.h" #include "videodsp.h" @@ -327,13 +326,6 @@ typedef struct MpegEncContext { int dct_count[2]; uint16_t (*dct_offset)[64]; - /* bit rate control */ - int64_t total_bits; - int frame_bits; ///< bits used for the current frame - int stuffing_bits; ///< bits used for stuffing - int next_lambda; ///< next lambda used for retrying to encode a frame - RateControlContext rc_context; ///< contains stuff only accessed in ratecontrol.c - /* statistics, used for 2-pass encoding */ int mv_bits; int header_bits; diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index ffa9484669..7f24c1baa6 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -84,7 +84,7 @@ #define QMAT_SHIFT_MMX 16 #define QMAT_SHIFT 21 -static int encode_picture(MpegEncContext *s, const AVPacket *pkt); +static int encode_picture(MPVMainEncContext *const s, const AVPacket *pkt); static int dct_quantize_refine(MpegEncContext *s, int16_t *block, int16_t *weight, int16_t *orig, int n, int qscale); static int sse_mb(MpegEncContext *s); static void denoise_dct_c(MpegEncContext *s, int16_t *block); @@ -1008,7 +1008,8 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) #endif } - if ((ret = ff_rate_control_init(s)) < 0) + ret = ff_rate_control_init(m); + if (ret < 0) return ret; if (m->b_frame_strategy == 2) { @@ -1043,7 +1044,7 @@ av_cold int ff_mpv_encode_end(AVCodecContext *avctx) MPVMainEncContext *const m = avctx->priv_data; MpegEncContext *const s = &m->s; - ff_rate_control_uninit(&s->rc_context); + ff_rate_control_uninit(&m->rc_context); ff_mpv_common_end(s); av_refstruct_pool_uninit(&s->picture_pool); @@ -1622,7 +1623,7 @@ static int set_bframe_chain_length(MPVMainEncContext *const m) // FIXME check that the gop check above is +-1 correct av_refstruct_unref(&s->input_picture[0]); - ff_vbv_update(s, 0); + ff_vbv_update(m, 0); return 0; } @@ -1642,15 +1643,15 @@ static int set_bframe_chain_length(MPVMainEncContext *const m) for (int i = 0; i < s->max_b_frames + 1; i++) { int pict_num = s->input_picture[0]->display_picture_number + i; - if (pict_num >= s->rc_context.num_entries) + if (pict_num >= m->rc_context.num_entries) break; if (!s->input_picture[i]) { - s->rc_context.entry[pict_num - 1].new_pict_type = AV_PICTURE_TYPE_P; + m->rc_context.entry[pict_num - 1].new_pict_type = AV_PICTURE_TYPE_P; break; } s->input_picture[i]->f->pict_type = - s->rc_context.entry[pict_num].new_pict_type; + m->rc_context.entry[pict_num].new_pict_type; } } @@ -1918,7 +1919,7 @@ int ff_mpv_encode_picture(AVCodecContext *avctx, AVPacket *pkt, //emms_c(); frame_start(s); vbv_retry: - ret = encode_picture(s, pkt); + ret = encode_picture(m, pkt); if (growing_buffer) { av_assert0(s->pb.buf == avctx->internal->byte_buffer); pkt->data = s->pb.buf; @@ -1933,14 +1934,14 @@ vbv_retry: ff_mjpeg_encode_picture_trailer(&s->pb, s->header_bits); if (avctx->rc_buffer_size) { - RateControlContext *rcc = &s->rc_context; + RateControlContext *rcc = &m->rc_context; int max_size = FFMAX(rcc->buffer_index * avctx->rc_max_available_vbv_use, rcc->buffer_index - 500); int hq = (avctx->mb_decision == FF_MB_DECISION_RD || avctx->trellis); int min_step = hq ? 1 : (1<<(FF_LAMBDA_SHIFT + 7))/139; if (put_bits_count(&s->pb) > max_size && s->lambda < s->lmax) { - s->next_lambda = FFMAX(s->lambda + min_step, s->lambda * + m->next_lambda = FFMAX(s->lambda + min_step, s->lambda * (s->qscale + 1) / s->qscale); if (s->adaptive_quant) { int i; @@ -1968,7 +1969,7 @@ vbv_retry: } if (avctx->flags & AV_CODEC_FLAG_PASS1) - ff_write_pass1_stats(s); + ff_write_pass1_stats(m); for (int i = 0; i < MPV_MAX_PLANES; i++) avctx->error[i] += s->encoding_error[i]; @@ -1982,10 +1983,10 @@ vbv_retry: s->misc_bits + s->i_tex_bits + s->p_tex_bits); flush_put_bits(&s->pb); - s->frame_bits = put_bits_count(&s->pb); + m->frame_bits = put_bits_count(&s->pb); - stuffing_count = ff_vbv_update(s, s->frame_bits); - s->stuffing_bits = 8*stuffing_count; + stuffing_count = ff_vbv_update(m, m->frame_bits); + m->stuffing_bits = 8*stuffing_count; if (stuffing_count) { if (put_bytes_left(&s->pb, 0) < stuffing_count + 50) { av_log(avctx, AV_LOG_ERROR, "stuffing too large\n"); @@ -2009,10 +2010,10 @@ vbv_retry: break; default: av_log(avctx, AV_LOG_ERROR, "vbv buffer overflow\n"); - s->stuffing_bits = 0; + m->stuffing_bits = 0; } flush_put_bits(&s->pb); - s->frame_bits = put_bits_count(&s->pb); + m->frame_bits = put_bits_count(&s->pb); } /* update MPEG-1/2 vbv_delay for CBR */ @@ -2027,9 +2028,9 @@ vbv_retry: int vbv_delay, min_delay; double inbits = avctx->rc_max_rate * av_q2d(avctx->time_base); - int minbits = s->frame_bits - 8 * + int minbits = m->frame_bits - 8 * (s->vbv_delay_pos - 1); - double bits = s->rc_context.buffer_index + minbits - inbits; + double bits = m->rc_context.buffer_index + minbits - inbits; uint8_t *const vbv_delay_ptr = s->pb.buf + s->vbv_delay_pos; if (bits < 0) @@ -2064,7 +2065,7 @@ vbv_retry: return ret; } } - s->total_bits += s->frame_bits; + m->total_bits += m->frame_bits; pkt->pts = s->cur_pic.ptr->f->pts; pkt->duration = s->cur_pic.ptr->f->duration; @@ -2089,14 +2090,14 @@ vbv_retry: if (s->mb_info) av_packet_shrink_side_data(pkt, AV_PKT_DATA_H263_MB_INFO, s->mb_info_size); } else { - s->frame_bits = 0; + m->frame_bits = 0; } ff_mpv_unref_picture(&s->cur_pic); - av_assert1((s->frame_bits & 7) == 0); + av_assert1((m->frame_bits & 7) == 0); - pkt->size = s->frame_bits / 8; + pkt->size = m->frame_bits / 8; *got_packet = !!pkt->size; return 0; } @@ -3611,12 +3612,15 @@ static void merge_context_after_encode(MpegEncContext *dst, MpegEncContext *src) flush_put_bits(&dst->pb); } -static int estimate_qp(MpegEncContext *s, int dry_run){ - if (s->next_lambda){ - s->cur_pic.ptr->f->quality = s->next_lambda; - if(!dry_run) s->next_lambda= 0; +static int estimate_qp(MPVMainEncContext *const m, int dry_run) +{ + MpegEncContext *const s = &m->s; + + if (m->next_lambda){ + s->cur_pic.ptr->f->quality = m->next_lambda; + if(!dry_run) m->next_lambda= 0; } else if (!s->fixed_qscale) { - int quality = ff_rate_estimate_qscale(s, dry_run); + int quality = ff_rate_estimate_qscale(m, dry_run); s->cur_pic.ptr->f->quality = quality; if (s->cur_pic.ptr->f->quality < 0) return -1; @@ -3661,8 +3665,9 @@ static void set_frame_distances(MpegEncContext * s){ } } -static int encode_picture(MpegEncContext *s, const AVPacket *pkt) +static int encode_picture(MPVMainEncContext *const m, const AVPacket *pkt) { + MpegEncContext *const s = &m->s; int i, ret; int bits; int context_count = s->slice_context_count; @@ -3689,9 +3694,10 @@ static int encode_picture(MpegEncContext *s, const AVPacket *pkt) } if (s->avctx->flags & AV_CODEC_FLAG_PASS2) { - if (estimate_qp(s,1) < 0) - return -1; - ff_get_2pass_fcode(s); + ret = estimate_qp(m, 1); + if (ret < 0) + return ret; + ff_get_2pass_fcode(m); } else if (!(s->avctx->flags & AV_CODEC_FLAG_QSCALE)) { if(s->pict_type==AV_PICTURE_TYPE_B) s->lambda= s->last_lambda_for[s->pict_type]; @@ -3814,8 +3820,9 @@ static int encode_picture(MpegEncContext *s, const AVPacket *pkt) } } - if (estimate_qp(s, 0) < 0) - return -1; + ret = estimate_qp(m, 0); + if (ret < 0) + return ret; if (s->qscale < 3 && s->max_qcoeff <= 128 && s->pict_type == AV_PICTURE_TYPE_I && diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h index 7b5635e50e..c1d2821038 100644 --- a/libavcodec/mpegvideoenc.h +++ b/libavcodec/mpegvideoenc.h @@ -32,6 +32,7 @@ #include "libavutil/opt.h" #include "mpegvideo.h" +#include "ratecontrol.h" #define MPVENC_MAX_B_FRAMES 16 @@ -43,6 +44,13 @@ typedef struct MPVMainEncContext { int b_frame_strategy; int b_sensitivity; int brd_scale; + + /* bit rate control */ + int64_t total_bits; + int frame_bits; ///< bits used for the current frame + int stuffing_bits; ///< bits used for stuffing + int next_lambda; ///< next lambda used for retrying to encode a frame + RateControlContext rc_context; ///< contains stuff only accessed in ratecontrol.c } MPVMainEncContext; #define MAX_FCODE 7 @@ -94,7 +102,7 @@ typedef struct MPVMainEncContext { #define FF_MPV_OFFSET(x) offsetof(MpegEncContext, x) #define FF_MPV_MAIN_OFFSET(x) offsetof(MPVMainEncContext, x) -#define FF_RC_OFFSET(x) offsetof(MpegEncContext, rc_context.x) +#define FF_RC_OFFSET(x) offsetof(MPVMainEncContext, rc_context.x) #define FF_MPV_OPT_FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM) #define FF_MPV_COMMON_OPTS \ FF_MPV_OPT_CMP_FUNC, \ diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c index f5e0b70a9a..ebc3a30fc1 100644 --- a/libavcodec/ratecontrol.c +++ b/libavcodec/ratecontrol.c @@ -35,8 +35,9 @@ #include "mpegvideoenc.h" #include "libavutil/eval.h" -void ff_write_pass1_stats(MpegEncContext *s) +void ff_write_pass1_stats(MPVMainEncContext *const m) { + const MpegEncContext *const s = &m->s; snprintf(s->avctx->stats_out, 256, "in:%d out:%d type:%d q:%d itex:%d ptex:%d mv:%d misc:%d " "fcode:%d bcode:%d mc-var:%"PRId64" var:%"PRId64" icount:%d hbits:%d;\n", @@ -101,9 +102,10 @@ static double bits2qp_cb(void *rce, double qp) return bits2qp(rce, qp); } -static double get_diff_limited_q(MpegEncContext *s, const RateControlEntry *rce, double q) +static double get_diff_limited_q(MPVMainEncContext *m, const RateControlEntry *rce, double q) { - RateControlContext *rcc = &s->rc_context; + MpegEncContext *const s = &m->s; + RateControlContext *const rcc = &m->rc_context; AVCodecContext *a = s->avctx; const int pict_type = rce->new_pict_type; const double last_p_q = rcc->last_qscale_for[AV_PICTURE_TYPE_P]; @@ -168,10 +170,11 @@ static void get_qminmax(int *qmin_ret, int *qmax_ret, MpegEncContext *s, int pic *qmax_ret = qmax; } -static double modify_qscale(MpegEncContext *s, const RateControlEntry *rce, +static double modify_qscale(MPVMainEncContext *const m, const RateControlEntry *rce, double q, int frame_num) { - RateControlContext *rcc = &s->rc_context; + MpegEncContext *const s = &m->s; + RateControlContext *const rcc = &m->rc_context; const double buffer_size = s->avctx->rc_buffer_size; const double fps = get_fps(s->avctx); const double min_rate = s->avctx->rc_min_rate / fps; @@ -259,10 +262,11 @@ static double modify_qscale(MpegEncContext *s, const RateControlEntry *rce, /** * Modify the bitrate curve from pass1 for one frame. */ -static double get_qscale(MpegEncContext *s, RateControlEntry *rce, +static double get_qscale(MPVMainEncContext *const m, RateControlEntry *rce, double rate_factor, int frame_num) { - RateControlContext *rcc = &s->rc_context; + MpegEncContext *const s = &m->s; + RateControlContext *rcc = &m->rc_context; AVCodecContext *a = s->avctx; const int pict_type = rce->new_pict_type; const double mb_num = s->mb_num; @@ -332,9 +336,10 @@ static double get_qscale(MpegEncContext *s, RateControlEntry *rce, return q; } -static int init_pass2(MpegEncContext *s) +static int init_pass2(MPVMainEncContext *const m) { - RateControlContext *rcc = &s->rc_context; + RateControlContext *const rcc = &m->rc_context; + MpegEncContext *const s = &m->s; AVCodecContext *a = s->avctx; int i, toobig; AVRational fps = get_fpsQ(s->avctx); @@ -393,7 +398,7 @@ static int init_pass2(MpegEncContext *s) for (i = 0; i < rcc->num_entries; i++) { const RateControlEntry *rce = &rcc->entry[i]; - qscale[i] = get_qscale(s, &rcc->entry[i], rate_factor, i); + qscale[i] = get_qscale(m, &rcc->entry[i], rate_factor, i); rcc->last_qscale_for[rce->pict_type] = qscale[i]; } av_assert0(filter_size % 2 == 1); @@ -402,13 +407,13 @@ static int init_pass2(MpegEncContext *s) for (i = FFMAX(0, rcc->num_entries - 300); i < rcc->num_entries; i++) { const RateControlEntry *rce = &rcc->entry[i]; - qscale[i] = get_diff_limited_q(s, rce, qscale[i]); + qscale[i] = get_diff_limited_q(m, rce, qscale[i]); } for (i = rcc->num_entries - 1; i >= 0; i--) { const RateControlEntry *rce = &rcc->entry[i]; - qscale[i] = get_diff_limited_q(s, rce, qscale[i]); + qscale[i] = get_diff_limited_q(m, rce, qscale[i]); } /* smooth curve */ @@ -438,10 +443,10 @@ static int init_pass2(MpegEncContext *s) RateControlEntry *rce = &rcc->entry[i]; double bits; - rce->new_qscale = modify_qscale(s, rce, blurred_qscale[i], i); + rce->new_qscale = modify_qscale(m, rce, blurred_qscale[i], i); bits = qp2bits(rce, rce->new_qscale) + rce->mv_bits + rce->misc_bits; - bits += 8 * ff_vbv_update(s, bits); + bits += 8 * ff_vbv_update(m, bits); rce->expected_bits = expected_bits; expected_bits += bits; @@ -494,9 +499,10 @@ static int init_pass2(MpegEncContext *s) return 0; } -av_cold int ff_rate_control_init(MpegEncContext *s) +av_cold int ff_rate_control_init(MPVMainEncContext *const m) { - RateControlContext *rcc = &s->rc_context; + MpegEncContext *const s = &m->s; + RateControlContext *rcc = &m->rc_context; int i, res; static const char * const const_names[] = { "PI", @@ -632,7 +638,7 @@ av_cold int ff_rate_control_init(MpegEncContext *s) p = next; } - res = init_pass2(s); + res = init_pass2(m); if (res < 0) return res; } @@ -686,7 +692,7 @@ av_cold int ff_rate_control_init(MpegEncContext *s) rcc->mv_bits_sum[rce.pict_type] += rce.mv_bits; rcc->frame_count[rce.pict_type]++; - get_qscale(s, &rce, rcc->pass1_wanted_bits / rcc->pass1_rc_eq_output_sum, i); + get_qscale(m, &rce, rcc->pass1_wanted_bits / rcc->pass1_rc_eq_output_sum, i); // FIXME misbehaves a little for variable fps rcc->pass1_wanted_bits += s->bit_rate / get_fps(s->avctx); @@ -717,9 +723,10 @@ av_cold void ff_rate_control_uninit(RateControlContext *rcc) av_freep(&rcc->cplx_tab); } -int ff_vbv_update(MpegEncContext *s, int frame_size) +int ff_vbv_update(MPVMainEncContext *m, int frame_size) { - RateControlContext *rcc = &s->rc_context; + MpegEncContext *const s = &m->s; + RateControlContext *const rcc = &m->rc_context; const double fps = get_fps(s->avctx); const int buffer_size = s->avctx->rc_buffer_size; const double min_rate = s->avctx->rc_min_rate / fps; @@ -893,9 +900,10 @@ static void adaptive_quantization(RateControlContext *const rcc, } } -void ff_get_2pass_fcode(MpegEncContext *s) +void ff_get_2pass_fcode(MPVMainEncContext *const m) { - const RateControlContext *rcc = &s->rc_context; + MpegEncContext *const s = &m->s; + const RateControlContext *rcc = &m->rc_context; const RateControlEntry *rce = &rcc->entry[s->picture_number]; s->f_code = rce->f_code; @@ -904,8 +912,10 @@ void ff_get_2pass_fcode(MpegEncContext *s) // FIXME rd or at least approx for dquant -float ff_rate_estimate_qscale(MpegEncContext *s, int dry_run) +float ff_rate_estimate_qscale(MPVMainEncContext *const m, int dry_run) { + MpegEncContext *const s = &m->s; + RateControlContext *rcc = &m->rc_context; float q; int qmin, qmax; float br_compensation; @@ -914,7 +924,6 @@ float ff_rate_estimate_qscale(MpegEncContext *s, int dry_run) double fps; int picture_number = s->picture_number; int64_t wanted_bits; - RateControlContext *rcc = &s->rc_context; AVCodecContext *a = s->avctx; RateControlEntry local_rce, *rce; double bits; @@ -931,11 +940,11 @@ float ff_rate_estimate_qscale(MpegEncContext *s, int dry_run) const int64_t last_var = s->last_pict_type == AV_PICTURE_TYPE_I ? rcc->last_mb_var_sum : rcc->last_mc_mb_var_sum; - av_assert1(s->frame_bits >= s->stuffing_bits); + av_assert1(m->frame_bits >= m->stuffing_bits); update_predictor(&rcc->pred[s->last_pict_type], rcc->last_qscale, sqrt(last_var), - s->frame_bits - s->stuffing_bits); + m->frame_bits - m->stuffing_bits); } if (s->avctx->flags & AV_CODEC_FLAG_PASS2) { @@ -970,7 +979,7 @@ float ff_rate_estimate_qscale(MpegEncContext *s, int dry_run) wanted_bits = (int64_t)wanted_bits_double; } - diff = s->total_bits - wanted_bits; + diff = m->total_bits - wanted_bits; br_compensation = (a->bit_rate_tolerance - diff) / a->bit_rate_tolerance; if (br_compensation <= 0.0) br_compensation = 0.001; @@ -984,7 +993,7 @@ float ff_rate_estimate_qscale(MpegEncContext *s, int dry_run) q = rce->new_qscale / br_compensation; ff_dlog(s->avctx, "%f %f %f last:%d var:%"PRId64" type:%d//\n", q, rce->new_qscale, - br_compensation, s->frame_bits, var, pict_type); + br_compensation, m->frame_bits, var, pict_type); } else { rce->pict_type = rce->new_pict_type = pict_type; @@ -1015,12 +1024,12 @@ float ff_rate_estimate_qscale(MpegEncContext *s, int dry_run) rate_factor = rcc->pass1_wanted_bits / rcc->pass1_rc_eq_output_sum * br_compensation; - q = get_qscale(s, rce, rate_factor, picture_number); + q = get_qscale(m, rce, rate_factor, picture_number); if (q < 0) return -1; av_assert0(q > 0.0); - q = get_diff_limited_q(s, rce, q); + q = get_diff_limited_q(m, rce, q); av_assert0(q > 0.0); // FIXME type dependent blur like in 2-pass @@ -1034,7 +1043,7 @@ float ff_rate_estimate_qscale(MpegEncContext *s, int dry_run) } av_assert0(q > 0.0); - q = modify_qscale(s, rce, q, picture_number); + q = modify_qscale(m, rce, q, picture_number); rcc->pass1_wanted_bits += s->bit_rate / fps; @@ -1047,8 +1056,8 @@ float ff_rate_estimate_qscale(MpegEncContext *s, int dry_run) "size:%d var:%"PRId64"/%"PRId64" br:%"PRId64" fps:%d\n", av_get_picture_type_char(pict_type), qmin, q, qmax, picture_number, - wanted_bits / 1000, s->total_bits / 1000, - br_compensation, short_term_q, s->frame_bits, + wanted_bits / 1000, m->total_bits / 1000, + br_compensation, short_term_q, m->frame_bits, s->mb_var_sum, s->mc_mb_var_sum, s->bit_rate / 1000, (int)fps); } diff --git a/libavcodec/ratecontrol.h b/libavcodec/ratecontrol.h index b889491335..3bcfa5658a 100644 --- a/libavcodec/ratecontrol.h +++ b/libavcodec/ratecontrol.h @@ -93,14 +93,14 @@ typedef struct RateControlContext{ float *cplx_tab, *bits_tab; }RateControlContext; -struct MpegEncContext; +typedef struct MPVMainEncContext MPVMainEncContext; /* rate control */ -int ff_rate_control_init(struct MpegEncContext *s); -float ff_rate_estimate_qscale(struct MpegEncContext *s, int dry_run); -void ff_write_pass1_stats(struct MpegEncContext *s); -int ff_vbv_update(struct MpegEncContext *s, int frame_size); -void ff_get_2pass_fcode(struct MpegEncContext *s); +int ff_rate_control_init(MPVMainEncContext *m); +float ff_rate_estimate_qscale(MPVMainEncContext *m, int dry_run); +void ff_write_pass1_stats(MPVMainEncContext *m); +int ff_vbv_update(MPVMainEncContext *m, int frame_size); +void ff_get_2pass_fcode(MPVMainEncContext *m); void ff_rate_control_uninit(RateControlContext *rcc); #endif /* AVCODEC_RATECONTROL_H */ diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c index 4d69c3053d..830f6f5096 100644 --- a/libavcodec/snowenc.c +++ b/libavcodec/snowenc.c @@ -61,7 +61,7 @@ typedef struct SnowEncContext { int scenechange_threshold; MECmpContext mecc; - MpegEncContext m; // needed for motion estimation, should not be used for anything else, the idea is to eventually make the motion estimation independent of MpegEncContext, so this will be removed then (FIXME/XXX) + MPVMainEncContext m; // needed for motion estimation, should not be used for anything else, the idea is to eventually make the motion estimation independent of MpegEncContext, so this will be removed then (FIXME/XXX) MPVPicture cur_pic, last_pic; #define ME_CACHE_SIZE 1024 unsigned me_cache[ME_CACHE_SIZE]; @@ -160,7 +160,7 @@ static av_cold int encode_init(AVCodecContext *avctx) { SnowEncContext *const enc = avctx->priv_data; SnowContext *const s = &enc->com; - MpegEncContext *const mpv = &enc->m; + MpegEncContext *const mpv = &enc->m.s; int plane_index, ret; int i; @@ -217,7 +217,7 @@ static av_cold int encode_init(AVCodecContext *avctx) mcf(12,12) ff_me_cmp_init(&enc->mecc, avctx); - ret = ff_me_init(&enc->m.me, avctx, &enc->mecc, 0); + ret = ff_me_init(&mpv->me, avctx, &enc->mecc, 0); if (ret < 0) return ret; ff_mpegvideoencdsp_init(&enc->mpvencdsp, avctx); @@ -252,7 +252,7 @@ static av_cold int encode_init(AVCodecContext *avctx) return AVERROR(ENOMEM); } if((avctx->flags&AV_CODEC_FLAG_PASS2) || !(avctx->flags&AV_CODEC_FLAG_QSCALE)){ - ret = ff_rate_control_init(mpv); + ret = ff_rate_control_init(&enc->m); if(ret < 0) return ret; } @@ -369,7 +369,7 @@ static inline int get_penalty_factor(int lambda, int lambda2, int type){ static int encode_q_branch(SnowEncContext *enc, int level, int x, int y) { SnowContext *const s = &enc->com; - MotionEstContext *const c = &enc->m.me; + MotionEstContext *const c = &enc->m.s.me; uint8_t p_buffer[1024]; uint8_t i_buffer[1024]; uint8_t p_state[sizeof(s->block_state)]; @@ -435,9 +435,9 @@ static int encode_q_branch(SnowEncContext *enc, int level, int x, int y) last_mv[2][0]= bottom->mx; last_mv[2][1]= bottom->my; - enc->m.mb_stride = 2; - enc->m.mb_x = - enc->m.mb_y = 0; + enc->m.s.mb_stride = 2; + enc->m.s.mb_x = + enc->m.s.mb_y = 0; c->skip= 0; av_assert1(c-> stride == stride); @@ -446,7 +446,7 @@ static int encode_q_branch(SnowEncContext *enc, int level, int x, int y) c->penalty_factor = get_penalty_factor(enc->lambda, enc->lambda2, c->avctx->me_cmp); c->sub_penalty_factor= get_penalty_factor(enc->lambda, enc->lambda2, c->avctx->me_sub_cmp); c->mb_penalty_factor = get_penalty_factor(enc->lambda, enc->lambda2, c->avctx->mb_cmp); - c->current_mv_penalty = c->mv_penalty[enc->m.f_code=1] + MAX_DMV; + c->current_mv_penalty = c->mv_penalty[enc->m.s.f_code=1] + MAX_DMV; c->xmin = - x*block_w - 16+3; c->ymin = - y*block_w - 16+3; @@ -482,7 +482,7 @@ static int encode_q_branch(SnowEncContext *enc, int level, int x, int y) for(ref=0; ref<s->ref_frames; ref++){ init_ref(c, current_data, s->last_picture[ref]->data, NULL, block_w*x, block_w*y, 0); - ref_score= ff_epzs_motion_search(&enc->m, &ref_mx, &ref_my, P, 0, /*ref_index*/ 0, last_mv, + ref_score = ff_epzs_motion_search(&enc->m.s, &ref_mx, &ref_my, P, 0, /*ref_index*/ 0, last_mv, (1<<16)>>shift, level-LOG2_MB_SIZE+4, block_w); av_assert2(ref_mx >= c->xmin); @@ -490,8 +490,10 @@ static int encode_q_branch(SnowEncContext *enc, int level, int x, int y) av_assert2(ref_my >= c->ymin); av_assert2(ref_my <= c->ymax); - ref_score= c->sub_motion_search(&enc->m, &ref_mx, &ref_my, ref_score, 0, 0, level-LOG2_MB_SIZE+4, block_w); - ref_score= ff_get_mb_score(&enc->m, ref_mx, ref_my, 0, 0, level-LOG2_MB_SIZE+4, block_w, 0); + ref_score = c->sub_motion_search(&enc->m.s, &ref_mx, &ref_my, ref_score, + 0, 0, level-LOG2_MB_SIZE+4, block_w); + ref_score = ff_get_mb_score(&enc->m.s, ref_mx, ref_my, 0, 0, + level-LOG2_MB_SIZE+4, block_w, 0); ref_score+= 2*av_log2(2*ref)*c->penalty_factor; if(s->ref_mvs[ref]){ s->ref_mvs[ref][index][0]= ref_mx; @@ -567,7 +569,7 @@ static int encode_q_branch(SnowEncContext *enc, int level, int x, int y) if (vard <= 64 || vard < varc) c->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc); else - c->scene_change_score += enc->m.qscale; + c->scene_change_score += enc->m.s.qscale; } if(level!=s->block_max_depth){ @@ -670,7 +672,7 @@ static int get_dc(SnowEncContext *enc, int mb_x, int mb_y, int plane_index) const int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size; const int ref_stride= s->current_picture->linesize[plane_index]; const uint8_t *src = s->input_picture->data[plane_index]; - IDWTELEM *dst= (IDWTELEM*)enc->m.sc.obmc_scratchpad + plane_index*block_size*block_size*4; //FIXME change to unsigned + IDWTELEM *dst= (IDWTELEM*)enc->m.s.sc.obmc_scratchpad + plane_index*block_size*block_size*4; //FIXME change to unsigned const int b_stride = s->b_width << s->block_max_depth; const int w= p->width; const int h= p->height; @@ -768,7 +770,7 @@ static int get_block_rd(SnowEncContext *enc, int mb_x, int mb_y, const int ref_stride= s->current_picture->linesize[plane_index]; uint8_t *dst= s->current_picture->data[plane_index]; const uint8_t *src = s->input_picture->data[plane_index]; - IDWTELEM *pred= (IDWTELEM*)enc->m.sc.obmc_scratchpad + plane_index*block_size*block_size*4; + IDWTELEM *pred= (IDWTELEM*)enc->m.s.sc.obmc_scratchpad + plane_index*block_size*block_size*4; uint8_t *cur = s->scratchbuf; uint8_t *tmp = s->emu_edge_buffer; const int b_stride = s->b_width << s->block_max_depth; @@ -831,19 +833,19 @@ static int get_block_rd(SnowEncContext *enc, int mb_x, int mb_y, * to improve the score of the whole frame, thus iterative motion * estimation does not always converge. */ if(s->avctx->me_cmp == FF_CMP_W97) - distortion = ff_w97_32_c(&enc->m, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, 32); + distortion = ff_w97_32_c(&enc->m.s, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, 32); else if(s->avctx->me_cmp == FF_CMP_W53) - distortion = ff_w53_32_c(&enc->m, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, 32); + distortion = ff_w53_32_c(&enc->m.s, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, 32); else{ distortion = 0; for(i=0; i<4; i++){ int off = sx+16*(i&1) + (sy+16*(i>>1))*ref_stride; - distortion += enc->m.me.me_cmp[0](&enc->m, src + off, dst + off, ref_stride, 16); + distortion += enc->m.s.me.me_cmp[0](&enc->m.s, src + off, dst + off, ref_stride, 16); } } }else{ av_assert2(block_w==8); - distortion = enc->m.me.me_cmp[0](&enc->m, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, block_w*2); + distortion = enc->m.s.me.me_cmp[0](&enc->m.s, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, block_w*2); } if(plane_index==0){ @@ -909,7 +911,7 @@ static int get_4block_rd(SnowEncContext *enc, int mb_x, int mb_y, int plane_inde } av_assert1(block_w== 8 || block_w==16); - distortion += enc->m.me.me_cmp[block_w==8](&enc->m, src + x + y*ref_stride, dst + x + y*ref_stride, ref_stride, block_h); + distortion += enc->m.s.me.me_cmp[block_w==8](&enc->m.s, src + x + y*ref_stride, dst + x + y*ref_stride, ref_stride, block_h); } if(plane_index==0){ @@ -1706,11 +1708,11 @@ static int ratecontrol_1pass(SnowEncContext *enc, AVFrame *pict) coef_sum = (uint64_t)coef_sum * coef_sum >> 16; if(pict->pict_type == AV_PICTURE_TYPE_I){ - enc->m.mb_var_sum = coef_sum; - enc->m.mc_mb_var_sum = 0; + enc->m.s.mb_var_sum = coef_sum; + enc->m.s.mc_mb_var_sum = 0; }else{ - enc->m.mc_mb_var_sum = coef_sum; - enc->m.mb_var_sum = 0; + enc->m.s.mc_mb_var_sum = coef_sum; + enc->m.s.mb_var_sum = 0; } pict->quality= ff_rate_estimate_qscale(&enc->m, 1); @@ -1757,7 +1759,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, { SnowEncContext *const enc = avctx->priv_data; SnowContext *const s = &enc->com; - MpegEncContext *const mpv = &enc->m; + MpegEncContext *const mpv = &enc->m.s; RangeCoder * const c= &s->c; AVCodecInternal *avci = avctx->internal; AVFrame *pic; @@ -1793,10 +1795,10 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, mpv->picture_number = avctx->frame_num; if(avctx->flags&AV_CODEC_FLAG_PASS2){ - mpv->pict_type = pic->pict_type = mpv->rc_context.entry[avctx->frame_num].new_pict_type; + mpv->pict_type = pic->pict_type = enc->m.rc_context.entry[avctx->frame_num].new_pict_type; s->keyframe = pic->pict_type == AV_PICTURE_TYPE_I; if(!(avctx->flags&AV_CODEC_FLAG_QSCALE)) { - pic->quality = ff_rate_estimate_qscale(mpv, 0); + pic->quality = ff_rate_estimate_qscale(&enc->m, 0); if (pic->quality < 0) return -1; } @@ -1877,7 +1879,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, mpv->qdsp = enc->qdsp; //move mpv->hdsp = s->hdsp; - ff_me_init_pic(&enc->m); + ff_me_init_pic(mpv); s->hdsp = mpv->hdsp; } @@ -2043,17 +2045,19 @@ redo_frame: s->current_picture->pict_type = pic->pict_type; s->current_picture->quality = pic->quality; - mpv->frame_bits = 8 * (s->c.bytestream - s->c.bytestream_start); - mpv->p_tex_bits = mpv->frame_bits - mpv->misc_bits - mpv->mv_bits; - mpv->total_bits += 8*(s->c.bytestream - s->c.bytestream_start); + enc->m.frame_bits = 8 * (s->c.bytestream - s->c.bytestream_start); + mpv->p_tex_bits = enc->m.frame_bits - mpv->misc_bits - mpv->mv_bits; + enc->m.total_bits += 8*(s->c.bytestream - s->c.bytestream_start); enc->cur_pic.display_picture_number = enc->cur_pic.coded_picture_number = avctx->frame_num; enc->cur_pic.f->quality = pic->quality; - if (enc->pass1_rc) - if (ff_rate_estimate_qscale(mpv, 0) < 0) - return -1; + if (enc->pass1_rc) { + ret = ff_rate_estimate_qscale(&enc->m, 0); + if (ret < 0) + return ret; + } if(avctx->flags&AV_CODEC_FLAG_PASS1) - ff_write_pass1_stats(mpv); + ff_write_pass1_stats(&enc->m); mpv->last_pict_type = mpv->pict_type; emms_c(); @@ -2088,10 +2092,10 @@ static av_cold int encode_end(AVCodecContext *avctx) av_freep(&s->ref_scores[i]); } - enc->m.me.temp = NULL; - av_freep(&enc->m.me.scratchpad); - av_freep(&enc->m.me.map); - av_freep(&enc->m.sc.obmc_scratchpad); + enc->m.s.me.temp = NULL; + av_freep(&enc->m.s.me.scratchpad); + av_freep(&enc->m.s.me.map); + av_freep(&enc->m.s.sc.obmc_scratchpad); av_freep(&avctx->stats_out); -- 2.45.2 [-- Attachment #6: 0005-avcodec-mpegvideo_enc-Precalculate-which-frames-to-r.patch --] [-- Type: text/x-patch, Size: 2700 bytes --] From bc39e9e03975c50cce5b73629ae2ba1266021b98 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sat, 1 Mar 2025 01:48:08 +0100 Subject: [PATCH 05/77] avcodec/mpegvideo_enc: Precalculate which frames to reconstruct Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpegvideo.h | 3 +++ libavcodec/mpegvideo_enc.c | 16 +++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 75b1fff245..0bb12a343e 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -499,6 +499,9 @@ typedef struct MpegEncContext { int lmin, lmax; int vbv_ignore_qmax; + /// Bitfield containing information which frames to reconstruct. + int frame_reconstruction_bitfield; + /* flag to indicate a reinitialization is required, e.g. after * a frame size change */ int context_reinit; diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 7f24c1baa6..d2bd6f4a18 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -897,6 +897,18 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) AV_CODEC_FLAG_INTERLACED_ME) || s->alternate_scan); + if (avctx->flags & AV_CODEC_FLAG_PSNR || avctx->mb_decision == FF_MB_DECISION_RD || + s->frame_skip_threshold || s->frame_skip_factor) { + s->frame_reconstruction_bitfield = (1 << AV_PICTURE_TYPE_I) | + (1 << AV_PICTURE_TYPE_P) | + (1 << AV_PICTURE_TYPE_B); + } else if (!s->intra_only) { + s->frame_reconstruction_bitfield = (1 << AV_PICTURE_TYPE_I) | + (1 << AV_PICTURE_TYPE_P); + } else { + s->frame_reconstruction_bitfield = 0; + } + if (s->lmin > s->lmax) { av_log(avctx, AV_LOG_WARNING, "Clipping lmin value to %d\n", s->lmax); s->lmin = s->lmax; @@ -1122,9 +1134,7 @@ static void mpv_reconstruct_mb(MpegEncContext *s, int16_t block[12][64]) } } - if ((s->avctx->flags & AV_CODEC_FLAG_PSNR) || s->frame_skip_threshold || s->frame_skip_factor || - !((s->intra_only || s->pict_type == AV_PICTURE_TYPE_B) && - s->avctx->mb_decision != FF_MB_DECISION_RD)) { // FIXME precalc + if ((1 << s->pict_type) & s->frame_reconstruction_bitfield) { uint8_t *dest_y = s->dest[0], *dest_cb = s->dest[1], *dest_cr = s->dest[2]; int dct_linesize, dct_offset; const int linesize = s->cur_pic.linesize[0]; -- 2.45.2 [-- Attachment #7: 0006-avcodec-mpegvideo-Move-frame_skip_-fields-to-MPVMain.patch --] [-- Type: text/x-patch, Size: 8602 bytes --] From 0cc58c515276ccb0c6c6fbf1d5828dc4f72b510a Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sat, 1 Mar 2025 02:04:41 +0100 Subject: [PATCH 06/77] avcodec/mpegvideo: Move frame_skip_* fields to MPVMainEncContext Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpegvideo.h | 7 ------- libavcodec/mpegvideo_enc.c | 31 +++++++++++++++++-------------- libavcodec/mpegvideoenc.h | 15 +++++++++++---- 3 files changed, 28 insertions(+), 25 deletions(-) diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 0bb12a343e..2cc6dbf534 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -510,13 +510,6 @@ typedef struct MpegEncContext { int error_rate; - /* frame skip options for encoding */ - int frame_skip_threshold; - int frame_skip_factor; - int frame_skip_exp; - int frame_skip_cmp; - me_cmp_func frame_skip_cmp_fn; - int scenechange_threshold; int noise_reduction; diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index d2bd6f4a18..1b7a4c1236 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -307,8 +307,9 @@ av_cold void ff_dct_encode_init(MpegEncContext *s) s->dct_quantize = dct_quantize_trellis_c; } -static av_cold int me_cmp_init(MpegEncContext *s, AVCodecContext *avctx) +static av_cold int me_cmp_init(MPVMainEncContext *const m, AVCodecContext *avctx) { + MpegEncContext *const s = &m->s; MECmpContext mecc; me_cmp_func me_cmp[6]; int ret; @@ -317,10 +318,10 @@ static av_cold int me_cmp_init(MpegEncContext *s, AVCodecContext *avctx) ret = ff_me_init(&s->me, avctx, &mecc, 1); if (ret < 0) return ret; - ret = ff_set_cmp(&mecc, me_cmp, s->frame_skip_cmp, 1); + ret = ff_set_cmp(&mecc, me_cmp, m->frame_skip_cmp, 1); if (ret < 0) return ret; - s->frame_skip_cmp_fn = me_cmp[1]; + m->frame_skip_cmp_fn = me_cmp[1]; if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) { ret = ff_set_cmp(&mecc, me_cmp, avctx->ildct_cmp, 1); if (ret < 0) @@ -898,7 +899,7 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) s->alternate_scan); if (avctx->flags & AV_CODEC_FLAG_PSNR || avctx->mb_decision == FF_MB_DECISION_RD || - s->frame_skip_threshold || s->frame_skip_factor) { + m->frame_skip_threshold || m->frame_skip_factor) { s->frame_reconstruction_bitfield = (1 << AV_PICTURE_TYPE_I) | (1 << AV_PICTURE_TYPE_P) | (1 << AV_PICTURE_TYPE_B); @@ -922,7 +923,7 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) ff_fdctdsp_init(&s->fdsp, avctx); ff_mpegvideoencdsp_init(&s->mpvencdsp, avctx); ff_pixblockdsp_init(&s->pdsp, avctx); - ret = me_cmp_init(s, avctx); + ret = me_cmp_init(m, avctx); if (ret < 0) return ret; @@ -1402,8 +1403,10 @@ fail: return ret; } -static int skip_check(MpegEncContext *s, const MPVPicture *p, const MPVPicture *ref) +static int skip_check(MPVMainEncContext *const m, + const MPVPicture *p, const MPVPicture *ref) { + MpegEncContext *const s = &m->s; int x, y, plane; int score = 0; int64_t score64 = 0; @@ -1416,9 +1419,9 @@ static int skip_check(MpegEncContext *s, const MPVPicture *p, const MPVPicture * int off = p->shared ? 0 : 16; const uint8_t *dptr = p->f->data[plane] + 8 * (x + y * stride) + off; const uint8_t *rptr = ref->f->data[plane] + 8 * (x + y * stride); - int v = s->frame_skip_cmp_fn(s, dptr, rptr, stride, 8); + int v = m->frame_skip_cmp_fn(s, dptr, rptr, stride, 8); - switch (FFABS(s->frame_skip_exp)) { + switch (FFABS(m->frame_skip_exp)) { case 0: score = FFMAX(score, v); break; case 1: score += FFABS(v); break; case 2: score64 += v * (int64_t)v; break; @@ -1432,13 +1435,13 @@ static int skip_check(MpegEncContext *s, const MPVPicture *p, const MPVPicture * if (score) score64 = score; - if (s->frame_skip_exp < 0) + if (m->frame_skip_exp < 0) score64 = pow(score64 / (double)(s->mb_width * s->mb_height), - -1.0/s->frame_skip_exp); + -1.0/m->frame_skip_exp); - if (score64 < s->frame_skip_threshold) + if (score64 < m->frame_skip_threshold) return 1; - if (score64 < ((s->frame_skip_factor * (int64_t) s->lambda) >> 8)) + if (score64 < ((m->frame_skip_factor * (int64_t) s->lambda) >> 8)) return 1; return 0; } @@ -1626,10 +1629,10 @@ static int set_bframe_chain_length(MPVMainEncContext *const m) return 0; /* set next picture type & ordering */ - if (s->frame_skip_threshold || s->frame_skip_factor) { + if (m->frame_skip_threshold || m->frame_skip_factor) { if (s->picture_in_gop_number < s->gop_size && s->next_pic.ptr && - skip_check(s, s->input_picture[0], s->next_pic.ptr)) { + skip_check(m, s->input_picture[0], s->next_pic.ptr)) { // FIXME check that the gop check above is +-1 correct av_refstruct_unref(&s->input_picture[0]); diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h index c1d2821038..9f0d63c31e 100644 --- a/libavcodec/mpegvideoenc.h +++ b/libavcodec/mpegvideoenc.h @@ -45,6 +45,13 @@ typedef struct MPVMainEncContext { int b_sensitivity; int brd_scale; + /* frame skip options */ + int frame_skip_threshold; + int frame_skip_factor; + int frame_skip_exp; + int frame_skip_cmp; + me_cmp_func frame_skip_cmp_fn; + /* bit rate control */ int64_t total_bits; int frame_bits; ///< bits used for the current frame @@ -134,10 +141,10 @@ FF_MPV_OPT_CMP_FUNC, \ {"border_mask", "increase the quantizer for macroblocks close to borders", FF_MPV_OFFSET(border_masking), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, FF_MPV_OPT_FLAGS}, \ {"lmin", "minimum Lagrange factor (VBR)", FF_MPV_OFFSET(lmin), AV_OPT_TYPE_INT, {.i64 = 2*FF_QP2LAMBDA }, 0, INT_MAX, FF_MPV_OPT_FLAGS }, \ {"lmax", "maximum Lagrange factor (VBR)", FF_MPV_OFFSET(lmax), AV_OPT_TYPE_INT, {.i64 = 31*FF_QP2LAMBDA }, 0, INT_MAX, FF_MPV_OPT_FLAGS }, \ -{"skip_threshold", "Frame skip threshold", FF_MPV_OFFSET(frame_skip_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ -{"skip_factor", "Frame skip factor", FF_MPV_OFFSET(frame_skip_factor), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ -{"skip_exp", "Frame skip exponent", FF_MPV_OFFSET(frame_skip_exp), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ -{"skip_cmp", "Frame skip compare function", FF_MPV_OFFSET(frame_skip_cmp), AV_OPT_TYPE_INT, {.i64 = FF_CMP_DCTMAX }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, .unit = "cmp_func" }, \ +{"skip_threshold", "Frame skip threshold", FF_MPV_MAIN_OFFSET(frame_skip_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"skip_factor", "Frame skip factor", FF_MPV_MAIN_OFFSET(frame_skip_factor), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"skip_exp", "Frame skip exponent", FF_MPV_MAIN_OFFSET(frame_skip_exp), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"skip_cmp", "Frame skip compare function", FF_MPV_MAIN_OFFSET(frame_skip_cmp), AV_OPT_TYPE_INT, {.i64 = FF_CMP_DCTMAX }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, .unit = "cmp_func" }, \ {"sc_threshold", "Scene change threshold", FF_MPV_OFFSET(scenechange_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ {"noise_reduction", "Noise reduction", FF_MPV_OFFSET(noise_reduction), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ {"ps", "RTP payload size in bytes", FF_MPV_OFFSET(rtp_payload_size), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ -- 2.45.2 [-- Attachment #8: 0007-avcodec-h261enc-Make-h261_encode_init-call-ff_mpv_en.patch --] [-- Type: text/x-patch, Size: 3696 bytes --] From 8f5523200a086f092218e87ca2f2b3aeebd040b8 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sat, 1 Mar 2025 23:37:50 +0100 Subject: [PATCH 07/77] avcodec/h261enc: Make h261_encode_init() call ff_mpv_encode_init() Right now, ff_mpv_encode_init() is set as FFCodec.init and calls ff_h261_encode_init(). The opposite is more natural and avoids a non-static function. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/h261enc.c | 17 +++++++++-------- libavcodec/h261enc.h | 1 - libavcodec/mpegvideo_enc.c | 5 ----- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/libavcodec/h261enc.c b/libavcodec/h261enc.c index 264efb0aa3..36c50db6df 100644 --- a/libavcodec/h261enc.c +++ b/libavcodec/h261enc.c @@ -352,20 +352,21 @@ static av_cold void h261_encode_init_static(void) mv_codes[0][1] = 1; } -av_cold int ff_h261_encode_init(MpegEncContext *s) +static av_cold int h261_encode_init(AVCodecContext *avctx) { - H261EncContext *const h = (H261EncContext*)s; static AVOnce init_static_once = AV_ONCE_INIT; + H261EncContext *const h = avctx->priv_data; + MpegEncContext *const s = &h->s.s; - if (s->width == 176 && s->height == 144) { + if (avctx->width == 176 && avctx->height == 144) { h->format = H261_QCIF; - } else if (s->width == 352 && s->height == 288) { + } else if (avctx->width == 352 && avctx->height == 288) { h->format = H261_CIF; } else { - av_log(s->avctx, AV_LOG_ERROR, + av_log(avctx, AV_LOG_ERROR, "The specified picture size of %dx%d is not valid for the " "H.261 codec.\nValid sizes are 176x144, 352x288\n", - s->width, s->height); + avctx->width, avctx->height); return AVERROR(EINVAL); } s->private_ctx = &h->common; @@ -380,7 +381,7 @@ av_cold int ff_h261_encode_init(MpegEncContext *s) s->intra_ac_vlc_last_length = s->inter_ac_vlc_last_length = uni_h261_rl_len_last; ff_thread_once(&init_static_once, h261_encode_init_static); - return 0; + return ff_mpv_encode_init(avctx); } const FFCodec ff_h261_encoder = { @@ -391,7 +392,7 @@ const FFCodec ff_h261_encoder = { .p.priv_class = &ff_mpv_enc_class, .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(H261EncContext), - .init = ff_mpv_encode_init, + .init = h261_encode_init, FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), .close = ff_mpv_encode_end, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, diff --git a/libavcodec/h261enc.h b/libavcodec/h261enc.h index d8fdcad7aa..7877d8aa9d 100644 --- a/libavcodec/h261enc.h +++ b/libavcodec/h261enc.h @@ -34,6 +34,5 @@ void ff_h261_reorder_mb_index(MpegEncContext *s); void ff_h261_encode_mb(MpegEncContext *s, int16_t block[6][64], int motion_x, int motion_y); void ff_h261_encode_picture_header(MpegEncContext *s); -int ff_h261_encode_init(MpegEncContext *s); #endif diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 1b7a4c1236..5c2f73b2d1 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -778,11 +778,6 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) s->low_delay = 1; break; case AV_CODEC_ID_H261: - if (!CONFIG_H261_ENCODER) - return AVERROR_ENCODER_NOT_FOUND; - ret = ff_h261_encode_init(s); - if (ret < 0) - return ret; s->out_format = FMT_H261; avctx->delay = 0; s->low_delay = 1; -- 2.45.2 [-- Attachment #9: 0008-avcodec-mpegvideo-Don-t-initialize-yc-_dc_scale_tabl.patch --] [-- Type: text/x-patch, Size: 2838 bytes --] From b77de4fb3b253c8ab9459853d092825dddd9af1b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Mon, 3 Mar 2025 17:26:00 +0100 Subject: [PATCH 08/77] avcodec/mpegvideo: Don't initialize [yc]_dc_scale_table by default Only the H.263-based decoders as well as the encoders need it; so move it to ff_h263_decode_init() as well as ff_mpv_encode_init(). Also for the latter make it only set these tables if none are already set. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/h263dec.c | 5 ++++- libavcodec/mpegvideo.c | 2 -- libavcodec/mpegvideo_enc.c | 6 +++++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c index 2d806fc703..8434f6e7cf 100644 --- a/libavcodec/h263dec.c +++ b/libavcodec/h263dec.c @@ -41,8 +41,8 @@ #include "mpeg_er.h" #include "mpeg4video.h" #include "mpeg4videodec.h" -#include "mpeg4videodefs.h" #include "mpegvideo.h" +#include "mpegvideodata.h" #include "mpegvideodec.h" #include "msmpeg4dec.h" #include "thread.h" @@ -102,6 +102,9 @@ av_cold int ff_h263_decode_init(AVCodecContext *avctx) s->decode_mb = ff_h263_decode_mb; s->low_delay = 1; + s->y_dc_scale_table = + s->c_dc_scale_table = ff_mpeg1_dc_scale_table; + // 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; diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 4b69b5b65c..9cd67151aa 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -482,8 +482,6 @@ int ff_update_duplicate_context(MpegEncContext *dst, const MpegEncContext *src) */ av_cold void ff_mpv_common_defaults(MpegEncContext *s) { - s->y_dc_scale_table = - s->c_dc_scale_table = ff_mpeg1_dc_scale_table; s->chroma_qscale_table = ff_default_chroma_qscale_table; s->progressive_frame = 1; s->progressive_sequence = 1; diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 5c2f73b2d1..7eb381af36 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -276,7 +276,6 @@ static av_cold void mpv_encode_init_static(void) /** * Set the given MpegEncContext to defaults for encoding. - * the changed fields will not depend upon the prior state of the MpegEncContext. */ static av_cold void mpv_encode_defaults(MpegEncContext *s) { @@ -288,6 +287,11 @@ static av_cold void mpv_encode_defaults(MpegEncContext *s) s->fcode_tab = default_fcode_tab + MAX_MV; + if (!s->y_dc_scale_table) { + s->y_dc_scale_table = + s->c_dc_scale_table = ff_mpeg1_dc_scale_table; + } + s->input_picture_number = 0; s->picture_in_gop_number = 0; } -- 2.45.2 [-- Attachment #10: 0009-avcodec-speedhqenc-Make-speedhq_encode_init-call-ff_.patch --] [-- Type: text/x-patch, Size: 4016 bytes --] From c3e33d9885a3e4a31f657ef9b1fb52311ac5d921 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sat, 1 Mar 2025 23:37:50 +0100 Subject: [PATCH 09/77] avcodec/speedhqenc: Make speedhq_encode_init() call ff_mpv_encode_init() Right now, ff_mpv_encode_init() is set as FFCodec.init and calls ff_speedhq_encode_init(). The opposite is more natural and avoids a non-static function. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpegvideo_enc.c | 4 ---- libavcodec/speedhqenc.c | 22 ++++++++++++++-------- libavcodec/speedhqenc.h | 1 - 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 7eb381af36..1f55512674 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -774,10 +774,6 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) case AV_CODEC_ID_SPEEDHQ: s->out_format = FMT_SPEEDHQ; s->intra_only = 1; /* force intra only for SHQ */ - if (!CONFIG_SPEEDHQ_ENCODER) - return AVERROR_ENCODER_NOT_FOUND; - if ((ret = ff_speedhq_encode_init(s)) < 0) - return ret; avctx->delay = 0; s->low_delay = 1; break; diff --git a/libavcodec/speedhqenc.c b/libavcodec/speedhqenc.c index a0baa869cc..de1bc0cfca 100644 --- a/libavcodec/speedhqenc.c +++ b/libavcodec/speedhqenc.c @@ -95,26 +95,26 @@ static av_cold void speedhq_init_static_data(void) ff_speedhq_vlc_table, uni_speedhq_ac_vlc_len); } -av_cold int ff_speedhq_encode_init(MpegEncContext *s) +static av_cold int speedhq_encode_init(AVCodecContext *avctx) { static AVOnce init_static_once = AV_ONCE_INIT; + MpegEncContext *const s = avctx->priv_data; + int ret; - if (s->width > 65500 || s->height > 65500) { - av_log(s->avctx, AV_LOG_ERROR, "SpeedHQ does not support resolutions above 65500x65500\n"); + if (avctx->width > 65500 || avctx->height > 65500) { + av_log(avctx, AV_LOG_ERROR, "SpeedHQ does not support resolutions above 65500x65500\n"); return AVERROR(EINVAL); } // border is not implemented correctly at the moment, see ticket #10078 - if (s->width % 16) { - av_log(s->avctx, AV_LOG_ERROR, "width must be a multiple of 16\n"); + if (avctx->width % 16) { + av_log(avctx, AV_LOG_ERROR, "width must be a multiple of 16\n"); return AVERROR_PATCHWELCOME; } s->min_qcoeff = -2048; s->max_qcoeff = 2047; - ff_thread_once(&init_static_once, speedhq_init_static_data); - s->intra_ac_vlc_length = s->intra_ac_vlc_last_length = s->intra_chroma_ac_vlc_length = @@ -123,6 +123,12 @@ av_cold int ff_speedhq_encode_init(MpegEncContext *s) s->y_dc_scale_table = s->c_dc_scale_table = ff_mpeg12_dc_scale_table[3]; + ret = ff_mpv_encode_init(avctx); + if (ret < 0) + return ret; + + ff_thread_once(&init_static_once, speedhq_init_static_data); + switch (s->avctx->pix_fmt) { case AV_PIX_FMT_YUV420P: s->avctx->codec_tag = MKTAG('S','H','Q','0'); @@ -280,7 +286,7 @@ const FFCodec ff_speedhq_encoder = { .p.priv_class = &ff_mpv_enc_class, .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(SpeedHQEncContext), - .init = ff_mpv_encode_init, + .init = speedhq_encode_init, FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), .close = ff_mpv_encode_end, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, diff --git a/libavcodec/speedhqenc.h b/libavcodec/speedhqenc.h index 15be9764d7..66ef7ee023 100644 --- a/libavcodec/speedhqenc.h +++ b/libavcodec/speedhqenc.h @@ -33,7 +33,6 @@ #include "mpegvideo.h" -int ff_speedhq_encode_init(MpegEncContext *s); void ff_speedhq_encode_close(MpegEncContext *s); void ff_speedhq_encode_mb(MpegEncContext *s, int16_t block[12][64]); -- 2.45.2 [-- Attachment #11: 0010-avcodec-speedhqenc-Avoid-indirection.patch --] [-- Type: text/x-patch, Size: 1821 bytes --] From 67be5b312ac5b2f5ca28131c6d72ba2254c955a8 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sun, 2 Mar 2025 00:34:19 +0100 Subject: [PATCH 10/77] avcodec/speedhqenc: Avoid indirection Namely use avctx directly instead of s->avctx. While just at it, also move the switch to the other checks involving avctx. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/speedhqenc.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/libavcodec/speedhqenc.c b/libavcodec/speedhqenc.c index de1bc0cfca..2e09016935 100644 --- a/libavcodec/speedhqenc.c +++ b/libavcodec/speedhqenc.c @@ -112,6 +112,20 @@ static av_cold int speedhq_encode_init(AVCodecContext *avctx) return AVERROR_PATCHWELCOME; } + switch (avctx->pix_fmt) { + case AV_PIX_FMT_YUV420P: + avctx->codec_tag = MKTAG('S','H','Q','0'); + break; + case AV_PIX_FMT_YUV422P: + avctx->codec_tag = MKTAG('S','H','Q','2'); + break; + case AV_PIX_FMT_YUV444P: + avctx->codec_tag = MKTAG('S','H','Q','4'); + break; + default: + av_assert0(0); + } + s->min_qcoeff = -2048; s->max_qcoeff = 2047; @@ -129,20 +143,6 @@ static av_cold int speedhq_encode_init(AVCodecContext *avctx) ff_thread_once(&init_static_once, speedhq_init_static_data); - switch (s->avctx->pix_fmt) { - case AV_PIX_FMT_YUV420P: - s->avctx->codec_tag = MKTAG('S','H','Q','0'); - break; - case AV_PIX_FMT_YUV422P: - s->avctx->codec_tag = MKTAG('S','H','Q','2'); - break; - case AV_PIX_FMT_YUV444P: - s->avctx->codec_tag = MKTAG('S','H','Q','4'); - break; - default: - av_assert0(0); - } - return 0; } -- 2.45.2 [-- Attachment #12: 0011-avcodec-mjpegenc-Make-mjpeg_encode_init-call-ff_mpv_.patch --] [-- Type: text/x-patch, Size: 5340 bytes --] From ee2d713903d78262c0b1c7700318bf0ec5ff1aa7 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Mon, 3 Mar 2025 02:13:31 +0100 Subject: [PATCH 11/77] avcodec/mjpegenc: Make mjpeg_encode_init() call ff_mpv_encode_init() Right now, ff_mpv_encode_init() is set as FFCodec.init and calls ff_speedhq_encode_init(). The opposite is more natural, avoids a non-static function and allows to reuse e.g. slice_context_count instead of duplicating the logic from ff_mpv_common_init(). Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mjpegenc.c | 37 ++++++++++++++++++------------------- libavcodec/mjpegenc.h | 1 - libavcodec/mpegvideo_enc.c | 2 -- 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c index 0a2d6eebd3..f34e89235d 100644 --- a/libavcodec/mjpegenc.c +++ b/libavcodec/mjpegenc.c @@ -283,10 +283,6 @@ static int alloc_huffman(MpegEncContext *s) size_t num_mbs, num_blocks, num_codes; int blocks_per_mb; - // We need to init this here as the mjpeg init is called before the common init, - s->mb_width = (s->width + 15) / 16; - s->mb_height = (s->height + 15) / 16; - switch (s->chroma_format) { case CHROMA_420: blocks_per_mb = 6; break; case CHROMA_422: blocks_per_mb = 8; break; @@ -305,34 +301,30 @@ static int alloc_huffman(MpegEncContext *s) return 0; } -av_cold int ff_mjpeg_encode_init(MpegEncContext *s) +static av_cold int mjpeg_encode_init(AVCodecContext *avctx) { - MJpegContext *const m = &((MJPEGEncContext*)s)->mjpeg; - int ret, use_slices; + MJPEGEncContext *const m2 = avctx->priv_data; + MJpegContext *const m = &m2->mjpeg; + MpegEncContext *const s = &m2->mpeg.s; + int ret; s->mjpeg_ctx = m; - use_slices = s->avctx->slices > 0 ? s->avctx->slices > 1 : - (s->avctx->active_thread_type & FF_THREAD_SLICE) && - s->avctx->thread_count > 1; - - if (use_slices) - m->huffman = HUFFMAN_TABLE_DEFAULT; if (s->mpv_flags & FF_MPV_FLAG_QP_RD) { // Used to produce garbage with MJPEG. - av_log(s->avctx, AV_LOG_ERROR, + av_log(avctx, AV_LOG_ERROR, "QP RD is no longer compatible with MJPEG or AMV\n"); return AVERROR(EINVAL); } /* The following check is automatically true for AMV, * but it doesn't hurt either. */ - ret = ff_mjpeg_encode_check_pix_fmt(s->avctx); + ret = ff_mjpeg_encode_check_pix_fmt(avctx); if (ret < 0) return ret; - if (s->width > 65500 || s->height > 65500) { - av_log(s->avctx, AV_LOG_ERROR, "JPEG does not support resolutions above 65500x65500\n"); + if (avctx->width > 65500 || avctx->height > 65500) { + av_log(avctx, AV_LOG_ERROR, "JPEG does not support resolutions above 65500x65500\n"); return AVERROR(EINVAL); } @@ -366,9 +358,16 @@ av_cold int ff_mjpeg_encode_init(MpegEncContext *s) s->intra_chroma_ac_vlc_length = s->intra_chroma_ac_vlc_last_length = m->uni_chroma_ac_vlc_len; + ret = ff_mpv_encode_init(avctx); + if (ret < 0) + return ret; + // Buffers start out empty. m->huff_ncode = 0; + if (s->slice_context_count > 1) + m->huffman = HUFFMAN_TABLE_DEFAULT; + if (m->huffman == HUFFMAN_TABLE_OPTIMAL) return alloc_huffman(s); @@ -681,7 +680,7 @@ const FFCodec ff_mjpeg_encoder = { .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_MJPEG, .priv_data_size = sizeof(MJPEGEncContext), - .init = ff_mpv_encode_init, + .init = mjpeg_encode_init, FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), .close = mjpeg_encode_close, .p.capabilities = AV_CODEC_CAP_DR1 | @@ -711,7 +710,7 @@ const FFCodec ff_amv_encoder = { .p.id = AV_CODEC_ID_AMV, .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(MJPEGEncContext), - .init = ff_mpv_encode_init, + .init = mjpeg_encode_init, FF_CODEC_ENCODE_CB(amv_encode_picture), .close = mjpeg_encode_close, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, diff --git a/libavcodec/mjpegenc.h b/libavcodec/mjpegenc.h index 1ac0d6de7e..2c98de057a 100644 --- a/libavcodec/mjpegenc.h +++ b/libavcodec/mjpegenc.h @@ -94,7 +94,6 @@ static inline void put_marker(PutBitContext *p, enum JpegMarker code) typedef struct MpegEncContext MpegEncContext; -int ff_mjpeg_encode_init(MpegEncContext *s); void ff_mjpeg_amv_encode_picture_header(MpegEncContext *s); void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[12][64]); int ff_mjpeg_encode_stuffing(MpegEncContext *s); diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 1f55512674..d2e3ed1d8c 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -765,8 +765,6 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) case AV_CODEC_ID_AMV: s->out_format = FMT_MJPEG; s->intra_only = 1; /* force intra only for jpeg */ - if ((ret = ff_mjpeg_encode_init(s)) < 0) - return ret; avctx->delay = 0; s->low_delay = 1; break; -- 2.45.2 [-- Attachment #13: 0012-avcodec-mjpegenc-Simplify-allocating-huffman-table.patch --] [-- Type: text/x-patch, Size: 2220 bytes --] From d1c52483aeeab5584a685146ab86f746cc941834 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Mon, 3 Mar 2025 02:36:55 +0100 Subject: [PATCH 12/77] avcodec/mjpegenc: Simplify allocating huffman table Reuse the already computed value of macroblocks; use an array instead of a switch, evaluate 64 * sizeof(MJpegHuffmanCode) at compile-time. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mjpegenc.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c index f34e89235d..6f9818baf2 100644 --- a/libavcodec/mjpegenc.c +++ b/libavcodec/mjpegenc.c @@ -277,25 +277,21 @@ fail: return ret; } -static int alloc_huffman(MpegEncContext *s) +static int alloc_huffman(MJPEGEncContext *const m2) { - MJpegContext *m = s->mjpeg_ctx; - size_t num_mbs, num_blocks, num_codes; - int blocks_per_mb; - - switch (s->chroma_format) { - case CHROMA_420: blocks_per_mb = 6; break; - case CHROMA_422: blocks_per_mb = 8; break; - case CHROMA_444: blocks_per_mb = 12; break; - default: av_assert0(0); + MJpegContext *const m = &m2->mjpeg; + MpegEncContext *const s = &m2->mpeg.s; + static const char blocks_per_mb[] = { + [CHROMA_420] = 6, [CHROMA_422] = 8, [CHROMA_444] = 12 }; + size_t num_blocks, num_codes; // Make sure we have enough space to hold this frame. - num_mbs = s->mb_width * s->mb_height; - num_blocks = num_mbs * blocks_per_mb; + num_blocks = s->mb_num * blocks_per_mb[s->chroma_format]; num_codes = num_blocks * 64; - m->huff_buffer = av_malloc_array(num_codes, sizeof(MJpegHuffmanCode)); + m->huff_buffer = av_malloc_array(num_codes, + 64 /* codes per MB */ * sizeof(MJpegHuffmanCode)); if (!m->huff_buffer) return AVERROR(ENOMEM); return 0; @@ -369,7 +365,7 @@ static av_cold int mjpeg_encode_init(AVCodecContext *avctx) m->huffman = HUFFMAN_TABLE_DEFAULT; if (m->huffman == HUFFMAN_TABLE_OPTIMAL) - return alloc_huffman(s); + return alloc_huffman(m2); return 0; } -- 2.45.2 [-- Attachment #14: 0013-avcodec-mpegvideo_enc-Only-set-fcode_tab-if-unset.patch --] [-- Type: text/x-patch, Size: 1198 bytes --] From fbd7724d012c9ff833c78d1e6944d7a6da4809b8 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Mon, 3 Mar 2025 18:07:02 +0100 Subject: [PATCH 13/77] avcodec/mpegvideo_enc: Only set fcode_tab if unset This is in preparation for merging ff_mpeg1_encode_init() into the MPEG-1/2 encoder's init function. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpegvideo_enc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index d2e3ed1d8c..398b06d929 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -283,10 +283,10 @@ static av_cold void mpv_encode_defaults(MpegEncContext *s) ff_mpv_common_defaults(s); - ff_thread_once(&init_static_once, mpv_encode_init_static); - - s->fcode_tab = default_fcode_tab + MAX_MV; - + if (!s->fcode_tab) { + s->fcode_tab = default_fcode_tab + MAX_MV; + ff_thread_once(&init_static_once, mpv_encode_init_static); + } if (!s->y_dc_scale_table) { s->y_dc_scale_table = s->c_dc_scale_table = ff_mpeg1_dc_scale_table; -- 2.45.2 [-- Attachment #15: 0014-avcodec-mpeg12enc-Move-encode_init-to-the-end-of-the.patch --] [-- Type: text/x-patch, Size: 13119 bytes --] From 67b4194006c40618d20adfe53863bda2364faa59 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Mon, 3 Mar 2025 18:11:10 +0100 Subject: [PATCH 14/77] avcodec/mpeg12enc: Move encode_init() to the end of the file Will avoid forward declarations later. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpeg12enc.c | 298 ++++++++++++++++++++--------------------- 1 file changed, 149 insertions(+), 149 deletions(-) diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index bb61b4f4fe..730e0411c7 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -137,155 +137,6 @@ av_cold void ff_mpeg1_init_uni_ac_vlc(const int8_t max_level[], } #if CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER -static int find_frame_rate_index(AVCodecContext *avctx, MPEG12EncContext *mpeg12) -{ - int i; - AVRational bestq = (AVRational) {0, 0}; - AVRational ext; - AVRational target = av_inv_q(avctx->time_base); - - for (i = 1; i < 14; i++) { - if (avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL && - i >= 9) - break; - - for (ext.num=1; ext.num <= 4; ext.num++) { - for (ext.den=1; ext.den <= 32; ext.den++) { - AVRational q = av_mul_q(ext, ff_mpeg12_frame_rate_tab[i]); - - if (avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO && (ext.den!=1 || ext.num!=1)) - continue; - if (av_gcd(ext.den, ext.num) != 1) - continue; - - if ( bestq.num==0 - || av_nearer_q(target, bestq, q) < 0 - || ext.num==1 && ext.den==1 && av_nearer_q(target, bestq, q) == 0) { - bestq = q; - mpeg12->frame_rate_index = i; - mpeg12->frame_rate_ext.num = ext.num; - mpeg12->frame_rate_ext.den = ext.den; - } - } - } - } - - if (av_cmp_q(target, bestq)) - return -1; - else - return 0; -} - -static av_cold int encode_init(AVCodecContext *avctx) -{ - MPEG12EncContext *const mpeg12 = avctx->priv_data; - int ret; - int max_size = avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO ? 16383 : 4095; - - if (avctx->width > max_size || avctx->height > max_size) { - av_log(avctx, AV_LOG_ERROR, "%s does not support resolutions above %dx%d\n", - CONFIG_SMALL ? avctx->codec->name : avctx->codec->long_name, - max_size, max_size); - return AVERROR(EINVAL); - } - if ((avctx->width & 0xFFF) == 0 && (avctx->height & 0xFFF) == 1) { - av_log(avctx, AV_LOG_ERROR, "Width / Height is invalid for MPEG2\n"); - return AVERROR(EINVAL); - } - - if (avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) { - if ((avctx->width & 0xFFF) == 0 || (avctx->height & 0xFFF) == 0) { - av_log(avctx, AV_LOG_ERROR, "Width or Height are not allowed to be multiples of 4096\n" - "add '-strict %d' if you want to use them anyway.\n", FF_COMPLIANCE_UNOFFICIAL); - return AVERROR(EINVAL); - } - } - - if (mpeg12->mpeg.s.q_scale_type == 1) { - if (avctx->qmax > 28) { - av_log(avctx, AV_LOG_ERROR, - "non linear quant only supports qmax <= 28 currently\n"); - return AVERROR_PATCHWELCOME; - } - } - - if (avctx->profile == AV_PROFILE_UNKNOWN) { - if (avctx->level != AV_LEVEL_UNKNOWN) { - av_log(avctx, AV_LOG_ERROR, "Set profile and level\n"); - return AVERROR(EINVAL); - } - /* Main or 4:2:2 */ - avctx->profile = avctx->pix_fmt == AV_PIX_FMT_YUV420P ? AV_PROFILE_MPEG2_MAIN - : AV_PROFILE_MPEG2_422; - } - if (avctx->level == AV_LEVEL_UNKNOWN) { - if (avctx->profile == AV_PROFILE_MPEG2_422) { /* 4:2:2 */ - if (avctx->width <= 720 && avctx->height <= 608) - avctx->level = 5; /* Main */ - else - avctx->level = 2; /* High */ - } else { - if (avctx->profile != AV_PROFILE_MPEG2_HIGH && - avctx->pix_fmt != AV_PIX_FMT_YUV420P) { - av_log(avctx, AV_LOG_ERROR, - "Only High(1) and 4:2:2(0) profiles support 4:2:2 color sampling\n"); - return AVERROR(EINVAL); - } - if (avctx->width <= 720 && avctx->height <= 576) - avctx->level = 8; /* Main */ - else if (avctx->width <= 1440) - avctx->level = 6; /* High 1440 */ - else - avctx->level = 4; /* High */ - } - } - - if ((ret = ff_mpv_encode_init(avctx)) < 0) - return ret; - - if (find_frame_rate_index(avctx, mpeg12) < 0) { - if (avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { - av_log(avctx, AV_LOG_ERROR, "MPEG-1/2 does not support %d/%d fps\n", - avctx->time_base.den, avctx->time_base.num); - return AVERROR(EINVAL); - } else { - av_log(avctx, AV_LOG_INFO, - "MPEG-1/2 does not support %d/%d fps, there may be AV sync issues\n", - avctx->time_base.den, avctx->time_base.num); - } - } - - if (avctx->rc_max_rate && - avctx->rc_min_rate == avctx->rc_max_rate && - 90000LL * (avctx->rc_buffer_size - 1) > - avctx->rc_max_rate * 0xFFFFLL) { - av_log(avctx, AV_LOG_INFO, - "Warning vbv_delay will be set to 0xFFFF (=VBR) as the " - "specified vbv buffer is too large for the given bitrate!\n"); - } - - if (mpeg12->drop_frame_timecode) - mpeg12->tc.flags |= AV_TIMECODE_FLAG_DROPFRAME; - if (mpeg12->drop_frame_timecode && mpeg12->frame_rate_index != 4) { - av_log(avctx, AV_LOG_ERROR, - "Drop frame time code only allowed with 1001/30000 fps\n"); - return AVERROR(EINVAL); - } - - if (mpeg12->tc_opt_str) { - AVRational rate = ff_mpeg12_frame_rate_tab[mpeg12->frame_rate_index]; - int ret = av_timecode_init_from_string(&mpeg12->tc, rate, mpeg12->tc_opt_str, avctx); - if (ret < 0) - return ret; - mpeg12->drop_frame_timecode = !!(mpeg12->tc.flags & AV_TIMECODE_FLAG_DROPFRAME); - mpeg12->timecode_frame_start = mpeg12->tc.start; - } else { - mpeg12->timecode_frame_start = 0; // default is -1 - } - - return 0; -} - static void put_header(MpegEncContext *s, uint32_t header) { align_put_bits(&s->pb); @@ -1179,6 +1030,155 @@ av_cold void ff_mpeg1_encode_init(MpegEncContext *s) ff_thread_once(&init_static_once, mpeg12_encode_init_static); } +static av_cold int find_frame_rate_index(AVCodecContext *avctx, MPEG12EncContext *mpeg12) +{ + AVRational bestq = (AVRational) {0, 0}; + AVRational ext; + AVRational target = av_inv_q(avctx->time_base); + + for (int i = 1; i < 14; i++) { + if (avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL && + i >= 9) + break; + + for (ext.num = 1; ext.num <= 4; ext.num++) { + for (ext.den = 1; ext.den <= 32; ext.den++) { + AVRational q = av_mul_q(ext, ff_mpeg12_frame_rate_tab[i]); + + if (avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO && (ext.den!=1 || ext.num!=1)) + continue; + if (av_gcd(ext.den, ext.num) != 1) + continue; + + if ( bestq.num==0 + || av_nearer_q(target, bestq, q) < 0 + || ext.num==1 && ext.den==1 && av_nearer_q(target, bestq, q) == 0) { + bestq = q; + mpeg12->frame_rate_index = i; + mpeg12->frame_rate_ext.num = ext.num; + mpeg12->frame_rate_ext.den = ext.den; + } + } + } + } + + if (av_cmp_q(target, bestq)) + return -1; + else + return 0; +} + +static av_cold int encode_init(AVCodecContext *avctx) +{ + MPEG12EncContext *const mpeg12 = avctx->priv_data; + int ret; + int max_size = avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO ? 16383 : 4095; + + if (avctx->width > max_size || avctx->height > max_size) { + av_log(avctx, AV_LOG_ERROR, "%s does not support resolutions above %dx%d\n", + CONFIG_SMALL ? avctx->codec->name : avctx->codec->long_name, + max_size, max_size); + return AVERROR(EINVAL); + } + if ((avctx->width & 0xFFF) == 0 && (avctx->height & 0xFFF) == 1) { + av_log(avctx, AV_LOG_ERROR, "Width / Height is invalid for MPEG2\n"); + return AVERROR(EINVAL); + } + + if (avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) { + if ((avctx->width & 0xFFF) == 0 || (avctx->height & 0xFFF) == 0) { + av_log(avctx, AV_LOG_ERROR, "Width or Height are not allowed to be multiples of 4096\n" + "add '-strict %d' if you want to use them anyway.\n", FF_COMPLIANCE_UNOFFICIAL); + return AVERROR(EINVAL); + } + } + + if (mpeg12->mpeg.s.q_scale_type == 1) { + if (avctx->qmax > 28) { + av_log(avctx, AV_LOG_ERROR, + "non linear quant only supports qmax <= 28 currently\n"); + return AVERROR_PATCHWELCOME; + } + } + + if (avctx->profile == AV_PROFILE_UNKNOWN) { + if (avctx->level != AV_LEVEL_UNKNOWN) { + av_log(avctx, AV_LOG_ERROR, "Set profile and level\n"); + return AVERROR(EINVAL); + } + /* Main or 4:2:2 */ + avctx->profile = avctx->pix_fmt == AV_PIX_FMT_YUV420P ? AV_PROFILE_MPEG2_MAIN + : AV_PROFILE_MPEG2_422; + } + if (avctx->level == AV_LEVEL_UNKNOWN) { + if (avctx->profile == AV_PROFILE_MPEG2_422) { /* 4:2:2 */ + if (avctx->width <= 720 && avctx->height <= 608) + avctx->level = 5; /* Main */ + else + avctx->level = 2; /* High */ + } else { + if (avctx->profile != AV_PROFILE_MPEG2_HIGH && + avctx->pix_fmt != AV_PIX_FMT_YUV420P) { + av_log(avctx, AV_LOG_ERROR, + "Only High(1) and 4:2:2(0) profiles support 4:2:2 color sampling\n"); + return AVERROR(EINVAL); + } + if (avctx->width <= 720 && avctx->height <= 576) + avctx->level = 8; /* Main */ + else if (avctx->width <= 1440) + avctx->level = 6; /* High 1440 */ + else + avctx->level = 4; /* High */ + } + } + + ret = ff_mpv_encode_init(avctx); + if (ret < 0) + return ret; + + if (find_frame_rate_index(avctx, mpeg12) < 0) { + if (avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { + av_log(avctx, AV_LOG_ERROR, "MPEG-1/2 does not support %d/%d fps\n", + avctx->time_base.den, avctx->time_base.num); + return AVERROR(EINVAL); + } else { + av_log(avctx, AV_LOG_INFO, + "MPEG-1/2 does not support %d/%d fps, there may be AV sync issues\n", + avctx->time_base.den, avctx->time_base.num); + } + } + + if (avctx->rc_max_rate && + avctx->rc_min_rate == avctx->rc_max_rate && + 90000LL * (avctx->rc_buffer_size - 1) > + avctx->rc_max_rate * 0xFFFFLL) { + av_log(avctx, AV_LOG_INFO, + "Warning vbv_delay will be set to 0xFFFF (=VBR) as the " + "specified vbv buffer is too large for the given bitrate!\n"); + } + + if (mpeg12->drop_frame_timecode) + mpeg12->tc.flags |= AV_TIMECODE_FLAG_DROPFRAME; + if (mpeg12->drop_frame_timecode && mpeg12->frame_rate_index != 4) { + av_log(avctx, AV_LOG_ERROR, + "Drop frame time code only allowed with 1001/30000 fps\n"); + return AVERROR(EINVAL); + } + + if (mpeg12->tc_opt_str) { + AVRational rate = ff_mpeg12_frame_rate_tab[mpeg12->frame_rate_index]; + int ret = av_timecode_init_from_string(&mpeg12->tc, rate, mpeg12->tc_opt_str, avctx); + if (ret < 0) + return ret; + mpeg12->drop_frame_timecode = !!(mpeg12->tc.flags & AV_TIMECODE_FLAG_DROPFRAME); + mpeg12->timecode_frame_start = mpeg12->tc.start; + } else { + mpeg12->timecode_frame_start = 0; // default is -1 + } + + return 0; +} + #define OFFSET(x) offsetof(MPEG12EncContext, x) #define VE AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM #define COMMON_OPTS \ -- 2.45.2 [-- Attachment #16: 0015-avcodec-mpeg12enc-Merge-ff_mpeg1_encode_init-into-or.patch --] [-- Type: text/x-patch, Size: 5004 bytes --] From 24b7f2a2d10d2e62b54bd2cea97fe29492cced75 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Mon, 3 Mar 2025 18:28:13 +0100 Subject: [PATCH 15/77] avcodec/mpeg12enc: Merge ff_mpeg1_encode_init() into ordinary init Everything except setting the dc_scale_tables can be done before calling ff_mpv_encode_init(); setting the dc_scale_tables unfortunately still has to be performed via a (now inlined) callback performed by ff_mpv_encode_init() as it relies on intra_dc_precision having been sanitized. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpeg12enc.c | 58 +++++++++++++++++++----------------------- libavcodec/mpeg12enc.h | 9 ++++++- 2 files changed, 34 insertions(+), 33 deletions(-) diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index 730e0411c7..c1e6cc84db 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -46,7 +46,6 @@ #include "mpeg12vlc.h" #include "mpegutils.h" #include "mpegvideo.h" -#include "mpegvideodata.h" #include "mpegvideoenc.h" #include "profiles.h" #include "rl.h" @@ -1000,36 +999,6 @@ static av_cold void mpeg12_encode_init_static(void) fcode_tab[mv + MAX_MV] = f_code; } -av_cold void ff_mpeg1_encode_init(MpegEncContext *s) -{ - static AVOnce init_static_once = AV_ONCE_INIT; - - s->y_dc_scale_table = - s->c_dc_scale_table = ff_mpeg12_dc_scale_table[s->intra_dc_precision]; - - s->me.mv_penalty = mv_penalty; - s->fcode_tab = fcode_tab + MAX_MV; - if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO) { - s->min_qcoeff = -255; - s->max_qcoeff = 255; - } else { - s->min_qcoeff = -2047; - s->max_qcoeff = 2047; - s->mpeg_quant = 1; - } - if (s->intra_vlc_format) { - s->intra_ac_vlc_length = - s->intra_ac_vlc_last_length = uni_mpeg2_ac_vlc_len; - } else { - s->intra_ac_vlc_length = - s->intra_ac_vlc_last_length = uni_mpeg1_ac_vlc_len; - } - s->inter_ac_vlc_length = - s->inter_ac_vlc_last_length = uni_mpeg1_ac_vlc_len; - - ff_thread_once(&init_static_once, mpeg12_encode_init_static); -} - static av_cold int find_frame_rate_index(AVCodecContext *avctx, MPEG12EncContext *mpeg12) { AVRational bestq = (AVRational) {0, 0}; @@ -1070,7 +1039,10 @@ static av_cold int find_frame_rate_index(AVCodecContext *avctx, MPEG12EncContext static av_cold int encode_init(AVCodecContext *avctx) { + static AVOnce init_static_once = AV_ONCE_INIT; MPEG12EncContext *const mpeg12 = avctx->priv_data; + MPVMainEncContext *const m = &mpeg12->mpeg; + MpegEncContext *const s = &m->s; int ret; int max_size = avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO ? 16383 : 4095; @@ -1093,7 +1065,7 @@ static av_cold int encode_init(AVCodecContext *avctx) } } - if (mpeg12->mpeg.s.q_scale_type == 1) { + if (s->q_scale_type == 1) { if (avctx->qmax > 28) { av_log(avctx, AV_LOG_ERROR, "non linear quant only supports qmax <= 28 currently\n"); @@ -1132,6 +1104,26 @@ static av_cold int encode_init(AVCodecContext *avctx) } } + s->me.mv_penalty = mv_penalty; + s->fcode_tab = fcode_tab + MAX_MV; + if (avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO) { + s->min_qcoeff = -255; + s->max_qcoeff = 255; + } else { + s->min_qcoeff = -2047; + s->max_qcoeff = 2047; + s->mpeg_quant = 1; + } + if (s->intra_vlc_format) { + s->intra_ac_vlc_length = + s->intra_ac_vlc_last_length = uni_mpeg2_ac_vlc_len; + } else { + s->intra_ac_vlc_length = + s->intra_ac_vlc_last_length = uni_mpeg1_ac_vlc_len; + } + s->inter_ac_vlc_length = + s->inter_ac_vlc_last_length = uni_mpeg1_ac_vlc_len; + ret = ff_mpv_encode_init(avctx); if (ret < 0) return ret; @@ -1176,6 +1168,8 @@ static av_cold int encode_init(AVCodecContext *avctx) mpeg12->timecode_frame_start = 0; // default is -1 } + ff_thread_once(&init_static_once, mpeg12_encode_init_static); + return 0; } diff --git a/libavcodec/mpeg12enc.h b/libavcodec/mpeg12enc.h index 0b35af8a30..908971905d 100644 --- a/libavcodec/mpeg12enc.h +++ b/libavcodec/mpeg12enc.h @@ -25,11 +25,18 @@ #include <stdint.h> #include "mpegvideo.h" +#include "mpegvideodata.h" void ff_mpeg1_encode_picture_header(MpegEncContext *s); void ff_mpeg1_encode_mb(MpegEncContext *s, int16_t block[8][64], int motion_x, int motion_y); -void ff_mpeg1_encode_init(MpegEncContext *s); void ff_mpeg1_encode_slice_header(MpegEncContext *s); +// Must not be called before intra_dc_precision has been sanitized in ff_mpv_encode_init() +static inline void ff_mpeg1_encode_init(MpegEncContext *s) +{ + s->y_dc_scale_table = + s->c_dc_scale_table = ff_mpeg12_dc_scale_table[s->intra_dc_precision]; +} + #endif /* AVCODEC_MPEG12ENC_H */ -- 2.45.2 [-- Attachment #17: 0016-avcodec-mpeg12enc-Don-t-write-invalid-MPEG-1-slice-h.patch --] [-- Type: text/x-patch, Size: 3926 bytes --] From 06ce4b8647097489ac4d56f7f80693430132feb2 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sat, 15 Mar 2025 04:30:11 +0100 Subject: [PATCH 16/77] avcodec/mpeg12enc: Don't write invalid MPEG-1 slice headers The valid values for slice_start_code are 0x1..0xAF, which implies that one can't start a slice with row nb > 174 (zero-based). This problem can be encountered with files of sufficient height (more than 2800 pixels) either by using the slice option or by imposing an RTP payload limit. Fix this by making the last slice start on the maximum allowed slice row if necessary and divide the first 174 rows to the remaining slices. This will impede parallelism both in the decoder and encoder, but that is unavoidable. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpeg12enc.c | 26 ++++++++++++++++++++++++++ libavcodec/mpegvideo_enc.c | 4 +++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index c1e6cc84db..d84d628563 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -25,6 +25,7 @@ * MPEG-1/2 encoder */ +#include <assert.h> #include <stdint.h> #include "config.h" @@ -324,6 +325,7 @@ void ff_mpeg1_encode_slice_header(MpegEncContext *s) /* slice_vertical_position_extension */ put_bits(&s->pb, 3, s->mb_y >> 7); } else { + av_assert1(s->mb_y <= SLICE_MAX_START_CODE - SLICE_MIN_START_CODE); put_header(s, SLICE_MIN_START_CODE + s->mb_y); } put_qscale(s); @@ -1128,6 +1130,30 @@ static av_cold int encode_init(AVCodecContext *avctx) if (ret < 0) return ret; + if (avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO && + s->thread_context[s->slice_context_count - 1]->start_mb_y > + SLICE_MAX_START_CODE - SLICE_MIN_START_CODE) { + // MPEG-1 slices must not start at a MB row number that would make + // their start code > SLICE_MAX_START_CODE. So make the last slice + // bigger if needed and evenly distribute the first 174 rows. + static_assert(MAX_THREADS <= 1 + SLICE_MAX_START_CODE - SLICE_MIN_START_CODE, + "With more than 175 slice contexts, we have to handle " + "the case in which there is no work to do for some " + "slice contexts."); + const int mb_height = SLICE_MAX_START_CODE - SLICE_MIN_START_CODE; + const int nb_slices = s->slice_context_count - 1; + + s->thread_context[nb_slices]->start_mb_y = mb_height; + + av_assert1(nb_slices >= 1); + for (int i = 0; i < nb_slices; i++) { + s->thread_context[i]->start_mb_y = + (mb_height * (i ) + nb_slices / 2) / nb_slices; + s->thread_context[i]->end_mb_y = + (mb_height * (i + 1) + nb_slices / 2) / nb_slices; + } + } + if (find_frame_rate_index(avctx, mpeg12) < 0) { if (avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { av_log(avctx, AV_LOG_ERROR, "MPEG-1/2 does not support %d/%d fps\n", diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 398b06d929..2cba4deca3 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -3077,7 +3077,9 @@ static int encode_thread(AVCodecContext *c, void *arg){ case AV_CODEC_ID_MPEG2VIDEO: if(s->mb_x==0 && s->mb_y!=0) is_gob_start=1; case AV_CODEC_ID_MPEG1VIDEO: - if(s->mb_skip_run) is_gob_start=0; + if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO && s->mb_y >= 175 || + s->mb_skip_run) + is_gob_start=0; break; case AV_CODEC_ID_MJPEG: if(s->mb_x==0 && s->mb_y!=0) is_gob_start=1; -- 2.45.2 [-- Attachment #18: 0017-avcodec-pthread_slice-Remove-MPEG-1-height-hack.patch --] [-- Type: text/x-patch, Size: 1238 bytes --] From d045df9d51b5162fa29ecd2ccb92588ee5976b5c Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sat, 15 Mar 2025 04:59:55 +0100 Subject: [PATCH 17/77] avcodec/pthread_slice: Remove MPEG-1 height hack This is no longer necessary given that the MPEG-1 encoder now adapts the size of the last slice to ensure that no slice header has an invalid slice_start_code. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/pthread_slice.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/libavcodec/pthread_slice.c b/libavcodec/pthread_slice.c index 8fd3fdafd3..4714fef106 100644 --- a/libavcodec/pthread_slice.c +++ b/libavcodec/pthread_slice.c @@ -115,12 +115,6 @@ av_cold int ff_slice_thread_init(AVCodecContext *avctx) int thread_count = avctx->thread_count; void (*mainfunc)(void *); - // We cannot do this in the encoder init as the threads are created before - if (ff_codec_is_encoder(avctx->codec) && - avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO && - avctx->height > 2800) - thread_count = avctx->thread_count = 1; - if (!thread_count) { int nb_cpus = av_cpu_count(); if (avctx->height) -- 2.45.2 [-- Attachment #19: 0018-avcodec-pthread_slice-Return-error-on-error.patch --] [-- Type: text/x-patch, Size: 1545 bytes --] From d80f255e10e7a5ef14df6479114a92dbd1c1c37f Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sat, 15 Mar 2025 05:24:51 +0100 Subject: [PATCH 18/77] avcodec/pthread_slice: Return error on error Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/pthread_slice.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libavcodec/pthread_slice.c b/libavcodec/pthread_slice.c index 4714fef106..f9da670735 100644 --- a/libavcodec/pthread_slice.c +++ b/libavcodec/pthread_slice.c @@ -132,14 +132,16 @@ av_cold int ff_slice_thread_init(AVCodecContext *avctx) } avctx->internal->thread_ctx = c = av_mallocz(sizeof(*c)); + if (!c) + return AVERROR(ENOMEM); mainfunc = ffcodec(avctx->codec)->caps_internal & FF_CODEC_CAP_SLICE_THREAD_HAS_MF ? &main_function : NULL; - if (!c || (thread_count = avpriv_slicethread_create(&c->thread, avctx, worker_func, mainfunc, thread_count)) <= 1) { - if (c) - avpriv_slicethread_free(&c->thread); - av_freep(&avctx->internal->thread_ctx); + thread_count = avpriv_slicethread_create(&c->thread, avctx, worker_func, + mainfunc, thread_count); + if (thread_count <= 1) { + ff_slice_thread_free(avctx); avctx->thread_count = 1; avctx->active_thread_type = 0; - return 0; + return thread_count < 0 ? thread_count : 0; } avctx->thread_count = thread_count; -- 2.45.2 [-- Attachment #20: 0019-avutil-slicethread-Remove-NULL-pointer-check-when-fr.patch --] [-- Type: text/x-patch, Size: 1248 bytes --] From 351c46b4dc3a1d63c148aaf611bf9bde3de34598 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sat, 15 Mar 2025 05:30:15 +0100 Subject: [PATCH 19/77] avutil/slicethread: Remove NULL pointer check when freeing avpriv_slicethread_free() is one of our functions that takes a pointer to a pointer and resets the pointer when done. It is legal for such functions to be passed a pointer to a NULL pointer, yet passing a NULL pointer would be insane and should not be tolerated. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavutil/slicethread.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libavutil/slicethread.c b/libavutil/slicethread.c index e6b82e31b6..6593d58abc 100644 --- a/libavutil/slicethread.c +++ b/libavutil/slicethread.c @@ -224,13 +224,12 @@ void avpriv_slicethread_execute(AVSliceThread *ctx, int nb_jobs, int execute_mai void avpriv_slicethread_free(AVSliceThread **pctx) { - AVSliceThread *ctx; + AVSliceThread *ctx = *pctx; int nb_workers, i; - if (!pctx || !*pctx) + if (!ctx) return; - ctx = *pctx; nb_workers = ctx->nb_threads; if (!ctx->main_func) nb_workers--; -- 2.45.2 [-- Attachment #21: 0020-avutil-slicethread-Mark-avpriv_slicethread_-create-f.patch --] [-- Type: text/x-patch, Size: 1210 bytes --] From 803680237e97a86d1d7f2c9afcf8823d66dec819 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sat, 15 Mar 2025 05:34:29 +0100 Subject: [PATCH 20/77] avutil/slicethread: Mark avpriv_slicethread_{create,free} as av_cold Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavutil/slicethread.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavutil/slicethread.c b/libavutil/slicethread.c index 6593d58abc..7650fc66ad 100644 --- a/libavutil/slicethread.c +++ b/libavutil/slicethread.c @@ -95,6 +95,7 @@ static void *attribute_align_arg thread_worker(void *v) } } +av_cold int avpriv_slicethread_create(AVSliceThread **pctx, void *priv, void (*worker_func)(void *priv, int jobnr, int threadnr, int nb_jobs, int nb_threads), void (*main_func)(void *priv), @@ -222,7 +223,7 @@ void avpriv_slicethread_execute(AVSliceThread *ctx, int nb_jobs, int execute_mai } } -void avpriv_slicethread_free(AVSliceThread **pctx) +av_cold void avpriv_slicethread_free(AVSliceThread **pctx) { AVSliceThread *ctx = *pctx; int nb_workers, i; -- 2.45.2 [-- Attachment #22: 0021-avcodec-mpeg4videoenc-Add-Mpeg4EncContext-and-move-t.patch --] [-- Type: text/x-patch, Size: 7626 bytes --] From ee671d14898fc311152f37fbd1d81719a9172848 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sun, 2 Mar 2025 01:03:10 +0100 Subject: [PATCH 21/77] avcodec/mpeg4videoenc: Add Mpeg4EncContext and move time_increment_bits It is only ever used by the main encoder thread. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpeg4videoenc.c | 36 +++++++++++++++++++++++++++--------- libavcodec/mpeg4videoenc.h | 4 ++-- libavcodec/mpegvideo.h | 2 -- libavcodec/mpegvideo_enc.c | 3 +-- 4 files changed, 30 insertions(+), 15 deletions(-) diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c index 11872f29eb..18f97bb81d 100644 --- a/libavcodec/mpeg4videoenc.c +++ b/libavcodec/mpeg4videoenc.c @@ -71,6 +71,17 @@ static uint8_t uni_mpeg4_inter_rl_len[64 * 64 * 2 * 2]; * max run: 29/41 */ +typedef struct Mpeg4EncContext { + MPVMainEncContext m; + /// number of bits to represent the fractional part of time + int time_increment_bits; +} Mpeg4EncContext; + +static inline Mpeg4EncContext *mainctx_to_mpeg4(MPVMainEncContext *m) +{ + return (Mpeg4EncContext*)m; +} + /** * Return the number of bits that encoding the 8x8 block in block would need. * @param[in] block_last_index last index in scantable order that refers to a non zero element in block. @@ -960,10 +971,11 @@ static void mpeg4_encode_visual_object_header(MpegEncContext *s) ff_mpeg4_stuffing(&s->pb); } -static void mpeg4_encode_vol_header(MpegEncContext *s, +static void mpeg4_encode_vol_header(Mpeg4EncContext *const m4, int vo_number, int vol_number) { + MpegEncContext *const s = &m4->m.s; int vo_ver_id, vo_type, aspect_ratio_info; if (s->max_b_frames || s->quarter_sample) { @@ -1002,8 +1014,8 @@ static void mpeg4_encode_vol_header(MpegEncContext *s, put_bits(&s->pb, 1, 1); /* marker bit */ put_bits(&s->pb, 16, s->avctx->time_base.den); - if (s->time_increment_bits < 1) - s->time_increment_bits = 1; + if (m4->time_increment_bits < 1) + m4->time_increment_bits = 1; put_bits(&s->pb, 1, 1); /* marker bit */ put_bits(&s->pb, 1, 0); /* fixed vop rate=no */ put_bits(&s->pb, 1, 1); /* marker bit */ @@ -1050,8 +1062,10 @@ static void mpeg4_encode_vol_header(MpegEncContext *s, } /* write MPEG-4 VOP header */ -int ff_mpeg4_encode_picture_header(MpegEncContext *s) +int ff_mpeg4_encode_picture_header(MPVMainEncContext *const m) { + Mpeg4EncContext *const m4 = mainctx_to_mpeg4(m); + MpegEncContext *const s = &m->s; uint64_t time_incr; int64_t time_div, time_mod; @@ -1060,7 +1074,7 @@ int ff_mpeg4_encode_picture_header(MpegEncContext *s) if (s->avctx->strict_std_compliance < FF_COMPLIANCE_VERY_STRICT) // HACK, the reference sw is buggy mpeg4_encode_visual_object_header(s); if (s->avctx->strict_std_compliance < FF_COMPLIANCE_VERY_STRICT || s->picture_number == 0) // HACK, the reference sw is buggy - mpeg4_encode_vol_header(s, 0, 0); + mpeg4_encode_vol_header(m4, 0, 0); } mpeg4_encode_gop_header(s); } @@ -1085,7 +1099,7 @@ int ff_mpeg4_encode_picture_header(MpegEncContext *s) put_bits(&s->pb, 1, 0); put_bits(&s->pb, 1, 1); /* marker */ - put_bits(&s->pb, s->time_increment_bits, time_mod); /* time increment */ + put_bits(&s->pb, m4->time_increment_bits, time_mod); /* time increment */ put_bits(&s->pb, 1, 1); /* marker */ put_bits(&s->pb, 1, 1); /* vop coded */ if (s->pict_type == AV_PICTURE_TYPE_P) { @@ -1276,7 +1290,8 @@ static av_cold void mpeg4_encode_init_static(void) static av_cold int encode_init(AVCodecContext *avctx) { static AVOnce init_static_once = AV_ONCE_INIT; - MpegEncContext *s = avctx->priv_data; + Mpeg4EncContext *const m4 = avctx->priv_data; + MpegEncContext *const s = &m4->m.s; int ret; if (avctx->width >= (1<<13) || avctx->height >= (1<<13)) { @@ -1290,7 +1305,10 @@ static av_cold int encode_init(AVCodecContext *avctx) ff_thread_once(&init_static_once, mpeg4_encode_init_static); + m4->time_increment_bits = av_log2(avctx->time_base.den - 1) + 1; + s->fcode_tab = fcode_tab + MAX_MV; + s->min_qcoeff = -2048; s->max_qcoeff = 2047; s->intra_ac_vlc_length = uni_mpeg4_intra_rl_len; @@ -1309,7 +1327,7 @@ static av_cold int encode_init(AVCodecContext *avctx) init_put_bits(&s->pb, s->avctx->extradata, 1024); mpeg4_encode_visual_object_header(s); - mpeg4_encode_vol_header(s, 0, 0); + mpeg4_encode_vol_header(m4, 0, 0); // ff_mpeg4_stuffing(&s->pb); ? flush_put_bits(&s->pb); @@ -1395,7 +1413,7 @@ const FFCodec ff_mpeg4_encoder = { CODEC_LONG_NAME("MPEG-4 part 2"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_MPEG4, - .priv_data_size = sizeof(MPVMainEncContext), + .priv_data_size = sizeof(Mpeg4EncContext), .init = encode_init, FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), .close = ff_mpv_encode_end, diff --git a/libavcodec/mpeg4videoenc.h b/libavcodec/mpeg4videoenc.h index f0d5c3d077..1c53ce4ede 100644 --- a/libavcodec/mpeg4videoenc.h +++ b/libavcodec/mpeg4videoenc.h @@ -25,14 +25,14 @@ #include <stdint.h> -#include "mpegvideo.h" +#include "mpegvideoenc.h" #include "put_bits.h" void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], int motion_x, int motion_y); void ff_set_mpeg4_time(MpegEncContext *s); -int ff_mpeg4_encode_picture_header(MpegEncContext *s); +int ff_mpeg4_encode_picture_header(MPVMainEncContext *m); void ff_mpeg4_encode_video_packet_header(MpegEncContext *s); void ff_mpeg4_stuffing(PutBitContext *pbc); diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 2cc6dbf534..b532088730 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -362,8 +362,6 @@ typedef struct MpegEncContext { /* MPEG-4 specific */ int studio_profile; int dct_precision; - /// number of bits to represent the fractional part of time (encoder only) - int time_increment_bits; int last_time_base; int time_base; ///< time in seconds of last I,P,S Frame int64_t time; ///< time of current frame diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 2cba4deca3..ab67f5444d 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -746,7 +746,6 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) (1 << 16) - 1); return AVERROR(EINVAL); } - s->time_increment_bits = av_log2(avctx->time_base.den - 1) + 1; switch (avctx->codec->id) { #if CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER @@ -3919,7 +3918,7 @@ static int encode_picture(MPVMainEncContext *const m, const AVPacket *pkt) ff_msmpeg4_encode_picture_header(s); #endif else if (CONFIG_MPEG4_ENCODER && s->h263_pred) { - ret = ff_mpeg4_encode_picture_header(s); + ret = ff_mpeg4_encode_picture_header(m); if (ret < 0) return ret; } else if (CONFIG_RV10_ENCODER && s->codec_id == AV_CODEC_ID_RV10) { -- 2.45.2 [-- Attachment #23: 0022-avcodec-mpegvideo_enc-Move-MPEG-4-specific-check-to-.patch --] [-- Type: text/x-patch, Size: 2228 bytes --] From 653ef25c0d328cc705144f0601da81238915e173 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sun, 2 Mar 2025 02:20:03 +0100 Subject: [PATCH 22/77] avcodec/mpegvideo_enc: Move MPEG-4 specific check to mpeg4videoenc.c Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpeg4videoenc.c | 9 +++++++++ libavcodec/mpegvideo_enc.c | 10 ---------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c index 18f97bb81d..c265316ed6 100644 --- a/libavcodec/mpeg4videoenc.c +++ b/libavcodec/mpeg4videoenc.c @@ -1305,6 +1305,15 @@ static av_cold int encode_init(AVCodecContext *avctx) ff_thread_once(&init_static_once, mpeg4_encode_init_static); + if (avctx->time_base.den > (1 << 16) - 1) { + av_log(avctx, AV_LOG_ERROR, + "timebase %d/%d not supported by MPEG 4 standard, " + "the maximum admitted value for the timebase denominator " + "is %d\n", avctx->time_base.num, avctx->time_base.den, + (1 << 16) - 1); + return AVERROR(EINVAL); + } + m4->time_increment_bits = av_log2(avctx->time_base.den - 1) + 1; s->fcode_tab = fcode_tab + MAX_MV; diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index ab67f5444d..0a9c18ff79 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -737,16 +737,6 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_DEBUG, "intra_quant_bias = %d inter_quant_bias = %d\n",s->intra_quant_bias,s->inter_quant_bias); - if (avctx->codec_id == AV_CODEC_ID_MPEG4 && - avctx->time_base.den > (1 << 16) - 1) { - av_log(avctx, AV_LOG_ERROR, - "timebase %d/%d not supported by MPEG 4 standard, " - "the maximum admitted value for the timebase denominator " - "is %d\n", avctx->time_base.num, avctx->time_base.den, - (1 << 16) - 1); - return AVERROR(EINVAL); - } - switch (avctx->codec->id) { #if CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER case AV_CODEC_ID_MPEG2VIDEO: -- 2.45.2 [-- Attachment #24: 0023-avcodec-mpegvideo-Move-sequence-level-properties-to-.patch --] [-- Type: text/x-patch, Size: 17822 bytes --] From 77ab1578003a88587c83ef9d8cc52ca837e6337c Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sun, 2 Mar 2025 02:55:04 +0100 Subject: [PATCH 23/77] avcodec/mpegvideo: Move sequence-level properties to MPVMainEncContext Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpeg12enc.c | 14 ++++--- libavcodec/mpeg12enc.h | 4 +- libavcodec/mpegvideo.h | 15 ------- libavcodec/mpegvideo_enc.c | 86 +++++++++++++++++++------------------- libavcodec/mpegvideoenc.h | 16 +++++++ libavcodec/ratecontrol.c | 4 +- 6 files changed, 71 insertions(+), 68 deletions(-) diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index d84d628563..ed2c63086f 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -144,9 +144,9 @@ static void put_header(MpegEncContext *s, uint32_t header) } /* put sequence header if needed */ -static void mpeg1_encode_sequence_header(MpegEncContext *s) +static void mpeg1_encode_sequence_header(MPEG12EncContext *mpeg12) { - MPEG12EncContext *const mpeg12 = (MPEG12EncContext*)s; + MpegEncContext *const s = &mpeg12->mpeg.s; unsigned int vbv_buffer_size, fps, v; int constraint_parameter_flag; AVRational framerate = ff_mpeg12_frame_rate_tab[mpeg12->frame_rate_index]; @@ -299,7 +299,7 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) put_bits(&s->pb, 6, (uint32_t)((time_code / fps) % 60)); put_bits(&s->pb, 6, (uint32_t)((time_code % fps))); put_bits(&s->pb, 1, !!(s->avctx->flags & AV_CODEC_FLAG_CLOSED_GOP) || - s->intra_only || !mpeg12->gop_picture_number); + mpeg12->mpeg.intra_only || !mpeg12->gop_picture_number); put_bits(&s->pb, 1, 0); // broken link } @@ -333,11 +333,13 @@ void ff_mpeg1_encode_slice_header(MpegEncContext *s) put_bits(&s->pb, 1, 0); } -void ff_mpeg1_encode_picture_header(MpegEncContext *s) +void ff_mpeg1_encode_picture_header(MPVMainEncContext *const m) { - MPEG12EncContext *const mpeg12 = (MPEG12EncContext*)s; + MPEG12EncContext *const mpeg12 = (MPEG12EncContext*)m; + MpegEncContext *const s = &m->s; const AVFrameSideData *side_data; - mpeg1_encode_sequence_header(s); + + mpeg1_encode_sequence_header(mpeg12); /* MPEG-1 picture header */ put_header(s, PICTURE_START_CODE); diff --git a/libavcodec/mpeg12enc.h b/libavcodec/mpeg12enc.h index 908971905d..fa1504177a 100644 --- a/libavcodec/mpeg12enc.h +++ b/libavcodec/mpeg12enc.h @@ -24,10 +24,10 @@ #include <stdint.h> -#include "mpegvideo.h" +#include "mpegvideoenc.h" #include "mpegvideodata.h" -void ff_mpeg1_encode_picture_header(MpegEncContext *s); +void ff_mpeg1_encode_picture_header(MPVMainEncContext *m); void ff_mpeg1_encode_mb(MpegEncContext *s, int16_t block[8][64], int motion_x, int motion_y); void ff_mpeg1_encode_slice_header(MpegEncContext *s); diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index b532088730..3259c1117c 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -91,8 +91,6 @@ typedef struct MpegEncContext { void *private_ctx; /* the following parameters must be initialized before encoding */ int width, height;///< picture size. must be a multiple of 16 - int gop_size; - int intra_only; ///< if true, only intra pictures are generated int64_t bit_rate; ///< wanted bit rate enum OutputFormat out_format; ///< output format int h263_pred; ///< use MPEG-4/H.263 ac/dc predictions @@ -114,10 +112,7 @@ typedef struct MpegEncContext { /* sequence parameters */ int context_initialized; - int input_picture_number; ///< used to set pic->display_picture_number, should not be used for/by anything else - int coded_picture_number; ///< used to set pic->coded_picture_number, should not be used for/by anything else int picture_number; //FIXME remove, unclear definition - int picture_in_gop_number; ///< 0-> first pic in gop, ... int mb_width, mb_height; ///< number of MBs horizontally & vertically int mb_stride; ///< mb_width+1 used for some arrays to allow simple addressing of left & top MBs without sig11 int b8_stride; ///< 2*mb_width+1 used for some 8x8 block arrays to allow simple addressing @@ -131,16 +126,6 @@ typedef struct MpegEncContext { BufferPoolContext buffer_pools; - int64_t user_specified_pts; ///< last non-zero pts from AVFrame which was passed into avcodec_send_frame() - /** - * pts difference between the first and second input frame, used for - * calculating dts of the first frame when there's a delay */ - int64_t dts_delta; - /** - * reordered pts to be used as dts for the next output frame when there's - * a delay */ - int64_t reordered_pts; - /** bit output */ PutBitContext pb; diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 0a9c18ff79..cc3c7a745f 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -291,9 +291,6 @@ static av_cold void mpv_encode_defaults(MpegEncContext *s) s->y_dc_scale_table = s->c_dc_scale_table = ff_mpeg1_dc_scale_table; } - - s->input_picture_number = 0; - s->picture_in_gop_number = 0; } av_cold void ff_dct_encode_init(MpegEncContext *s) @@ -354,9 +351,10 @@ static av_cold int me_cmp_init(MPVMainEncContext *const m, AVCodecContext *avctx } #define ALLOCZ_ARRAYS(p, mult, numb) ((p) = av_calloc(numb, mult * sizeof(*(p)))) -static av_cold int init_matrices(MpegEncContext *s, AVCodecContext *avctx) +static av_cold int init_matrices(MPVMainEncContext *const m, AVCodecContext *avctx) { - const int nb_matrices = 1 + (s->out_format == FMT_MJPEG) + !s->intra_only; + MpegEncContext *const s = &m->s; + const int nb_matrices = 1 + (s->out_format == FMT_MJPEG) + !m->intra_only; const uint16_t *intra_matrix, *inter_matrix; int ret; @@ -368,14 +366,14 @@ static av_cold int init_matrices(MpegEncContext *s, AVCodecContext *avctx) s->q_chroma_intra_matrix = s->q_intra_matrix + 32; s->q_chroma_intra_matrix16 = s->q_intra_matrix16 + 32; // No need to set q_inter_matrix - av_assert1(s->intra_only); + av_assert1(m->intra_only); // intra_matrix, chroma_intra_matrix will be set later for MJPEG. return 0; } else { s->q_chroma_intra_matrix = s->q_intra_matrix; s->q_chroma_intra_matrix16 = s->q_intra_matrix16; } - if (!s->intra_only) { + if (!m->intra_only) { s->q_inter_matrix = s->q_intra_matrix + 32; s->q_inter_matrix16 = s->q_intra_matrix16 + 32; } @@ -460,7 +458,7 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) avctx->gop_size, 600); avctx->gop_size = 600; } - s->gop_size = avctx->gop_size; + m->gop_size = avctx->gop_size; s->avctx = avctx; if (avctx->max_b_frames > MPVENC_MAX_B_FRAMES) { av_log(avctx, AV_LOG_ERROR, "Too many B-frames requested, maximum " @@ -499,13 +497,13 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_ERROR, "intra dc precision too large\n"); return AVERROR(EINVAL); } - s->user_specified_pts = AV_NOPTS_VALUE; + m->user_specified_pts = AV_NOPTS_VALUE; - if (s->gop_size <= 1) { - s->intra_only = 1; - s->gop_size = 12; + if (m->gop_size <= 1) { + m->intra_only = 1; + m->gop_size = 12; } else { - s->intra_only = 0; + m->intra_only = 0; } /* Fixed QSCALE */ @@ -753,14 +751,14 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) case AV_CODEC_ID_MJPEG: case AV_CODEC_ID_AMV: s->out_format = FMT_MJPEG; - s->intra_only = 1; /* force intra only for jpeg */ + m->intra_only = 1; /* force intra only for jpeg */ avctx->delay = 0; s->low_delay = 1; break; #endif case AV_CODEC_ID_SPEEDHQ: s->out_format = FMT_SPEEDHQ; - s->intra_only = 1; /* force intra only for SHQ */ + m->intra_only = 1; /* force intra only for SHQ */ avctx->delay = 0; s->low_delay = 1; break; @@ -885,7 +883,7 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) s->frame_reconstruction_bitfield = (1 << AV_PICTURE_TYPE_I) | (1 << AV_PICTURE_TYPE_P) | (1 << AV_PICTURE_TYPE_B); - } else if (!s->intra_only) { + } else if (!m->intra_only) { s->frame_reconstruction_bitfield = (1 << AV_PICTURE_TYPE_I) | (1 << AV_PICTURE_TYPE_P); } else { @@ -916,7 +914,7 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) !(s->picture_pool = ff_mpv_alloc_pic_pool(0))) return AVERROR(ENOMEM); - ret = init_matrices(s, avctx); + ret = init_matrices(m, avctx); if (ret < 0) return ret; @@ -1259,11 +1257,11 @@ static int load_input_picture(MPVMainEncContext *const m, const AVFrame *pic_arg if (pic_arg) { pts = pic_arg->pts; - display_picture_number = s->input_picture_number++; + display_picture_number = m->input_picture_number++; if (pts != AV_NOPTS_VALUE) { - if (s->user_specified_pts != AV_NOPTS_VALUE) { - int64_t last = s->user_specified_pts; + if (m->user_specified_pts != AV_NOPTS_VALUE) { + int64_t last = m->user_specified_pts; if (pts <= last) { av_log(s->avctx, AV_LOG_ERROR, @@ -1273,13 +1271,13 @@ static int load_input_picture(MPVMainEncContext *const m, const AVFrame *pic_arg } if (!s->low_delay && display_picture_number == 1) - s->dts_delta = pts - last; + m->dts_delta = pts - last; } - s->user_specified_pts = pts; + m->user_specified_pts = pts; } else { - if (s->user_specified_pts != AV_NOPTS_VALUE) { - s->user_specified_pts = - pts = s->user_specified_pts + 1; + if (m->user_specified_pts != AV_NOPTS_VALUE) { + m->user_specified_pts = + pts = m->user_specified_pts + 1; av_log(s->avctx, AV_LOG_INFO, "Warning: AVFrame.pts=? trying to guess (%"PRId64")\n", pts); @@ -1612,7 +1610,7 @@ static int set_bframe_chain_length(MPVMainEncContext *const m) /* set next picture type & ordering */ if (m->frame_skip_threshold || m->frame_skip_factor) { - if (s->picture_in_gop_number < s->gop_size && + if (m->picture_in_gop_number < m->gop_size && s->next_pic.ptr && skip_check(m, s->input_picture[0], s->next_pic.ptr)) { // FIXME check that the gop check above is +-1 correct @@ -1624,13 +1622,13 @@ static int set_bframe_chain_length(MPVMainEncContext *const m) } } - if (/*s->picture_in_gop_number >= s->gop_size ||*/ - !s->next_pic.ptr || s->intra_only) { + if (/* m->picture_in_gop_number >= m->gop_size || */ + !s->next_pic.ptr || m->intra_only) { s->reordered_input_picture[0] = s->input_picture[0]; s->input_picture[0] = NULL; s->reordered_input_picture[0]->f->pict_type = AV_PICTURE_TYPE_I; s->reordered_input_picture[0]->coded_picture_number = - s->coded_picture_number++; + m->coded_picture_number++; } else { int b_frames = 0; @@ -1700,10 +1698,10 @@ static int set_bframe_chain_length(MPVMainEncContext *const m) "warning, too many B-frames in a row\n"); } - if (s->picture_in_gop_number + b_frames >= s->gop_size) { + if (m->picture_in_gop_number + b_frames >= m->gop_size) { if ((s->mpv_flags & FF_MPV_FLAG_STRICT_GOP) && - s->gop_size > s->picture_in_gop_number) { - b_frames = s->gop_size - s->picture_in_gop_number - 1; + m->gop_size > m->picture_in_gop_number) { + b_frames = m->gop_size - m->picture_in_gop_number - 1; } else { if (s->avctx->flags & AV_CODEC_FLAG_CLOSED_GOP) b_frames = 0; @@ -1720,14 +1718,14 @@ static int set_bframe_chain_length(MPVMainEncContext *const m) if (s->reordered_input_picture[0]->f->pict_type != AV_PICTURE_TYPE_I) s->reordered_input_picture[0]->f->pict_type = AV_PICTURE_TYPE_P; s->reordered_input_picture[0]->coded_picture_number = - s->coded_picture_number++; + m->coded_picture_number++; for (int i = 0; i < b_frames; i++) { s->reordered_input_picture[i + 1] = s->input_picture[i]; s->input_picture[i] = NULL; s->reordered_input_picture[i + 1]->f->pict_type = AV_PICTURE_TYPE_B; s->reordered_input_picture[i + 1]->coded_picture_number = - s->coded_picture_number++; + m->coded_picture_number++; } } @@ -1794,11 +1792,13 @@ fail: return ret; } -static void frame_end(MpegEncContext *s) +static void frame_end(MPVMainEncContext *const m) { + MpegEncContext *const s = &m->s; + if (s->unrestricted_mv && s->cur_pic.reference && - !s->intra_only) { + !m->intra_only) { int hshift = s->chroma_x_shift; int vshift = s->chroma_y_shift; s->mpvencdsp.draw_edges(s->cur_pic.data[0], @@ -1878,7 +1878,7 @@ int ff_mpv_encode_picture(AVCodecContext *avctx, AVPacket *pkt, s->vbv_ignore_qmax = 0; - s->picture_in_gop_number++; + m->picture_in_gop_number++; ret = load_input_picture(m, pic_arg); if (ret < 0) @@ -1923,7 +1923,7 @@ vbv_retry: if (ret < 0) return -1; - frame_end(s); + frame_end(m); if ((CONFIG_MJPEG_ENCODER || CONFIG_AMV_ENCODER) && s->out_format == FMT_MJPEG) ff_mjpeg_encode_picture_trailer(&s->pb, s->header_bits); @@ -2066,10 +2066,10 @@ vbv_retry: pkt->duration = s->cur_pic.ptr->f->duration; if (!s->low_delay && s->pict_type != AV_PICTURE_TYPE_B) { if (!s->cur_pic.ptr->coded_picture_number) - pkt->dts = pkt->pts - s->dts_delta; + pkt->dts = pkt->pts - m->dts_delta; else - pkt->dts = s->reordered_pts; - s->reordered_pts = pkt->pts; + pkt->dts = m->reordered_pts; + m->reordered_pts = pkt->pts; } else pkt->dts = pkt->pts; @@ -3882,7 +3882,7 @@ static int encode_picture(MPVMainEncContext *const m, const AVPacket *pkt) s->cur_pic.ptr->f->pict_type = s->pict_type; if (s->cur_pic.ptr->f->flags & AV_FRAME_FLAG_KEY) - s->picture_in_gop_number=0; + m->picture_in_gop_number = 0; s->mb_x = s->mb_y = 0; s->last_bits= put_bits_count(&s->pb); @@ -3925,7 +3925,7 @@ static int encode_picture(MPVMainEncContext *const m, const AVPacket *pkt) break; case FMT_MPEG1: if (CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER) - ff_mpeg1_encode_picture_header(s); + ff_mpeg1_encode_picture_header(m); break; default: av_assert0(0); diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h index 9f0d63c31e..a76d17f63e 100644 --- a/libavcodec/mpegvideoenc.h +++ b/libavcodec/mpegvideoenc.h @@ -39,6 +39,22 @@ typedef struct MPVMainEncContext { MpegEncContext s; ///< The main slicecontext + int intra_only; ///< if true, only intra pictures are generated + int gop_size; + int picture_in_gop_number; ///< 0-> first pic in gop, ... + int input_picture_number; ///< used to set pic->display_picture_number + int coded_picture_number; ///< used to set pic->coded_picture_number + + int64_t user_specified_pts; ///< last non-zero pts from user-supplied AVFrame + /** + * pts difference between the first and second input frame, used for + * calculating dts of the first frame when there's a delay */ + int64_t dts_delta; + /** + * reordered pts to be used as dts for the next output frame when there's + * a delay */ + int64_t reordered_pts; + /// temporary frames used by b_frame_strategy = 2 AVFrame *tmp_frames[MPVENC_MAX_B_FRAMES + 2]; int b_frame_strategy; diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c index ebc3a30fc1..4aa358a4e5 100644 --- a/libavcodec/ratecontrol.c +++ b/libavcodec/ratecontrol.c @@ -660,7 +660,7 @@ av_cold int ff_rate_control_init(MPVMainEncContext *const m) double bits = rcc->initial_cplx * (i / 10000.0 + 1.0) * s->mb_num; RateControlEntry rce; - if (i % ((s->gop_size + 3) / 4) == 0) + if (i % ((m->gop_size + 3) / 4) == 0) rce.pict_type = AV_PICTURE_TYPE_I; else if (i % (s->max_b_frames + 1)) rce.pict_type = AV_PICTURE_TYPE_B; @@ -1033,7 +1033,7 @@ float ff_rate_estimate_qscale(MPVMainEncContext *const m, int dry_run) av_assert0(q > 0.0); // FIXME type dependent blur like in 2-pass - if (pict_type == AV_PICTURE_TYPE_P || s->intra_only) { + if (pict_type == AV_PICTURE_TYPE_P || m->intra_only) { rcc->short_term_qsum *= a->qblur; rcc->short_term_qcount *= a->qblur; -- 2.45.2 [-- Attachment #25: 0024-avcodec-mpegvideo-Move-ratecontrol-adjacent-fields-t.patch --] [-- Type: text/x-patch, Size: 15567 bytes --] From f1ee64b9e2b800ff6e4f58efd161b9d3a6bcdefe Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sun, 2 Mar 2025 04:01:24 +0100 Subject: [PATCH 24/77] avcodec/mpegvideo: Move ratecontrol-adjacent fields to MPVMainEncContext Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpegvideo.h | 6 ------ libavcodec/mpegvideo_enc.c | 40 ++++++++++++++++++++------------------ libavcodec/mpegvideoenc.h | 15 ++++++++++---- libavcodec/ratecontrol.c | 18 +++++++++-------- libavcodec/snowenc.c | 4 ++-- 5 files changed, 44 insertions(+), 39 deletions(-) diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 3259c1117c..6c71d9bc01 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -101,7 +101,6 @@ typedef struct MpegEncContext { int h263_flv; ///< use flv H.263 header enum AVCodecID codec_id; /* see AV_CODEC_ID_xxx */ - int fixed_qscale; ///< fixed qscale if non zero int encoding; ///< true if we are encoding (vs decoding) int max_b_frames; ///< max number of B-frames for encoding int luma_elim_threshold; @@ -478,10 +477,6 @@ typedef struct MpegEncContext { me_cmp_func sse_cmp[2]; int (*sum_abs_dctelem)(const int16_t *block); - float border_masking; - int lmin, lmax; - int vbv_ignore_qmax; - /// Bitfield containing information which frames to reconstruct. int frame_reconstruction_bitfield; @@ -493,7 +488,6 @@ typedef struct MpegEncContext { int error_rate; - int scenechange_threshold; int noise_reduction; int intra_penalty; diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index cc3c7a745f..06314dc602 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -195,8 +195,10 @@ void ff_convert_matrix(MpegEncContext *s, int (*qmat)[64], } } -static inline void update_qscale(MpegEncContext *s) +static inline void update_qscale(MPVMainEncContext *const m) { + MpegEncContext *const s = &m->s; + if (s->q_scale_type == 1 && 0) { int i; int bestdiff=INT_MAX; @@ -205,7 +207,7 @@ static inline void update_qscale(MpegEncContext *s) for (i = 0 ; i<FF_ARRAY_ELEMS(ff_mpeg2_non_linear_qscale); i++) { int diff = FFABS((ff_mpeg2_non_linear_qscale[i]<<(FF_LAMBDA_SHIFT + 6)) - (int)s->lambda * 139); if (ff_mpeg2_non_linear_qscale[i] < s->avctx->qmin || - (ff_mpeg2_non_linear_qscale[i] > s->avctx->qmax && !s->vbv_ignore_qmax)) + (ff_mpeg2_non_linear_qscale[i] > s->avctx->qmax && !m->vbv_ignore_qmax)) continue; if (diff < bestdiff) { bestdiff = diff; @@ -216,7 +218,7 @@ static inline void update_qscale(MpegEncContext *s) } else { s->qscale = (s->lambda * 139 + FF_LAMBDA_SCALE * 64) >> (FF_LAMBDA_SHIFT + 7); - s->qscale = av_clip(s->qscale, s->avctx->qmin, s->vbv_ignore_qmax ? 31 : s->avctx->qmax); + s->qscale = av_clip(s->qscale, s->avctx->qmin, m->vbv_ignore_qmax ? 31 : s->avctx->qmax); } s->lambda2 = (s->lambda * s->lambda + FF_LAMBDA_SCALE / 2) >> @@ -507,16 +509,16 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) } /* Fixed QSCALE */ - s->fixed_qscale = !!(avctx->flags & AV_CODEC_FLAG_QSCALE); + m->fixed_qscale = !!(avctx->flags & AV_CODEC_FLAG_QSCALE); s->adaptive_quant = (avctx->lumi_masking || avctx->dark_masking || avctx->temporal_cplx_masking || avctx->spatial_cplx_masking || avctx->p_masking || - s->border_masking || + m->border_masking || (s->mpv_flags & FF_MPV_FLAG_QP_RD)) && - !s->fixed_qscale; + !m->fixed_qscale; s->loop_filter = !!(avctx->flags & AV_CODEC_FLAG_LOOP_FILTER); @@ -580,7 +582,7 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } - if (!s->fixed_qscale && + if (!m->fixed_qscale && avctx->bit_rate * av_q2d(avctx->time_base) > avctx->bit_rate_tolerance) { double nbt = avctx->bit_rate * av_q2d(avctx->time_base) * 5; @@ -675,7 +677,7 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } - if (s->scenechange_threshold < 1000000000 && + if (m->scenechange_threshold < 1000000000 && (avctx->flags & AV_CODEC_FLAG_CLOSED_GOP)) { av_log(avctx, AV_LOG_ERROR, "closed gop with scene change detection are not supported yet, " @@ -890,9 +892,9 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) s->frame_reconstruction_bitfield = 0; } - if (s->lmin > s->lmax) { - av_log(avctx, AV_LOG_WARNING, "Clipping lmin value to %d\n", s->lmax); - s->lmin = s->lmax; + if (m->lmin > m->lmax) { + av_log(avctx, AV_LOG_WARNING, "Clipping lmin value to %d\n", m->lmax); + m->lmin = m->lmax; } /* init */ @@ -1876,7 +1878,7 @@ int ff_mpv_encode_picture(AVCodecContext *avctx, AVPacket *pkt, ff_mpv_unref_picture(&s->cur_pic); - s->vbv_ignore_qmax = 0; + m->vbv_ignore_qmax = 0; m->picture_in_gop_number++; @@ -1935,7 +1937,7 @@ vbv_retry: int min_step = hq ? 1 : (1<<(FF_LAMBDA_SHIFT + 7))/139; if (put_bits_count(&s->pb) > max_size && - s->lambda < s->lmax) { + s->lambda < m->lmax) { m->next_lambda = FFMAX(s->lambda + min_step, s->lambda * (s->qscale + 1) / s->qscale); if (s->adaptive_quant) { @@ -1955,7 +1957,7 @@ vbv_retry: s->time_base = s->last_time_base; s->last_non_b_time = s->time - s->pp_time; } - s->vbv_ignore_qmax = 1; + m->vbv_ignore_qmax = 1; av_log(avctx, AV_LOG_VERBOSE, "reencoding frame due to VBV\n"); goto vbv_retry; } @@ -3616,7 +3618,7 @@ static int estimate_qp(MPVMainEncContext *const m, int dry_run) if (m->next_lambda){ s->cur_pic.ptr->f->quality = m->next_lambda; if(!dry_run) m->next_lambda= 0; - } else if (!s->fixed_qscale) { + } else if (!m->fixed_qscale) { int quality = ff_rate_estimate_qscale(m, dry_run); s->cur_pic.ptr->f->quality = quality; if (s->cur_pic.ptr->f->quality < 0) @@ -3643,7 +3645,7 @@ static int estimate_qp(MPVMainEncContext *const m, int dry_run) //FIXME broken }else s->lambda = s->cur_pic.ptr->f->quality; - update_qscale(s); + update_qscale(m); return 0; } @@ -3700,7 +3702,7 @@ static int encode_picture(MPVMainEncContext *const m, const AVPacket *pkt) s->lambda= s->last_lambda_for[s->pict_type]; else s->lambda= s->last_lambda_for[s->last_non_b_pict_type]; - update_qscale(s); + update_qscale(m); } ff_me_init_pic(s); @@ -3742,7 +3744,7 @@ static int encode_picture(MPVMainEncContext *const m, const AVPacket *pkt) for(i=0; i<s->mb_stride*s->mb_height; i++) s->mb_type[i]= CANDIDATE_MB_TYPE_INTRA; - if(!s->fixed_qscale){ + if (!m->fixed_qscale) { /* finding spatial complexity for I-frame rate control */ s->avctx->execute(s->avctx, mb_var_thread, &s->thread_context[0], NULL, context_count, sizeof(void*)); } @@ -3754,7 +3756,7 @@ static int encode_picture(MPVMainEncContext *const m, const AVPacket *pkt) s->mb_var_sum = s->me. mb_var_sum_temp; emms_c(); - if (s->me.scene_change_score > s->scenechange_threshold && + if (s->me.scene_change_score > m->scenechange_threshold && s->pict_type == AV_PICTURE_TYPE_P) { s->pict_type= AV_PICTURE_TYPE_I; for(i=0; i<s->mb_stride*s->mb_height; i++) diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h index a76d17f63e..1fbe5590df 100644 --- a/libavcodec/mpegvideoenc.h +++ b/libavcodec/mpegvideoenc.h @@ -39,6 +39,8 @@ typedef struct MPVMainEncContext { MpegEncContext s; ///< The main slicecontext + int scenechange_threshold; + int intra_only; ///< if true, only intra pictures are generated int gop_size; int picture_in_gop_number; ///< 0-> first pic in gop, ... @@ -61,6 +63,10 @@ typedef struct MPVMainEncContext { int b_sensitivity; int brd_scale; + float border_masking; + int lmin, lmax; + int vbv_ignore_qmax; + /* frame skip options */ int frame_skip_threshold; int frame_skip_factor; @@ -73,6 +79,7 @@ typedef struct MPVMainEncContext { int frame_bits; ///< bits used for the current frame int stuffing_bits; ///< bits used for stuffing int next_lambda; ///< next lambda used for retrying to encode a frame + int fixed_qscale; ///< fixed qscale if non zero RateControlContext rc_context; ///< contains stuff only accessed in ratecontrol.c } MPVMainEncContext; @@ -154,14 +161,14 @@ FF_MPV_OPT_CMP_FUNC, \ FF_RC_OFFSET(rc_eq), AV_OPT_TYPE_STRING, .flags = FF_MPV_OPT_FLAGS }, \ {"rc_init_cplx", "initial complexity for 1-pass encoding", FF_RC_OFFSET(initial_cplx), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, FF_MPV_OPT_FLAGS}, \ {"rc_buf_aggressivity", "currently useless", FF_RC_OFFSET(buffer_aggressivity), AV_OPT_TYPE_FLOAT, {.dbl = 1.0 }, -FLT_MAX, FLT_MAX, FF_MPV_OPT_FLAGS}, \ -{"border_mask", "increase the quantizer for macroblocks close to borders", FF_MPV_OFFSET(border_masking), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, FF_MPV_OPT_FLAGS}, \ -{"lmin", "minimum Lagrange factor (VBR)", FF_MPV_OFFSET(lmin), AV_OPT_TYPE_INT, {.i64 = 2*FF_QP2LAMBDA }, 0, INT_MAX, FF_MPV_OPT_FLAGS }, \ -{"lmax", "maximum Lagrange factor (VBR)", FF_MPV_OFFSET(lmax), AV_OPT_TYPE_INT, {.i64 = 31*FF_QP2LAMBDA }, 0, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"border_mask", "increase the quantizer for macroblocks close to borders", FF_MPV_MAIN_OFFSET(border_masking), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, FF_MPV_OPT_FLAGS}, \ +{"lmin", "minimum Lagrange factor (VBR)", FF_MPV_MAIN_OFFSET(lmin), AV_OPT_TYPE_INT, {.i64 = 2*FF_QP2LAMBDA }, 0, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"lmax", "maximum Lagrange factor (VBR)", FF_MPV_MAIN_OFFSET(lmax), AV_OPT_TYPE_INT, {.i64 = 31*FF_QP2LAMBDA }, 0, INT_MAX, FF_MPV_OPT_FLAGS }, \ {"skip_threshold", "Frame skip threshold", FF_MPV_MAIN_OFFSET(frame_skip_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ {"skip_factor", "Frame skip factor", FF_MPV_MAIN_OFFSET(frame_skip_factor), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ {"skip_exp", "Frame skip exponent", FF_MPV_MAIN_OFFSET(frame_skip_exp), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ {"skip_cmp", "Frame skip compare function", FF_MPV_MAIN_OFFSET(frame_skip_cmp), AV_OPT_TYPE_INT, {.i64 = FF_CMP_DCTMAX }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, .unit = "cmp_func" }, \ -{"sc_threshold", "Scene change threshold", FF_MPV_OFFSET(scenechange_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"sc_threshold", "Scene change threshold", FF_MPV_MAIN_OFFSET(scenechange_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ {"noise_reduction", "Noise reduction", FF_MPV_OFFSET(noise_reduction), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ {"ps", "RTP payload size in bytes", FF_MPV_OFFSET(rtp_payload_size), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c index 4aa358a4e5..f4df67aab0 100644 --- a/libavcodec/ratecontrol.c +++ b/libavcodec/ratecontrol.c @@ -142,10 +142,11 @@ static double get_diff_limited_q(MPVMainEncContext *m, const RateControlEntry *r /** * Get the qmin & qmax for pict_type. */ -static void get_qminmax(int *qmin_ret, int *qmax_ret, MpegEncContext *s, int pict_type) +static void get_qminmax(int *qmin_ret, int *qmax_ret, MPVMainEncContext *const m, int pict_type) { - int qmin = s->lmin; - int qmax = s->lmax; + MpegEncContext *const s = &m->s; + int qmin = m->lmin; + int qmax = m->lmax; av_assert0(qmin <= qmax); @@ -182,7 +183,7 @@ static double modify_qscale(MPVMainEncContext *const m, const RateControlEntry * const int pict_type = rce->new_pict_type; int qmin, qmax; - get_qminmax(&qmin, &qmax, s, pict_type); + get_qminmax(&qmin, &qmax, m, pict_type); /* modulation */ if (rcc->qmod_freq && @@ -784,15 +785,16 @@ static void update_predictor(Predictor *p, double q, double var, double size) } static void adaptive_quantization(RateControlContext *const rcc, - MpegEncContext *const s, double q) + MPVMainEncContext *const m, double q) { + MpegEncContext *const s = &m->s; int i; const float lumi_masking = s->avctx->lumi_masking / (128.0 * 128.0); const float dark_masking = s->avctx->dark_masking / (128.0 * 128.0); const float temp_cplx_masking = s->avctx->temporal_cplx_masking; const float spatial_cplx_masking = s->avctx->spatial_cplx_masking; const float p_masking = s->avctx->p_masking; - const float border_masking = s->border_masking; + const float border_masking = m->border_masking; float bits_sum = 0.0; float cplx_sum = 0.0; float *cplx_tab = rcc->cplx_tab; @@ -932,7 +934,7 @@ float ff_rate_estimate_qscale(MPVMainEncContext *const m, int dry_run) const int pict_type = s->pict_type; emms_c(); - get_qminmax(&qmin, &qmax, s, pict_type); + get_qminmax(&qmin, &qmax, m, pict_type); fps = get_fps(s->avctx); /* update predictors */ @@ -1068,7 +1070,7 @@ float ff_rate_estimate_qscale(MPVMainEncContext *const m, int dry_run) q = qmax; if (s->adaptive_quant) - adaptive_quantization(rcc, s, q); + adaptive_quantization(rcc, m, q); else q = (int)(q + 0.5); diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c index 830f6f5096..d974a12f6b 100644 --- a/libavcodec/snowenc.c +++ b/libavcodec/snowenc.c @@ -228,8 +228,8 @@ static av_cold int encode_init(AVCodecContext *avctx) mpv->avctx = avctx; mpv->bit_rate= avctx->bit_rate; - mpv->lmin = avctx->mb_lmin; - mpv->lmax = avctx->mb_lmax; + enc->m.lmin = avctx->mb_lmin; + enc->m.lmax = avctx->mb_lmax; mpv->mb_num = (avctx->width * avctx->height + 255) / 256; // For ratecontrol mpv->me.temp = -- 2.45.2 [-- Attachment #26: 0025-avcodec-mpegvideoenc-Disable-scenechange-threshold-o.patch --] [-- Type: text/x-patch, Size: 4563 bytes --] From bbea7caa24368f0543f8bff9395741d34201e83b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sat, 15 Mar 2025 06:29:35 +0100 Subject: [PATCH 25/77] avcodec/mpegvideoenc: Disable scenechange threshold opt for MJPEG, AMV It makes no sense for them. Also do the same for the mv0 flag. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpegvideoenc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h index 1fbe5590df..17bf50443d 100644 --- a/libavcodec/mpegvideoenc.h +++ b/libavcodec/mpegvideoenc.h @@ -142,7 +142,6 @@ FF_MPV_OPT_CMP_FUNC, \ { "qp_rd", "Use rate distortion optimization for qp selection", 0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_QP_RD }, 0, 0, FF_MPV_OPT_FLAGS, .unit = "mpv_flags" },\ { "cbp_rd", "use rate distortion optimization for CBP", 0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_CBP_RD }, 0, 0, FF_MPV_OPT_FLAGS, .unit = "mpv_flags" },\ { "naq", "normalize adaptive quantization", 0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_NAQ }, 0, 0, FF_MPV_OPT_FLAGS, .unit = "mpv_flags" },\ -{ "mv0", "always try a mb with mv=<0,0>", 0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_MV0 }, 0, 0, FF_MPV_OPT_FLAGS, .unit = "mpv_flags" },\ { "luma_elim_threshold", "single coefficient elimination threshold for luminance (negative values also consider dc coefficient)",\ FF_MPV_OFFSET(luma_elim_threshold), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS },\ { "chroma_elim_threshold", "single coefficient elimination threshold for chrominance (negative values also consider dc coefficient)",\ @@ -168,7 +167,6 @@ FF_MPV_OPT_CMP_FUNC, \ {"skip_factor", "Frame skip factor", FF_MPV_MAIN_OFFSET(frame_skip_factor), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ {"skip_exp", "Frame skip exponent", FF_MPV_MAIN_OFFSET(frame_skip_exp), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ {"skip_cmp", "Frame skip compare function", FF_MPV_MAIN_OFFSET(frame_skip_cmp), AV_OPT_TYPE_INT, {.i64 = FF_CMP_DCTMAX }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, .unit = "cmp_func" }, \ -{"sc_threshold", "Scene change threshold", FF_MPV_MAIN_OFFSET(scenechange_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ {"noise_reduction", "Noise reduction", FF_MPV_OFFSET(noise_reduction), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ {"ps", "RTP payload size in bytes", FF_MPV_OFFSET(rtp_payload_size), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ @@ -178,6 +176,7 @@ FF_MPV_OPT_CMP_FUNC, \ {"brd_scale", "Downscale frames for dynamic B-frame decision", FF_MPV_MAIN_OFFSET(brd_scale), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 3, FF_MPV_OPT_FLAGS }, #define FF_MPV_COMMON_MOTION_EST_OPTS \ +{ "mv0", "always try a mb with mv=<0,0>", 0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_MV0 }, 0, 0, FF_MPV_OPT_FLAGS, .unit = "mpv_flags" },\ {"motion_est", "motion estimation algorithm", FF_MPV_OFFSET(motion_est), AV_OPT_TYPE_INT, {.i64 = FF_ME_EPZS }, FF_ME_ZERO, FF_ME_XONE, FF_MPV_OPT_FLAGS, .unit = "motion_est" }, \ { "zero", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_ZERO }, 0, 0, FF_MPV_OPT_FLAGS, .unit = "motion_est" }, \ { "epzs", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_EPZS }, 0, 0, FF_MPV_OPT_FLAGS, .unit = "motion_est" }, \ @@ -185,6 +184,7 @@ FF_MPV_OPT_CMP_FUNC, \ {"mepc", "Motion estimation bitrate penalty compensation (1.0 = 256)", FF_MPV_OFFSET(me_penalty_compensation), AV_OPT_TYPE_INT, {.i64 = 256 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ {"mepre", "pre motion estimation", FF_MPV_OFFSET(me_pre), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ {"intra_penalty", "Penalty for intra blocks in block decision", FF_MPV_OFFSET(intra_penalty), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX/2, FF_MPV_OPT_FLAGS }, \ +{"sc_threshold", "Scene change threshold", FF_MPV_MAIN_OFFSET(scenechange_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ extern const AVClass ff_mpv_enc_class; -- 2.45.2 [-- Attachment #27: 0026-avcodec-mpegvideo-Move-macroblock-variance-stats-to-.patch --] [-- Type: text/x-patch, Size: 5948 bytes --] From 922e53781b442add21a381da7ef713e72ca8adb8 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Thu, 13 Oct 2022 02:15:46 +0200 Subject: [PATCH 26/77] avcodec/mpegvideo: Move macroblock-variance stats to MPVMainEncContext Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpegvideo.h | 2 -- libavcodec/mpegvideo_enc.c | 6 +++--- libavcodec/mpegvideoenc.h | 3 +++ libavcodec/ratecontrol.c | 16 ++++++++-------- libavcodec/snowenc.c | 8 ++++---- 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 6c71d9bc01..bdd3196060 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -230,8 +230,6 @@ typedef struct MpegEncContext { uint16_t *mb_var; ///< Table for MB variances uint16_t *mc_mb_var; ///< Table for motion compensated MB variances uint8_t *mb_mean; ///< Table for MB luminance - int64_t mb_var_sum; ///< sum of MB variance for current frame - int64_t mc_mb_var_sum; ///< motion compensated MB variance for current frame uint64_t encoding_error[MPV_MAX_PLANES]; int motion_est; ///< ME algorithm diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 06314dc602..44bad9eb52 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -3752,8 +3752,8 @@ static int encode_picture(MPVMainEncContext *const m, const AVPacket *pkt) for(i=1; i<context_count; i++){ merge_context_after_me(s, s->thread_context[i]); } - s->mc_mb_var_sum = s->me.mc_mb_var_sum_temp; - s->mb_var_sum = s->me. mb_var_sum_temp; + m->mc_mb_var_sum = s->me.mc_mb_var_sum_temp; + m->mb_var_sum = s->me. mb_var_sum_temp; emms_c(); if (s->me.scene_change_score > m->scenechange_threshold && @@ -3764,7 +3764,7 @@ static int encode_picture(MPVMainEncContext *const m, const AVPacket *pkt) if (s->msmpeg4_version >= MSMP4_V3) s->no_rounding=1; ff_dlog(s->avctx, "Scene change detected, encoding as I Frame %"PRId64" %"PRId64"\n", - s->mb_var_sum, s->mc_mb_var_sum); + m->mb_var_sum, m->mc_mb_var_sum); } if(!s->umvplus){ diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h index 17bf50443d..283fa8f705 100644 --- a/libavcodec/mpegvideoenc.h +++ b/libavcodec/mpegvideoenc.h @@ -81,6 +81,9 @@ typedef struct MPVMainEncContext { int next_lambda; ///< next lambda used for retrying to encode a frame int fixed_qscale; ///< fixed qscale if non zero RateControlContext rc_context; ///< contains stuff only accessed in ratecontrol.c + + int64_t mb_var_sum; ///< sum of MB variance for current frame + int64_t mc_mb_var_sum; ///< motion compensated MB variance for current frame } MPVMainEncContext; #define MAX_FCODE 7 diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c index f4df67aab0..9c5d34dfde 100644 --- a/libavcodec/ratecontrol.c +++ b/libavcodec/ratecontrol.c @@ -51,8 +51,8 @@ void ff_write_pass1_stats(MPVMainEncContext *const m) s->misc_bits, s->f_code, s->b_code, - s->mc_mb_var_sum, - s->mb_var_sum, + m->mc_mb_var_sum, + m->mb_var_sum, s->i_count, s->header_bits); } @@ -986,7 +986,7 @@ float ff_rate_estimate_qscale(MPVMainEncContext *const m, int dry_run) if (br_compensation <= 0.0) br_compensation = 0.001; - var = pict_type == AV_PICTURE_TYPE_I ? s->mb_var_sum : s->mc_mb_var_sum; + var = pict_type == AV_PICTURE_TYPE_I ? m->mb_var_sum : m->mc_mb_var_sum; short_term_q = 0; /* avoid warning */ if (s->avctx->flags & AV_CODEC_FLAG_PASS2) { @@ -999,8 +999,8 @@ float ff_rate_estimate_qscale(MPVMainEncContext *const m, int dry_run) } else { rce->pict_type = rce->new_pict_type = pict_type; - rce->mc_mb_var_sum = s->mc_mb_var_sum; - rce->mb_var_sum = s->mb_var_sum; + rce->mc_mb_var_sum = m->mc_mb_var_sum; + rce->mb_var_sum = m->mb_var_sum; rce->qscale = FF_QP2LAMBDA * 2; rce->f_code = s->f_code; rce->b_code = s->b_code; @@ -1060,7 +1060,7 @@ float ff_rate_estimate_qscale(MPVMainEncContext *const m, int dry_run) qmin, q, qmax, picture_number, wanted_bits / 1000, m->total_bits / 1000, br_compensation, short_term_q, m->frame_bits, - s->mb_var_sum, s->mc_mb_var_sum, + m->mb_var_sum, m->mc_mb_var_sum, s->bit_rate / 1000, (int)fps); } @@ -1076,8 +1076,8 @@ float ff_rate_estimate_qscale(MPVMainEncContext *const m, int dry_run) if (!dry_run) { rcc->last_qscale = q; - rcc->last_mc_mb_var_sum = s->mc_mb_var_sum; - rcc->last_mb_var_sum = s->mb_var_sum; + rcc->last_mc_mb_var_sum = m->mc_mb_var_sum; + rcc->last_mb_var_sum = m->mb_var_sum; } return q; } diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c index d974a12f6b..e074e878d6 100644 --- a/libavcodec/snowenc.c +++ b/libavcodec/snowenc.c @@ -1708,11 +1708,11 @@ static int ratecontrol_1pass(SnowEncContext *enc, AVFrame *pict) coef_sum = (uint64_t)coef_sum * coef_sum >> 16; if(pict->pict_type == AV_PICTURE_TYPE_I){ - enc->m.s.mb_var_sum = coef_sum; - enc->m.s.mc_mb_var_sum = 0; + enc->m.mb_var_sum = coef_sum; + enc->m.mc_mb_var_sum = 0; }else{ - enc->m.s.mc_mb_var_sum = coef_sum; - enc->m.s.mb_var_sum = 0; + enc->m.mc_mb_var_sum = coef_sum; + enc->m.mb_var_sum = 0; } pict->quality= ff_rate_estimate_qscale(&enc->m, 1); -- 2.45.2 [-- Attachment #28: 0027-avcodec-mpegvideo-Move-header_bits-to-MPVMainEncCont.patch --] [-- Type: text/x-patch, Size: 5051 bytes --] From 626b8ecf0e9767a11ca419ab0e56a2926c744dd4 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sat, 29 Jan 2022 05:34:14 +0100 Subject: [PATCH 27/77] avcodec/mpegvideo: Move header_bits to MPVMainEncContext The header is always written by the main thread, so it is not surprising that header_bits can be moved to MPVMainEncContext as well. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mjpegenc.c | 10 +++++++--- libavcodec/mpegvideo.h | 1 - libavcodec/mpegvideo_enc.c | 6 +++--- libavcodec/mpegvideoenc.h | 1 + libavcodec/ratecontrol.c | 2 +- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c index 6f9818baf2..a77a703f53 100644 --- a/libavcodec/mjpegenc.c +++ b/libavcodec/mjpegenc.c @@ -119,8 +119,9 @@ void ff_mjpeg_amv_encode_picture_header(MpegEncContext *s) * * @param s The MpegEncContext. */ -static void mjpeg_encode_picture_frame(MpegEncContext *s) +static void mjpeg_encode_picture_frame(MPVMainEncContext *const main) { + MpegEncContext *const s = &main->s; int nbits, code, table_id; MJpegContext *m = s->mjpeg_ctx; uint8_t *huff_size[4] = { m->huff_size_dc_luminance, @@ -134,7 +135,7 @@ static void mjpeg_encode_picture_frame(MpegEncContext *s) size_t total_bits = 0; size_t bytes_needed; - s->header_bits = get_bits_diff(s); + main->header_bits = get_bits_diff(s); // Estimate the total size first for (int i = 0; i < m->huff_ncode; i++) { table_id = m->huff_buffer[i].table_id; @@ -240,6 +241,9 @@ int ff_mjpeg_encode_stuffing(MpegEncContext *s) #if CONFIG_MJPEG_ENCODER if (m->huffman == HUFFMAN_TABLE_OPTIMAL) { + /* HUFFMAN_TABLE_OPTIMAL is incompatible with slice threading, + * therefore the following cast is allowed. */ + MPVMainEncContext *const main = (MPVMainEncContext*)s; mjpeg_build_optimal_huffman(m); @@ -253,7 +257,7 @@ int ff_mjpeg_encode_stuffing(MpegEncContext *s) s->intra_chroma_ac_vlc_last_length = m->uni_chroma_ac_vlc_len; mjpeg_encode_picture_header(s); - mjpeg_encode_picture_frame(s); + mjpeg_encode_picture_frame(main); } #endif diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index bdd3196060..fcc51af41a 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -310,7 +310,6 @@ typedef struct MpegEncContext { /* statistics, used for 2-pass encoding */ int mv_bits; - int header_bits; int i_tex_bits; int p_tex_bits; int i_count; diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 44bad9eb52..d4f4f825ff 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -1928,7 +1928,7 @@ vbv_retry: frame_end(m); if ((CONFIG_MJPEG_ENCODER || CONFIG_AMV_ENCODER) && s->out_format == FMT_MJPEG) - ff_mjpeg_encode_picture_trailer(&s->pb, s->header_bits); + ff_mjpeg_encode_picture_trailer(&s->pb, m->header_bits); if (avctx->rc_buffer_size) { RateControlContext *rcc = &m->rc_context; @@ -1976,7 +1976,7 @@ vbv_retry: s->pict_type); if (avctx->flags & AV_CODEC_FLAG_PASS1) - assert(put_bits_count(&s->pb) == s->header_bits + s->mv_bits + + assert(put_bits_count(&s->pb) == m->header_bits + s->mv_bits + s->misc_bits + s->i_tex_bits + s->p_tex_bits); flush_put_bits(&s->pb); @@ -3933,7 +3933,7 @@ static int encode_picture(MPVMainEncContext *const m, const AVPacket *pkt) av_assert0(0); } bits= put_bits_count(&s->pb); - s->header_bits= bits - s->last_bits; + m->header_bits = bits - s->last_bits; for(i=1; i<context_count; i++){ update_duplicate_context_after_me(s->thread_context[i], s); diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h index 283fa8f705..9c70fe6d71 100644 --- a/libavcodec/mpegvideoenc.h +++ b/libavcodec/mpegvideoenc.h @@ -77,6 +77,7 @@ typedef struct MPVMainEncContext { /* bit rate control */ int64_t total_bits; int frame_bits; ///< bits used for the current frame + int header_bits; int stuffing_bits; ///< bits used for stuffing int next_lambda; ///< next lambda used for retrying to encode a frame int fixed_qscale; ///< fixed qscale if non zero diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c index 9c5d34dfde..895e557877 100644 --- a/libavcodec/ratecontrol.c +++ b/libavcodec/ratecontrol.c @@ -54,7 +54,7 @@ void ff_write_pass1_stats(MPVMainEncContext *const m) m->mc_mb_var_sum, m->mb_var_sum, s->i_count, - s->header_bits); + m->header_bits); } static AVRational get_fpsQ(AVCodecContext *avctx) -- 2.45.2 [-- Attachment #29: 0028-avcodec-speedhqenc-Move-speedhq_encode_init-down.patch --] [-- Type: text/x-patch, Size: 4100 bytes --] From 7522f0eb03977271057f67252b0f70393fb7d00c Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Mon, 3 Mar 2025 19:24:25 +0100 Subject: [PATCH 28/77] avcodec/speedhqenc: Move speedhq_encode_init() down Will avoid forward declarations later. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/speedhqenc.c | 102 ++++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/libavcodec/speedhqenc.c b/libavcodec/speedhqenc.c index 2e09016935..daccd0c3bf 100644 --- a/libavcodec/speedhqenc.c +++ b/libavcodec/speedhqenc.c @@ -95,57 +95,6 @@ static av_cold void speedhq_init_static_data(void) ff_speedhq_vlc_table, uni_speedhq_ac_vlc_len); } -static av_cold int speedhq_encode_init(AVCodecContext *avctx) -{ - static AVOnce init_static_once = AV_ONCE_INIT; - MpegEncContext *const s = avctx->priv_data; - int ret; - - if (avctx->width > 65500 || avctx->height > 65500) { - av_log(avctx, AV_LOG_ERROR, "SpeedHQ does not support resolutions above 65500x65500\n"); - return AVERROR(EINVAL); - } - - // border is not implemented correctly at the moment, see ticket #10078 - if (avctx->width % 16) { - av_log(avctx, AV_LOG_ERROR, "width must be a multiple of 16\n"); - return AVERROR_PATCHWELCOME; - } - - switch (avctx->pix_fmt) { - case AV_PIX_FMT_YUV420P: - avctx->codec_tag = MKTAG('S','H','Q','0'); - break; - case AV_PIX_FMT_YUV422P: - avctx->codec_tag = MKTAG('S','H','Q','2'); - break; - case AV_PIX_FMT_YUV444P: - avctx->codec_tag = MKTAG('S','H','Q','4'); - break; - default: - av_assert0(0); - } - - s->min_qcoeff = -2048; - s->max_qcoeff = 2047; - - s->intra_ac_vlc_length = - s->intra_ac_vlc_last_length = - s->intra_chroma_ac_vlc_length = - s->intra_chroma_ac_vlc_last_length = uni_speedhq_ac_vlc_len; - - s->y_dc_scale_table = - s->c_dc_scale_table = ff_mpeg12_dc_scale_table[3]; - - ret = ff_mpv_encode_init(avctx); - if (ret < 0) - return ret; - - ff_thread_once(&init_static_once, speedhq_init_static_data); - - return 0; -} - void ff_speedhq_encode_picture_header(MpegEncContext *s) { SpeedHQEncContext *ctx = (SpeedHQEncContext*)s; @@ -278,6 +227,57 @@ void ff_speedhq_encode_mb(MpegEncContext *s, int16_t block[12][64]) s->i_tex_bits += get_bits_diff(s); } +static av_cold int speedhq_encode_init(AVCodecContext *avctx) +{ + static AVOnce init_static_once = AV_ONCE_INIT; + MpegEncContext *const s = avctx->priv_data; + int ret; + + if (avctx->width > 65500 || avctx->height > 65500) { + av_log(avctx, AV_LOG_ERROR, "SpeedHQ does not support resolutions above 65500x65500\n"); + return AVERROR(EINVAL); + } + + // border is not implemented correctly at the moment, see ticket #10078 + if (avctx->width % 16) { + av_log(avctx, AV_LOG_ERROR, "width must be a multiple of 16\n"); + return AVERROR_PATCHWELCOME; + } + + switch (avctx->pix_fmt) { + case AV_PIX_FMT_YUV420P: + avctx->codec_tag = MKTAG('S','H','Q','0'); + break; + case AV_PIX_FMT_YUV422P: + avctx->codec_tag = MKTAG('S','H','Q','2'); + break; + case AV_PIX_FMT_YUV444P: + avctx->codec_tag = MKTAG('S','H','Q','4'); + break; + default: + av_assert0(0); + } + + s->min_qcoeff = -2048; + s->max_qcoeff = 2047; + + s->intra_ac_vlc_length = + s->intra_ac_vlc_last_length = + s->intra_chroma_ac_vlc_length = + s->intra_chroma_ac_vlc_last_length = uni_speedhq_ac_vlc_len; + + s->y_dc_scale_table = + s->c_dc_scale_table = ff_mpeg12_dc_scale_table[3]; + + ret = ff_mpv_encode_init(avctx); + if (ret < 0) + return ret; + + ff_thread_once(&init_static_once, speedhq_init_static_data); + + return 0; +} + const FFCodec ff_speedhq_encoder = { .p.name = "speedhq", CODEC_LONG_NAME("NewTek SpeedHQ"), -- 2.45.2 [-- Attachment #30: 0029-avcodec-wmv2enc-Move-wmv2_encode_init-down.patch --] [-- Type: text/x-patch, Size: 2252 bytes --] From c32a691d3a2215fa6b714aa0d73b1c494aa99aed Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Mon, 3 Mar 2025 19:28:41 +0100 Subject: [PATCH 29/77] avcodec/wmv2enc: Move wmv2_encode_init() down Will avoid forward declarations later. While just at it, forward ff_mpv_encode_init() errors. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/wmv2enc.c | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/libavcodec/wmv2enc.c b/libavcodec/wmv2enc.c index 33569a6d39..55fcc91484 100644 --- a/libavcodec/wmv2enc.c +++ b/libavcodec/wmv2enc.c @@ -73,27 +73,6 @@ static int encode_ext_header(WMV2EncContext *w) return 0; } -static av_cold int wmv2_encode_init(AVCodecContext *avctx) -{ - WMV2EncContext *const w = avctx->priv_data; - MpegEncContext *const s = &w->msmpeg4.m.s; - - s->private_ctx = &w->common; - if (ff_mpv_encode_init(avctx) < 0) - return -1; - - ff_wmv2_common_init(s); - - avctx->extradata_size = WMV2_EXTRADATA_SIZE; - avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!avctx->extradata) - return AVERROR(ENOMEM); - - encode_ext_header(w); - - return 0; -} - int ff_wmv2_encode_picture_header(MpegEncContext *s) { WMV2EncContext *const w = (WMV2EncContext *) s; @@ -237,6 +216,29 @@ void ff_wmv2_encode_mb(MpegEncContext *s, int16_t block[6][64], s->p_tex_bits += get_bits_diff(s); } +static av_cold int wmv2_encode_init(AVCodecContext *avctx) +{ + WMV2EncContext *const w = avctx->priv_data; + MpegEncContext *const s = &w->msmpeg4.m.s; + int ret; + + s->private_ctx = &w->common; + ret = ff_mpv_encode_init(avctx); + if (ret < 0) + return ret; + + ff_wmv2_common_init(s); + + avctx->extradata_size = WMV2_EXTRADATA_SIZE; + avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) + return AVERROR(ENOMEM); + + encode_ext_header(w); + + return 0; +} + const FFCodec ff_wmv2_encoder = { .p.name = "wmv2", CODEC_LONG_NAME("Windows Media Video 8"), -- 2.45.2 [-- Attachment #31: 0030-avcodec-mpegvideo_enc-Use-function-ptr-for-encode_pi.patch --] [-- Type: text/x-patch, Size: 23570 bytes --] From 6408dfb58ffd0f06f85ce0e3b2366675cf9e9539 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Mon, 3 Mar 2025 23:35:01 +0100 Subject: [PATCH 30/77] avcodec/mpegvideo_enc: Use function ptr for encode_picture_header This gets rid of a switch and (in case of FMT_H263) several ifs. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/flvenc.c | 5 +++- libavcodec/flvenc.h | 5 ++-- libavcodec/h261enc.c | 8 ++++-- libavcodec/h261enc.h | 1 - libavcodec/h263enc.h | 3 +- libavcodec/ituh263enc.c | 13 +++++++-- libavcodec/mjpegenc.c | 12 +++++--- libavcodec/mjpegenc.h | 1 - libavcodec/mpeg12enc.c | 6 +++- libavcodec/mpeg12enc.h | 3 +- libavcodec/mpeg4videoenc.c | 7 +++-- libavcodec/mpeg4videoenc.h | 4 +-- libavcodec/mpegvideo_enc.c | 58 ++++++++------------------------------ libavcodec/mpegvideoenc.h | 2 ++ libavcodec/msmpeg4enc.c | 40 +++++++++++++++----------- libavcodec/msmpeg4enc.h | 3 +- libavcodec/rv10enc.c | 3 +- libavcodec/rv10enc.h | 6 ++-- libavcodec/rv20enc.c | 6 +++- libavcodec/speedhqenc.c | 12 ++++++-- libavcodec/speedhqenc.h | 1 - libavcodec/wmv2enc.c | 6 ++-- libavcodec/wmv2enc.h | 1 - 23 files changed, 107 insertions(+), 99 deletions(-) diff --git a/libavcodec/flvenc.c b/libavcodec/flvenc.c index 0cd20f026d..b4a30fe558 100644 --- a/libavcodec/flvenc.c +++ b/libavcodec/flvenc.c @@ -23,8 +23,9 @@ #include "mpegvideo.h" #include "mpegvideoenc.h" -void ff_flv_encode_picture_header(MpegEncContext *s) +int ff_flv_encode_picture_header(MPVMainEncContext *const m) { + MpegEncContext *const s = &m->s; int format; align_put_bits(&s->pb); @@ -61,6 +62,8 @@ void ff_flv_encode_picture_header(MpegEncContext *s) put_bits(&s->pb, 1, 1); /* DeblockingFlag: on */ put_bits(&s->pb, 5, s->qscale); /* Quantizer */ put_bits(&s->pb, 1, 0); /* ExtraInformation */ + + return 0; } void ff_flv2_encode_ac_esc(PutBitContext *pb, int slevel, int level, diff --git a/libavcodec/flvenc.h b/libavcodec/flvenc.h index 1ecbb46b17..3dc7480376 100644 --- a/libavcodec/flvenc.h +++ b/libavcodec/flvenc.h @@ -21,10 +21,11 @@ #ifndef AVCODEC_FLVENC_H #define AVCODEC_FLVENC_H -#include "mpegvideo.h" #include "put_bits.h" -void ff_flv_encode_picture_header(MpegEncContext *s); +typedef struct MPVMainEncContext MPVMainEncContext; + +int ff_flv_encode_picture_header(MPVMainEncContext *const m); void ff_flv2_encode_ac_esc(PutBitContext *pb, int slevel, int level, int run, int last); diff --git a/libavcodec/h261enc.c b/libavcodec/h261enc.c index 36c50db6df..bfe805bcdf 100644 --- a/libavcodec/h261enc.c +++ b/libavcodec/h261enc.c @@ -66,9 +66,10 @@ typedef struct H261EncContext { } format; } H261EncContext; -void ff_h261_encode_picture_header(MpegEncContext *s) +static int h261_encode_picture_header(MPVMainEncContext *const m) { - H261EncContext *const h = (H261EncContext *)s; + H261EncContext *const h = (H261EncContext *)m; + MpegEncContext *const s = &h->s.s; int temp_ref; align_put_bits(&s->pb); @@ -94,6 +95,8 @@ void ff_h261_encode_picture_header(MpegEncContext *s) put_bits(&s->pb, 1, 0); /* no PEI */ h->gob_number = h->format - 1; s->mb_skip_run = 0; + + return 0; } /** @@ -370,6 +373,7 @@ static av_cold int h261_encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } s->private_ctx = &h->common; + h->s.encode_picture_header = h261_encode_picture_header; s->min_qcoeff = -127; s->max_qcoeff = 127; diff --git a/libavcodec/h261enc.h b/libavcodec/h261enc.h index 7877d8aa9d..092363b6f3 100644 --- a/libavcodec/h261enc.h +++ b/libavcodec/h261enc.h @@ -33,6 +33,5 @@ void ff_h261_reorder_mb_index(MpegEncContext *s); void ff_h261_encode_mb(MpegEncContext *s, int16_t block[6][64], int motion_x, int motion_y); -void ff_h261_encode_picture_header(MpegEncContext *s); #endif diff --git a/libavcodec/h263enc.h b/libavcodec/h263enc.h index 71e30931aa..29a785dfeb 100644 --- a/libavcodec/h263enc.h +++ b/libavcodec/h263enc.h @@ -26,8 +26,7 @@ const uint8_t (*ff_h263_get_mv_penalty(void))[MAX_DMV*2+1]; -void ff_h263_encode_init(MpegEncContext *s); -void ff_h263_encode_picture_header(MpegEncContext *s); +void ff_h263_encode_init(MPVMainEncContext *m); void ff_h263_encode_gob_header(MpegEncContext * s, int mb_line); void ff_h263_encode_mb(MpegEncContext *s, int16_t block[6][64], diff --git a/libavcodec/ituh263enc.c b/libavcodec/ituh263enc.c index 825b398455..c82e0ceffd 100644 --- a/libavcodec/ituh263enc.c +++ b/libavcodec/ituh263enc.c @@ -221,8 +221,9 @@ av_const int ff_h263_aspect_to_info(AVRational aspect){ return FF_ASPECT_EXTENDED; } -void ff_h263_encode_picture_header(MpegEncContext * s) +static int h263_encode_picture_header(MPVMainEncContext *const m) { + MpegEncContext *const s = &m->s; int format, coded_frame_rate, coded_frame_rate_base, i, temp_ref; int best_clock_code=1; int best_divisor=60; @@ -354,6 +355,8 @@ void ff_h263_encode_picture_header(MpegEncContext * s) put_bits(&s->pb, 1, 1); } + + return 0; } /** @@ -819,8 +822,10 @@ void ff_h263_update_mb(MpegEncContext *s) ff_h263_update_motion_val(s); } -av_cold void ff_h263_encode_init(MpegEncContext *s) +av_cold void ff_h263_encode_init(MPVMainEncContext *const m) { + MpegEncContext *const s = &m->s; + s->me.mv_penalty = ff_h263_get_mv_penalty(); // FIXME exact table for MSMPEG4 & H.263+ s->intra_ac_vlc_length =s->inter_ac_vlc_length = uni_h263_inter_rl_len; @@ -854,6 +859,7 @@ av_cold void ff_h263_encode_init(MpegEncContext *s) break; // Note for MPEG-4 & H.263 the dc-scale table will be set per frame as needed later case AV_CODEC_ID_FLV1: + m->encode_picture_header = ff_flv_encode_picture_header; if (s->h263_flv > 1) { s->min_qcoeff= -1023; s->max_qcoeff= 1023; @@ -866,6 +872,9 @@ av_cold void ff_h263_encode_init(MpegEncContext *s) s->min_qcoeff= -127; s->max_qcoeff= 127; } + // H.263, H.263+; will be overwritten for MSMPEG-4 later + if (!m->encode_picture_header) + m->encode_picture_header = h263_encode_picture_header; ff_h263dsp_init(&s->h263dsp); } diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c index a77a703f53..7706f52148 100644 --- a/libavcodec/mjpegenc.c +++ b/libavcodec/mjpegenc.c @@ -104,13 +104,16 @@ static void mjpeg_encode_picture_header(MpegEncContext *s) s->thread_context[i]->esc_pos = 0; } -void ff_mjpeg_amv_encode_picture_header(MpegEncContext *s) +static int mjpeg_amv_encode_picture_header(MPVMainEncContext *const m) { - MJPEGEncContext *const m = (MJPEGEncContext*)s; - av_assert2(s->mjpeg_ctx == &m->mjpeg); + MJPEGEncContext *const m2 = (MJPEGEncContext*)m; + MpegEncContext *const s = &m->s; + av_assert2(s->mjpeg_ctx == &m2->mjpeg); /* s->huffman == HUFFMAN_TABLE_OPTIMAL can only be true for MJPEG. */ - if (!CONFIG_MJPEG_ENCODER || m->mjpeg.huffman != HUFFMAN_TABLE_OPTIMAL) + if (!CONFIG_MJPEG_ENCODER || m2->mjpeg.huffman != HUFFMAN_TABLE_OPTIMAL) mjpeg_encode_picture_header(s); + + return 0; } #if CONFIG_MJPEG_ENCODER @@ -309,6 +312,7 @@ static av_cold int mjpeg_encode_init(AVCodecContext *avctx) int ret; s->mjpeg_ctx = m; + m2->mpeg.encode_picture_header = mjpeg_amv_encode_picture_header; if (s->mpv_flags & FF_MPV_FLAG_QP_RD) { // Used to produce garbage with MJPEG. diff --git a/libavcodec/mjpegenc.h b/libavcodec/mjpegenc.h index 2c98de057a..9610656aaa 100644 --- a/libavcodec/mjpegenc.h +++ b/libavcodec/mjpegenc.h @@ -94,7 +94,6 @@ static inline void put_marker(PutBitContext *p, enum JpegMarker code) typedef struct MpegEncContext MpegEncContext; -void ff_mjpeg_amv_encode_picture_header(MpegEncContext *s); void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[12][64]); int ff_mjpeg_encode_stuffing(MpegEncContext *s); diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index ed2c63086f..f28a41f5ff 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -333,7 +333,7 @@ void ff_mpeg1_encode_slice_header(MpegEncContext *s) put_bits(&s->pb, 1, 0); } -void ff_mpeg1_encode_picture_header(MPVMainEncContext *const m) +static int mpeg1_encode_picture_header(MPVMainEncContext *const m) { MPEG12EncContext *const mpeg12 = (MPEG12EncContext*)m; MpegEncContext *const s = &m->s; @@ -485,6 +485,8 @@ void ff_mpeg1_encode_picture_header(MPVMainEncContext *const m) s->mb_y = 0; ff_mpeg1_encode_slice_header(s); + + return 0; } static inline void put_mb_modes(MpegEncContext *s, int n, int bits, @@ -1108,6 +1110,8 @@ static av_cold int encode_init(AVCodecContext *avctx) } } + m->encode_picture_header = mpeg1_encode_picture_header; + s->me.mv_penalty = mv_penalty; s->fcode_tab = fcode_tab + MAX_MV; if (avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO) { diff --git a/libavcodec/mpeg12enc.h b/libavcodec/mpeg12enc.h index fa1504177a..6c3709bbff 100644 --- a/libavcodec/mpeg12enc.h +++ b/libavcodec/mpeg12enc.h @@ -24,10 +24,9 @@ #include <stdint.h> -#include "mpegvideoenc.h" +#include "mpegvideo.h" #include "mpegvideodata.h" -void ff_mpeg1_encode_picture_header(MPVMainEncContext *m); void ff_mpeg1_encode_mb(MpegEncContext *s, int16_t block[8][64], int motion_x, int motion_y); void ff_mpeg1_encode_slice_header(MpegEncContext *s); diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c index c265316ed6..f34ea1fcb4 100644 --- a/libavcodec/mpeg4videoenc.c +++ b/libavcodec/mpeg4videoenc.c @@ -1062,7 +1062,7 @@ static void mpeg4_encode_vol_header(Mpeg4EncContext *const m4, } /* write MPEG-4 VOP header */ -int ff_mpeg4_encode_picture_header(MPVMainEncContext *const m) +static int mpeg4_encode_picture_header(MPVMainEncContext *const m) { Mpeg4EncContext *const m4 = mainctx_to_mpeg4(m); MpegEncContext *const s = &m->s; @@ -1291,7 +1291,8 @@ static av_cold int encode_init(AVCodecContext *avctx) { static AVOnce init_static_once = AV_ONCE_INIT; Mpeg4EncContext *const m4 = avctx->priv_data; - MpegEncContext *const s = &m4->m.s; + MPVMainEncContext *const m = &m4->m; + MpegEncContext *const s = &m->s; int ret; if (avctx->width >= (1<<13) || avctx->height >= (1<<13)) { @@ -1299,6 +1300,8 @@ static av_cold int encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } + m->encode_picture_header = mpeg4_encode_picture_header; + ff_qpeldsp_init(&s->qdsp); if ((ret = ff_mpv_encode_init(avctx)) < 0) return ret; diff --git a/libavcodec/mpeg4videoenc.h b/libavcodec/mpeg4videoenc.h index 1c53ce4ede..4565a518b2 100644 --- a/libavcodec/mpeg4videoenc.h +++ b/libavcodec/mpeg4videoenc.h @@ -25,14 +25,14 @@ #include <stdint.h> -#include "mpegvideoenc.h" #include "put_bits.h" +typedef struct MpegEncContext MpegEncContext; + void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], int motion_x, int motion_y); void ff_set_mpeg4_time(MpegEncContext *s); -int ff_mpeg4_encode_picture_header(MPVMainEncContext *m); void ff_mpeg4_encode_video_packet_header(MpegEncContext *s); void ff_mpeg4_stuffing(PutBitContext *pbc); diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index d4f4f825ff..03a8ae2687 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -66,7 +66,6 @@ #include "qpeldsp.h" #include "faandct.h" #include "aandcttab.h" -#include "flvenc.h" #include "mpeg4video.h" #include "mpeg4videodata.h" #include "mpeg4videoenc.h" @@ -809,12 +808,17 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) avctx->delay = 0; s->low_delay = 1; break; +#if CONFIG_RV10_ENCODER case AV_CODEC_ID_RV10: + m->encode_picture_header = ff_rv10_encode_picture_header; s->out_format = FMT_H263; avctx->delay = 0; s->low_delay = 1; break; +#endif +#if CONFIG_RV20_ENCODER case AV_CODEC_ID_RV20: + m->encode_picture_header = ff_rv20_encode_picture_header; s->out_format = FMT_H263; avctx->delay = 0; s->low_delay = 1; @@ -824,6 +828,7 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) s->loop_filter = 1; s->unrestricted_mv = 0; break; +#endif case AV_CODEC_ID_MPEG4: s->out_format = FMT_H263; s->h263_pred = 1; @@ -996,10 +1001,10 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) } if (CONFIG_H263_ENCODER && s->out_format == FMT_H263) { - ff_h263_encode_init(s); + ff_h263_encode_init(m); #if CONFIG_MSMPEG4ENC if (s->msmpeg4_version != MSMP4_UNUSED) - ff_msmpeg4_encode_init(s); + ff_msmpeg4_encode_init(m); #endif } @@ -3888,50 +3893,9 @@ static int encode_picture(MPVMainEncContext *const m, const AVPacket *pkt) s->mb_x = s->mb_y = 0; s->last_bits= put_bits_count(&s->pb); - switch(s->out_format) { -#if CONFIG_MJPEG_ENCODER || CONFIG_AMV_ENCODER - case FMT_MJPEG: - ff_mjpeg_amv_encode_picture_header(s); - break; -#endif - case FMT_SPEEDHQ: - if (CONFIG_SPEEDHQ_ENCODER) - ff_speedhq_encode_picture_header(s); - break; - case FMT_H261: - if (CONFIG_H261_ENCODER) - ff_h261_encode_picture_header(s); - break; - case FMT_H263: - if (CONFIG_WMV2_ENCODER && s->codec_id == AV_CODEC_ID_WMV2) - ff_wmv2_encode_picture_header(s); -#if CONFIG_MSMPEG4ENC - else if (s->msmpeg4_version != MSMP4_UNUSED) - ff_msmpeg4_encode_picture_header(s); -#endif - else if (CONFIG_MPEG4_ENCODER && s->h263_pred) { - ret = ff_mpeg4_encode_picture_header(m); - if (ret < 0) - return ret; - } else if (CONFIG_RV10_ENCODER && s->codec_id == AV_CODEC_ID_RV10) { - ret = ff_rv10_encode_picture_header(s); - if (ret < 0) - return ret; - } - else if (CONFIG_RV20_ENCODER && s->codec_id == AV_CODEC_ID_RV20) - ff_rv20_encode_picture_header(s); - else if (CONFIG_FLV_ENCODER && s->codec_id == AV_CODEC_ID_FLV1) - ff_flv_encode_picture_header(s); - else if (CONFIG_H263_ENCODER) - ff_h263_encode_picture_header(s); - break; - case FMT_MPEG1: - if (CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER) - ff_mpeg1_encode_picture_header(m); - break; - default: - av_assert0(0); - } + ret = m->encode_picture_header(m); + if (ret < 0) + return ret; bits= put_bits_count(&s->pb); m->header_bits = bits - s->last_bits; diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h index 9c70fe6d71..cd82b16590 100644 --- a/libavcodec/mpegvideoenc.h +++ b/libavcodec/mpegvideoenc.h @@ -74,6 +74,8 @@ typedef struct MPVMainEncContext { int frame_skip_cmp; me_cmp_func frame_skip_cmp_fn; + int (*encode_picture_header)(struct MPVMainEncContext *m); + /* bit rate control */ int64_t total_bits; int frame_bits; ///< bits used for the current frame diff --git a/libavcodec/msmpeg4enc.c b/libavcodec/msmpeg4enc.c index 98b72e4d58..01d5707370 100644 --- a/libavcodec/msmpeg4enc.c +++ b/libavcodec/msmpeg4enc.c @@ -135,20 +135,6 @@ static av_cold void msmpeg4_encode_init_static(void) } } -av_cold void ff_msmpeg4_encode_init(MpegEncContext *s) -{ - static AVOnce init_static_once = AV_ONCE_INIT; - - ff_msmpeg4_common_init(s); - if (s->msmpeg4_version >= MSMP4_WMV1) { - s->min_qcoeff = -255; - s->max_qcoeff = 255; - } - - /* init various encoding tables */ - ff_thread_once(&init_static_once, msmpeg4_encode_init_static); -} - static void find_best_tables(MSMPEG4EncContext *ms) { MpegEncContext *const s = &ms->m.s; @@ -215,9 +201,10 @@ static void find_best_tables(MSMPEG4EncContext *ms) } /* write MSMPEG4 compatible frame header */ -void ff_msmpeg4_encode_picture_header(MpegEncContext * s) +static int msmpeg4_encode_picture_header(MPVMainEncContext *const m) { - MSMPEG4EncContext *const ms = (MSMPEG4EncContext*)s; + MSMPEG4EncContext *const ms = (MSMPEG4EncContext*)m; + MpegEncContext *const s = &m->s; find_best_tables(ms); @@ -275,6 +262,8 @@ void ff_msmpeg4_encode_picture_header(MpegEncContext * s) s->esc3_level_length= 0; s->esc3_run_length= 0; + + return 0; } void ff_msmpeg4_encode_ext_header(MpegEncContext * s) @@ -674,6 +663,25 @@ void ff_msmpeg4_encode_block(MpegEncContext * s, int16_t * block, int n) } } +av_cold void ff_msmpeg4_encode_init(MPVMainEncContext *const m) +{ + MpegEncContext *const s = &m->s; + static AVOnce init_static_once = AV_ONCE_INIT; + + ff_msmpeg4_common_init(s); + + if (s->msmpeg4_version <= MSMP4_WMV1) + m->encode_picture_header = msmpeg4_encode_picture_header; + + if (s->msmpeg4_version >= MSMP4_WMV1) { + s->min_qcoeff = -255; + s->max_qcoeff = 255; + } + + /* init various encoding tables */ + ff_thread_once(&init_static_once, msmpeg4_encode_init_static); +} + const FFCodec ff_msmpeg4v2_encoder = { .p.name = "msmpeg4v2", CODEC_LONG_NAME("MPEG-4 part 2 Microsoft variant version 2"), diff --git a/libavcodec/msmpeg4enc.h b/libavcodec/msmpeg4enc.h index 72992176de..5511e01283 100644 --- a/libavcodec/msmpeg4enc.h +++ b/libavcodec/msmpeg4enc.h @@ -33,8 +33,7 @@ typedef struct MSMPEG4EncContext { unsigned ac_stats[2][2][MAX_LEVEL + 1][MAX_RUN + 1][2]; } MSMPEG4EncContext; -void ff_msmpeg4_encode_init(MpegEncContext *s); -void ff_msmpeg4_encode_picture_header(MpegEncContext *s); +void ff_msmpeg4_encode_init(MPVMainEncContext *m); void ff_msmpeg4_encode_ext_header(MpegEncContext *s); void ff_msmpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], int motion_x, int motion_y); diff --git a/libavcodec/rv10enc.c b/libavcodec/rv10enc.c index d55fa7c2b0..0b5065212d 100644 --- a/libavcodec/rv10enc.c +++ b/libavcodec/rv10enc.c @@ -31,8 +31,9 @@ #include "put_bits.h" #include "rv10enc.h" -int ff_rv10_encode_picture_header(MpegEncContext *s) +int ff_rv10_encode_picture_header(MPVMainEncContext *const m) { + MpegEncContext *const s = &m->s; int full_frame= 0; align_put_bits(&s->pb); diff --git a/libavcodec/rv10enc.h b/libavcodec/rv10enc.h index fc3665e839..5aa7250e87 100644 --- a/libavcodec/rv10enc.h +++ b/libavcodec/rv10enc.h @@ -21,9 +21,9 @@ #ifndef AVCODEC_RV10ENC_H #define AVCODEC_RV10ENC_H -#include "mpegvideo.h" +typedef struct MPVMainEncContext MPVMainEncContext; -int ff_rv10_encode_picture_header(MpegEncContext *s); -void ff_rv20_encode_picture_header(MpegEncContext *s); +int ff_rv10_encode_picture_header(MPVMainEncContext *m); +int ff_rv20_encode_picture_header(MPVMainEncContext *m); #endif /* AVCODEC_RV10ENC_H */ diff --git a/libavcodec/rv20enc.c b/libavcodec/rv20enc.c index cacda6fdda..1a59fd4c70 100644 --- a/libavcodec/rv20enc.c +++ b/libavcodec/rv20enc.c @@ -34,7 +34,10 @@ #include "put_bits.h" #include "rv10enc.h" -void ff_rv20_encode_picture_header(MpegEncContext *s) { +int ff_rv20_encode_picture_header(MPVMainEncContext *const m) +{ + MpegEncContext *const s = &m->s; + put_bits(&s->pb, 2, s->pict_type); //I 0 vs. 1 ? put_bits(&s->pb, 1, 0); /* unknown bit */ put_bits(&s->pb, 5, s->qscale); @@ -60,6 +63,7 @@ void ff_rv20_encode_picture_header(MpegEncContext *s) { s->y_dc_scale_table= s->c_dc_scale_table= ff_mpeg1_dc_scale_table; } + return 0; } const FFCodec ff_rv20_encoder = { diff --git a/libavcodec/speedhqenc.c b/libavcodec/speedhqenc.c index daccd0c3bf..1ba5dcc68f 100644 --- a/libavcodec/speedhqenc.c +++ b/libavcodec/speedhqenc.c @@ -95,9 +95,10 @@ static av_cold void speedhq_init_static_data(void) ff_speedhq_vlc_table, uni_speedhq_ac_vlc_len); } -void ff_speedhq_encode_picture_header(MpegEncContext *s) +static int speedhq_encode_picture_header(MPVMainEncContext *const m) { - SpeedHQEncContext *ctx = (SpeedHQEncContext*)s; + SpeedHQEncContext *const ctx = (SpeedHQEncContext*)m; + MpegEncContext *const s = &m->s; put_bits_le(&s->pb, 8, 100 - s->qscale * 2); /* FIXME why doubled */ put_bits_le(&s->pb, 24, 4); /* no second field */ @@ -105,6 +106,8 @@ void ff_speedhq_encode_picture_header(MpegEncContext *s) ctx->slice_start = 4; /* length of first slice, will be filled out later */ put_bits_le(&s->pb, 24, 0); + + return 0; } void ff_speedhq_end_slice(MpegEncContext *s) @@ -230,7 +233,8 @@ void ff_speedhq_encode_mb(MpegEncContext *s, int16_t block[12][64]) static av_cold int speedhq_encode_init(AVCodecContext *avctx) { static AVOnce init_static_once = AV_ONCE_INIT; - MpegEncContext *const s = avctx->priv_data; + MPVMainEncContext *const m = avctx->priv_data; + MpegEncContext *const s = &m->s; int ret; if (avctx->width > 65500 || avctx->height > 65500) { @@ -258,6 +262,8 @@ static av_cold int speedhq_encode_init(AVCodecContext *avctx) av_assert0(0); } + m->encode_picture_header = speedhq_encode_picture_header; + s->min_qcoeff = -2048; s->max_qcoeff = 2047; diff --git a/libavcodec/speedhqenc.h b/libavcodec/speedhqenc.h index 66ef7ee023..b0e6662279 100644 --- a/libavcodec/speedhqenc.h +++ b/libavcodec/speedhqenc.h @@ -36,7 +36,6 @@ void ff_speedhq_encode_close(MpegEncContext *s); void ff_speedhq_encode_mb(MpegEncContext *s, int16_t block[12][64]); -void ff_speedhq_encode_picture_header(MpegEncContext *s); void ff_speedhq_end_slice(MpegEncContext *s); static inline int ff_speedhq_mb_rows_in_slice(int slice_num, int mb_height) diff --git a/libavcodec/wmv2enc.c b/libavcodec/wmv2enc.c index 55fcc91484..d70a680fb3 100644 --- a/libavcodec/wmv2enc.c +++ b/libavcodec/wmv2enc.c @@ -73,9 +73,10 @@ static int encode_ext_header(WMV2EncContext *w) return 0; } -int ff_wmv2_encode_picture_header(MpegEncContext *s) +static int wmv2_encode_picture_header(MPVMainEncContext *const m) { - WMV2EncContext *const w = (WMV2EncContext *) s; + WMV2EncContext *const w = (WMV2EncContext *) m; + MpegEncContext *const s = &m->s; put_bits(&s->pb, 1, s->pict_type - 1); if (s->pict_type == AV_PICTURE_TYPE_I) @@ -222,6 +223,7 @@ static av_cold int wmv2_encode_init(AVCodecContext *avctx) MpegEncContext *const s = &w->msmpeg4.m.s; int ret; + w->msmpeg4.m.encode_picture_header = wmv2_encode_picture_header; s->private_ctx = &w->common; ret = ff_mpv_encode_init(avctx); if (ret < 0) diff --git a/libavcodec/wmv2enc.h b/libavcodec/wmv2enc.h index 263265acf3..59046c6a07 100644 --- a/libavcodec/wmv2enc.h +++ b/libavcodec/wmv2enc.h @@ -23,7 +23,6 @@ #include "mpegvideo.h" -int ff_wmv2_encode_picture_header(MpegEncContext * s); void ff_wmv2_encode_mb(MpegEncContext * s, int16_t block[6][64], int motion_x, int motion_y); -- 2.45.2 [-- Attachment #32: 0031-avcodec-mpegvideo-Move-fcode_tab-to-MPVMainEncContex.patch --] [-- Type: text/x-patch, Size: 8118 bytes --] From 4712c5a9d583c529eeedf21b6f06edd0425f5d0c Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Mon, 7 Feb 2022 10:24:38 +0100 Subject: [PATCH 31/77] avcodec/mpegvideo: Move fcode_tab to MPVMainEncContext Only used by the main encoding thread. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/ituh263enc.c | 2 +- libavcodec/motion_est.c | 6 ++++-- libavcodec/motion_est.h | 3 ++- libavcodec/mpeg12enc.c | 2 +- libavcodec/mpeg4videoenc.c | 2 +- libavcodec/mpegvideo.h | 1 - libavcodec/mpegvideo_enc.c | 23 ++++++++++++----------- libavcodec/mpegvideoenc.h | 2 ++ 8 files changed, 23 insertions(+), 18 deletions(-) diff --git a/libavcodec/ituh263enc.c b/libavcodec/ituh263enc.c index c82e0ceffd..739f959e40 100644 --- a/libavcodec/ituh263enc.c +++ b/libavcodec/ituh263enc.c @@ -848,7 +848,7 @@ av_cold void ff_h263_encode_init(MPVMainEncContext *const m) break; case AV_CODEC_ID_H263P: if(s->umvplus) - s->fcode_tab = umv_fcode_tab + MAX_MV; + m->fcode_tab = umv_fcode_tab + MAX_MV; if(s->modified_quant){ s->min_qcoeff= -2047; s->max_qcoeff= 2047; diff --git a/libavcodec/motion_est.c b/libavcodec/motion_est.c index f7c8305847..7c08fe53eb 100644 --- a/libavcodec/motion_est.c +++ b/libavcodec/motion_est.c @@ -1596,12 +1596,14 @@ void ff_estimate_b_frame_motion(MpegEncContext * s, } /* find best f_code for ME which do unlimited searches */ -int ff_get_best_fcode(MpegEncContext * s, const int16_t (*mv_table)[2], int type) +int ff_get_best_fcode(MPVMainEncContext *const m, const int16_t (*mv_table)[2], int type) { + MpegEncContext *const s = &m->s; + if (s->motion_est != FF_ME_ZERO) { int score[8]; int i, y, range= s->avctx->me_range ? s->avctx->me_range : (INT_MAX/2); - const uint8_t * fcode_tab = s->fcode_tab; + const uint8_t * fcode_tab = m->fcode_tab; int best_fcode=-1; int best_score=-10000000; diff --git a/libavcodec/motion_est.h b/libavcodec/motion_est.h index 12f7cd43ab..d8a2cab3a0 100644 --- a/libavcodec/motion_est.h +++ b/libavcodec/motion_est.h @@ -29,6 +29,7 @@ #include "qpeldsp.h" struct MpegEncContext; +typedef struct MPVMainEncContext MPVMainEncContext; #if ARCH_IA64 // Limit static arrays to avoid gcc failing "short data segment overflowed" #define MAX_MV 1024 @@ -136,7 +137,7 @@ int ff_epzs_motion_search(struct MpegEncContext *s, int *mx_ptr, int *my_ptr, int ff_get_mb_score(struct MpegEncContext *s, int mx, int my, int src_index, int ref_index, int size, int h, int add_rate); -int ff_get_best_fcode(struct MpegEncContext *s, +int ff_get_best_fcode(MPVMainEncContext *m, const int16_t (*mv_table)[2], int type); void ff_fix_long_p_mvs(struct MpegEncContext *s, int type); diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index f28a41f5ff..b67f70c5cd 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -1113,7 +1113,7 @@ static av_cold int encode_init(AVCodecContext *avctx) m->encode_picture_header = mpeg1_encode_picture_header; s->me.mv_penalty = mv_penalty; - s->fcode_tab = fcode_tab + MAX_MV; + m->fcode_tab = fcode_tab + MAX_MV; if (avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO) { s->min_qcoeff = -255; s->max_qcoeff = 255; diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c index f34ea1fcb4..cc3c676e18 100644 --- a/libavcodec/mpeg4videoenc.c +++ b/libavcodec/mpeg4videoenc.c @@ -1319,7 +1319,7 @@ static av_cold int encode_init(AVCodecContext *avctx) m4->time_increment_bits = av_log2(avctx->time_base.den - 1) + 1; - s->fcode_tab = fcode_tab + MAX_MV; + m->fcode_tab = fcode_tab + MAX_MV; s->min_qcoeff = -2048; s->max_qcoeff = 2047; diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index fcc51af41a..49e8159769 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -253,7 +253,6 @@ typedef struct MpegEncContext { int mv[2][4][2]; int field_select[2][2]; int last_mv[2][2][2]; ///< last MV, used for MV prediction in MPEG-1 & B-frame MPEG-4 - const uint8_t *fcode_tab; ///< smallest fcode needed for each MV int16_t direct_scale_mv[2][64]; ///< precomputed to avoid divisions in ff_mpeg4_set_direct_mv MotionEstContext me; diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 03a8ae2687..08fc72edb4 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -278,14 +278,15 @@ static av_cold void mpv_encode_init_static(void) /** * Set the given MpegEncContext to defaults for encoding. */ -static av_cold void mpv_encode_defaults(MpegEncContext *s) +static av_cold void mpv_encode_defaults(MPVMainEncContext *const m) { + MpegEncContext *const s = &m->s; static AVOnce init_static_once = AV_ONCE_INIT; ff_mpv_common_defaults(s); - if (!s->fcode_tab) { - s->fcode_tab = default_fcode_tab + MAX_MV; + if (!m->fcode_tab) { + m->fcode_tab = default_fcode_tab + MAX_MV; ff_thread_once(&init_static_once, mpv_encode_init_static); } if (!s->y_dc_scale_table) { @@ -429,7 +430,7 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) int i, ret; int mb_array_size, mv_table_size; - mpv_encode_defaults(s); + mpv_encode_defaults(m); switch (avctx->pix_fmt) { case AV_PIX_FMT_YUVJ444P: @@ -3774,12 +3775,12 @@ static int encode_picture(MPVMainEncContext *const m, const AVPacket *pkt) if(!s->umvplus){ if(s->pict_type==AV_PICTURE_TYPE_P || s->pict_type==AV_PICTURE_TYPE_S) { - s->f_code= ff_get_best_fcode(s, s->p_mv_table, CANDIDATE_MB_TYPE_INTER); + s->f_code = ff_get_best_fcode(m, s->p_mv_table, CANDIDATE_MB_TYPE_INTER); if (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) { int a,b; - a= ff_get_best_fcode(s, s->p_field_mv_table[0][0], CANDIDATE_MB_TYPE_INTER_I); //FIXME field_select - b= ff_get_best_fcode(s, s->p_field_mv_table[1][1], CANDIDATE_MB_TYPE_INTER_I); + a = ff_get_best_fcode(m, s->p_field_mv_table[0][0], CANDIDATE_MB_TYPE_INTER_I); //FIXME field_select + b = ff_get_best_fcode(m, s->p_field_mv_table[1][1], CANDIDATE_MB_TYPE_INTER_I); s->f_code= FFMAX3(s->f_code, a, b); } @@ -3796,12 +3797,12 @@ static int encode_picture(MPVMainEncContext *const m, const AVPacket *pkt) } else if (s->pict_type == AV_PICTURE_TYPE_B) { int a, b; - a = ff_get_best_fcode(s, s->b_forw_mv_table, CANDIDATE_MB_TYPE_FORWARD); - b = ff_get_best_fcode(s, s->b_bidir_forw_mv_table, CANDIDATE_MB_TYPE_BIDIR); + a = ff_get_best_fcode(m, s->b_forw_mv_table, CANDIDATE_MB_TYPE_FORWARD); + b = ff_get_best_fcode(m, s->b_bidir_forw_mv_table, CANDIDATE_MB_TYPE_BIDIR); s->f_code = FFMAX(a, b); - a = ff_get_best_fcode(s, s->b_back_mv_table, CANDIDATE_MB_TYPE_BACKWARD); - b = ff_get_best_fcode(s, s->b_bidir_back_mv_table, CANDIDATE_MB_TYPE_BIDIR); + a = ff_get_best_fcode(m, s->b_back_mv_table, CANDIDATE_MB_TYPE_BACKWARD); + b = ff_get_best_fcode(m, s->b_bidir_back_mv_table, CANDIDATE_MB_TYPE_BIDIR); s->b_code = FFMAX(a, b); ff_fix_long_mvs(s, NULL, 0, s->b_forw_mv_table, s->f_code, CANDIDATE_MB_TYPE_FORWARD, 1); diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h index cd82b16590..4b74f8eb46 100644 --- a/libavcodec/mpegvideoenc.h +++ b/libavcodec/mpegvideoenc.h @@ -67,6 +67,8 @@ typedef struct MPVMainEncContext { int lmin, lmax; int vbv_ignore_qmax; + const uint8_t *fcode_tab; ///< smallest fcode needed for each MV + /* frame skip options */ int frame_skip_threshold; int frame_skip_factor; -- 2.45.2 [-- Attachment #33: 0032-avcodec-speedhqenc-Remove-declaration-of-non-existen.patch --] [-- Type: text/x-patch, Size: 775 bytes --] From 8d086d13a3cda9ec275bddebeff16ed331b1129e Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Tue, 4 Mar 2025 18:40:11 +0100 Subject: [PATCH 32/77] avcodec/speedhqenc: Remove declaration of non-existent function Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/speedhqenc.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libavcodec/speedhqenc.h b/libavcodec/speedhqenc.h index b0e6662279..f02fa1f51a 100644 --- a/libavcodec/speedhqenc.h +++ b/libavcodec/speedhqenc.h @@ -33,7 +33,6 @@ #include "mpegvideo.h" -void ff_speedhq_encode_close(MpegEncContext *s); void ff_speedhq_encode_mb(MpegEncContext *s, int16_t block[12][64]); void ff_speedhq_end_slice(MpegEncContext *s); -- 2.45.2 [-- Attachment #34: 0033-avcodec-mjpegenc-Move-mjpeg_encode_init-down.patch --] [-- Type: text/x-patch, Size: 6714 bytes --] From 126096175de96dfd1d9b75dffd4b31fd6bfe1a63 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Tue, 4 Mar 2025 18:42:44 +0100 Subject: [PATCH 33/77] avcodec/mjpegenc: Move mjpeg_encode_init() down Will avoid a forward declaration later. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mjpegenc.c | 149 +++++++++++++++++++++--------------------- 1 file changed, 75 insertions(+), 74 deletions(-) diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c index 7706f52148..4c7a25832b 100644 --- a/libavcodec/mjpegenc.c +++ b/libavcodec/mjpegenc.c @@ -304,80 +304,6 @@ static int alloc_huffman(MJPEGEncContext *const m2) return 0; } -static av_cold int mjpeg_encode_init(AVCodecContext *avctx) -{ - MJPEGEncContext *const m2 = avctx->priv_data; - MJpegContext *const m = &m2->mjpeg; - MpegEncContext *const s = &m2->mpeg.s; - int ret; - - s->mjpeg_ctx = m; - m2->mpeg.encode_picture_header = mjpeg_amv_encode_picture_header; - - if (s->mpv_flags & FF_MPV_FLAG_QP_RD) { - // Used to produce garbage with MJPEG. - av_log(avctx, AV_LOG_ERROR, - "QP RD is no longer compatible with MJPEG or AMV\n"); - return AVERROR(EINVAL); - } - - /* The following check is automatically true for AMV, - * but it doesn't hurt either. */ - ret = ff_mjpeg_encode_check_pix_fmt(avctx); - if (ret < 0) - return ret; - - if (avctx->width > 65500 || avctx->height > 65500) { - av_log(avctx, AV_LOG_ERROR, "JPEG does not support resolutions above 65500x65500\n"); - return AVERROR(EINVAL); - } - - s->min_qcoeff=-1023; - s->max_qcoeff= 1023; - - // Build default Huffman tables. - // These may be overwritten later with more optimal Huffman tables, but - // they are needed at least right now for some processes like trellis. - ff_mjpeg_build_huffman_codes(m->huff_size_dc_luminance, - m->huff_code_dc_luminance, - ff_mjpeg_bits_dc_luminance, - ff_mjpeg_val_dc); - ff_mjpeg_build_huffman_codes(m->huff_size_dc_chrominance, - m->huff_code_dc_chrominance, - ff_mjpeg_bits_dc_chrominance, - ff_mjpeg_val_dc); - ff_mjpeg_build_huffman_codes(m->huff_size_ac_luminance, - m->huff_code_ac_luminance, - ff_mjpeg_bits_ac_luminance, - ff_mjpeg_val_ac_luminance); - ff_mjpeg_build_huffman_codes(m->huff_size_ac_chrominance, - m->huff_code_ac_chrominance, - ff_mjpeg_bits_ac_chrominance, - ff_mjpeg_val_ac_chrominance); - - init_uni_ac_vlc(m->huff_size_ac_luminance, m->uni_ac_vlc_len); - init_uni_ac_vlc(m->huff_size_ac_chrominance, m->uni_chroma_ac_vlc_len); - s->intra_ac_vlc_length = - s->intra_ac_vlc_last_length = m->uni_ac_vlc_len; - s->intra_chroma_ac_vlc_length = - s->intra_chroma_ac_vlc_last_length = m->uni_chroma_ac_vlc_len; - - ret = ff_mpv_encode_init(avctx); - if (ret < 0) - return ret; - - // Buffers start out empty. - m->huff_ncode = 0; - - if (s->slice_context_count > 1) - m->huffman = HUFFMAN_TABLE_DEFAULT; - - if (m->huffman == HUFFMAN_TABLE_OPTIMAL) - return alloc_huffman(m2); - - return 0; -} - static av_cold int mjpeg_encode_close(AVCodecContext *avctx) { MJPEGEncContext *const mjpeg = avctx->priv_data; @@ -603,6 +529,81 @@ void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[12][64]) } } +static av_cold int mjpeg_encode_init(AVCodecContext *avctx) +{ + MJPEGEncContext *const m2 = avctx->priv_data; + MJpegContext *const m = &m2->mjpeg; + MpegEncContext *const s = &m2->mpeg.s; + int ret; + + s->mjpeg_ctx = m; + m2->mpeg.encode_picture_header = mjpeg_amv_encode_picture_header; + + if (s->mpv_flags & FF_MPV_FLAG_QP_RD) { + // Used to produce garbage with MJPEG. + av_log(avctx, AV_LOG_ERROR, + "QP RD is no longer compatible with MJPEG or AMV\n"); + return AVERROR(EINVAL); + } + + /* The following check is automatically true for AMV, + * but it doesn't hurt either. */ + ret = ff_mjpeg_encode_check_pix_fmt(avctx); + if (ret < 0) + return ret; + + if (avctx->width > 65500 || avctx->height > 65500) { + av_log(avctx, AV_LOG_ERROR, "JPEG does not support resolutions above 65500x65500\n"); + return AVERROR(EINVAL); + } + + // Build default Huffman tables. + // These may be overwritten later with more optimal Huffman tables, but + // they are needed at least right now for some processes like trellis. + ff_mjpeg_build_huffman_codes(m->huff_size_dc_luminance, + m->huff_code_dc_luminance, + ff_mjpeg_bits_dc_luminance, + ff_mjpeg_val_dc); + ff_mjpeg_build_huffman_codes(m->huff_size_dc_chrominance, + m->huff_code_dc_chrominance, + ff_mjpeg_bits_dc_chrominance, + ff_mjpeg_val_dc); + ff_mjpeg_build_huffman_codes(m->huff_size_ac_luminance, + m->huff_code_ac_luminance, + ff_mjpeg_bits_ac_luminance, + ff_mjpeg_val_ac_luminance); + ff_mjpeg_build_huffman_codes(m->huff_size_ac_chrominance, + m->huff_code_ac_chrominance, + ff_mjpeg_bits_ac_chrominance, + ff_mjpeg_val_ac_chrominance); + + init_uni_ac_vlc(m->huff_size_ac_luminance, m->uni_ac_vlc_len); + init_uni_ac_vlc(m->huff_size_ac_chrominance, m->uni_chroma_ac_vlc_len); + + s->min_qcoeff = -1023; + s->max_qcoeff = 1023; + + s->intra_ac_vlc_length = + s->intra_ac_vlc_last_length = m->uni_ac_vlc_len; + s->intra_chroma_ac_vlc_length = + s->intra_chroma_ac_vlc_last_length = m->uni_chroma_ac_vlc_len; + + ret = ff_mpv_encode_init(avctx); + if (ret < 0) + return ret; + + // Buffers start out empty. + m->huff_ncode = 0; + + if (s->slice_context_count > 1) + m->huffman = HUFFMAN_TABLE_DEFAULT; + + if (m->huffman == HUFFMAN_TABLE_OPTIMAL) + return alloc_huffman(m2); + + return 0; +} + #if CONFIG_AMV_ENCODER // maximum over s->mjpeg_vsample[i] #define V_MAX 2 -- 2.45.2 [-- Attachment #35: 0034-avcodec-mpegvideo_enc-Use-func-ptr-for-encoding-macr.patch --] [-- Type: text/x-patch, Size: 18160 bytes --] From ff0dfff3fa4af98ae908edc18249293aacbc50a2 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Tue, 4 Mar 2025 19:09:24 +0100 Subject: [PATCH 34/77] avcodec/mpegvideo_enc: Use func ptr for encoding macroblocks It gets rid of a switch (with accompanying CONFIG_*_ENCODER checks); for MJPEG, it even lets one perform the check for whether one is really encoding or only recording the macroblock once during init. Furthermore, the switch actually contained lots of dead code -- it is compiled three times (for different pixel formats: 420, 422, 444), yet most encoders only support 420. The approach used here automatically fixes this. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/h261enc.c | 5 ++-- libavcodec/h261enc.h | 2 -- libavcodec/h263enc.h | 3 --- libavcodec/ituh263enc.c | 8 ++++--- libavcodec/mjpegenc.c | 19 +++++++++++---- libavcodec/mjpegenc.h | 1 - libavcodec/mpeg12enc.c | 5 ++-- libavcodec/mpeg12enc.h | 2 -- libavcodec/mpeg4videoenc.c | 5 ++-- libavcodec/mpeg4videoenc.h | 3 --- libavcodec/mpegvideo.h | 4 ++++ libavcodec/mpegvideo_enc.c | 48 +------------------------------------- libavcodec/msmpeg4enc.c | 10 ++++---- libavcodec/msmpeg4enc.h | 2 -- libavcodec/speedhqenc.c | 4 +++- libavcodec/speedhqenc.h | 2 -- libavcodec/wmv2enc.c | 6 ++--- libavcodec/wmv2enc.h | 30 ------------------------ 18 files changed, 45 insertions(+), 114 deletions(-) delete mode 100644 libavcodec/wmv2enc.h diff --git a/libavcodec/h261enc.c b/libavcodec/h261enc.c index bfe805bcdf..81711b3a16 100644 --- a/libavcodec/h261enc.c +++ b/libavcodec/h261enc.c @@ -228,8 +228,8 @@ static void h261_encode_block(H261EncContext *h, int16_t *block, int n) put_bits(&s->pb, 2, 0x2); // EOB } -void ff_h261_encode_mb(MpegEncContext *s, int16_t block[6][64], - int motion_x, int motion_y) +static void h261_encode_mb(MpegEncContext *const s, int16_t block[6][64], + int motion_x, int motion_y) { /* The following is only allowed because this encoder * does not use slice threading. */ @@ -374,6 +374,7 @@ static av_cold int h261_encode_init(AVCodecContext *avctx) } s->private_ctx = &h->common; h->s.encode_picture_header = h261_encode_picture_header; + s->encode_mb = h261_encode_mb; s->min_qcoeff = -127; s->max_qcoeff = 127; diff --git a/libavcodec/h261enc.h b/libavcodec/h261enc.h index 092363b6f3..79cdd31c2f 100644 --- a/libavcodec/h261enc.h +++ b/libavcodec/h261enc.h @@ -31,7 +31,5 @@ #include "mpegvideo.h" void ff_h261_reorder_mb_index(MpegEncContext *s); -void ff_h261_encode_mb(MpegEncContext *s, int16_t block[6][64], - int motion_x, int motion_y); #endif diff --git a/libavcodec/h263enc.h b/libavcodec/h263enc.h index 29a785dfeb..dd9caa7969 100644 --- a/libavcodec/h263enc.h +++ b/libavcodec/h263enc.h @@ -28,9 +28,6 @@ const uint8_t (*ff_h263_get_mv_penalty(void))[MAX_DMV*2+1]; void ff_h263_encode_init(MPVMainEncContext *m); void ff_h263_encode_gob_header(MpegEncContext * s, int mb_line); -void ff_h263_encode_mb(MpegEncContext *s, - int16_t block[6][64], - int motion_x, int motion_y); void ff_h263_encode_mba(MpegEncContext *s); void ff_clean_h263_qscales(MpegEncContext *s); diff --git a/libavcodec/ituh263enc.c b/libavcodec/ituh263enc.c index 739f959e40..deaf7dc5c6 100644 --- a/libavcodec/ituh263enc.c +++ b/libavcodec/ituh263enc.c @@ -608,9 +608,9 @@ static int h263_pred_dc(MpegEncContext * s, int n, int16_t **dc_val_ptr) return pred_dc; } -void ff_h263_encode_mb(MpegEncContext * s, - int16_t block[6][64], - int motion_x, int motion_y) +static void h263_encode_mb(MpegEncContext *const s, + int16_t block[][64], + int motion_x, int motion_y) { int cbpc, cbpy, i, cbp, pred_x, pred_y; int16_t pred_dc; @@ -875,6 +875,8 @@ av_cold void ff_h263_encode_init(MPVMainEncContext *const m) // H.263, H.263+; will be overwritten for MSMPEG-4 later if (!m->encode_picture_header) m->encode_picture_header = h263_encode_picture_header; + if (!s->encode_mb) + s->encode_mb = h263_encode_mb; ff_h263dsp_init(&s->h263dsp); } diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c index 4c7a25832b..6c58c04892 100644 --- a/libavcodec/mjpegenc.c +++ b/libavcodec/mjpegenc.c @@ -463,10 +463,10 @@ static void encode_block(MpegEncContext *s, int16_t *block, int n) put_bits(&s->pb, huff_size_ac[0], huff_code_ac[0]); } -void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[12][64]) +static void mjpeg_record_mb(MpegEncContext *const s, int16_t block[][64], + int unused_x, int unused_y) { int i; - if (s->mjpeg_ctx->huffman == HUFFMAN_TABLE_OPTIMAL) { if (s->chroma_format == CHROMA_444) { record_block(s, block[0], 0); record_block(s, block[2], 2); @@ -495,7 +495,12 @@ void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[12][64]) record_block(s, block[7], 7); } } - } else { +} + +static void mjpeg_encode_mb(MpegEncContext *const s, int16_t block[][64], + int unused_x, int unused_y) +{ + int i; if (s->chroma_format == CHROMA_444) { encode_block(s, block[0], 0); encode_block(s, block[2], 2); @@ -526,7 +531,6 @@ void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[12][64]) } s->i_tex_bits += get_bits_diff(s); - } } static av_cold int mjpeg_encode_init(AVCodecContext *avctx) @@ -538,6 +542,8 @@ static av_cold int mjpeg_encode_init(AVCodecContext *avctx) s->mjpeg_ctx = m; m2->mpeg.encode_picture_header = mjpeg_amv_encode_picture_header; + // May be overridden below + s->encode_mb = mjpeg_encode_mb; if (s->mpv_flags & FF_MPV_FLAG_QP_RD) { // Used to produce garbage with MJPEG. @@ -598,8 +604,11 @@ static av_cold int mjpeg_encode_init(AVCodecContext *avctx) if (s->slice_context_count > 1) m->huffman = HUFFMAN_TABLE_DEFAULT; - if (m->huffman == HUFFMAN_TABLE_OPTIMAL) + if (m->huffman == HUFFMAN_TABLE_OPTIMAL) { + // If we are here, we have only one slice_context. So no loop necessary. + s->encode_mb = mjpeg_record_mb; return alloc_huffman(m2); + } return 0; } diff --git a/libavcodec/mjpegenc.h b/libavcodec/mjpegenc.h index 9610656aaa..ceacba9893 100644 --- a/libavcodec/mjpegenc.h +++ b/libavcodec/mjpegenc.h @@ -94,7 +94,6 @@ static inline void put_marker(PutBitContext *p, enum JpegMarker code) typedef struct MpegEncContext MpegEncContext; -void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[12][64]); int ff_mjpeg_encode_stuffing(MpegEncContext *s); #endif /* AVCODEC_MJPEGENC_H */ diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index b67f70c5cd..1ef88d23b8 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -929,8 +929,8 @@ static av_always_inline void mpeg1_encode_mb_internal(MpegEncContext *s, } } -void ff_mpeg1_encode_mb(MpegEncContext *s, int16_t block[8][64], - int motion_x, int motion_y) +static void mpeg12_encode_mb(MpegEncContext *s, int16_t block[][64], + int motion_x, int motion_y) { if (!s->mb_intra) s->last_dc[0] = s->last_dc[1] = s->last_dc[2] = 128 << s->intra_dc_precision; @@ -1111,6 +1111,7 @@ static av_cold int encode_init(AVCodecContext *avctx) } m->encode_picture_header = mpeg1_encode_picture_header; + s->encode_mb = mpeg12_encode_mb; s->me.mv_penalty = mv_penalty; m->fcode_tab = fcode_tab + MAX_MV; diff --git a/libavcodec/mpeg12enc.h b/libavcodec/mpeg12enc.h index 6c3709bbff..8ffa471a63 100644 --- a/libavcodec/mpeg12enc.h +++ b/libavcodec/mpeg12enc.h @@ -27,8 +27,6 @@ #include "mpegvideo.h" #include "mpegvideodata.h" -void ff_mpeg1_encode_mb(MpegEncContext *s, int16_t block[8][64], - int motion_x, int motion_y); void ff_mpeg1_encode_slice_header(MpegEncContext *s); // Must not be called before intra_dc_precision has been sanitized in ff_mpv_encode_init() diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c index cc3c676e18..4f97199eba 100644 --- a/libavcodec/mpeg4videoenc.c +++ b/libavcodec/mpeg4videoenc.c @@ -499,8 +499,8 @@ static inline int get_b_cbp(MpegEncContext *s, int16_t block[6][64], // FIXME this is duplicated to h263.c static const int dquant_code[5] = { 1, 0, 9, 2, 3 }; -void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], - int motion_x, int motion_y) +static void mpeg4_encode_mb(MpegEncContext *const s, int16_t block[][64], + int motion_x, int motion_y) { int cbpc, cbpy, pred_x, pred_y; PutBitContext *const pb2 = s->data_partitioning ? &s->pb2 : &s->pb; @@ -1301,6 +1301,7 @@ static av_cold int encode_init(AVCodecContext *avctx) } m->encode_picture_header = mpeg4_encode_picture_header; + s->encode_mb = mpeg4_encode_mb; ff_qpeldsp_init(&s->qdsp); if ((ret = ff_mpv_encode_init(avctx)) < 0) diff --git a/libavcodec/mpeg4videoenc.h b/libavcodec/mpeg4videoenc.h index 4565a518b2..0727be6750 100644 --- a/libavcodec/mpeg4videoenc.h +++ b/libavcodec/mpeg4videoenc.h @@ -29,9 +29,6 @@ typedef struct MpegEncContext MpegEncContext; -void ff_mpeg4_encode_mb(MpegEncContext *s, - int16_t block[6][64], - int motion_x, int motion_y); void ff_set_mpeg4_time(MpegEncContext *s); void ff_mpeg4_encode_video_packet_header(MpegEncContext *s); diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 49e8159769..bdab782b29 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -438,7 +438,11 @@ typedef struct MpegEncContext { int16_t (*block)[64]; ///< points to one of the following blocks int16_t (*blocks)[12][64]; // for HQ mode we need to keep the best block + union { int (*decode_mb)(struct MpegEncContext *s, int16_t block[12][64]); // used by some codecs to avoid a switch() + void (*encode_mb)(struct MpegEncContext *s, int16_t block[][64], + int motion_x, int motion_y); + }; #define SLICE_OK 0 #define SLICE_ERROR -1 diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 08fc72edb4..6650e5b35d 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -71,7 +71,6 @@ #include "mpeg4videoenc.h" #include "internal.h" #include "bytestream.h" -#include "wmv2enc.h" #include "rv10enc.h" #include "packet_internal.h" #include "libavutil/refstruct.h" @@ -2562,52 +2561,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, } } - /* huffman encode */ - switch(s->codec_id){ //FIXME funct ptr could be slightly faster - case AV_CODEC_ID_MPEG1VIDEO: - case AV_CODEC_ID_MPEG2VIDEO: - if (CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER) - ff_mpeg1_encode_mb(s, s->block, motion_x, motion_y); - break; - case AV_CODEC_ID_MPEG4: - if (CONFIG_MPEG4_ENCODER) - ff_mpeg4_encode_mb(s, s->block, motion_x, motion_y); - break; - case AV_CODEC_ID_MSMPEG4V2: - case AV_CODEC_ID_MSMPEG4V3: - case AV_CODEC_ID_WMV1: - if (CONFIG_MSMPEG4ENC) - ff_msmpeg4_encode_mb(s, s->block, motion_x, motion_y); - break; - case AV_CODEC_ID_WMV2: - if (CONFIG_WMV2_ENCODER) - ff_wmv2_encode_mb(s, s->block, motion_x, motion_y); - break; - case AV_CODEC_ID_H261: - if (CONFIG_H261_ENCODER) - ff_h261_encode_mb(s, s->block, motion_x, motion_y); - break; - case AV_CODEC_ID_H263: - case AV_CODEC_ID_H263P: - case AV_CODEC_ID_FLV1: - case AV_CODEC_ID_RV10: - case AV_CODEC_ID_RV20: - if (CONFIG_H263_ENCODER) - ff_h263_encode_mb(s, s->block, motion_x, motion_y); - break; -#if CONFIG_MJPEG_ENCODER || CONFIG_AMV_ENCODER - case AV_CODEC_ID_MJPEG: - case AV_CODEC_ID_AMV: - ff_mjpeg_encode_mb(s, s->block); - break; -#endif - case AV_CODEC_ID_SPEEDHQ: - if (CONFIG_SPEEDHQ_ENCODER) - ff_speedhq_encode_mb(s, s->block); - break; - default: - av_assert1(0); - } + s->encode_mb(s, s->block, motion_x, motion_y); } static void encode_mb(MpegEncContext *s, int motion_x, int motion_y) diff --git a/libavcodec/msmpeg4enc.c b/libavcodec/msmpeg4enc.c index 01d5707370..9e58a91a80 100644 --- a/libavcodec/msmpeg4enc.c +++ b/libavcodec/msmpeg4enc.c @@ -370,9 +370,9 @@ static void msmpeg4v2_encode_motion(MpegEncContext * s, int val) } } -void ff_msmpeg4_encode_mb(MpegEncContext * s, - int16_t block[6][64], - int motion_x, int motion_y) +static void msmpeg4_encode_mb(MpegEncContext *const s, + int16_t block[][64], + int motion_x, int motion_y) { int cbp, coded_cbp, i; int pred_x, pred_y; @@ -670,8 +670,10 @@ av_cold void ff_msmpeg4_encode_init(MPVMainEncContext *const m) ff_msmpeg4_common_init(s); - if (s->msmpeg4_version <= MSMP4_WMV1) + if (s->msmpeg4_version <= MSMP4_WMV1) { m->encode_picture_header = msmpeg4_encode_picture_header; + s->encode_mb = msmpeg4_encode_mb; + } if (s->msmpeg4_version >= MSMP4_WMV1) { s->min_qcoeff = -255; diff --git a/libavcodec/msmpeg4enc.h b/libavcodec/msmpeg4enc.h index 5511e01283..dde1fb6b93 100644 --- a/libavcodec/msmpeg4enc.h +++ b/libavcodec/msmpeg4enc.h @@ -35,8 +35,6 @@ typedef struct MSMPEG4EncContext { void ff_msmpeg4_encode_init(MPVMainEncContext *m); void ff_msmpeg4_encode_ext_header(MpegEncContext *s); -void ff_msmpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], - int motion_x, int motion_y); void ff_msmpeg4_encode_block(MpegEncContext * s, int16_t * block, int n); void ff_msmpeg4_handle_slices(MpegEncContext *s); void ff_msmpeg4_encode_motion(MpegEncContext * s, int mx, int my); diff --git a/libavcodec/speedhqenc.c b/libavcodec/speedhqenc.c index 1ba5dcc68f..1e28702f18 100644 --- a/libavcodec/speedhqenc.c +++ b/libavcodec/speedhqenc.c @@ -207,7 +207,8 @@ static void encode_block(MpegEncContext *s, int16_t *block, int n) put_bits_le(&s->pb, 4, 6); } -void ff_speedhq_encode_mb(MpegEncContext *s, int16_t block[12][64]) +static void speedhq_encode_mb(MpegEncContext *const s, int16_t block[12][64], + int unused_x, int unused_y) { int i; for(i=0;i<6;i++) { @@ -263,6 +264,7 @@ static av_cold int speedhq_encode_init(AVCodecContext *avctx) } m->encode_picture_header = speedhq_encode_picture_header; + s->encode_mb = speedhq_encode_mb; s->min_qcoeff = -2048; s->max_qcoeff = 2047; diff --git a/libavcodec/speedhqenc.h b/libavcodec/speedhqenc.h index f02fa1f51a..e804ce714a 100644 --- a/libavcodec/speedhqenc.h +++ b/libavcodec/speedhqenc.h @@ -33,8 +33,6 @@ #include "mpegvideo.h" -void ff_speedhq_encode_mb(MpegEncContext *s, int16_t block[12][64]); - void ff_speedhq_end_slice(MpegEncContext *s); static inline int ff_speedhq_mb_rows_in_slice(int slice_num, int mb_height) diff --git a/libavcodec/wmv2enc.c b/libavcodec/wmv2enc.c index d70a680fb3..3ab3e75722 100644 --- a/libavcodec/wmv2enc.c +++ b/libavcodec/wmv2enc.c @@ -29,7 +29,6 @@ #include "msmpeg4data.h" #include "msmpeg4_vc1_data.h" #include "wmv2.h" -#include "wmv2enc.h" #define WMV2_EXTRADATA_SIZE 4 @@ -147,8 +146,8 @@ static int wmv2_encode_picture_header(MPVMainEncContext *const m) /* Nearly identical to wmv1 but that is just because we do not use the * useless M$ crap features. It is duplicated here in case someone wants * to add support for these crap features. */ -void ff_wmv2_encode_mb(MpegEncContext *s, int16_t block[6][64], - int motion_x, int motion_y) +static void wmv2_encode_mb(MpegEncContext *const s, int16_t block[][64], + int motion_x, int motion_y) { WMV2EncContext *const w = (WMV2EncContext *) s; int cbp, coded_cbp, i; @@ -224,6 +223,7 @@ static av_cold int wmv2_encode_init(AVCodecContext *avctx) int ret; w->msmpeg4.m.encode_picture_header = wmv2_encode_picture_header; + s->encode_mb = wmv2_encode_mb; s->private_ctx = &w->common; ret = ff_mpv_encode_init(avctx); if (ret < 0) diff --git a/libavcodec/wmv2enc.h b/libavcodec/wmv2enc.h deleted file mode 100644 index 59046c6a07..0000000000 --- a/libavcodec/wmv2enc.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2002 The FFmpeg Project - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVCODEC_WMV2ENC_H -#define AVCODEC_WMV2ENC_H - -#include "mpegvideo.h" - -void ff_wmv2_encode_mb(MpegEncContext * s, int16_t block[6][64], - int motion_x, int motion_y); - - -#endif -- 2.45.2 [-- Attachment #36: 0035-avcodec-mjpegenc-Reindent-after-the-previous-commit.patch --] [-- Type: text/x-patch, Size: 4993 bytes --] From 85a48c91d7df84aedcb7de0a3ef86c3234f51d68 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Tue, 4 Mar 2025 19:26:50 +0100 Subject: [PATCH 35/77] avcodec/mjpegenc: Reindent after the previous commit Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mjpegenc.c | 102 ++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 53 deletions(-) diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c index 6c58c04892..a6f202da0a 100644 --- a/libavcodec/mjpegenc.c +++ b/libavcodec/mjpegenc.c @@ -466,71 +466,67 @@ static void encode_block(MpegEncContext *s, int16_t *block, int n) static void mjpeg_record_mb(MpegEncContext *const s, int16_t block[][64], int unused_x, int unused_y) { - int i; - if (s->chroma_format == CHROMA_444) { - record_block(s, block[0], 0); - record_block(s, block[2], 2); - record_block(s, block[4], 4); - record_block(s, block[8], 8); + if (s->chroma_format == CHROMA_444) { + record_block(s, block[0], 0); + record_block(s, block[2], 2); + record_block(s, block[4], 4); + record_block(s, block[8], 8); + record_block(s, block[5], 5); + record_block(s, block[9], 9); + + if (16*s->mb_x+8 < s->width) { + record_block(s, block[1], 1); + record_block(s, block[3], 3); + record_block(s, block[6], 6); + record_block(s, block[10], 10); + record_block(s, block[7], 7); + record_block(s, block[11], 11); + } + } else { + for (int i = 0; i < 5; i++) + record_block(s, block[i], i); + if (s->chroma_format == CHROMA_420) { record_block(s, block[5], 5); - record_block(s, block[9], 9); - - if (16*s->mb_x+8 < s->width) { - record_block(s, block[1], 1); - record_block(s, block[3], 3); - record_block(s, block[6], 6); - record_block(s, block[10], 10); - record_block(s, block[7], 7); - record_block(s, block[11], 11); - } } else { - for(i=0;i<5;i++) { - record_block(s, block[i], i); - } - if (s->chroma_format == CHROMA_420) { - record_block(s, block[5], 5); - } else { - record_block(s, block[6], 6); - record_block(s, block[5], 5); - record_block(s, block[7], 7); - } + record_block(s, block[6], 6); + record_block(s, block[5], 5); + record_block(s, block[7], 7); } + } } static void mjpeg_encode_mb(MpegEncContext *const s, int16_t block[][64], int unused_x, int unused_y) { - int i; - if (s->chroma_format == CHROMA_444) { - encode_block(s, block[0], 0); - encode_block(s, block[2], 2); - encode_block(s, block[4], 4); - encode_block(s, block[8], 8); + if (s->chroma_format == CHROMA_444) { + encode_block(s, block[0], 0); + encode_block(s, block[2], 2); + encode_block(s, block[4], 4); + encode_block(s, block[8], 8); + encode_block(s, block[5], 5); + encode_block(s, block[9], 9); + + if (16 * s->mb_x + 8 < s->width) { + encode_block(s, block[1], 1); + encode_block(s, block[3], 3); + encode_block(s, block[6], 6); + encode_block(s, block[10], 10); + encode_block(s, block[7], 7); + encode_block(s, block[11], 11); + } + } else { + for (int i = 0; i < 5; i++) + encode_block(s, block[i], i); + if (s->chroma_format == CHROMA_420) { encode_block(s, block[5], 5); - encode_block(s, block[9], 9); - - if (16*s->mb_x+8 < s->width) { - encode_block(s, block[1], 1); - encode_block(s, block[3], 3); - encode_block(s, block[6], 6); - encode_block(s, block[10], 10); - encode_block(s, block[7], 7); - encode_block(s, block[11], 11); - } } else { - for(i=0;i<5;i++) { - encode_block(s, block[i], i); - } - if (s->chroma_format == CHROMA_420) { - encode_block(s, block[5], 5); - } else { - encode_block(s, block[6], 6); - encode_block(s, block[5], 5); - encode_block(s, block[7], 7); - } + encode_block(s, block[6], 6); + encode_block(s, block[5], 5); + encode_block(s, block[7], 7); } + } - s->i_tex_bits += get_bits_diff(s); + s->i_tex_bits += get_bits_diff(s); } static av_cold int mjpeg_encode_init(AVCodecContext *avctx) -- 2.45.2 [-- Attachment #37: 0036-avcodec-mpegvideo-Add-pointer-to-main-context-to-sli.patch --] [-- Type: text/x-patch, Size: 2686 bytes --] From f0abfd94263082284c6e434d98dc9a093c9e170d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sat, 15 Mar 2025 07:16:33 +0100 Subject: [PATCH 36/77] avcodec/mpegvideo: Add pointer to main context to slice contexts It is a pointer to const to allow the slice threads to inspect values without modifying them; also make it a simple cast for codecs that don't support slice threading. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpegvideo.c | 2 ++ libavcodec/mpegvideo.h | 4 ++++ libavcodec/mpegvideoenc.h | 12 ++++++++++++ 3 files changed, 18 insertions(+) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 9cd67151aa..bc367fba07 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -387,6 +387,8 @@ av_cold int ff_mpv_init_duplicate_contexts(MpegEncContext *s) { int nb_slices = s->slice_context_count, ret; + s->parent = s; + /* We initialize the copies before the original so that * fields allocated in init_duplicate_context are NULL after * copying. This prevents double-frees upon allocation error. */ diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index bdab782b29..04eade13aa 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -86,6 +86,10 @@ typedef struct MpegEncContext { uint8_t permutated_intra_v_scantable[64]; struct AVCodecContext *avctx; + union { + const struct MpegEncContext *parent; + const struct MPVMainEncContext *encparent; + }; /* The following pointer is intended for codecs sharing code * between decoder and encoder and in need of a common context to do so. */ void *private_ctx; diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h index 4b74f8eb46..65bb3447b3 100644 --- a/libavcodec/mpegvideoenc.h +++ b/libavcodec/mpegvideoenc.h @@ -30,6 +30,7 @@ #include <float.h> +#include "libavutil/avassert.h" #include "libavutil/opt.h" #include "mpegvideo.h" #include "ratecontrol.h" @@ -91,6 +92,17 @@ typedef struct MPVMainEncContext { int64_t mc_mb_var_sum; ///< motion compensated MB variance for current frame } MPVMainEncContext; +static inline const MPVMainEncContext *slice_to_mainenc(const MpegEncContext *s) +{ +#ifdef NO_SLICE_THREADING_HERE + av_assert2(s->slice_context_count <= 1 && + !(s->avctx->codec->capabilities & AV_CODEC_CAP_SLICE_THREADS)); + return (const MPVMainEncContext*)s; +#else + return s->encparent; +#endif +} + #define MAX_FCODE 7 #define UNI_AC_ENC_INDEX(run,level) ((run)*128 + (level)) #define INPLACE_OFFSET 16 -- 2.45.2 [-- Attachment #38: 0037-avcodec-mpegvideo-Move-max_b_frames-to-MPVMainEncCon.patch --] [-- Type: text/x-patch, Size: 14009 bytes --] From 45f19ed03d4c17dfbc0b8ab5e04fa9c1d11a6fe8 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Tue, 18 Mar 2025 11:20:25 +0100 Subject: [PATCH 37/77] avcodec/mpegvideo: Move max_b_frames to MPVMainEncContext Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpeg4videoenc.c | 17 +++++++------- libavcodec/mpegvideo.h | 1 - libavcodec/mpegvideo_enc.c | 48 ++++++++++++++++++-------------------- libavcodec/mpegvideoenc.h | 1 + libavcodec/ratecontrol.c | 6 ++--- 5 files changed, 36 insertions(+), 37 deletions(-) diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c index 4f97199eba..d54064cd89 100644 --- a/libavcodec/mpeg4videoenc.c +++ b/libavcodec/mpeg4videoenc.c @@ -650,11 +650,11 @@ static void mpeg4_encode_mb(MpegEncContext *const s, int16_t block[][64], if ((cbp | motion_x | motion_y | s->dquant) == 0 && s->mv_type == MV_TYPE_16X16) { + const MPVMainEncContext *const m = slice_to_mainenc(s); /* Check if the B-frames can skip it too, as we must skip it * if we skip here why didn't they just compress * the skip-mb bits instead of reusing them ?! */ - if (s->max_b_frames > 0) { - int i; + if (m->max_b_frames > 0) { int x, y, offset; const uint8_t *p_pic; @@ -665,7 +665,7 @@ static void mpeg4_encode_mb(MpegEncContext *const s, int16_t block[][64], p_pic = s->new_pic->data[0] + offset; s->mb_skipped = 1; - for (i = 0; i < s->max_b_frames; i++) { + for (int i = 0; i < m->max_b_frames; i++) { const uint8_t *b_pic; int diff; const MPVPicture *pic = s->reordered_input_picture[i + 1]; @@ -929,14 +929,15 @@ static void mpeg4_encode_gop_header(MpegEncContext *s) ff_mpeg4_stuffing(&s->pb); } -static void mpeg4_encode_visual_object_header(MpegEncContext *s) +static void mpeg4_encode_visual_object_header(MPVMainEncContext *const m) { + MpegEncContext *const s = &m->s; int profile_and_level_indication; int vo_ver_id; if (s->avctx->profile != AV_PROFILE_UNKNOWN) { profile_and_level_indication = s->avctx->profile << 4; - } else if (s->max_b_frames || s->quarter_sample) { + } else if (m->max_b_frames || s->quarter_sample) { profile_and_level_indication = 0xF0; // adv simple } else { profile_and_level_indication = 0x00; // simple @@ -978,7 +979,7 @@ static void mpeg4_encode_vol_header(Mpeg4EncContext *const m4, MpegEncContext *const s = &m4->m.s; int vo_ver_id, vo_type, aspect_ratio_info; - if (s->max_b_frames || s->quarter_sample) { + if (m4->m.max_b_frames || s->quarter_sample) { vo_ver_id = 5; vo_type = ADV_SIMPLE_VO_TYPE; } else { @@ -1072,7 +1073,7 @@ static int mpeg4_encode_picture_header(MPVMainEncContext *const m) if (s->pict_type == AV_PICTURE_TYPE_I) { if (!(s->avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)) { if (s->avctx->strict_std_compliance < FF_COMPLIANCE_VERY_STRICT) // HACK, the reference sw is buggy - mpeg4_encode_visual_object_header(s); + mpeg4_encode_visual_object_header(m); if (s->avctx->strict_std_compliance < FF_COMPLIANCE_VERY_STRICT || s->picture_number == 0) // HACK, the reference sw is buggy mpeg4_encode_vol_header(m4, 0, 0); } @@ -1339,7 +1340,7 @@ static av_cold int encode_init(AVCodecContext *avctx) return AVERROR(ENOMEM); init_put_bits(&s->pb, s->avctx->extradata, 1024); - mpeg4_encode_visual_object_header(s); + mpeg4_encode_visual_object_header(m); mpeg4_encode_vol_header(m4, 0, 0); // ff_mpeg4_stuffing(&s->pb); ? diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 04eade13aa..d25b5cdf3a 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -106,7 +106,6 @@ typedef struct MpegEncContext { enum AVCodecID codec_id; /* see AV_CODEC_ID_xxx */ int encoding; ///< true if we are encoding (vs decoding) - int max_b_frames; ///< max number of B-frames for encoding int luma_elim_threshold; int chroma_elim_threshold; int workaround_bugs; ///< workaround bugs in encoders which cannot be detected automatically diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 6650e5b35d..ffa652d02d 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -470,9 +470,9 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) "max b frames must be 0 or positive for mpegvideo based encoders\n"); return AVERROR(EINVAL); } - s->max_b_frames = avctx->max_b_frames; + m->max_b_frames = avctx->max_b_frames; s->codec_id = avctx->codec->id; - if (s->max_b_frames && !(avctx->codec->capabilities & AV_CODEC_CAP_DELAY)) { + if (m->max_b_frames && !(avctx->codec->capabilities & AV_CODEC_CAP_DELAY)) { av_log(avctx, AV_LOG_ERROR, "B-frames not supported by codec\n"); return AVERROR(EINVAL); } @@ -692,7 +692,7 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) "set strict_std_compliance to 'unofficial' or lower in order to allow it\n"); return AVERROR(EINVAL); } - if (s->max_b_frames != 0) { + if (m->max_b_frames != 0) { av_log(avctx, AV_LOG_ERROR, "B-frames cannot be used with low delay\n"); return AVERROR(EINVAL); @@ -744,7 +744,7 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) case AV_CODEC_ID_MPEG1VIDEO: s->out_format = FMT_MPEG1; s->low_delay = !!(avctx->flags & AV_CODEC_FLAG_LOW_DELAY); - avctx->delay = s->low_delay ? 0 : (s->max_b_frames + 1); + avctx->delay = s->low_delay ? 0 : (m->max_b_frames + 1); ff_mpeg1_encode_init(s); break; #endif @@ -834,8 +834,8 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) s->h263_pred = 1; s->unrestricted_mv = 1; s->flipflop_rounding = 1; - s->low_delay = s->max_b_frames ? 0 : 1; - avctx->delay = s->low_delay ? 0 : (s->max_b_frames + 1); + s->low_delay = m->max_b_frames ? 0 : 1; + avctx->delay = s->low_delay ? 0 : (m->max_b_frames + 1); break; case AV_CODEC_ID_MSMPEG4V2: s->out_format = FMT_H263; @@ -1013,7 +1013,7 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) return ret; if (m->b_frame_strategy == 2) { - for (i = 0; i < s->max_b_frames + 2; i++) { + for (int i = 0; i < m->max_b_frames + 2; i++) { m->tmp_frames[i] = av_frame_alloc(); if (!m->tmp_frames[i]) return AVERROR(ENOMEM); @@ -1255,7 +1255,7 @@ static int load_input_picture(MPVMainEncContext *const m, const AVFrame *pic_arg MPVPicture *pic = NULL; int64_t pts; int display_picture_number = 0, ret; - int encoding_delay = s->max_b_frames ? s->max_b_frames + int encoding_delay = m->max_b_frames ? m->max_b_frames : (s->low_delay ? 0 : 1); int flush_offset = 1; int direct = 1; @@ -1461,7 +1461,7 @@ static int estimate_best_b_count(MPVMainEncContext *const m) const int scale = m->brd_scale; int width = s->width >> scale; int height = s->height >> scale; - int i, j, out_size, p_lambda, b_lambda, lambda2; + int out_size, p_lambda, b_lambda, lambda2; int64_t best_rd = INT64_MAX; int best_b_count = -1; int ret = 0; @@ -1481,7 +1481,7 @@ static int estimate_best_b_count(MPVMainEncContext *const m) lambda2 = (b_lambda * b_lambda + (1 << FF_LAMBDA_SHIFT) / 2) >> FF_LAMBDA_SHIFT; - for (i = 0; i < s->max_b_frames + 2; i++) { + for (int i = 0; i < m->max_b_frames + 2; i++) { const MPVPicture *pre_input_ptr = i ? s->input_picture[i - 1] : s->next_pic.ptr; @@ -1513,7 +1513,7 @@ static int estimate_best_b_count(MPVMainEncContext *const m) } } - for (j = 0; j < s->max_b_frames + 1; j++) { + for (int j = 0; j < m->max_b_frames + 1; j++) { AVCodecContext *c; int64_t rd = 0; @@ -1536,7 +1536,7 @@ static int estimate_best_b_count(MPVMainEncContext *const m) c->me_sub_cmp = s->avctx->me_sub_cmp; c->pix_fmt = AV_PIX_FMT_YUV420P; c->time_base = s->avctx->time_base; - c->max_b_frames = s->max_b_frames; + c->max_b_frames = m->max_b_frames; ret = avcodec_open2(c, s->avctx->codec, NULL); if (ret < 0) @@ -1554,8 +1554,8 @@ static int estimate_best_b_count(MPVMainEncContext *const m) //rd += (out_size * lambda2) >> FF_LAMBDA_SHIFT; - for (i = 0; i < s->max_b_frames + 1; i++) { - int is_p = i % (j + 1) == j || i == s->max_b_frames; + for (int i = 0; i < m->max_b_frames + 1; i++) { + int is_p = i % (j + 1) == j || i == m->max_b_frames; m->tmp_frames[i + 1]->pict_type = is_p ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_B; @@ -1640,7 +1640,7 @@ static int set_bframe_chain_length(MPVMainEncContext *const m) int b_frames = 0; if (s->avctx->flags & AV_CODEC_FLAG_PASS2) { - for (int i = 0; i < s->max_b_frames + 1; i++) { + for (int i = 0; i < m->max_b_frames + 1; i++) { int pict_num = s->input_picture[0]->display_picture_number + i; if (pict_num >= m->rc_context.num_entries) @@ -1656,12 +1656,11 @@ static int set_bframe_chain_length(MPVMainEncContext *const m) } if (m->b_frame_strategy == 0) { - b_frames = s->max_b_frames; + b_frames = m->max_b_frames; while (b_frames && !s->input_picture[b_frames]) b_frames--; } else if (m->b_frame_strategy == 1) { - int i; - for (i = 1; i < s->max_b_frames + 1; i++) { + for (int i = 1; i < m->max_b_frames + 1; i++) { if (s->input_picture[i] && s->input_picture[i]->b_frame_score == 0) { s->input_picture[i]->b_frame_score = @@ -1671,19 +1670,18 @@ static int set_bframe_chain_length(MPVMainEncContext *const m) s->linesize) + 1; } } - for (i = 0; i < s->max_b_frames + 1; i++) { + for (int i = 0; i < m->max_b_frames + 1; i++) { if (!s->input_picture[i] || s->input_picture[i]->b_frame_score - 1 > - s->mb_num / m->b_sensitivity) + s->mb_num / m->b_sensitivity) { + b_frames = FFMAX(0, i - 1); break; + } } - b_frames = FFMAX(0, i - 1); - /* reset scores */ - for (i = 0; i < b_frames + 1; i++) { + for (int i = 0; i < b_frames + 1; i++) s->input_picture[i]->b_frame_score = 0; - } } else if (m->b_frame_strategy == 2) { b_frames = estimate_best_b_count(m); if (b_frames < 0) { @@ -1700,7 +1698,7 @@ static int set_bframe_chain_length(MPVMainEncContext *const m) b_frames = i; } if (s->input_picture[b_frames]->f->pict_type == AV_PICTURE_TYPE_B && - b_frames == s->max_b_frames) { + b_frames == m->max_b_frames) { av_log(s->avctx, AV_LOG_ERROR, "warning, too many B-frames in a row\n"); } diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h index 65bb3447b3..27bd099aad 100644 --- a/libavcodec/mpegvideoenc.h +++ b/libavcodec/mpegvideoenc.h @@ -44,6 +44,7 @@ typedef struct MPVMainEncContext { int intra_only; ///< if true, only intra pictures are generated int gop_size; + int max_b_frames; ///< max number of B-frames int picture_in_gop_number; ///< 0-> first pic in gop, ... int input_picture_number; ///< used to set pic->display_picture_number int coded_picture_number; ///< used to set pic->coded_picture_number diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c index 895e557877..20e3ccabf8 100644 --- a/libavcodec/ratecontrol.c +++ b/libavcodec/ratecontrol.c @@ -581,7 +581,7 @@ av_cold int ff_rate_control_init(MPVMainEncContext *const m) p = s->avctx->stats_in; for (i = -1; p; i++) p = strchr(p + 1, ';'); - i += s->max_b_frames; + i += m->max_b_frames; if (i <= 0 || i >= INT_MAX / sizeof(RateControlEntry)) return -1; rcc->entry = av_mallocz(i * sizeof(RateControlEntry)); @@ -602,7 +602,7 @@ av_cold int ff_rate_control_init(MPVMainEncContext *const m) /* read stats */ p = s->avctx->stats_in; - for (i = 0; i < rcc->num_entries - s->max_b_frames; i++) { + for (i = 0; i < rcc->num_entries - m->max_b_frames; i++) { RateControlEntry *rce; int picture_number; int e; @@ -663,7 +663,7 @@ av_cold int ff_rate_control_init(MPVMainEncContext *const m) if (i % ((m->gop_size + 3) / 4) == 0) rce.pict_type = AV_PICTURE_TYPE_I; - else if (i % (s->max_b_frames + 1)) + else if (i % (m->max_b_frames + 1)) rce.pict_type = AV_PICTURE_TYPE_B; else rce.pict_type = AV_PICTURE_TYPE_P; -- 2.45.2 [-- Attachment #39: 0038-avcodec-mpegvideo-Move-MPVPicture-arrays-to-MPVMainE.patch --] [-- Type: text/x-patch, Size: 18360 bytes --] From 9a126503f549cd5f8f39f1c9bf515633489adfc1 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Tue, 18 Mar 2025 11:47:58 +0100 Subject: [PATCH 38/77] avcodec/mpegvideo: Move MPVPicture arrays to MPVMainEncContext Also avoid allocations while at it. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpeg4videoenc.c | 11 ++-- libavcodec/mpegvideo.h | 2 - libavcodec/mpegvideo_enc.c | 124 ++++++++++++++++++------------------- libavcodec/mpegvideoenc.h | 3 + 4 files changed, 68 insertions(+), 72 deletions(-) diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c index d54064cd89..4c31e7e9c8 100644 --- a/libavcodec/mpeg4videoenc.c +++ b/libavcodec/mpeg4videoenc.c @@ -668,7 +668,7 @@ static void mpeg4_encode_mb(MpegEncContext *const s, int16_t block[][64], for (int i = 0; i < m->max_b_frames; i++) { const uint8_t *b_pic; int diff; - const MPVPicture *pic = s->reordered_input_picture[i + 1]; + const MPVPicture *pic = m->reordered_input_picture[i + 1]; if (!pic || pic->f->pict_type != AV_PICTURE_TYPE_B) break; @@ -900,16 +900,17 @@ void ff_set_mpeg4_time(MpegEncContext *s) } } -static void mpeg4_encode_gop_header(MpegEncContext *s) +static void mpeg4_encode_gop_header(MPVMainEncContext *const m) { + MpegEncContext *const s = &m->s; int64_t hours, minutes, seconds; int64_t time; put_bits32(&s->pb, GOP_STARTCODE); time = s->cur_pic.ptr->f->pts; - if (s->reordered_input_picture[1]) - time = FFMIN(time, s->reordered_input_picture[1]->f->pts); + if (m->reordered_input_picture[1]) + time = FFMIN(time, m->reordered_input_picture[1]->f->pts); time = time * s->avctx->time_base.num; s->last_time_base = FFUDIV(time, s->avctx->time_base.den); @@ -1077,7 +1078,7 @@ static int mpeg4_encode_picture_header(MPVMainEncContext *const m) if (s->avctx->strict_std_compliance < FF_COMPLIANCE_VERY_STRICT || s->picture_number == 0) // HACK, the reference sw is buggy mpeg4_encode_vol_header(m4, 0, 0); } - mpeg4_encode_gop_header(s); + mpeg4_encode_gop_header(m); } s->partitioned_frame = s->data_partitioning && s->pict_type != AV_PICTURE_TYPE_B; diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index d25b5cdf3a..12cb8fc3d5 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -123,8 +123,6 @@ typedef struct MpegEncContext { ptrdiff_t linesize; ///< line size, in bytes, may be different from width ptrdiff_t uvlinesize; ///< line size, for chroma in bytes, may be different from width struct AVRefStructPool *picture_pool; ///< Pool for MPVPictures - MPVPicture **input_picture;///< next pictures on display order for encoding - MPVPicture **reordered_input_picture; ///< pointer to the next pictures in coded order for encoding BufferPoolContext buffer_pools; diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index ffa652d02d..8af572a69e 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -915,8 +915,6 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) return ret; if (!(avctx->stats_out = av_mallocz(256)) || - !FF_ALLOCZ_TYPED_ARRAY(s->input_picture, MPVENC_MAX_B_FRAMES + 1) || - !FF_ALLOCZ_TYPED_ARRAY(s->reordered_input_picture, MPVENC_MAX_B_FRAMES + 1) || !(s->new_pic = av_frame_alloc()) || !(s->picture_pool = ff_mpv_alloc_pic_pool(0))) return AVERROR(ENOMEM); @@ -1049,11 +1047,9 @@ av_cold int ff_mpv_encode_end(AVCodecContext *avctx) ff_mpv_common_end(s); av_refstruct_pool_uninit(&s->picture_pool); - if (s->input_picture && s->reordered_input_picture) { - for (int i = 0; i < MPVENC_MAX_B_FRAMES + 1; i++) { - av_refstruct_unref(&s->input_picture[i]); - av_refstruct_unref(&s->reordered_input_picture[i]); - } + for (int i = 0; i < MPVENC_MAX_B_FRAMES + 1; i++) { + av_refstruct_unref(&m->input_picture[i]); + av_refstruct_unref(&m->reordered_input_picture[i]); } for (int i = 0; i < FF_ARRAY_ELEMS(m->tmp_frames); i++) av_frame_free(&m->tmp_frames[i]); @@ -1077,8 +1073,6 @@ av_cold int ff_mpv_encode_end(AVCodecContext *avctx) av_freep(&s->q_intra_matrix); av_freep(&s->q_intra_matrix16); - av_freep(&s->input_picture); - av_freep(&s->reordered_input_picture); av_freep(&s->dct_offset); av_freep(&s->mb_var); av_freep(&s->mc_mb_var); @@ -1260,7 +1254,7 @@ static int load_input_picture(MPVMainEncContext *const m, const AVFrame *pic_arg int flush_offset = 1; int direct = 1; - av_assert1(!s->input_picture[0]); + av_assert1(!m->input_picture[0]); if (pic_arg) { pts = pic_arg->pts; @@ -1363,14 +1357,14 @@ static int load_input_picture(MPVMainEncContext *const m, const AVFrame *pic_arg pic->display_picture_number = display_picture_number; pic->f->pts = pts; // we set this here to avoid modifying pic_arg - } else if (!s->reordered_input_picture[1]) { + } else if (!m->reordered_input_picture[1]) { /* Flushing: When the above check is true, the encoder is about to run * out of frames to encode. Check if there are input_pictures left; - * if so, ensure s->input_picture[0] contains the first picture. + * if so, ensure m->input_picture[0] contains the first picture. * A flush_offset != 1 will only happen if we did not receive enough * input frames. */ for (flush_offset = 0; flush_offset < encoding_delay + 1; flush_offset++) - if (s->input_picture[flush_offset]) + if (m->input_picture[flush_offset]) break; encoding_delay -= flush_offset - 1; @@ -1378,11 +1372,11 @@ static int load_input_picture(MPVMainEncContext *const m, const AVFrame *pic_arg /* shift buffer entries */ for (int i = flush_offset; i <= MPVENC_MAX_B_FRAMES; i++) - s->input_picture[i - flush_offset] = s->input_picture[i]; + m->input_picture[i - flush_offset] = m->input_picture[i]; for (int i = MPVENC_MAX_B_FRAMES + 1 - flush_offset; i <= MPVENC_MAX_B_FRAMES; i++) - s->input_picture[i] = NULL; + m->input_picture[i] = NULL; - s->input_picture[encoding_delay] = pic; + m->input_picture[encoding_delay] = pic; return 0; fail: @@ -1482,7 +1476,7 @@ static int estimate_best_b_count(MPVMainEncContext *const m) FF_LAMBDA_SHIFT; for (int i = 0; i < m->max_b_frames + 2; i++) { - const MPVPicture *pre_input_ptr = i ? s->input_picture[i - 1] : + const MPVPicture *pre_input_ptr = i ? m->input_picture[i - 1] : s->next_pic.ptr; if (pre_input_ptr) { @@ -1517,7 +1511,7 @@ static int estimate_best_b_count(MPVMainEncContext *const m) AVCodecContext *c; int64_t rd = 0; - if (!s->input_picture[j]) + if (!m->input_picture[j]) break; c = avcodec_alloc_context3(NULL); @@ -1612,16 +1606,16 @@ static int set_bframe_chain_length(MPVMainEncContext *const m) MpegEncContext *const s = &m->s; /* Either nothing to do or can't do anything */ - if (s->reordered_input_picture[0] || !s->input_picture[0]) + if (m->reordered_input_picture[0] || !m->input_picture[0]) return 0; /* set next picture type & ordering */ if (m->frame_skip_threshold || m->frame_skip_factor) { if (m->picture_in_gop_number < m->gop_size && s->next_pic.ptr && - skip_check(m, s->input_picture[0], s->next_pic.ptr)) { + skip_check(m, m->input_picture[0], s->next_pic.ptr)) { // FIXME check that the gop check above is +-1 correct - av_refstruct_unref(&s->input_picture[0]); + av_refstruct_unref(&m->input_picture[0]); ff_vbv_update(m, 0); @@ -1631,48 +1625,48 @@ static int set_bframe_chain_length(MPVMainEncContext *const m) if (/* m->picture_in_gop_number >= m->gop_size || */ !s->next_pic.ptr || m->intra_only) { - s->reordered_input_picture[0] = s->input_picture[0]; - s->input_picture[0] = NULL; - s->reordered_input_picture[0]->f->pict_type = AV_PICTURE_TYPE_I; - s->reordered_input_picture[0]->coded_picture_number = + m->reordered_input_picture[0] = m->input_picture[0]; + m->input_picture[0] = NULL; + m->reordered_input_picture[0]->f->pict_type = AV_PICTURE_TYPE_I; + m->reordered_input_picture[0]->coded_picture_number = m->coded_picture_number++; } else { int b_frames = 0; if (s->avctx->flags & AV_CODEC_FLAG_PASS2) { for (int i = 0; i < m->max_b_frames + 1; i++) { - int pict_num = s->input_picture[0]->display_picture_number + i; + int pict_num = m->input_picture[0]->display_picture_number + i; if (pict_num >= m->rc_context.num_entries) break; - if (!s->input_picture[i]) { + if (!m->input_picture[i]) { m->rc_context.entry[pict_num - 1].new_pict_type = AV_PICTURE_TYPE_P; break; } - s->input_picture[i]->f->pict_type = + m->input_picture[i]->f->pict_type = m->rc_context.entry[pict_num].new_pict_type; } } if (m->b_frame_strategy == 0) { b_frames = m->max_b_frames; - while (b_frames && !s->input_picture[b_frames]) + while (b_frames && !m->input_picture[b_frames]) b_frames--; } else if (m->b_frame_strategy == 1) { for (int i = 1; i < m->max_b_frames + 1; i++) { - if (s->input_picture[i] && - s->input_picture[i]->b_frame_score == 0) { - s->input_picture[i]->b_frame_score = + if (m->input_picture[i] && + m->input_picture[i]->b_frame_score == 0) { + m->input_picture[i]->b_frame_score = get_intra_count(s, - s->input_picture[i ]->f->data[0], - s->input_picture[i - 1]->f->data[0], + m->input_picture[i ]->f->data[0], + m->input_picture[i - 1]->f->data[0], s->linesize) + 1; } } for (int i = 0; i < m->max_b_frames + 1; i++) { - if (!s->input_picture[i] || - s->input_picture[i]->b_frame_score - 1 > + if (!m->input_picture[i] || + m->input_picture[i]->b_frame_score - 1 > s->mb_num / m->b_sensitivity) { b_frames = FFMAX(0, i - 1); break; @@ -1681,11 +1675,11 @@ static int set_bframe_chain_length(MPVMainEncContext *const m) /* reset scores */ for (int i = 0; i < b_frames + 1; i++) - s->input_picture[i]->b_frame_score = 0; + m->input_picture[i]->b_frame_score = 0; } else if (m->b_frame_strategy == 2) { b_frames = estimate_best_b_count(m); if (b_frames < 0) { - av_refstruct_unref(&s->input_picture[0]); + av_refstruct_unref(&m->input_picture[0]); return b_frames; } } @@ -1693,11 +1687,11 @@ static int set_bframe_chain_length(MPVMainEncContext *const m) emms_c(); for (int i = b_frames - 1; i >= 0; i--) { - int type = s->input_picture[i]->f->pict_type; + int type = m->input_picture[i]->f->pict_type; if (type && type != AV_PICTURE_TYPE_B) b_frames = i; } - if (s->input_picture[b_frames]->f->pict_type == AV_PICTURE_TYPE_B && + if (m->input_picture[b_frames]->f->pict_type == AV_PICTURE_TYPE_B && b_frames == m->max_b_frames) { av_log(s->avctx, AV_LOG_ERROR, "warning, too many B-frames in a row\n"); @@ -1710,26 +1704,26 @@ static int set_bframe_chain_length(MPVMainEncContext *const m) } else { if (s->avctx->flags & AV_CODEC_FLAG_CLOSED_GOP) b_frames = 0; - s->input_picture[b_frames]->f->pict_type = AV_PICTURE_TYPE_I; + m->input_picture[b_frames]->f->pict_type = AV_PICTURE_TYPE_I; } } if ((s->avctx->flags & AV_CODEC_FLAG_CLOSED_GOP) && b_frames && - s->input_picture[b_frames]->f->pict_type == AV_PICTURE_TYPE_I) + m->input_picture[b_frames]->f->pict_type == AV_PICTURE_TYPE_I) b_frames--; - s->reordered_input_picture[0] = s->input_picture[b_frames]; - s->input_picture[b_frames] = NULL; - if (s->reordered_input_picture[0]->f->pict_type != AV_PICTURE_TYPE_I) - s->reordered_input_picture[0]->f->pict_type = AV_PICTURE_TYPE_P; - s->reordered_input_picture[0]->coded_picture_number = + m->reordered_input_picture[0] = m->input_picture[b_frames]; + m->input_picture[b_frames] = NULL; + if (m->reordered_input_picture[0]->f->pict_type != AV_PICTURE_TYPE_I) + m->reordered_input_picture[0]->f->pict_type = AV_PICTURE_TYPE_P; + m->reordered_input_picture[0]->coded_picture_number = m->coded_picture_number++; for (int i = 0; i < b_frames; i++) { - s->reordered_input_picture[i + 1] = s->input_picture[i]; - s->input_picture[i] = NULL; - s->reordered_input_picture[i + 1]->f->pict_type = + m->reordered_input_picture[i + 1] = m->input_picture[i]; + m->input_picture[i] = NULL; + m->reordered_input_picture[i + 1]->f->pict_type = AV_PICTURE_TYPE_B; - s->reordered_input_picture[i + 1]->coded_picture_number = + m->reordered_input_picture[i + 1]->coded_picture_number = m->coded_picture_number++; } } @@ -1742,34 +1736,34 @@ static int select_input_picture(MPVMainEncContext *const m) MpegEncContext *const s = &m->s; int ret; - av_assert1(!s->reordered_input_picture[0]); + av_assert1(!m->reordered_input_picture[0]); for (int i = 1; i <= MPVENC_MAX_B_FRAMES; i++) - s->reordered_input_picture[i - 1] = s->reordered_input_picture[i]; - s->reordered_input_picture[MPVENC_MAX_B_FRAMES] = NULL; + m->reordered_input_picture[i - 1] = m->reordered_input_picture[i]; + m->reordered_input_picture[MPVENC_MAX_B_FRAMES] = NULL; ret = set_bframe_chain_length(m); - av_assert1(!s->input_picture[0]); + av_assert1(!m->input_picture[0]); if (ret < 0) return ret; av_frame_unref(s->new_pic); - if (s->reordered_input_picture[0]) { - s->reordered_input_picture[0]->reference = - s->reordered_input_picture[0]->f->pict_type != AV_PICTURE_TYPE_B; + if (m->reordered_input_picture[0]) { + m->reordered_input_picture[0]->reference = + m->reordered_input_picture[0]->f->pict_type != AV_PICTURE_TYPE_B; - if (s->reordered_input_picture[0]->shared || s->avctx->rc_buffer_size) { + if (m->reordered_input_picture[0]->shared || s->avctx->rc_buffer_size) { // input is a shared pix, so we can't modify it -> allocate a new // one & ensure that the shared one is reuseable - av_frame_move_ref(s->new_pic, s->reordered_input_picture[0]->f); + av_frame_move_ref(s->new_pic, m->reordered_input_picture[0]->f); - ret = prepare_picture(s, s->reordered_input_picture[0]->f, s->new_pic); + ret = prepare_picture(s, m->reordered_input_picture[0]->f, s->new_pic); if (ret < 0) goto fail; } else { // input is not a shared pix -> reuse buffer for current_pix - ret = av_frame_ref(s->new_pic, s->reordered_input_picture[0]->f); + ret = av_frame_ref(s->new_pic, m->reordered_input_picture[0]->f); if (ret < 0) goto fail; for (int i = 0; i < MPV_MAX_PLANES; i++) { @@ -1777,8 +1771,8 @@ static int select_input_picture(MPVMainEncContext *const m) s->new_pic->data[i] += INPLACE_OFFSET; } } - s->cur_pic.ptr = s->reordered_input_picture[0]; - s->reordered_input_picture[0] = NULL; + s->cur_pic.ptr = m->reordered_input_picture[0]; + m->reordered_input_picture[0] = NULL; av_assert1(s->mb_width == s->buffer_pools.alloc_mb_width); av_assert1(s->mb_height == s->buffer_pools.alloc_mb_height); av_assert1(s->mb_stride == s->buffer_pools.alloc_mb_stride); @@ -1793,7 +1787,7 @@ static int select_input_picture(MPVMainEncContext *const m) } return 0; fail: - av_refstruct_unref(&s->reordered_input_picture[0]); + av_refstruct_unref(&m->reordered_input_picture[0]); return ret; } diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h index 27bd099aad..f02708e7ec 100644 --- a/libavcodec/mpegvideoenc.h +++ b/libavcodec/mpegvideoenc.h @@ -49,6 +49,9 @@ typedef struct MPVMainEncContext { int input_picture_number; ///< used to set pic->display_picture_number int coded_picture_number; ///< used to set pic->coded_picture_number + MPVPicture *input_picture[MPVENC_MAX_B_FRAMES + 1]; ///< next pictures in display order + MPVPicture *reordered_input_picture[MPVENC_MAX_B_FRAMES + 1]; ///< next pictures in coded order + int64_t user_specified_pts; ///< last non-zero pts from user-supplied AVFrame /** * pts difference between the first and second input frame, used for -- 2.45.2 [-- Attachment #40: 0039-avcodec-mpegvideo-Move-vbv_delay_pos-to-MPVMainEncCo.patch --] [-- Type: text/x-patch, Size: 2848 bytes --] From 61883272a086fff9550f1df3f932a438b9ed6517 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Tue, 18 Mar 2025 11:52:20 +0100 Subject: [PATCH 39/77] avcodec/mpegvideo: Move vbv_delay_pos to MPVMainEncContext Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpeg12enc.c | 2 +- libavcodec/mpegvideo.h | 1 - libavcodec/mpegvideo_enc.c | 4 ++-- libavcodec/mpegvideoenc.h | 3 +++ 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index 1ef88d23b8..43addcfda9 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -350,7 +350,7 @@ static int mpeg1_encode_picture_header(MPVMainEncContext *const m) (s->picture_number - mpeg12->gop_picture_number) & 0x3ff); put_bits(&s->pb, 3, s->pict_type); - s->vbv_delay_pos = put_bytes_count(&s->pb, 0); + m->vbv_delay_pos = put_bytes_count(&s->pb, 0); put_bits(&s->pb, 16, 0xFFFF); /* vbv_delay */ // RAL: Forward f_code also needed for B-frames diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 12cb8fc3d5..ed9224d2fe 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -401,7 +401,6 @@ typedef struct MpegEncContext { /* MPEG-1 specific */ int last_mv_dir; ///< last mv_dir, used for B-frame encoding - int vbv_delay_pos; ///< offset of vbv_delay in the bitstream /* MPEG-2-specific - I wished not to have to support this mess. */ int progressive_sequence; diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 8af572a69e..cb1cf972d8 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -2023,9 +2023,9 @@ vbv_retry: double inbits = avctx->rc_max_rate * av_q2d(avctx->time_base); int minbits = m->frame_bits - 8 * - (s->vbv_delay_pos - 1); + (m->vbv_delay_pos - 1); double bits = m->rc_context.buffer_index + minbits - inbits; - uint8_t *const vbv_delay_ptr = s->pb.buf + s->vbv_delay_pos; + uint8_t *const vbv_delay_ptr = s->pb.buf + m->vbv_delay_pos; if (bits < 0) av_log(avctx, AV_LOG_ERROR, diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h index f02708e7ec..18741e9c22 100644 --- a/libavcodec/mpegvideoenc.h +++ b/libavcodec/mpegvideoenc.h @@ -72,6 +72,9 @@ typedef struct MPVMainEncContext { int lmin, lmax; int vbv_ignore_qmax; + /* MPEG-1/2 specific */ + int vbv_delay_pos; ///< offset of vbv_delay in the bitstream + const uint8_t *fcode_tab; ///< smallest fcode needed for each MV /* frame skip options */ -- 2.45.2 [-- Attachment #41: 0040-avcodec-mpegvideoenc-Add-bit_rate-to-MPVMainEncConte.patch --] [-- Type: text/x-patch, Size: 9507 bytes --] From a28b4480676c75333b84f95f450c6e2d1efe9e64 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sat, 15 Mar 2025 07:25:15 +0100 Subject: [PATCH 40/77] avcodec/mpegvideoenc: Add bit_rate to MPVMainEncContext Use it instead of the MpegEncContext field which will be removed soon. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpeg12enc.c | 2 +- libavcodec/mpegvideo_enc.c | 2 +- libavcodec/mpegvideoenc.h | 1 + libavcodec/msmpeg4enc.c | 15 ++++++++++----- libavcodec/ratecontrol.c | 16 ++++++++-------- libavcodec/snowenc.c | 2 +- libavcodec/wmv2enc.c | 4 ++-- 7 files changed, 24 insertions(+), 18 deletions(-) diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index 43addcfda9..ae87f28d66 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -198,7 +198,7 @@ static void mpeg1_encode_sequence_header(MPEG12EncContext *mpeg12) else /* VBV calculation: Scaled so that a VCD has the proper * VBV size of 40 kilobytes */ - vbv_buffer_size = av_rescale_rnd(s->bit_rate, 20, 1151929 / 2, AV_ROUND_ZERO) * 8 * 1024; + vbv_buffer_size = av_rescale_rnd(mpeg12->mpeg.bit_rate, 20, 1151929 / 2, AV_ROUND_ZERO) * 8 * 1024; vbv_buffer_size = (vbv_buffer_size + 16383) / 16384; put_sbits(&s->pb, 18, v); diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index cb1cf972d8..116c974098 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -449,7 +449,7 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) avctx->bits_per_raw_sample = av_clip(avctx->bits_per_raw_sample, 0, 8); - s->bit_rate = avctx->bit_rate; + m->bit_rate = avctx->bit_rate; s->width = avctx->width; s->height = avctx->height; if (avctx->gop_size > 600 && diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h index 18741e9c22..57b91d169a 100644 --- a/libavcodec/mpegvideoenc.h +++ b/libavcodec/mpegvideoenc.h @@ -87,6 +87,7 @@ typedef struct MPVMainEncContext { int (*encode_picture_header)(struct MPVMainEncContext *m); /* bit rate control */ + int64_t bit_rate; int64_t total_bits; int frame_bits; ///< bits used for the current frame int header_bits; diff --git a/libavcodec/msmpeg4enc.c b/libavcodec/msmpeg4enc.c index 9e58a91a80..e5501e5e32 100644 --- a/libavcodec/msmpeg4enc.c +++ b/libavcodec/msmpeg4enc.c @@ -30,6 +30,8 @@ #include <stdint.h> #include <string.h> +#define NO_SLICE_THREADING_HERE + #include "libavutil/attributes.h" #include "libavutil/avutil.h" #include "libavutil/thread.h" @@ -222,8 +224,10 @@ static int msmpeg4_encode_picture_header(MPVMainEncContext *const m) s->use_skip_mb_code = 1; /* only if P-frame */ s->per_mb_rl_table = 0; if (s->msmpeg4_version == MSMP4_WMV1) - s->inter_intra_pred= (s->width*s->height < 320*240 && s->bit_rate<=II_BITRATE && s->pict_type==AV_PICTURE_TYPE_P); - ff_dlog(s->avctx, "%d %"PRId64" %d %d %d\n", s->pict_type, s->bit_rate, + s->inter_intra_pred = s->width * s->height < 320*240 && + m->bit_rate <= II_BITRATE && + s->pict_type == AV_PICTURE_TYPE_P; + ff_dlog(s->avctx, "%d %"PRId64" %d %d %d\n", s->pict_type, m->bit_rate, s->inter_intra_pred, s->width, s->height); if (s->pict_type == AV_PICTURE_TYPE_I) { @@ -232,7 +236,7 @@ static int msmpeg4_encode_picture_header(MPVMainEncContext *const m) if (s->msmpeg4_version == MSMP4_WMV1) { ff_msmpeg4_encode_ext_header(s); - if(s->bit_rate>MBAC_BITRATE) + if (m->bit_rate > MBAC_BITRATE) put_bits(&s->pb, 1, s->per_mb_rl_table); } @@ -247,7 +251,7 @@ static int msmpeg4_encode_picture_header(MPVMainEncContext *const m) } else { put_bits(&s->pb, 1, s->use_skip_mb_code); - if (s->msmpeg4_version == MSMP4_WMV1 && s->bit_rate > MBAC_BITRATE) + if (s->msmpeg4_version == MSMP4_WMV1 && m->bit_rate > MBAC_BITRATE) put_bits(&s->pb, 1, s->per_mb_rl_table); if (s->msmpeg4_version > MSMP4_V2) { @@ -268,6 +272,7 @@ static int msmpeg4_encode_picture_header(MPVMainEncContext *const m) void ff_msmpeg4_encode_ext_header(MpegEncContext * s) { + const MPVMainEncContext *const m = slice_to_mainenc(s); unsigned fps; if (s->avctx->framerate.num > 0 && s->avctx->framerate.den > 0) @@ -284,7 +289,7 @@ FF_ENABLE_DEPRECATION_WARNINGS put_bits(&s->pb, 5, FFMIN(fps, 31)); //yes 29.97 -> 29 - put_bits(&s->pb, 11, FFMIN(s->bit_rate / 1024, 2047)); + put_bits(&s->pb, 11, FFMIN(m->bit_rate / 1024, 2047)); if (s->msmpeg4_version >= MSMP4_V3) put_bits(&s->pb, 1, s->flipflop_rounding); diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c index 20e3ccabf8..0d2bf8fb30 100644 --- a/libavcodec/ratecontrol.c +++ b/libavcodec/ratecontrol.c @@ -347,7 +347,7 @@ static int init_pass2(MPVMainEncContext *const m) double complexity[5] = { 0 }; // approximate bits at quant=1 uint64_t const_bits[5] = { 0 }; // quantizer independent bits uint64_t all_const_bits; - uint64_t all_available_bits = av_rescale_q(s->bit_rate, + uint64_t all_available_bits = av_rescale_q(m->bit_rate, (AVRational){rcc->num_entries,1}, fps); double rate_factor = 0; @@ -477,8 +477,8 @@ static int init_pass2(MPVMainEncContext *const m) av_assert0(toobig <= 40); av_log(s->avctx, AV_LOG_DEBUG, "[lavc rc] requested bitrate: %"PRId64" bps expected bitrate: %"PRId64" bps\n", - s->bit_rate, - (int64_t)(expected_bits / ((double)all_available_bits / s->bit_rate))); + m->bit_rate, + (int64_t)(expected_bits / ((double)all_available_bits / m->bit_rate))); av_log(s->avctx, AV_LOG_DEBUG, "[lavc rc] estimated target average qp: %.3f\n", (float)qscale_sum / rcc->num_entries); @@ -696,7 +696,7 @@ av_cold int ff_rate_control_init(MPVMainEncContext *const m) get_qscale(m, &rce, rcc->pass1_wanted_bits / rcc->pass1_rc_eq_output_sum, i); // FIXME misbehaves a little for variable fps - rcc->pass1_wanted_bits += s->bit_rate / get_fps(s->avctx); + rcc->pass1_wanted_bits += m->bit_rate / get_fps(s->avctx); } } } @@ -971,9 +971,9 @@ float ff_rate_estimate_qscale(MPVMainEncContext *const m, int dry_run) dts_pic = s->last_pic.ptr; if (!dts_pic || dts_pic->f->pts == AV_NOPTS_VALUE) - wanted_bits_double = s->bit_rate * (double)picture_number / fps; + wanted_bits_double = m->bit_rate * (double)picture_number / fps; else - wanted_bits_double = s->bit_rate * (double)dts_pic->f->pts / fps; + wanted_bits_double = m->bit_rate * (double)dts_pic->f->pts / fps; if (wanted_bits_double > INT64_MAX) { av_log(s->avctx, AV_LOG_WARNING, "Bits exceed 64bit range\n"); wanted_bits = INT64_MAX; @@ -1047,7 +1047,7 @@ float ff_rate_estimate_qscale(MPVMainEncContext *const m, int dry_run) q = modify_qscale(m, rce, q, picture_number); - rcc->pass1_wanted_bits += s->bit_rate / fps; + rcc->pass1_wanted_bits += m->bit_rate / fps; av_assert0(q > 0.0); } @@ -1061,7 +1061,7 @@ float ff_rate_estimate_qscale(MPVMainEncContext *const m, int dry_run) wanted_bits / 1000, m->total_bits / 1000, br_compensation, short_term_q, m->frame_bits, m->mb_var_sum, m->mc_mb_var_sum, - s->bit_rate / 1000, (int)fps); + m->bit_rate / 1000, (int)fps); } if (q < qmin) diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c index e074e878d6..b4a329158f 100644 --- a/libavcodec/snowenc.c +++ b/libavcodec/snowenc.c @@ -227,7 +227,7 @@ static av_cold int encode_init(AVCodecContext *avctx) s->version=0; mpv->avctx = avctx; - mpv->bit_rate= avctx->bit_rate; + enc->m.bit_rate = avctx->bit_rate; enc->m.lmin = avctx->mb_lmin; enc->m.lmax = avctx->mb_lmax; mpv->mb_num = (avctx->width * avctx->height + 255) / 256; // For ratecontrol diff --git a/libavcodec/wmv2enc.c b/libavcodec/wmv2enc.c index 3ab3e75722..6eda38d05f 100644 --- a/libavcodec/wmv2enc.c +++ b/libavcodec/wmv2enc.c @@ -55,7 +55,7 @@ static int encode_ext_header(WMV2EncContext *w) init_put_bits(&pb, s->avctx->extradata, WMV2_EXTRADATA_SIZE); put_bits(&pb, 5, s->avctx->time_base.den / s->avctx->time_base.num); // yes 29.97 -> 29 - put_bits(&pb, 11, FFMIN(s->bit_rate / 1024, 2047)); + put_bits(&pb, 11, FFMIN(w->msmpeg4.m.bit_rate / 1024, 2047)); put_bits(&pb, 1, w->mspel_bit = 1); put_bits(&pb, 1, s->loop_filter); @@ -135,7 +135,7 @@ static int wmv2_encode_picture_header(MPVMainEncContext *const m) put_bits(&s->pb, 1, s->dc_table_index); put_bits(&s->pb, 1, s->mv_table_index); - s->inter_intra_pred = 0; // (s->width * s->height < 320 * 240 && s->bit_rate <= II_BITRATE); + s->inter_intra_pred = 0; // (s->width * s->height < 320 * 240 && m->bit_rate <= II_BITRATE); } s->esc3_level_length = 0; s->esc3_run_length = 0; -- 2.45.2 [-- Attachment #42: 0041-avcodec-mpeg12dec-Add-bit_rate-field-to-Mpeg1Context.patch --] [-- Type: text/x-patch, Size: 3693 bytes --] From d55f544cdde2b231d1f0f54f1cba706d383edd04 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sat, 15 Mar 2025 07:28:13 +0100 Subject: [PATCH 41/77] avcodec/mpeg12dec: Add bit_rate field to Mpeg1Context Use it instead of MpegEncContext.bit_rate which will be removed soon. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpeg12dec.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index 81cc543424..ed739be538 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -91,6 +91,7 @@ typedef struct Mpeg1Context { int first_slice; int extradata_decoded; int vbv_delay; + int64_t bit_rate; int64_t timecode_frame_start; /*< GOP timecode frame start number, in non drop frame format */ } Mpeg1Context; @@ -950,12 +951,12 @@ static int mpeg_decode_postinit(AVCodecContext *avctx) if (ret < 0) return ret; - if (avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO && s->bit_rate && - (s->bit_rate != 0x3FFFF*400)) { - avctx->rc_max_rate = s->bit_rate; - } else if (avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO && s->bit_rate && - (s->bit_rate != 0x3FFFF*400 || s1->vbv_delay != 0xFFFF)) { - avctx->bit_rate = s->bit_rate; + if (avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO && s1->bit_rate && + (s1->bit_rate != 0x3FFFF*400)) { + avctx->rc_max_rate = s1->bit_rate; + } else if (avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO && s1->bit_rate && + (s1->bit_rate != 0x3FFFF*400 || s1->vbv_delay != 0xFFFF)) { + avctx->bit_rate = s1->bit_rate; } s1->save_aspect = s->avctx->sample_aspect_ratio; s1->save_width = s->width; @@ -1075,7 +1076,7 @@ static void mpeg_decode_sequence_extension(Mpeg1Context *s1) s->width |= (horiz_size_ext << 12); s->height |= (vert_size_ext << 12); bit_rate_ext = get_bits(&s->gb, 12); /* XXX: handle it */ - s->bit_rate += (bit_rate_ext << 18) * 400LL; + s1->bit_rate += (bit_rate_ext << 18) * 400LL; check_marker(s->avctx, &s->gb, "after bit rate extension"); s->avctx->rc_buffer_size += get_bits(&s->gb, 8) * 1024 * 16 << 10; @@ -1093,7 +1094,7 @@ static void mpeg_decode_sequence_extension(Mpeg1Context *s1) av_log(s->avctx, AV_LOG_DEBUG, "profile: %d, level: %d ps: %d cf:%d vbv buffer: %d, bitrate:%"PRId64"\n", s->avctx->profile, s->avctx->level, s->progressive_sequence, s->chroma_format, - s->avctx->rc_buffer_size, s->bit_rate); + s->avctx->rc_buffer_size, s1->bit_rate); } static void mpeg_decode_sequence_display_extension(Mpeg1Context *s1) @@ -1799,7 +1800,7 @@ static int mpeg1_decode_sequence(AVCodecContext *avctx, "frame_rate_index %d is invalid\n", s1->frame_rate_index); s1->frame_rate_index = 1; } - s->bit_rate = get_bits(&s->gb, 18) * 400LL; + s1->bit_rate = get_bits(&s->gb, 18) * 400; if (check_marker(s->avctx, &s->gb, "in sequence header") == 0) { return AVERROR_INVALIDDATA; } @@ -1851,7 +1852,7 @@ static int mpeg1_decode_sequence(AVCodecContext *avctx, if (s->avctx->debug & FF_DEBUG_PICT_INFO) av_log(s->avctx, AV_LOG_DEBUG, "vbv buffer: %d, bitrate:%"PRId64", aspect_ratio_info: %d \n", - s->avctx->rc_buffer_size, s->bit_rate, s1->aspect_ratio_info); + s->avctx->rc_buffer_size, s1->bit_rate, s1->aspect_ratio_info); return 0; } -- 2.45.2 [-- Attachment #43: 0042-avcodec-msmpeg4dec-Add-MSMPEG4DecContext.patch --] [-- Type: text/x-patch, Size: 6547 bytes --] From 34f4b06de97cd99806d9847e2532f81199d2de1c Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sat, 15 Mar 2025 07:42:26 +0100 Subject: [PATCH 42/77] avcodec/msmpeg4dec: Add MSMPEG4DecContext This is in preparation for further commits. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/msmpeg4dec.c | 8 ++++---- libavcodec/msmpeg4dec.h | 10 ++++++++++ libavcodec/wmv2dec.c | 24 ++++++++++++------------ 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/libavcodec/msmpeg4dec.c b/libavcodec/msmpeg4dec.c index 0604dc8963..b7ff6126b1 100644 --- a/libavcodec/msmpeg4dec.c +++ b/libavcodec/msmpeg4dec.c @@ -845,7 +845,7 @@ const FFCodec ff_msmpeg4v1_decoder = { CODEC_LONG_NAME("MPEG-4 part 2 Microsoft variant version 1"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_MSMPEG4V1, - .priv_data_size = sizeof(MpegEncContext), + .priv_data_size = sizeof(MSMP4DecContext), .init = ff_msmpeg4_decode_init, FF_CODEC_DECODE_CB(ff_h263_decode_frame), .close = ff_mpv_decode_close, @@ -860,7 +860,7 @@ const FFCodec ff_msmpeg4v2_decoder = { CODEC_LONG_NAME("MPEG-4 part 2 Microsoft variant version 2"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_MSMPEG4V2, - .priv_data_size = sizeof(MpegEncContext), + .priv_data_size = sizeof(MSMP4DecContext), .init = ff_msmpeg4_decode_init, FF_CODEC_DECODE_CB(ff_h263_decode_frame), .close = ff_mpv_decode_close, @@ -875,7 +875,7 @@ const FFCodec ff_msmpeg4v3_decoder = { CODEC_LONG_NAME("MPEG-4 part 2 Microsoft variant version 3"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_MSMPEG4V3, - .priv_data_size = sizeof(MpegEncContext), + .priv_data_size = sizeof(MSMP4DecContext), .init = ff_msmpeg4_decode_init, FF_CODEC_DECODE_CB(ff_h263_decode_frame), .close = ff_mpv_decode_close, @@ -890,7 +890,7 @@ const FFCodec ff_wmv1_decoder = { CODEC_LONG_NAME("Windows Media Video 7"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_WMV1, - .priv_data_size = sizeof(MpegEncContext), + .priv_data_size = sizeof(MSMP4DecContext), .init = ff_msmpeg4_decode_init, FF_CODEC_DECODE_CB(ff_h263_decode_frame), .close = ff_mpv_decode_close, diff --git a/libavcodec/msmpeg4dec.h b/libavcodec/msmpeg4dec.h index 5daa7c6bc3..d024674f0d 100644 --- a/libavcodec/msmpeg4dec.h +++ b/libavcodec/msmpeg4dec.h @@ -28,6 +28,16 @@ #define INTER_INTRA_VLC_BITS 3 #define MB_NON_INTRA_VLC_BITS 9 +typedef struct MSMP4DecContext { + MpegEncContext m; +} MSMP4DecContext; + +static inline MSMP4DecContext *mpv_to_msmpeg4(MpegEncContext *s) +{ + // Only legal because no MSMPEG-4 decoder uses slice-threading. + return (MSMP4DecContext*)s; +} + extern const VLCElem *ff_mb_non_intra_vlc[4]; extern VLCElem ff_inter_intra_vlc[8]; diff --git a/libavcodec/wmv2dec.c b/libavcodec/wmv2dec.c index 7f43a5c0ba..5ab619c2ca 100644 --- a/libavcodec/wmv2dec.c +++ b/libavcodec/wmv2dec.c @@ -37,7 +37,7 @@ #include "wmv2dec.h" typedef struct WMV2DecContext { - MpegEncContext s; + MSMP4DecContext ms; WMV2Context common; IntraX8Context x8; int j_type_bit; @@ -59,7 +59,7 @@ typedef struct WMV2DecContext { static void wmv2_add_block(WMV2DecContext *w, int16_t *block1, uint8_t *dst, int stride, int n) { - MpegEncContext *const s = &w->s; + MpegEncContext *const s = &w->ms.m; if (s->block_last_index[n] >= 0) { switch (w->abt_type_table[n]) { @@ -103,7 +103,7 @@ static int parse_mb_skip(WMV2DecContext *w) { int mb_x, mb_y; int coded_mb_count = 0; - MpegEncContext *const s = &w->s; + MpegEncContext *const s = &w->ms.m; uint32_t *const mb_type = s->cur_pic.mb_type; w->skip_type = get_bits(&s->gb, 2); @@ -166,7 +166,7 @@ static int parse_mb_skip(WMV2DecContext *w) static int decode_ext_header(WMV2DecContext *w) { - MpegEncContext *const s = &w->s; + MpegEncContext *const s = &w->ms.m; GetBitContext gb; int fps; int code; @@ -336,8 +336,8 @@ int ff_wmv2_decode_secondary_picture_header(MpegEncContext *s) 2 * s->qscale, (s->qscale - 1) | 1, s->loop_filter, s->low_delay); - ff_er_add_slice(&w->s.er, 0, 0, - (w->s.mb_x >> 1) - 1, (w->s.mb_y >> 1) - 1, + ff_er_add_slice(&s->er, 0, 0, + (s->mb_x >> 1) - 1, (s->mb_y >> 1) - 1, ER_MB_END); return 1; } @@ -347,7 +347,7 @@ int ff_wmv2_decode_secondary_picture_header(MpegEncContext *s) static inline void wmv2_decode_motion(WMV2DecContext *w, int *mx_ptr, int *my_ptr) { - MpegEncContext *const s = &w->s; + MpegEncContext *const s = &w->ms.m; ff_msmpeg4_decode_motion(s, mx_ptr, my_ptr); @@ -359,7 +359,7 @@ static inline void wmv2_decode_motion(WMV2DecContext *w, int *mx_ptr, int *my_pt static int16_t *wmv2_pred_motion(WMV2DecContext *w, int *px, int *py) { - MpegEncContext *const s = &w->s; + MpegEncContext *const s = &w->ms.m; int xy, wrap, diff, type; int16_t *A, *B, *C, *mot_val; @@ -405,7 +405,7 @@ static int16_t *wmv2_pred_motion(WMV2DecContext *w, int *px, int *py) static inline int wmv2_decode_inter_block(WMV2DecContext *w, int16_t *block, int n, int cbp) { - MpegEncContext *const s = &w->s; + MpegEncContext *const s = &w->ms.m; static const int sub_cbp_table[3] = { 2, 3, 1 }; int sub_cbp, ret; @@ -561,7 +561,7 @@ static int wmv2_decode_mb(MpegEncContext *s, int16_t block[6][64]) static av_cold int wmv2_decode_init(AVCodecContext *avctx) { WMV2DecContext *const w = avctx->priv_data; - MpegEncContext *const s = &w->s; + MpegEncContext *const s = &w->ms.m; int ret; s->private_ctx = &w->common; @@ -575,8 +575,8 @@ static av_cold int wmv2_decode_init(AVCodecContext *avctx) decode_ext_header(w); - return ff_intrax8_common_init(avctx, &w->x8, w->s.block, - w->s.mb_width, w->s.mb_height); + return ff_intrax8_common_init(avctx, &w->x8, s->block, + s->mb_width, s->mb_height); } static av_cold int wmv2_decode_end(AVCodecContext *avctx) -- 2.45.2 [-- Attachment #44: 0043-avcodec-mpegvideo-Move-bit_rate-field-to-MSMP4DecCon.patch --] [-- Type: text/x-patch, Size: 6355 bytes --] From 08a06a9d6d1c3c2089a32c0b4645176266ca6630 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sat, 15 Mar 2025 07:59:47 +0100 Subject: [PATCH 43/77] avcodec/mpegvideo: Move bit_rate field to MSMP4DecContext Also make it an int as that is all MSMP4 needs. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpegvideo.h | 1 - libavcodec/msmpeg4dec.c | 21 ++++++++++++++------- libavcodec/msmpeg4dec.h | 1 + libavcodec/wmv2dec.c | 8 ++++---- 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index ed9224d2fe..136b9b18a7 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -95,7 +95,6 @@ typedef struct MpegEncContext { void *private_ctx; /* the following parameters must be initialized before encoding */ int width, height;///< picture size. must be a multiple of 16 - int64_t bit_rate; ///< wanted bit rate enum OutputFormat out_format; ///< output format int h263_pred; ///< use MPEG-4/H.263 ac/dc predictions int pb_frame; ///< PB-frame mode (0 = none, 1 = base, 2 = improved) diff --git a/libavcodec/msmpeg4dec.c b/libavcodec/msmpeg4dec.c index b7ff6126b1..aac12882d7 100644 --- a/libavcodec/msmpeg4dec.c +++ b/libavcodec/msmpeg4dec.c @@ -389,6 +389,7 @@ av_cold int ff_msmpeg4_decode_init(AVCodecContext *avctx) int ff_msmpeg4_decode_picture_header(MpegEncContext * s) { + MSMP4DecContext *const ms = mpv_to_msmpeg4(s); int code; // at minimum one bit per macroblock is required at least in a valid frame, @@ -457,8 +458,10 @@ int ff_msmpeg4_decode_picture_header(MpegEncContext * s) case MSMP4_WMV1: ff_msmpeg4_decode_ext_header(s, (2+5+5+17+7)/8); - if(s->bit_rate > MBAC_BITRATE) s->per_mb_rl_table= get_bits1(&s->gb); - else s->per_mb_rl_table= 0; + if (ms->bit_rate > MBAC_BITRATE) + s->per_mb_rl_table = get_bits1(&s->gb); + else + s->per_mb_rl_table = 0; if(!s->per_mb_rl_table){ s->rl_chroma_table_index = decode012(&s->gb); @@ -503,8 +506,10 @@ int ff_msmpeg4_decode_picture_header(MpegEncContext * s) case MSMP4_WMV1: s->use_skip_mb_code = get_bits1(&s->gb); - if(s->bit_rate > MBAC_BITRATE) s->per_mb_rl_table= get_bits1(&s->gb); - else s->per_mb_rl_table= 0; + if (ms->bit_rate > MBAC_BITRATE) + s->per_mb_rl_table = get_bits1(&s->gb); + else + s->per_mb_rl_table = 0; if(!s->per_mb_rl_table){ s->rl_table_index = decode012(&s->gb); @@ -514,7 +519,8 @@ int ff_msmpeg4_decode_picture_header(MpegEncContext * s) s->dc_table_index = get_bits1(&s->gb); s->mv_table_index = get_bits1(&s->gb); - s->inter_intra_pred= (s->width*s->height < 320*240 && s->bit_rate<=II_BITRATE); + s->inter_intra_pred = s->width*s->height < 320*240 && + ms->bit_rate <= II_BITRATE; break; } @@ -534,7 +540,7 @@ int ff_msmpeg4_decode_picture_header(MpegEncContext * s) s->no_rounding = 0; } } - ff_dlog(s->avctx, "%d %"PRId64" %d %d %d\n", s->pict_type, s->bit_rate, + ff_dlog(s->avctx, "%d %d %d %d %d\n", s->pict_type, ms->bit_rate, s->inter_intra_pred, s->width, s->height); s->esc3_level_length= 0; @@ -545,13 +551,14 @@ int ff_msmpeg4_decode_picture_header(MpegEncContext * s) int ff_msmpeg4_decode_ext_header(MpegEncContext * s, int buf_size) { + MSMP4DecContext *const ms = mpv_to_msmpeg4(s); int left= buf_size*8 - get_bits_count(&s->gb); int length = s->msmpeg4_version >= MSMP4_V3 ? 17 : 16; /* the alt_bitstream reader could read over the end so we need to check it */ if(left>=length && left<length+8) { skip_bits(&s->gb, 5); /* fps */ - s->bit_rate= get_bits(&s->gb, 11)*1024; + ms->bit_rate = get_bits(&s->gb, 11) * 1024; if (s->msmpeg4_version >= MSMP4_V3) s->flipflop_rounding= get_bits1(&s->gb); else diff --git a/libavcodec/msmpeg4dec.h b/libavcodec/msmpeg4dec.h index d024674f0d..47c4495f1d 100644 --- a/libavcodec/msmpeg4dec.h +++ b/libavcodec/msmpeg4dec.h @@ -30,6 +30,7 @@ typedef struct MSMP4DecContext { MpegEncContext m; + int bit_rate; } MSMP4DecContext; static inline MSMP4DecContext *mpv_to_msmpeg4(MpegEncContext *s) diff --git a/libavcodec/wmv2dec.c b/libavcodec/wmv2dec.c index 5ab619c2ca..02c3dc2535 100644 --- a/libavcodec/wmv2dec.c +++ b/libavcodec/wmv2dec.c @@ -177,7 +177,7 @@ static int decode_ext_header(WMV2DecContext *w) init_get_bits(&gb, s->avctx->extradata, 32); fps = get_bits(&gb, 5); - s->bit_rate = get_bits(&gb, 11) * 1024; + w->ms.bit_rate = get_bits(&gb, 11) * 1024; w->mspel_bit = get_bits1(&gb); s->loop_filter = get_bits1(&gb); w->abt_flag = get_bits1(&gb); @@ -193,10 +193,10 @@ static int decode_ext_header(WMV2DecContext *w) if (s->avctx->debug & FF_DEBUG_PICT_INFO) av_log(s->avctx, AV_LOG_DEBUG, - "fps:%d, br:%"PRId64", qpbit:%d, abt_flag:%d, j_type_bit:%d, " + "fps:%d, br:%d, qpbit:%d, abt_flag:%d, j_type_bit:%d, " "tl_mv_flag:%d, mbrl_bit:%d, code:%d, loop_filter:%d, " "slices:%d\n", - fps, s->bit_rate, w->mspel_bit, w->abt_flag, w->j_type_bit, + fps, w->ms.bit_rate, w->mspel_bit, w->abt_flag, w->j_type_bit, w->top_left_mv_flag, w->per_mb_rl_bit, code, s->loop_filter, code); return 0; @@ -313,7 +313,7 @@ int ff_wmv2_decode_secondary_picture_header(MpegEncContext *s) s->dc_table_index = get_bits1(&s->gb); s->mv_table_index = get_bits1(&s->gb); - s->inter_intra_pred = 0; // (s->width * s->height < 320 * 240 && s->bit_rate <= II_BITRATE); + s->inter_intra_pred = 0; // (s->width * s->height < 320 * 240 && w->ms.bit_rate <= II_BITRATE); s->no_rounding ^= 1; if (s->avctx->debug & FF_DEBUG_PICT_INFO) { -- 2.45.2 [-- Attachment #45: 0044-avcodec-msmpeg4enc-Use-LUT-to-write-motion-vectors.patch --] [-- Type: text/x-patch, Size: 4064 bytes --] From d58b21e1c18050428505d6f4e84924b307121439 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sat, 15 Mar 2025 08:25:24 +0100 Subject: [PATCH 44/77] avcodec/msmpeg4enc: Use LUT to write motion vectors Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/msmpeg4data.h | 1 - libavcodec/msmpeg4enc.c | 43 +++++++++++++++++++--------------------- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/libavcodec/msmpeg4data.h b/libavcodec/msmpeg4data.h index aa4ca86a05..4921548d0c 100644 --- a/libavcodec/msmpeg4data.h +++ b/libavcodec/msmpeg4data.h @@ -43,7 +43,6 @@ typedef struct MVTable { const uint8_t *table_mv_bits; const uint8_t *table_mvx; const uint8_t *table_mvy; - uint16_t *table_mv_index; /* encoding: convert mv to index in table_mv */ const VLCElem *vlc; /* decoding: vlc */ } MVTable; diff --git a/libavcodec/msmpeg4enc.c b/libavcodec/msmpeg4enc.c index e5501e5e32..b5da98f03b 100644 --- a/libavcodec/msmpeg4enc.c +++ b/libavcodec/msmpeg4enc.c @@ -50,21 +50,27 @@ static uint8_t rl_length[NB_RL_TABLES][MAX_LEVEL+1][MAX_RUN+1][2]; +// The lowest 8 bits of each entry are length, the other bits are the code. +// The index of the (mx, my) entry is (mx * 64) + my. +static uint32_t mv_vector_tables[2][4096]; + /* build the table which associate a (x,y) motion vector to a vlc */ -static av_cold void init_mv_table(MVTable *tab, uint16_t table_mv_index[4096]) +static av_cold void init_mv_table(const MVTable *tab, uint32_t mv_vector_table[4096], + unsigned escape_code, int escape_length) { int i, x, y; - tab->table_mv_index = table_mv_index; - - /* mark all entries as not used */ - for(i=0;i<4096;i++) - tab->table_mv_index[i] = MSMPEG4_MV_TABLES_NB_ELEMS; + for (int i = 0; i < 4096; i++) { + // Initialize to the table to "escaped". This code is equivalent to + // the following double loop (with x and y ranging over 0..63): + // tab[x * 64 + y] = (esc_code << 20) | (x << 14) | (y << 8) | esc_length + mv_vector_table[i] = (escape_code << 20) | (i << 8) | escape_length; + } for (i = 0; i < MSMPEG4_MV_TABLES_NB_ELEMS; i++) { x = tab->table_mvx[i]; y = tab->table_mvy[i]; - tab->table_mv_index[(x << 6) | y] = i; + mv_vector_table[(x << 6) | y] = (tab->table_mv_code[i] << 8) | tab->table_mv_bits[i]; } } @@ -122,9 +128,8 @@ static int get_size_of_code(const RLTable *rl, int last, int run, static av_cold void msmpeg4_encode_init_static(void) { - static uint16_t mv_index_tables[2][4096]; - init_mv_table(&ff_mv_tables[0], mv_index_tables[0]); - init_mv_table(&ff_mv_tables[1], mv_index_tables[1]); + init_mv_table(&ff_mv_tables[0], mv_vector_tables[0], 0x0000, 8 + 12); + init_mv_table(&ff_mv_tables[1], mv_vector_tables[1], 0x000b, 4 + 12); for (int i = 0; i < NB_RL_TABLES; i++) { for (int level = 1; level <= MAX_LEVEL; level++) { @@ -300,8 +305,8 @@ FF_ENABLE_DEPRECATION_WARNINGS void ff_msmpeg4_encode_motion(MpegEncContext * s, int mx, int my) { - int code; - MVTable *mv; + const uint32_t *const mv_vector_table = mv_vector_tables[s->mv_table_index]; + uint32_t code; /* modulo encoding */ /* WARNING : you cannot reach all the MVs even with the modulo @@ -317,17 +322,9 @@ void ff_msmpeg4_encode_motion(MpegEncContext * s, mx += 32; my += 32; - mv = &ff_mv_tables[s->mv_table_index]; - - code = mv->table_mv_index[(mx << 6) | my]; - put_bits(&s->pb, - mv->table_mv_bits[code], - mv->table_mv_code[code]); - if (code == MSMPEG4_MV_TABLES_NB_ELEMS) { - /* escape : code literally */ - put_bits(&s->pb, 6, mx); - put_bits(&s->pb, 6, my); - } + + code = mv_vector_table[(mx << 6) | my]; + put_bits(&s->pb, code & 0xff, code >> 8); } void ff_msmpeg4_handle_slices(MpegEncContext *s){ -- 2.45.2 [-- Attachment #46: 0045-avcodec-msmpeg4dec-Avoid-lookups-when-decoding-motio.patch --] [-- Type: text/x-patch, Size: 42404 bytes --] From 1307b017e5ece29921010a067504f3b0c207378c Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sat, 15 Mar 2025 10:28:05 +0100 Subject: [PATCH 45/77] avcodec/msmpeg4dec: Avoid lookups when decoding motion vector Up until now, the decoder uses VLCs to determine whether this is an escape element or an index in two separate tables giving the x and y components of the motion vector. Given that both these components fit into an int16_t and therefore into a VLCElem's symbol one can simply use a symbol table to avoid the latter lookups. This necessitated to combine the two tables for x and y components. While just at it, also switch to ff_vlc_init_tables_from_lengths(). This will allow to get rid of the code tables (about 4KiB) once the encoder has been ported, too. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/msmpeg4data.c | 510 ++++++++++++++++++++++++++++++++++++++- libavcodec/msmpeg4data.h | 7 +- libavcodec/msmpeg4dec.c | 42 ++-- libavcodec/msmpeg4enc.c | 2 +- 4 files changed, 536 insertions(+), 25 deletions(-) diff --git a/libavcodec/msmpeg4data.c b/libavcodec/msmpeg4data.c index 65546da66e..aac75abd7c 100644 --- a/libavcodec/msmpeg4data.c +++ b/libavcodec/msmpeg4data.c @@ -481,6 +481,515 @@ RLTable ff_rl_table[NB_RL_TABLES] = { /* motion vector table 0 */ +#define E(mvx, mvy) ((mvx << 8) | mvy) +#define ESCAPE 0 + +const uint16_t ff_msmp4_mv_table0[MSMPEG4_MV_TABLES_NB_ELEMS] = { + ESCAPE, E(31, 39), E(38, 31), E(24, 32), E(23, 30), E(34, 20), + E(33, 22), E(21, 29), E(28, 34), E(33, 24), E(49, 32), E(27, 41), + E(32, 2), E(40, 33), E(34, 39), E(37, 25), E(29, 26), E(38, 28), + E(43, 31), E(37, 33), E(31, 35), E(32, 35), E(25, 29), E(26, 28), + E(32, 42), E(33, 23), E(42, 31), E(35, 36), E(27, 31), E(36, 30), + E(21, 32), E(23, 32), E(43, 32), E(36, 32), E(39, 29), E(38, 30), + E(36, 34), E(34, 36), E(19, 30), E(20, 38), E(41, 41), E(26, 44), + E(41, 53), E(42, 11), E(42, 20), E(42, 25), E(26, 45), E(26, 46), + E(26, 47), E(26, 48), E( 1, 39), E(26, 52), E(37, 46), E(37, 49), + E(37, 63), E(23, 55), E(34, 44), E(42, 38), E(27, 13), E(43, 13), + E(34, 57), E(27, 22), E(31, 51), E(24, 16), E(33, 12), E(16, 28), + E( 3, 35), E(31, 57), E(24, 25), E(31, 33), E(33, 33), E(34, 32), + E(31, 34), E(34, 31), E(33, 20), E(24, 26), E( 4, 28), E(44, 28), + E(44, 29), E(11, 32), E(44, 31), E(31, 62), E(13, 34), E(13, 35), + E(44, 35), E(45, 19), E(13, 49), E(25, 48), E(22, 39), E(38, 40), + E(26, 18), E(38, 43), E(38, 46), E(39, 11), E(32, 6), E(30, 48), + E(39, 19), E(30, 49), E(22, 41), E(32, 10), E(26, 23), E(30, 58), + E(47, 17), E(47, 21), E(47, 23), E(19, 34), E(47, 30), E(30, 60), + E(31, 0), E(35, 44), E( 8, 34), E(23, 26), E(47, 37), E(47, 46), + E(27, 43), E(35, 49), E(47, 59), E(31, 4), E(48, 34), E(35, 59), + E(19, 37), E(36, 22), E(49, 25), E(49, 28), E(33, 46), E(31, 6), + E(39, 40), E(27, 59), E(39, 42), E(49, 36), E(49, 61), E(50, 28), + E(50, 30), E(50, 31), E(39, 43), E(31, 10), E(51, 22), E(51, 23), + E(39, 47), E(28, 20), E(33, 52), E(33, 55), E(21, 36), E(40, 25), + E(31, 16), E(52, 1), E(53, 11), E(40, 27), E(53, 29), E( 9, 5), + E(33, 63), E(31, 18), E(53, 41), E(54, 31), E(54, 34), E(54, 38), + E(55, 1), E(55, 5), E(34, 13), E(15, 28), E(56, 31), E(25, 17), + E(56, 38), E(21, 39), E(21, 41), E(40, 36), E(40, 37), E(25, 22), + E(40, 39), E(58, 33), E(36, 43), E( 5, 43), E(41, 15), E(41, 17), + E(12, 49), E(60, 30), E(41, 21), E(41, 22), E(37, 20), E(22, 10), + E(61, 17), E(18, 25), E(29, 54), E(29, 57), E(30, 3), E(61, 34), + E(30, 8), E(61, 36), E(62, 25), E(62, 31), E(30, 14), E(30, 15), + E(63, 19), E(18, 29), E(13, 25), E(30, 18), E(45, 30), E( 1, 63), + E(34, 16), E(31, 42), E(22, 28), E(35, 13), E(15, 33), E(46, 33), + E(46, 35), E(35, 19), E(31, 46), E(28, 43), E(29, 17), E(29, 19), + E(23, 36), E(41, 39), E(27, 24), E(14, 31), E(53, 32), E(53, 33), + E(27, 26), E(24, 28), E(32, 62), E(57, 33), E(32, 63), E(17, 33), + E(42, 39), E(37, 19), E(29, 49), E(33, 17), E( 1, 31), E(25, 43), + E(32, 13), E(32, 15), E(63, 29), E(26, 25), E(40, 35), E(23, 34), + E(27, 25), E(22, 33), E(24, 29), E(22, 31), E(39, 39), E(43, 35), + E(27, 36), E(37, 24), E( 6, 32), E(42, 30), E(24, 33), E(40, 31), + E(28, 39), E(32, 1), E(32, 41), E(41, 32), E(36, 31), E(28, 32), + E(35, 31), E(29, 31), E(38, 32), E(23, 31), E(27, 30), E(32, 59), + E(32, 22), E(32, 21), E(30, 39), E(35, 25), E(26, 34), E(34, 38), + E(30, 28), E(44, 33), E(36, 23), E(47, 33), E(26, 27), E(30, 44), + E(31, 60), E(41, 30), E(39, 36), E(33, 19), E(33, 29), E(32, 36), + E(22, 34), E(45, 31), E(36, 24), E(32, 16), E(45, 35), E(19, 32), + E(36, 27), E(32, 4), E(43, 33), E(60, 32), E(37, 31), E(35, 33), + E(35, 32), E(34, 29), E(33, 28), E(25, 33), E(25, 34), E(21, 33), + E(36, 35), E(37, 32), E(29, 39), E(31, 24), E(30, 41), E(31, 3), + E(41, 35), E(22, 32), E(32, 39), E(32, 30), E(33, 32), E(32, 29), + E(33, 35), E(31, 28), E(28, 30), E(26, 33), E(31, 49), E(39, 41), + E(20, 28), E(20, 29), E(44, 34), E(23, 38), E(33, 7), E(34, 61), + E(29, 29), E(31, 38), E(35, 11), E(33, 50), E(33, 13), E(28, 41), + E(41, 19), E(23, 47), E(41, 25), E(41, 26), E(29, 15), E(25, 42), + E(26, 41), E(49, 29), E(29, 45), E(24, 27), E(37, 17), E(49, 35), + E(34, 33), E(30, 35), E(50, 32), E(51, 29), E(51, 32), E(26, 24), + E(39, 13), E(25, 26), E(26, 26), E(15, 31), E(39, 24), E(18, 33), + E(42, 28), E(17, 30), E( 4, 31), E(31, 11), E(32, 45), E(32, 46), + E(60, 33), E( 1, 33), E(42, 35), E(32, 57), E( 0, 32), E(12, 32), + E(19, 35), E(35, 45), E(22, 38), E(30, 21), E( 5, 33), E( 5, 31), + E(17, 31), E(29, 21), E(22, 35), E(31, 5), E(31, 17), E(43, 29), + E(37, 38), E(27, 38), E(32, 18), E(32, 58), E(32, 19), E(33, 43), + E(29, 41), E(33, 41), E(31, 37), E(30, 37), E(41, 33), E( 7, 32), + E(28, 31), E(34, 27), E(30, 27), E(37, 28), E(26, 36), E(34, 30), + E(31, 29), E(33, 30), E(27, 32), E(38, 29), E(30, 25), E(36, 28), + E(37, 36), E(21, 34), E(23, 39), E(19, 53), E(34, 41), E(36, 33), + E(32, 28), E(25, 32), E(29, 32), E(29, 33), E(33, 27), E(29, 27), + E(43, 30), E(35, 41), E(29, 43), E(26, 39), E(22, 29), E(32, 7), + E(19, 29), E(32, 17), E(25, 28), E(31, 19), E(41, 28), E(49, 31), + E(28, 25), E(34, 19), E(28, 40), E(39, 26), E(34, 21), E(19, 33), + E(37, 39), E(38, 23), E(29, 40), E(21, 30), E(36, 39), E(42, 34), + E(27, 28), E(59, 33), E(38, 33), E(35, 28), E(33, 34), E(30, 32), + E(30, 36), E(23, 35), E(33, 21), E(35, 23), E(31, 21), E(30, 26), + E(41, 31), E(39, 32), E(32, 27), E(26, 30), E(31, 22), E(37, 37), + E(38, 27), E(39, 27), E(32, 43), E(23, 29), E(32, 60), E(27, 39), + E(25, 35), E(61, 32), E(30, 33), E(30, 34), E(34, 28), E(33, 36), + E(37, 27), E(20, 22), E(20, 27), E(41, 20), E(13, 29), E( 2, 33), + E( 5, 41), E( 5, 42), E( 1, 35), E(32, 24), E(34, 24), E( 5, 62), + E(32, 50), E( 6, 29), E(32, 53), E(35, 50), E(20, 35), E(35, 55), + E(27, 42), E(35, 61), E(35, 63), E(36, 4), E(36, 7), E(13, 42), + E(36, 21), E(41, 46), E(41, 47), E(33, 37), E(28, 33), E(41, 49), + E( 3, 27), E(30, 46), E(42, 17), E(27, 55), E(20, 41), E(30, 50), + E(27, 63), E(28, 4), E(30, 56), E(21, 18), E(33, 8), E(33, 10), + E(14, 18), E(24, 51), E(30, 63), E(42, 36), E(24, 55), E(33, 18), + E(25, 5), E(42, 55), E(43, 9), E(14, 29), E(43, 17), E(43, 21), + E(14, 30), E(43, 27), E( 7, 1), E(36, 59), E(37, 7), E(37, 11), + E(37, 12), E(37, 15), E( 7, 5), E(14, 42), E(25, 24), E(43, 41), + E(43, 43), E(44, 7), E(15, 27), E(37, 22), E( 7, 25), E( 7, 31), + E( 3, 30), E( 1, 37), E( 8, 22), E(15, 39), E(15, 53), E( 8, 29), + E(44, 36), E(44, 37), E(44, 48), E(45, 0), E(45, 5), E(45, 13), + E(45, 17), E( 8, 31), E( 8, 32), E(45, 26), E(21, 46), E(45, 28), + E(28, 44), E(28, 45), E(28, 46), E(21, 53), E(28, 49), E(28, 51), + E(22, 3), E(37, 41), E(46, 3), E(46, 22), E(37, 42), E( 8, 33), + E(29, 5), E(37, 45), E(29, 7), E(22, 22), E(46, 40), E(37, 53), + E(22, 24), E(29, 14), E(47, 25), E(47, 27), E(38, 10), E(38, 12), + E(16, 34), E(38, 16), E(38, 17), E(33, 53), E(38, 20), E(22, 26), + E(47, 39), E(47, 45), E(29, 18), E(25, 45), E(16, 35), E( 0, 33), + E(48, 31), E( 1, 49), E(34, 4), E(48, 39), E(48, 42), E(34, 11), + E(25, 51), E(26, 5), E(26, 13), E(49, 26), E(49, 27), E(26, 17), + E( 1, 52), E(49, 30), E( 4, 0), E(26, 22), E( 4, 12), E(49, 34), + E( 1, 62), E( 9, 36), E(49, 38), E(49, 41), E(49, 47), E(10, 30), + E(49, 63), E(17, 38), E(38, 41), E(17, 43), E(17, 59), E(50, 33), + E(38, 45), E(50, 37), E(50, 38), E(22, 40), E(38, 47), E(51, 24), + E(38, 48), E(38, 49), E(51, 30), E(39, 1), E(39, 10), E(18, 22), + E(22, 49), E(39, 15), E(51, 39), E(22, 59), E(52, 31), E(52, 32), + E(52, 33), E(39, 18), E(53, 13), E(53, 15), E(10, 31), E(23, 21), + E(18, 27), E(29, 44), E(10, 42), E(53, 39), E(29, 46), E(54, 17), + E(11, 26), E(54, 32), E(11, 30), E(11, 31), E(55, 0), E( 1, 30), + E(18, 34), E(55, 9), E(55, 12), E(55, 13), E(55, 25), E(55, 31), + E(55, 32), E(29, 55), E(34, 43), E(18, 35), E(29, 61), E(56, 33), + E(56, 35), E(34, 46), E(57, 25), E(34, 47), E(34, 48), E(29, 62), + E(29, 63), E(57, 38), E(57, 61), E(35, 1), E(35, 2), E(35, 5), + E(35, 7), E(35, 9), E(39, 46), E(35, 10), E(59, 34), E(59, 35), + E(18, 36), E(59, 55), E(39, 51), E(30, 7), E(18, 40), E(40, 23), + E(60, 34), E(60, 37), E(61, 5), E(30, 13), E(18, 42), E(61, 18), + E(61, 25), E(19, 27), E(19, 28), E(41, 11), E(17, 37), E(26, 42), + E(20, 39), E(45, 37), E(46, 31), E(32, 49), E(37, 21), E(22, 27), + E(47, 29), E(29, 47), E(31, 53), E(27, 40), E(29, 51), E(30, 16), + E(21, 26), E(33, 1), E(35, 40), E(18, 30), E(25, 41), E(33, 44), + E(50, 34), E(51, 25), E(42, 27), E( 2, 31), E(15, 35), E(51, 35), + E(53, 31), E(33, 15), E(25, 49), E(29, 1), E(55, 35), E(37, 40), + E(38, 5), E(33, 58), E(38, 21), E(59, 29), E(38, 22), E(33, 59), + E(39, 45), E(13, 31), E(32, 9), E(40, 26), E(61, 9), E(61, 29), + E(32, 11), E( 9, 32), E(44, 30), E( 3, 3), E(31, 13), E(29, 20), + E(25, 18), E(24, 35), E(48, 32), E(16, 32), E(28, 24), E(49, 33), + E(22, 30), E(34, 40), E(31, 47), E(38, 39), E(39, 37), E(44, 32), + E(11, 33), E(35, 24), E(30, 23), E(33, 45), E(33, 47), E(36, 25), + E(31, 59), E(40, 34), E(25, 27), E(27, 27), E(38, 26), E(31, 40), + E(36, 37), E(28, 27), E(32, 31), E(31, 31), E(34, 35), E(32, 37), + E(34, 34), E(24, 31), E(39, 34), E(34, 37), E(27, 33), E(28, 35), + E(31, 61), E(36, 26), E(25, 39), E(45, 33), E(25, 31), E(35, 34), + E( 3, 31), E(34, 22), E(38, 37), E(39, 25), E(40, 30), E(38, 25), + E( 1, 32), E(25, 30), E(39, 35), E(30, 38), E(37, 29), E(32, 40), + E(28, 28), E(29, 38), E(32, 5), E(37, 34), E(31, 27), E(35, 27), + E(27, 29), E(23, 27), E(28, 23), E(33, 42), E(46, 32), E(15, 32), + E(13, 33), E(24, 36), E(41, 37), E(24, 37), E(34, 17), E(34, 18), + E(30, 22), E(26, 40), E(24, 38), E(14, 32), E(60, 31), E(21, 35), + E(29, 24), E(39, 17), E(23, 25), E(35, 17), E(37, 23), E(30, 24), + E(32, 61), E(19, 31), E(24, 34), E(25, 25), E(26, 38), E(45, 32), + E(38, 35), E(36, 29), E( 3, 32), E(26, 29), E(36, 36), E(30, 31), + E(59, 32), E(28, 36), E(63, 32), E(26, 32), E(38, 34), E(63, 33), + E(31, 20), E(27, 11), E(20, 32), E(24, 30), E(33, 3), E(37, 35), + E(28, 38), E(39, 30), E(32, 3), E(31, 26), E(39, 31), E(35, 29), + E(31, 30), E(32, 38), E(23, 33), E(23, 3), E( 9, 29), E(25, 40), + E( 9, 31), E(29, 53), E(20, 30), E(30, 17), E(30, 20), E(42, 37), + E(18, 31), E(28, 42), E(25, 47), E(28, 47), E(28, 54), E(21, 38), + E(29, 9), E(43, 34), E(29, 13), E(43, 37), E(26, 21), E(44, 25), + E(44, 27), E(21, 43), E(38, 42), E(35, 30), E(21, 45), E(24, 40), + E(45, 25), E(45, 27), E(35, 46), E(39, 22), E(22, 25), E(35, 53), + E(36, 20), E(34, 2), E(34, 14), E(45, 39), E(34, 15), E(29, 22), + E(31, 44), E(46, 34), E(25, 21), E(46, 38), E(16, 33), E(17, 27), + E(31, 48), E(20, 34), E(32, 52), E(47, 35), E(47, 47), E(47, 49), + E(32, 54), E(49, 2), E(49, 13), E(49, 23), E(31, 52), E( 1, 29), + E(27, 45), E(28, 22), E(39, 49), E(39, 54), E(21, 21), E(36, 40), + E(23, 42), E(51, 31), E( 2, 30), E(40, 29), E(51, 34), E(32, 0), + E(53, 25), E(24, 23), E(30, 51), E(24, 24), E(30, 59), E(21, 28), + E(40, 38), E(57, 29), E(57, 31), E(31, 2), E(41, 13), E(58, 31), + E(32, 8), E(12, 31), E( 4, 33), E(32, 12), E(34, 45), E(59, 41), + E(31, 7), E(32, 14), E(13, 30), E( 9, 25), E(35, 18), E(26, 43), + E(35, 20), E(37, 43), E(61, 35), E(37, 44), E(63, 1), E(26, 49), + E(29, 42), E(41, 42), E(45, 34), E(33, 51), E(34, 42), E(47, 31), + E(41, 36), E(22, 36), E(42, 29), E(35, 21), E(35, 22), E(23, 37), + E(32, 44), E(35, 43), E(43, 25), E(32, 47), E( 7, 33), E(31, 45), + E(41, 27), E(20, 31), E(31, 58), E(16, 31), E(13, 32), E(63, 31), + E(25, 38), E(30, 43), E(33, 61), E(31, 43), E(41, 29), E(34, 23), + E(39, 28), E(47, 32), E(40, 28), E(58, 32), E(59, 31), E(41, 34), + E(33, 5), E( 3, 33), E(17, 32), E(61, 33), E(42, 33), E(21, 31), + E(26, 35), E(35, 26), E(29, 36), E(26, 31), E(33, 38), E(30, 30), + E(31, 32), E(33, 31), E(37, 30), E(31, 23), E(30, 42), E(26, 37), + E(33, 26), E(27, 35), E(31, 36), E(27, 34), E(35, 37), E(29, 23), + E(36, 38), E(61, 31), E(33, 40), E(37, 26), E(62, 32), E(35, 38), + E(57, 32), E(31, 41), E(34, 26), E(34, 25), E(40, 32), E(35, 35), + E(29, 34), E(32, 25), E(29, 30), E(28, 26), E(38, 18), E(23, 41), + E(32, 20), E(29, 28), E(29, 25), E(28, 37), E(42, 32), E(33, 39), + E(32, 26), E(31, 25), E(30, 40), E(35, 47), E(30, 45), E(30, 54), + E(31, 1), E(32, 23), E(33, 25), E(42, 26), E(47, 34), E(39, 38), + E(38, 14), E(40, 22), E(40, 24), E(51, 33), E(55, 34), E(56, 32), + E(18, 32), E(21, 37), E(39, 21), E(39, 23), E(33, 49), E(17, 35), + E(41, 23), E(23, 28), E(24, 39), E(43, 39), E(25, 23), E(31, 55), + E(20, 33), E(25, 37), E(38, 38), E(25, 36), E(27, 37), E(29, 37), + E( 4, 32), E(39, 33), E( 5, 32), E(28, 29), E(38, 24), E(17, 29), + E(35, 39), E( 2, 32), E(38, 36), E(30, 29), E(29, 35), E(32, 34), + E(32, 33), E(32, 32), +}; + +const uint8_t ff_msmp4_mv_table0_lens[MSMPEG4_MV_TABLES_NB_ELEMS] = { + 8, 12, 12, 13, 15, 15, 15, 15, 12, 15, 15, 15, 15, 14, 14, 14, 14, 14, + 14, 11, 9, 8, 13, 14, 14, 14, 14, 13, 11, 12, 12, 12, 12, 10, 13, 13, + 12, 12, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 6, 6, 7, + 8, 8, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 13, 12, 11, 10, + 9, 9, 11, 13, 13, 14, 14, 13, 13, 13, 13, 13, 12, 16, 16, 15, 15, 15, + 15, 15, 15, 15, 9, 10, 15, 15, 15, 15, 15, 15, 14, 14, 14, 13, 11, 9, + 8, 10, 11, 12, 14, 14, 13, 10, 13, 14, 14, 14, 14, 13, 11, 7, 5, 8, + 9, 11, 12, 13, 16, 16, 16, 16, 16, 16, 16, 16, 11, 12, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8, 10, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 14, 14, 11, 12, 13, 13, 11, 12, 13, 14, 14, 9, 9, 8, 10, 13, 13, 13, + 14, 16, 17, 17, 15, 11, 10, 10, 8, 9, 11, 13, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 14, 14, 12, 12, 8, 7, 11, 14, 14, 14, 14, 13, 13, 10, 10, 13, 14, 14, + 14, 14, 14, 14, 14, 14, 13, 12, 8, 9, 11, 11, 14, 17, 17, 17, 17, 17, + 17, 17, 17, 13, 13, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 11, 11, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 4, 5, 10, 10, 9, 13, 13, 12, 11, 12, 14, 14, 14, 14, 11, 10, + 14, 14, 14, 14, 14, 14, 13, 13, 13, 12, 12, 13, 13, 13, 13, 12, 11, 12, + 12, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 13, 12, 12, 13, 13, 8, + 12, 13, 13, 11, 12, 15, 16, 16, 14, 14, 14, 12, 13, 13, 12, 12, 11, 10, + 8, 11, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 10, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, + 13, 13, 12, 12, 12, 9, 4, 5, 12, 13, 14, 14, 12, 12, 10, 12, 12, 14, + 14, 14, 14, 14, 14, 13, 13, 13, 12, 12, 12, 10, 10, 10, 10, 14, 16, 16, + 15, 13, 13, 13, 12, 12, 11, 11, 13, 15, 15, 15, 15, 12, 11, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 14, 14, 14, 13, 12, 12, 11, 12, 12, 14, 14, 13, 13, 13, 10, 10, 6, + 4, 1, +}; + +/* motion vector table 1 */ + +const uint16_t ff_msmp4_mv_table1[MSMPEG4_MV_TABLES_NB_ELEMS] = { + E(32, 32), E(42, 39), E(35, 53), E( 3, 28), E(51, 39), E(35, 57), + E(16, 46), E(35, 10), E(30, 52), E(63, 27), E(57, 35), E(39, 42), + E(39, 45), E(25, 59), E(35, 15), E(51, 34), E(31, 9), E(48, 34), + E( 2, 33), E( 6, 31), E(34, 49), E(30, 43), E(28, 42), E(33, 51), + E(39, 27), E(33, 42), E(37, 25), E(60, 34), E(38, 60), E( 9, 38), + E(38, 33), E(51, 32), E(30, 22), E(33, 23), E(32, 24), E(32, 26), + E(32, 29), E(40, 29), E(27, 23), E(46, 29), E(31, 14), E( 9, 30), + E(35, 45), E(29, 49), E(31, 11), E(47, 32), E(32, 48), E(39, 35), + E(37, 31), E(25, 34), E(30, 25), E(24, 30), E(35, 25), E(61, 32), + E(39, 24), E(16, 24), E(36, 23), E(50, 32), E(32, 45), E(19, 33), + E(59, 33), E(29, 25), E(30, 36), E(63, 33), E(45, 39), E(31, 12), + E(60, 29), E(14, 24), E(34, 0), E(42, 20), E(24, 16), E( 0, 28), + E(37, 43), E(18, 35), E(61, 28), E(57, 1), E(30, 30), E(31, 33), + E(31, 35), E(26, 32), E(37, 49), E(28, 4), E(53, 21), E(20, 42), + E(46, 39), E(14, 29), E(47, 3), E(38, 44), E(38, 21), E(38, 53), + E( 9, 55), E(34, 11), E(39, 5), E(43, 3), E(17, 39), E(39, 53), + E(59, 28), E( 5, 25), E(27, 19), E( 0, 34), E(55, 31), E(46, 28), + E(19, 35), E(37, 41), E(62, 30), E(34, 44), E(30, 18), E(16, 29), + E(19, 34), E(49, 35), E(30, 41), E(25, 27), E(43, 32), E( 4, 32), + E(34, 25), E(27, 25), E(33, 19), E(32, 41), E(25, 29), E(62, 31), + E(24, 35), E(32, 38), E(30, 32), E(34, 33), E(34, 29), E(41, 36), + E(12, 28), E(27, 21), E(41, 25), E(39, 26), E(30, 24), E(37, 21), + E(14, 31), E( 5, 30), E(13, 34), E(35, 19), E(55, 34), E(30, 44), + E(40, 36), E(40, 38), E(42, 25), E(31, 19), E(27, 36), E(30, 42), + E(37, 27), E(31, 17), E(21, 33), E(45, 31), E(32, 44), E(39, 28), + E(20, 33), E(46, 33), E(47, 31), E(35, 23), E(19, 31), E(33, 30), + E(28, 32), E(36, 32), E(33, 32), E(34, 40), E( 8, 31), E(20, 28), + E(35, 39), E(43, 33), E(25, 23), E(45, 37), E(35, 3), E(33, 55), + E(35, 29), E(36, 41), E(54, 30), E(38, 22), E(27, 41), E(37, 24), + E(62, 33), E(40, 26), E(15, 35), E(59, 35), E(49, 30), E( 1, 33), + E(40, 33), E(32, 0), E(29, 37), E(32, 2), E( 3, 32), E(42, 32), + E(49, 31), E(21, 34), E(21, 30), E(14, 32), E( 5, 31), E(28, 36), + E(31, 21), E(51, 33), E(31, 55), E(29, 51), E(31, 38), E(62, 32), + E(34, 47), E(34, 48), E(39, 38), E(24, 24), E(32, 30), E(29, 32), + E(30, 34), E(35, 34), E(29, 15), E(25, 21), E(26, 36), E(33, 61), + E(31, 26), E(32, 34), E(30, 33), E(27, 31), E(23, 35), E(29, 50), + E(21, 25), E(31, 47), E(36, 37), E(35, 41), E(58, 31), E(29, 23), + E(29, 41), E(21, 29), E(20, 30), E(33, 24), E(32, 22), E(42, 35), + E(29, 46), E(10, 30), E(61, 29), E(33, 10), E(49, 34), E(35, 42), + E(34, 45), E( 3, 29), E(38, 42), E(39, 22), E(29, 3), E( 7, 33), + E(41, 27), E( 1, 34), E(30, 31), E(13, 32), E(28, 25), E(12, 32), + E(40, 28), E(25, 35), E(31, 61), E(28, 31), E(29, 34), E(34, 35), + E(28, 33), E(26, 33), E(35, 1), E( 4, 34), E(31, 58), E(33, 2), + E(39, 37), E(21, 31), E(60, 33), E(23, 28), E(15, 34), E(38, 30), + E(37, 33), E(34, 34), E(31, 28), E(23, 36), E(11, 35), E(37, 23), + E(28, 23), E(35, 13), E(30, 58), E(30, 3), E(24, 26), E( 1, 63), + E(43, 25), E(56, 31), E( 8, 34), E(32, 14), E(44, 33), E(32, 35), + E(26, 31), E(31, 5), E(33, 49), E(31, 20), E(36, 33), E(32, 1), + E(27, 33), E(31, 34), E(31, 30), E(28, 39), E(37, 36), E(43, 31), + E(31, 59), E(34, 39), E(31, 27), E(34, 61), E(42, 38), E(24, 39), + E(45, 25), E(30, 61), E(20, 29), E(23, 37), E( 8, 30), E(38, 41), + E(22, 26), E(33, 48), E(17, 28), E(52, 33), E(34, 50), E(29, 21), + E(32, 9), E(30, 23), E(49, 33), E(43, 35), E(28, 24), E(39, 39), + E(33, 21), E(33, 34), E(32, 28), E(30, 29), E(25, 37), E(32, 11), + E(48, 33), E( 2, 30), E(15, 31), E(20, 31), E(22, 35), E(53, 30), + E(43, 37), E(44, 29), E(29, 30), E( 1, 29), E(27, 40), E(31, 6), + E(41, 39), E(43, 28), E(41, 28), E(30, 19), E(31, 8), E(36, 22), + E(30, 45), E(25, 28), E(31, 51), E(28, 40), E(32, 25), E(21, 35), + E(24, 29), E(25, 25), E(15, 33), E(20, 32), E(40, 30), E(39, 34), + E(31, 46), E(17, 35), E(22, 32), E(39, 31), E(33, 28), E(29, 29), + E(21, 32), E(37, 37), E(43, 30), E(18, 30), E(32, 8), E(37, 32), + E(31, 32), E(31, 22), E(31, 40), E(57, 32), E(38, 29), E(33, 37), + E(35, 35), E(33, 63), E( 5, 34), E(55, 35), E(31, 10), E(33, 58), + E(30, 17), E(40, 37), E(23, 39), E(15, 30), E(29, 18), E(34, 54), + E(34, 14), E(59, 29), E(34, 16), E(30, 59), E(11, 30), E(13, 35), + E(38, 23), E( 5, 35), E(24, 28), E(33, 15), E(37, 30), E(25, 31), + E(36, 40), E(13, 33), E(33, 45), E(31, 49), E(32, 16), E(42, 31), + E(25, 33), E(32, 36), E(39, 25), E(11, 32), E(33, 5), E(61, 31), + E(63, 32), E(31, 4), E( 0, 30), E(30, 47), E(32, 62), E(37, 29), + E(31, 2), E(42, 36), E( 5, 29), E(30, 55), E(29, 20), E(29, 35), + E(34, 12), E(10, 31), E(44, 35), E(30, 14), E(63, 29), E(35, 18), + E(12, 34), E( 3, 34), E(33, 47), E(32, 51), E(39, 36), E(37, 39), + E(32, 53), E(32, 10), E(29, 24), E(17, 29), E(32, 20), E(29, 39), + E(33, 27), E(31, 36), E(32, 27), E(31, 3), E(30, 39), E(44, 32), + E(31, 37), E( 5, 33), E(44, 30), E(46, 31), E(32, 40), E(36, 25), + E(35, 40), E(26, 38), E(37, 38), E(33, 38), E(25, 32), E( 2, 32), + E(58, 33), E(26, 24), E(15, 29), E(31, 1), E(31, 25), E(17, 26), + E(25, 22), E(34, 2), E(43, 27), E(39, 23), E(34, 8), E(56, 30), + E(29, 55), E(23, 38), E(30, 60), E(12, 31), E(30, 4), E(10, 34), + E(35, 49), E( 9, 34), E(24, 27), E(58, 34), E(10, 33), E(12, 30), + E(54, 31), E(32, 56), E(34, 23), E(38, 27), E( 8, 32), E(22, 31), + E(34, 24), E(36, 36), E(17, 32), E(38, 36), E(33, 25), E(32, 33), + E(32, 31), E(58, 32), E(38, 28), E(38, 37), E(38, 26), E(22, 29), + E(29, 43), E(32, 61), E(25, 36), E(16, 33), E(35, 24), E(32, 55), + E(35, 43), E(33, 9), E(43, 29), E(18, 34), E(46, 34), E(38, 24), + E(35, 26), E(32, 6), E(60, 31), E( 1, 32), E(23, 33), E(30, 35), + E(27, 32), E(33, 26), E(41, 31), E(35, 38), E(33, 54), E(37, 42), + E(20, 35), E(41, 38), E(35, 46), E(29, 44), E(18, 26), E(61, 27), + E(30, 9), E(40, 39), E(24, 25), E(39, 21), E(39, 32), E(53, 29), + E(62, 28), E(26, 42), E(29, 13), E(33, 0), E(34, 5), E(53, 34), + E(49, 37), E(21, 28), E(27, 24), E(11, 29), E(63, 63), E(50, 33), + E(33, 18), E(18, 33), E(53, 33), E(60, 30), E(13, 31), E(32, 50), + E(36, 24), E(24, 34), E(27, 34), E(32, 58), E(38, 35), E(35, 28), + E(16, 32), E(33, 60), E(51, 30), E(32, 4), E(36, 39), E(43, 34), + E(45, 30), E(27, 39), E(45, 33), E(42, 33), E(30, 38), E(32, 17), + E(31, 43), E(20, 26), E(26, 22), E(23, 27), E( 7, 29), E(13, 25), + E( 6, 33), E(47, 25), E(29, 61), E(30, 0), E( 9, 35), E(51, 25), + E(22, 36), E(34, 15), E(21, 27), E(25, 40), E(33, 53), E(32, 37), + E(56, 33), E(57, 3), E(30, 10), E(38, 16), E(51, 37), E(51, 38), + E(38, 18), E(63, 30), E(28, 46), E(40, 27), E(35, 9), E(33, 6), + E(42, 28), E(29, 22), E(24, 38), E(30, 2), E(25, 26), E(31, 63), + E(52, 32), E(31, 57), E(29, 26), E(35, 31), E(32, 5), E(41, 32), + E(35, 21), E(38, 39), E( 4, 31), E(30, 40), E(17, 31), E( 9, 33), + E(22, 28), E(34, 18), E( 4, 30), E(17, 34), E(28, 22), E(55, 33), + E(42, 29), E(40, 34), E(46, 32), E(38, 34), E(48, 32), E(63, 31), + E(23, 31), E(39, 33), E(33, 3), E( 3, 31), E(18, 29), E(33, 62), + E(33, 8), E(24, 42), E(58, 28), E(58, 29), E(34, 3), E(49, 25), + E(29, 16), E(43, 26), E( 4, 29), E( 1, 35), E( 4, 28), E(42, 27), + E(35, 51), E(35, 61), E(30, 48), E(17, 37), E( 5, 9), E(56, 34), + E(25, 41), E(17, 30), E(20, 34), E(47, 35), E(34, 21), E(33, 13), + E(16, 34), E(40, 35), E(32, 19), E(28, 35), E(33, 36), E(36, 30), + E(25, 39), E(16, 30), E(42, 30), E(19, 32), E(30, 46), E(53, 32), + E(32, 23), E(29, 42), E(10, 32), E(11, 31), E(14, 33), E(34, 38), + E(32, 39), E(41, 29), E(26, 26), E(61, 7), E(25, 49), E(22, 33), + E(28, 38), E(36, 38), E(45, 32), E(34, 27), E(28, 30), E(34, 28), + E(33, 59), E(37, 45), E(36, 20), E(55, 29), E(28, 21), E(35, 5), + E(29, 5), E(50, 29), E(48, 28), E(52, 34), E( 2, 29), E(42, 24), + E(34, 10), E(40, 24), E(46, 35), E(46, 36), E(43, 38), E(33, 11), + E( 4, 33), E(33, 40), E(32, 18), E(36, 34), E(27, 35), E(35, 22), + E(35, 55), E(29, 11), E(29, 38), E(41, 33), E(29, 28), E( 7, 32), + E(44, 31), E(26, 25), E(39, 29), E(32, 3), E(16, 31), E(31, 53), + E(26, 27), E(34, 43), E(38, 25), E(29, 40), E(41, 35), E(35, 27), + E(36, 29), E(38, 31), E(29, 27), E(32, 43), E(27, 29), E(30, 37), + E(24, 32), ESCAPE, E(32, 63), E(24, 31), E(42, 34), E(48, 36), + E(20, 38), E(29, 53), E(31, 54), E(61, 33), E(41, 26), E( 7, 30), + E(30, 49), E(35, 20), E(19, 27), E(14, 30), E(21, 39), E( 8, 33), + E(39, 41), E(39, 49), E(40, 22), E(46, 38), E(55, 38), E(34, 4), + E( 6, 30), E(30, 8), E(34, 9), E(37, 3), E(25, 24), E(37, 22), + E(33, 50), E(22, 37), E(44, 36), E(52, 31), E(17, 27), E(35, 2), + E(31, 50), E(30, 21), E(24, 36), E(35, 33), E(22, 38), E(61, 30), + E(32, 12), E( 9, 31), E(45, 34), E(34, 20), E(31, 15), E(19, 29), + E( 9, 32), E(31, 62), E(18, 32), E(33, 17), E(33, 1), E(37, 34), + E(32, 15), E(22, 30), E(26, 30), E(59, 31), E(29, 9), E(36, 42), + E(46, 30), E(31, 13), E(35, 17), E(54, 32), E(29, 19), E(57, 31), + E(30, 20), E(50, 31), E( 3, 30), E(31, 7), E(63, 1), E(34, 17), + E(47, 34), E(41, 37), E(35, 63), E(40, 25), E(25, 30), E(37, 28), + E( 1, 31), E(26, 28), E(22, 34), E(35, 37), E(34, 32), E(60, 32), + E(27, 30), E(37, 19), E(28, 44), E(30, 1), E(50, 28), E(14, 28), + E(28, 48), E(55, 30), E( 6, 34), E(23, 41), E(19, 41), E(14, 38), + E(30, 12), E( 3, 27), E(30, 15), E(28, 0), E(28, 16), E(61, 34), + E(61, 35), E(47, 38), E(45, 28), E(48, 29), E(40, 40), E(40, 42), + E(34, 51), E(34, 52), E(25, 45), E(30, 54), E(29, 59), E(35, 59), + E( 4, 42), E(51, 31), E(18, 31), E(31, 44), E(14, 34), E(37, 26), + E(36, 35), E(37, 35), E(30, 26), E(31, 41), E(31, 39), E(23, 32), + E(23, 29), E(38, 40), E(31, 16), E(24, 37), E(32, 52), E(31, 48), + E(50, 30), E(28, 34), E(32, 21), E(33, 20), E(31, 18), E(49, 32), + E(34, 37), E(33, 29), E(31, 29), E(40, 31), E( 3, 33), E(28, 27), + E(26, 35), E(28, 28), E(33, 39), E(34, 26), E(26, 44), E(53, 37), + E(50, 26), E(26, 46), E(41, 24), E(27, 15), E(59, 39), E(27, 22), + E(29, 31), E(38, 46), E(39, 19), E( 3, 35), E(50, 38), E(43, 17), + E(47, 37), E(23, 23), E(33, 52), E(55, 55), E(35, 50), E(21, 37), + E(23, 26), E(35, 11), E(61, 37), E(33, 12), E(46, 24), E(52, 30), + E(35, 16), E(34, 13), E(24, 22), E(30, 13), E(43, 36), E(16, 35), + E(37, 40), E(21, 41), E( 2, 34), E(54, 33), E(27, 38), E( 9, 29), + E(33, 7), E(23, 25), E(19, 30), E(32, 54), E(29, 45), E(29, 47), + E(33, 46), E(28, 41), E(27, 27), E(32, 49), E(39, 30), E(33, 31), + E(59, 32), E(32, 42), E(33, 22), E(47, 29), E(49, 29), E(32, 59), + E(40, 32), E(31, 24), E(27, 37), E(23, 34), E(28, 37), E(36, 26), + E(32, 7), E(38, 32), E(29, 33), E(15, 32), E(30, 16), E(47, 30), + E(33, 14), E(27, 26), E(25, 38), E(54, 34), E(44, 34), E(45, 29), + E(50, 34), E(58, 30), E(51, 29), E(48, 30), E(33, 57), E(59, 30), + E( 6, 32), E(34, 22), E(27, 28), E(31, 45), E(30, 27), E(24, 33), + E(26, 29), E(33, 4), E(24, 41), E(45, 26), E(23, 30), E( 2, 31), + E(28, 29), E(35, 36), E(30, 28), E(34, 53), E(30, 51), E(55, 5), + E(55, 21), E( 1, 30), E(29, 2), E(29, 63), E(26, 41), E(28, 20), + E(25, 1), E(31, 56), E(36, 21), E(22, 24), E(17, 25), E(30, 5), + E(52, 28), E( 2, 35), E(44, 26), E(44, 28), E(57, 30), E(26, 18), + E(62, 29), E(41, 23), E(39, 40), E(57, 34), E(26, 20), E(46, 42), + E(49, 39), E(11, 34), E(16, 28), E(19, 61), E( 5, 38), E(34, 46), + E(57, 33), E(13, 29), E(26, 39), E(33, 44), E(13, 30), E(48, 31), + E(30, 50), E(11, 33), E( 7, 31), E(56, 32), E(34, 19), E(33, 43), + E(32, 46), E(34, 41), E(41, 30), E(36, 28), E(34, 31), E(33, 33), + E(33, 35), E(26, 34), E(28, 26), E(32, 13), E(41, 34), E( 0, 32), + E(32, 57), E(35, 30), E(35, 32), E(55, 32), E(26, 40), E( 0, 31), + E(26, 37), E(35, 47), E( 1, 1), E(51, 35), E(33, 16), E(53, 31), + E(31, 0), E(45, 35), E(12, 33), E(29, 1), E(29, 17), E(36, 27), + E( 5, 32), E(38, 38), E(59, 27), E(38, 62), E(39, 9), E(58, 36), + E(34, 42), E(31, 42), E(36, 31), E(47, 33), E(32, 47), E(17, 33), + E(31, 60), E(31, 23), E(33, 41), E(34, 30), E(34, 36), E(32, 60), + E(29, 36), E(38, 17), E(25, 9), E(49, 49), E(50, 24), E(22, 25), + E(28, 54), E(59, 34), E( 9, 39), E(59, 37), E( 7, 3), E(28, 1), + E(55, 25), E(17, 38), E( 4, 38), E(35, 44), E(50, 35), E(21, 36), + E(29, 12), E(44, 60), E(47, 36), E(18, 38), E(24, 40), E(19, 25), + E(25, 43), E(31, 31), +}; + +const uint8_t ff_msmp4_mv_table1_lens[MSMPEG4_MV_TABLES_NB_ELEMS] = { + 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 13, 13, 13, 14, 15, 15, 11, 13, 13, 12, 11, 10, + 8, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 12, 10, 12, 12, 12, 12, 10, + 14, 15, 15, 13, 13, 13, 12, 12, 11, 13, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 9, 6, 9, 10, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 13, 13, 11, 11, 12, 13, 13, 11, 12, 13, 13, 10, 7, 8, 10, 14, + 15, 15, 14, 14, 12, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, + 13, 13, 12, 13, 13, 13, 13, 13, 13, 13, 13, 8, 9, 9, 5, 13, 14, 14, + 12, 12, 14, 14, 14, 14, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, + 12, 12, 12, 11, 10, 11, 13, 13, 13, 13, 12, 12, 12, 13, 14, 14, 11, 12, + 14, 14, 14, 14, 7, 8, 9, 10, 14, 14, 13, 12, 11, 7, 8, 10, 13, 14, + 14, 13, 13, 13, 13, 13, 13, 13, 13, 12, 11, 13, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 8, 13, 13, 13, 13, 12, 12, 10, 10, 10, + 10, 11, 14, 14, 13, 13, 13, 12, 13, 14, 14, 11, 10, 9, 10, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 8, 11, 12, 13, 13, 10, 10, + 10, 8, 8, 13, 13, 12, 12, 12, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 12, 8, 9, 10, 13, 13, + 13, 13, 13, 13, 14, 14, 14, 14, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 13, 13, 13, 9, 13, 13, 13, 13, 12, 12, 12, 13, 13, 11, 10, 10, 10, + 11, 13, 13, 13, 13, 9, 4, 12, 12, 12, 12, 10, 10, 13, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 11, 10, + 13, 13, 13, 13, 12, 12, 10, 9, 13, 13, 12, 11, 11, 13, 14, 14, 12, 11, + 12, 14, 14, 14, 14, 10, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, + 13, 13, 13, 13, 12, 12, 10, 10, 9, 11, 12, 12, 10, 12, 13, 13, 11, 13, + 13, 13, 13, 11, 9, 11, 13, 14, 14, 12, 10, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 12, + 12, 12, 12, 12, 10, 5, 4, 12, 12, 13, 13, 13, 13, 10, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 12, 12, 12, 11, 11, 10, 9, 11, 11, 12, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 9, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 12, 11, 12, 12, 11, + 12, 13, 13, 10, 13, 13, 13, 13, 12, 12, 11, 12, 12, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 9, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 12, 8, 10, 10, + 13, 13, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 11, 12, 12, + 11, 10, 11, 11, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 12, 11, 10, 10, + 13, 13, 12, 12, 13, 13, 10, 13, 13, 13, 13, 11, 9, 12, 13, 14, 14, 12, + 12, 12, 12, 11, 10, 10, 12, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 13, 13, 12, 12, 10, 11, 13, 14, 14, 12, 11, 11, 12, + 13, 13, 11, 9, 13, 13, 13, 13, 13, 13, 12, 11, 11, 10, 11, 11, 11, 11, + 10, 4, 11, 11, 12, 14, 14, 14, 14, 11, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 13, 13, 13, 8, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 11, + 12, 12, 11, 11, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 14, 14, 11, 12, 12, 12, 12, 11, 6, 10, 11, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 11, 11, 11, 11, 10, 10, + 12, 13, 13, 13, 13, 13, 13, 10, 10, 13, 13, 12, 11, 8, 8, 11, 11, 12, + 12, 11, 10, 11, 14, 14, 14, 14, 14, 14, 14, 14, 8, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 11, 5, + 10, 11, 12, 13, 13, 10, 10, 11, 12, 12, 12, 12, 11, 9, 8, 12, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 11, 11, + 12, 13, 14, 14, 12, 12, 11, 11, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, + 12, 12, 12, 11, 7, 5, 8, 11, 12, 12, 12, 12, 11, 9, 7, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 10, 12, 14, 14, 14, 14, + 12, 12, 9, 12, 12, 12, 12, 11, 11, 8, 10, 10, 11, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 4, +}; + static const uint16_t table0_mv_code[1100] = { 0x0001, 0x0003, 0x0005, 0x0007, 0x0003, 0x0008, 0x000c, 0x0001, 0x0002, 0x001b, 0x0006, 0x000b, 0x0015, 0x0002, 0x000e, 0x000f, @@ -1045,7 +1554,6 @@ static const uint8_t table0_mvy[1099] = { 25, 27, 28, }; -/* motion vector table 1 */ static const uint16_t table1_mv_code[1100] = { 0x0000, 0x0007, 0x0009, 0x000f, 0x000a, 0x0011, 0x001a, 0x001c, 0x0011, 0x0031, 0x0025, 0x002d, 0x002f, 0x006f, 0x0075, 0x0041, diff --git a/libavcodec/msmpeg4data.h b/libavcodec/msmpeg4data.h index 4921548d0c..2217b5ea48 100644 --- a/libavcodec/msmpeg4data.h +++ b/libavcodec/msmpeg4data.h @@ -58,7 +58,12 @@ extern const uint8_t ff_wmv1_y_dc_scale_table[32]; extern const uint8_t ff_wmv1_c_dc_scale_table[32]; extern const uint8_t ff_old_ff_y_dc_scale_table[32]; -#define MSMPEG4_MV_TABLES_NB_ELEMS 1099 +#define MSMPEG4_MV_TABLES_NB_ELEMS 1100 +/// The entries are of the form (8 << mvx) | mvy. Escape value is zero. +extern const uint16_t ff_msmp4_mv_table0[MSMPEG4_MV_TABLES_NB_ELEMS]; +extern const uint8_t ff_msmp4_mv_table0_lens[MSMPEG4_MV_TABLES_NB_ELEMS]; +extern const uint16_t ff_msmp4_mv_table1[MSMPEG4_MV_TABLES_NB_ELEMS]; +extern const uint8_t ff_msmp4_mv_table1_lens[MSMPEG4_MV_TABLES_NB_ELEMS]; extern MVTable ff_mv_tables[2]; extern const uint8_t ff_v2_mb_type[8][2]; diff --git a/libavcodec/msmpeg4dec.c b/libavcodec/msmpeg4dec.c index aac12882d7..b60e218f6a 100644 --- a/libavcodec/msmpeg4dec.c +++ b/libavcodec/msmpeg4dec.c @@ -46,6 +46,8 @@ #define DEFAULT_INTER_INDEX 3 +static const VLCElem *mv_tables[2]; + static inline int msmpeg4v1_pred_dc(MpegEncContext * s, int n, int32_t **dc_val_ptr) { @@ -300,7 +302,6 @@ static av_cold void msmpeg4_decode_init_static(void) { static VLCElem vlc_buf[3714 + 2694 + 1636 + 2648 + 1532 + 2488]; VLCInitState state = VLC_INIT_STATE(vlc_buf); - MVTable *mv; INIT_FIRST_VLC_RL(ff_rl_table[0], 642); INIT_FIRST_VLC_RL(ff_rl_table[1], 1104); @@ -326,18 +327,16 @@ static av_cold void msmpeg4_decode_init_static(void) &ff_v2_mb_type[0][1], 2, 1, &ff_v2_mb_type[0][0], 2, 1, 0); - mv = &ff_mv_tables[0]; - mv->vlc = ff_vlc_init_tables_sparse(&state, MV_VLC_BITS, - MSMPEG4_MV_TABLES_NB_ELEMS + 1, - mv->table_mv_bits, 1, 1, - mv->table_mv_code, 2, 2, - NULL, 0, 0, 0); - mv = &ff_mv_tables[1]; - mv->vlc = ff_vlc_init_tables_sparse(&state, MV_VLC_BITS, - MSMPEG4_MV_TABLES_NB_ELEMS + 1, - mv->table_mv_bits, 1, 1, - mv->table_mv_code, 2, 2, - NULL, 0, 0, 0); + mv_tables[0] = ff_vlc_init_tables_from_lengths(&state, MV_VLC_BITS, + MSMPEG4_MV_TABLES_NB_ELEMS, + ff_msmp4_mv_table0_lens, 1, + ff_msmp4_mv_table0, 2, 2, + 0, 0); + mv_tables[1] = ff_vlc_init_tables_from_lengths(&state, MV_VLC_BITS, + MSMPEG4_MV_TABLES_NB_ELEMS, + ff_msmp4_mv_table1_lens, 1, + ff_msmp4_mv_table1, 2, 2, + 0, 0); for (unsigned i = 0; i < 4; i++) { ff_mb_non_intra_vlc[i] = @@ -817,18 +816,17 @@ int ff_msmpeg4_decode_block(MpegEncContext * s, int16_t * block, void ff_msmpeg4_decode_motion(MpegEncContext *s, int *mx_ptr, int *my_ptr) { - const MVTable *mv; - int code, mx, my; - - mv = &ff_mv_tables[s->mv_table_index]; + const VLCElem *const mv_vlc = mv_tables[s->mv_table_index]; + int sym, mx, my; - code = get_vlc2(&s->gb, mv->vlc, MV_VLC_BITS, 2); - if (code == MSMPEG4_MV_TABLES_NB_ELEMS) { + sym = get_vlc2(&s->gb, mv_vlc, MV_VLC_BITS, 2); + if (sym) { + mx = sym >> 8; + my = sym & 0xFF; + } else { + /* Escape */ mx = get_bits(&s->gb, 6); my = get_bits(&s->gb, 6); - } else { - mx = mv->table_mvx[code]; - my = mv->table_mvy[code]; } mx += *mx_ptr - 32; diff --git a/libavcodec/msmpeg4enc.c b/libavcodec/msmpeg4enc.c index b5da98f03b..5ce54a8d16 100644 --- a/libavcodec/msmpeg4enc.c +++ b/libavcodec/msmpeg4enc.c @@ -67,7 +67,7 @@ static av_cold void init_mv_table(const MVTable *tab, uint32_t mv_vector_table[4 mv_vector_table[i] = (escape_code << 20) | (i << 8) | escape_length; } - for (i = 0; i < MSMPEG4_MV_TABLES_NB_ELEMS; i++) { + for (i = 0; i < MSMPEG4_MV_TABLES_NB_ELEMS - 1; i++) { x = tab->table_mvx[i]; y = tab->table_mvy[i]; mv_vector_table[(x << 6) | y] = (tab->table_mv_code[i] << 8) | tab->table_mv_bits[i]; -- 2.45.2 [-- Attachment #47: 0046-avcodec-msmpeg4enc-Avoid-using-MVTable.patch --] [-- Type: text/x-patch, Size: 54656 bytes --] From 2b14bd1858de5e141a9d63b0601b69a0e89b12e4 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sat, 15 Mar 2025 11:08:38 +0100 Subject: [PATCH 46/77] avcodec/msmpeg4enc: Avoid using MVTable Switch to using the length+symbol table combination that is also used by the decoder and remove MVTable as well as the old tables altogether. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/msmpeg4data.c | 1139 -------------------------------------- libavcodec/msmpeg4data.h | 11 - libavcodec/msmpeg4enc.c | 24 +- 3 files changed, 15 insertions(+), 1159 deletions(-) diff --git a/libavcodec/msmpeg4data.c b/libavcodec/msmpeg4data.c index aac75abd7c..b3603f7db1 100644 --- a/libavcodec/msmpeg4data.c +++ b/libavcodec/msmpeg4data.c @@ -990,1145 +990,6 @@ const uint8_t ff_msmp4_mv_table1_lens[MSMPEG4_MV_TABLES_NB_ELEMS] = { 14, 4, }; -static const uint16_t table0_mv_code[1100] = { - 0x0001, 0x0003, 0x0005, 0x0007, 0x0003, 0x0008, 0x000c, 0x0001, - 0x0002, 0x001b, 0x0006, 0x000b, 0x0015, 0x0002, 0x000e, 0x000f, - 0x0014, 0x0020, 0x0022, 0x0025, 0x0027, 0x0029, 0x002d, 0x004b, - 0x004d, 0x0003, 0x0022, 0x0023, 0x0025, 0x0027, 0x0042, 0x0048, - 0x0049, 0x0050, 0x005c, 0x0091, 0x009f, 0x000e, 0x0043, 0x004c, - 0x0054, 0x0056, 0x008c, 0x0098, 0x009a, 0x009b, 0x00b1, 0x00b2, - 0x0120, 0x0121, 0x0126, 0x0133, 0x0139, 0x01a1, 0x01a4, 0x01a5, - 0x01a6, 0x01a7, 0x01ae, 0x01af, 0x000b, 0x0019, 0x0085, 0x0090, - 0x009b, 0x00aa, 0x00af, 0x010c, 0x010e, 0x011c, 0x011e, 0x0133, - 0x0144, 0x0160, 0x0174, 0x0175, 0x0177, 0x0178, 0x0249, 0x024b, - 0x0252, 0x0261, 0x0265, 0x0270, 0x0352, 0x0353, 0x0355, 0x0359, - 0x0010, 0x0011, 0x0013, 0x0034, 0x0035, 0x0036, 0x0037, 0x003d, - 0x003e, 0x0109, 0x0126, 0x0156, 0x021a, 0x021e, 0x023a, 0x023e, - 0x028e, 0x028f, 0x02cf, 0x0491, 0x0494, 0x049f, 0x04a0, 0x04a3, - 0x04a6, 0x04a7, 0x04ad, 0x04ae, 0x04c0, 0x04c4, 0x04c6, 0x04c8, - 0x04c9, 0x04f5, 0x04f6, 0x04f7, 0x0680, 0x0682, 0x0683, 0x0688, - 0x0689, 0x068d, 0x068e, 0x068f, 0x06a2, 0x06a3, 0x06a9, 0x06b0, - 0x06b1, 0x06b4, 0x06b5, 0x0024, 0x0060, 0x0063, 0x0078, 0x0079, - 0x0211, 0x0244, 0x0245, 0x0247, 0x0248, 0x0249, 0x024a, 0x024b, - 0x026b, 0x02af, 0x02b8, 0x02bb, 0x0436, 0x0476, 0x0477, 0x047e, - 0x04c8, 0x04c9, 0x04ca, 0x0514, 0x0586, 0x0587, 0x0598, 0x059d, - 0x05d9, 0x05da, 0x0920, 0x0921, 0x093b, 0x093c, 0x093d, 0x0942, - 0x0943, 0x0944, 0x0945, 0x0959, 0x095e, 0x095f, 0x0982, 0x0983, - 0x098e, 0x098f, 0x09c4, 0x09e7, 0x09e8, 0x09e9, 0x0d02, 0x0d17, - 0x0d18, 0x0d19, 0x0d41, 0x0d42, 0x0d43, 0x0d50, 0x0d5f, 0x0d6d, - 0x0d6e, 0x0d6f, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x041e, 0x041f, 0x0420, 0x0421, - 0x048c, 0x048d, 0x04d3, 0x04d4, 0x04d5, 0x055c, 0x055d, 0x0572, - 0x0573, 0x0574, 0x0575, 0x08de, 0x08df, 0x08fe, 0x08ff, 0x0996, - 0x0a36, 0x0a37, 0x0b08, 0x0b09, 0x0b0a, 0x0b0b, 0x0b32, 0x0b33, - 0x0b34, 0x0b35, 0x0b36, 0x0b37, 0x0b38, 0x0b39, 0x0bb0, 0x0bf7, - 0x0bf8, 0x0bf9, 0x0bfa, 0x0bfb, 0x0bfc, 0x0bfd, 0x0bfe, 0x0bff, - 0x1254, 0x1255, 0x1256, 0x1257, 0x1270, 0x1271, 0x1272, 0x1273, - 0x1274, 0x1275, 0x12ab, 0x12ac, 0x12ad, 0x12ae, 0x12af, 0x12b0, - 0x12b1, 0x1315, 0x1316, 0x1317, 0x13bf, 0x13c0, 0x13c1, 0x13c2, - 0x13c3, 0x13c4, 0x13c5, 0x13c6, 0x13c7, 0x13c8, 0x13c9, 0x13ca, - 0x13cb, 0x13cc, 0x13cd, 0x1a06, 0x1a07, 0x1a28, 0x1a29, 0x1a2a, - 0x1a2b, 0x1a2c, 0x1a2d, 0x1a80, 0x1abb, 0x1abc, 0x1abd, 0x1ad8, - 0x1ad9, 0x0094, 0x0095, 0x0096, 0x0097, 0x00a0, 0x00a1, 0x00a2, - 0x00a3, 0x0831, 0x0832, 0x0833, 0x0834, 0x0835, 0x0836, 0x0837, - 0x0838, 0x0839, 0x083a, 0x083b, 0x0939, 0x093a, 0x093b, 0x093c, - 0x093d, 0x093e, 0x093f, 0x09a0, 0x09a1, 0x09a2, 0x09a3, 0x09a4, - 0x09a5, 0x11ac, 0x11ad, 0x11ae, 0x11af, 0x11b0, 0x11b1, 0x11b2, - 0x11b3, 0x11b4, 0x11b5, 0x11b6, 0x11b7, 0x11b8, 0x11b9, 0x11ba, - 0x11bb, 0x132f, 0x1454, 0x1455, 0x1456, 0x1457, 0x1458, 0x1459, - 0x145a, 0x145b, 0x145c, 0x145d, 0x145e, 0x145f, 0x1460, 0x1461, - 0x1462, 0x1463, 0x1464, 0x1465, 0x1466, 0x1467, 0x1468, 0x1469, - 0x146a, 0x146b, 0x17de, 0x17df, 0x17e0, 0x17e1, 0x17e2, 0x17e3, - 0x17e4, 0x17e5, 0x17e6, 0x17e7, 0x17e8, 0x17e9, 0x17ea, 0x17eb, - 0x17ec, 0x17ed, 0x2540, 0x2541, 0x2542, 0x2543, 0x2544, 0x2545, - 0x2546, 0x2547, 0x2548, 0x2549, 0x254a, 0x254b, 0x254c, 0x254d, - 0x254e, 0x254f, 0x2550, 0x2551, 0x2552, 0x2553, 0x2554, 0x2555, - 0x2628, 0x2766, 0x2767, 0x2768, 0x2769, 0x276a, 0x276b, 0x276c, - 0x276d, 0x276e, 0x276f, 0x2770, 0x2771, 0x2772, 0x2773, 0x2774, - 0x2775, 0x2776, 0x2777, 0x2778, 0x2779, 0x277a, 0x277b, 0x277c, - 0x277d, 0x3503, 0x3544, 0x3545, 0x3546, 0x3547, 0x3560, 0x3561, - 0x3562, 0x3563, 0x3564, 0x3565, 0x3566, 0x3567, 0x3568, 0x3569, - 0x356a, 0x356b, 0x356c, 0x356d, 0x356e, 0x356f, 0x3570, 0x3571, - 0x3572, 0x3573, 0x3574, 0x3575, 0x03f0, 0x103d, 0x103e, 0x103f, - 0x1040, 0x1041, 0x1042, 0x1043, 0x1044, 0x1045, 0x1046, 0x1047, - 0x1048, 0x1049, 0x104a, 0x104b, 0x104c, 0x104d, 0x104e, 0x104f, - 0x1050, 0x1051, 0x1052, 0x1053, 0x1054, 0x1055, 0x1056, 0x1057, - 0x1058, 0x1059, 0x105a, 0x105b, 0x105c, 0x105d, 0x105e, 0x105f, - 0x1060, 0x1061, 0x1270, 0x1271, 0x21b8, 0x21b9, 0x21ba, 0x21bb, - 0x21bc, 0x21bd, 0x21be, 0x21bf, 0x21f0, 0x21f1, 0x21f2, 0x21f3, - 0x21f4, 0x21f5, 0x21f6, 0x21f7, 0x21f8, 0x21f9, 0x21fa, 0x21fb, - 0x21fc, 0x21fd, 0x21fe, 0x21ff, 0x2340, 0x2341, 0x2342, 0x2343, - 0x2344, 0x2345, 0x2346, 0x2347, 0x2348, 0x2349, 0x234a, 0x234b, - 0x234c, 0x234d, 0x234e, 0x234f, 0x2350, 0x2351, 0x2352, 0x2353, - 0x2354, 0x2355, 0x2356, 0x2357, 0x265c, 0x2f88, 0x2f89, 0x2f8a, - 0x2f8b, 0x2f8c, 0x2f8d, 0x2f8e, 0x2f8f, 0x2f90, 0x2f91, 0x2f92, - 0x2f93, 0x2f94, 0x2f95, 0x2f96, 0x2f97, 0x2f98, 0x2f99, 0x2f9a, - 0x2f9b, 0x2f9c, 0x2f9d, 0x2f9e, 0x2f9f, 0x2fa0, 0x2fa1, 0x2fa2, - 0x2fa3, 0x2fa4, 0x2fa5, 0x2fa6, 0x2fa7, 0x2fa8, 0x2fa9, 0x2faa, - 0x2fab, 0x2fac, 0x2fad, 0x2fae, 0x2faf, 0x2fb0, 0x2fb1, 0x2fb2, - 0x2fb3, 0x2fb4, 0x2fb5, 0x2fb6, 0x2fb7, 0x2fb8, 0x2fb9, 0x2fba, - 0x2fbb, 0x4c52, 0x4c53, 0x4e28, 0x4e29, 0x4e2a, 0x4e2b, 0x4e2c, - 0x4e2d, 0x4e2e, 0x4e2f, 0x4e30, 0x4e31, 0x4e32, 0x4e33, 0x4e34, - 0x4e35, 0x4e36, 0x4e37, 0x4e38, 0x4e39, 0x4e3a, 0x4e3b, 0x4e3c, - 0x4e3d, 0x4e3e, 0x4e3f, 0x4e80, 0x4e81, 0x4e82, 0x4e83, 0x4e84, - 0x4e85, 0x4e86, 0x4e87, 0x4e88, 0x4e89, 0x4e8a, 0x4e8b, 0x4e8c, - 0x4e8d, 0x4e8e, 0x4e8f, 0x4e90, 0x4e91, 0x4e92, 0x4e93, 0x4e94, - 0x4e95, 0x4e96, 0x4e97, 0x4e98, 0x4e99, 0x4e9a, 0x4e9b, 0x4e9c, - 0x4e9d, 0x4e9e, 0x4e9f, 0x4ea0, 0x4ea1, 0x4ea2, 0x4ea3, 0x4ea4, - 0x4ea5, 0x4ea6, 0x4ea7, 0x4ea8, 0x4ea9, 0x4eaa, 0x4eab, 0x4eac, - 0x4ead, 0x4eae, 0x4eaf, 0x4eb0, 0x4eb1, 0x4eb2, 0x4eb3, 0x4eb4, - 0x4eb5, 0x4eb6, 0x4eb7, 0x4eb8, 0x4eb9, 0x4eba, 0x4ebb, 0x4ebc, - 0x4ebd, 0x4ebe, 0x4ebf, 0x4ec0, 0x4ec1, 0x4ec2, 0x4ec3, 0x4ec4, - 0x4ec5, 0x4ec6, 0x4ec7, 0x4ec8, 0x4ec9, 0x4eca, 0x4ecb, 0x6a04, - 0x6a05, 0x07e2, 0x07e3, 0x07e4, 0x07e5, 0x07e6, 0x07e7, 0x07e8, - 0x07e9, 0x07ea, 0x07eb, 0x07ec, 0x07ed, 0x07ee, 0x07ef, 0x07f0, - 0x07f1, 0x07f2, 0x07f3, 0x07f4, 0x07f5, 0x07f6, 0x07f7, 0x07f8, - 0x07f9, 0x07fa, 0x07fb, 0x07fc, 0x07fd, 0x07fe, 0x07ff, 0x2000, - 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, - 0x2009, 0x200a, 0x200b, 0x200c, 0x200d, 0x200e, 0x200f, 0x2010, - 0x2011, 0x2012, 0x2013, 0x2014, 0x2015, 0x2016, 0x2017, 0x2018, - 0x2019, 0x201a, 0x201b, 0x201c, 0x201d, 0x201e, 0x201f, 0x2020, - 0x2021, 0x2022, 0x2023, 0x2024, 0x2025, 0x2026, 0x2027, 0x2028, - 0x2029, 0x202a, 0x202b, 0x202c, 0x202d, 0x202e, 0x202f, 0x2030, - 0x2031, 0x2032, 0x2033, 0x2034, 0x2035, 0x2036, 0x2037, 0x2038, - 0x2039, 0x203a, 0x203b, 0x203c, 0x203d, 0x203e, 0x203f, 0x2040, - 0x2041, 0x2042, 0x2043, 0x2044, 0x2045, 0x2046, 0x2047, 0x2048, - 0x2049, 0x204a, 0x204b, 0x204c, 0x204d, 0x204e, 0x204f, 0x2050, - 0x2051, 0x2052, 0x2053, 0x2054, 0x2055, 0x2056, 0x2057, 0x2058, - 0x2059, 0x205a, 0x205b, 0x205c, 0x205d, 0x205e, 0x205f, 0x2060, - 0x2061, 0x2062, 0x2063, 0x2064, 0x2065, 0x2066, 0x2067, 0x2068, - 0x2069, 0x206a, 0x206b, 0x206c, 0x206d, 0x206e, 0x206f, 0x2070, - 0x2071, 0x2072, 0x2073, 0x2074, 0x2075, 0x2076, 0x2077, 0x2078, - 0x2079, 0x4cba, 0x4cbb, 0x5d88, 0x5d89, 0x5d8a, 0x5d8b, 0x5d8c, - 0x5d8d, 0x5d8e, 0x5d8f, 0x5db0, 0x5db1, 0x5db2, 0x5db3, 0x5db4, - 0x5db5, 0x5db6, 0x5db7, 0x5db8, 0x5db9, 0x5dba, 0x5dbb, 0x5dbc, - 0x5dbd, 0x5dbe, 0x5dbf, 0x5e40, 0x5e41, 0x5e42, 0x5e43, 0x5e44, - 0x5e45, 0x5e46, 0x5e47, 0x5e48, 0x5e49, 0x5e4a, 0x5e4b, 0x5e4c, - 0x5e4d, 0x5e4e, 0x5e4f, 0x5e50, 0x5e51, 0x5e52, 0x5e53, 0x5e54, - 0x5e55, 0x5e56, 0x5e57, 0x5e58, 0x5e59, 0x5e5a, 0x5e5b, 0x5e5c, - 0x5e5d, 0x5e5e, 0x5e5f, 0x5e60, 0x5e61, 0x5e62, 0x5e63, 0x5e64, - 0x5e65, 0x5e66, 0x5e67, 0x5e68, 0x5e69, 0x5e6a, 0x5e6b, 0x5e6c, - 0x5e6d, 0x5e6e, 0x5e6f, 0x5e70, 0x5e71, 0x5e72, 0x5e73, 0x5e74, - 0x5e75, 0x5e76, 0x5e77, 0x5e78, 0x5e79, 0x5e7a, 0x5e7b, 0x5e7c, - 0x5e7d, 0x5e7e, 0x5e7f, 0x5e80, 0x5e81, 0x5e82, 0x5e83, 0x5e84, - 0x5e85, 0x5e86, 0x5e87, 0x5e88, 0x5e89, 0x5e8a, 0x5e8b, 0x5e8c, - 0x5e8d, 0x5e8e, 0x5e8f, 0x5e90, 0x5e91, 0x5e92, 0x5e93, 0x5e94, - 0x5e95, 0x5e96, 0x5e97, 0x5e98, 0x5e99, 0x5e9a, 0x5e9b, 0x5e9c, - 0x5e9d, 0x5e9e, 0x5e9f, 0x5ea0, 0x5ea1, 0x5ea2, 0x5ea3, 0x5ea4, - 0x5ea5, 0x5ea6, 0x5ea7, 0x5ea8, 0x5ea9, 0x5eaa, 0x5eab, 0x5eac, - 0x5ead, 0x5eae, 0x5eaf, 0x5eb0, 0x5eb1, 0x5eb2, 0x5eb3, 0x5eb4, - 0x5eb5, 0x5eb6, 0x5eb7, 0x5eb8, 0x5eb9, 0x5eba, 0x5ebb, 0x5ebc, - 0x5ebd, 0x5ebe, 0x5ebf, 0x5ec0, 0x5ec1, 0x5ec2, 0x5ec3, 0x5ec4, - 0x5ec5, 0x5ec6, 0x5ec7, 0x5ec8, 0x5ec9, 0x5eca, 0x5ecb, 0x5ecc, - 0x5ecd, 0x5ece, 0x5ecf, 0x5ed0, 0x5ed1, 0x5ed2, 0x5ed3, 0x5ed4, - 0x5ed5, 0x5ed6, 0x5ed7, 0x5ed8, 0x5ed9, 0x5eda, 0x5edb, 0x5edc, - 0x5edd, 0x5ede, 0x5edf, 0x5ee0, 0x5ee1, 0x5ee2, 0x5ee3, 0x5ee4, - 0x5ee5, 0x5ee6, 0x5ee7, 0x5ee8, 0x5ee9, 0x5eea, 0x5eeb, 0x5eec, - 0x5eed, 0x5eee, 0x5eef, 0x5ef0, 0x5ef1, 0x5ef2, 0x5ef3, 0x5ef4, - 0x5ef5, 0x5ef6, 0x5ef7, 0x5ef8, 0x5ef9, 0x5efa, 0x5efb, 0x5efc, - 0x5efd, 0x5efe, 0x5eff, 0x5f00, 0x5f01, 0x5f02, 0x5f03, 0x5f04, - 0x5f05, 0x5f06, 0x5f07, 0x5f08, 0x5f09, 0x5f0a, 0x5f0b, 0x5f0c, - 0x5f0d, 0x5f0e, 0x5f0f, 0x0000, -}; - -static const uint8_t table0_mv_bits[1100] = { - 1, 4, 4, 4, 5, 5, 5, 6, - 6, 6, 7, 7, 7, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 8, -}; - -static const uint8_t table0_mvx[1099] = { - 32, 32, 31, 32, 33, 31, 33, 31, - 33, 32, 34, 32, 30, 32, 31, 34, - 35, 32, 34, 33, 29, 33, 30, 30, - 31, 31, 35, 29, 33, 35, 33, 34, - 31, 29, 30, 34, 30, 36, 28, 32, - 34, 37, 30, 27, 32, 25, 39, 32, - 34, 32, 35, 35, 35, 31, 35, 29, - 32, 29, 30, 29, 37, 27, 36, 38, - 37, 33, 32, 31, 29, 31, 28, 36, - 33, 30, 34, 33, 33, 28, 27, 25, - 31, 26, 39, 32, 32, 31, 33, 39, - 31, 38, 28, 36, 21, 23, 43, 36, - 34, 41, 30, 25, 28, 31, 30, 34, - 38, 35, 61, 34, 28, 30, 37, 37, - 35, 27, 36, 3, 59, 38, 37, 32, - 31, 29, 26, 33, 37, 33, 27, 27, - 35, 34, 34, 40, 42, 33, 32, 29, - 4, 5, 28, 24, 25, 35, 39, 38, - 32, 23, 27, 32, 30, 35, 26, 34, - 60, 36, 29, 22, 26, 41, 7, 30, - 38, 30, 36, 29, 30, 41, 26, 25, - 32, 34, 24, 39, 1, 25, 39, 32, - 28, 29, 32, 38, 26, 36, 28, 63, - 28, 39, 23, 21, 26, 35, 31, 35, - 57, 31, 29, 29, 28, 30, 27, 35, - 2, 38, 40, 34, 37, 29, 38, 43, - 26, 32, 33, 42, 24, 40, 28, 32, - 32, 32, 36, 32, 43, 25, 21, 31, - 30, 31, 41, 29, 33, 37, 26, 37, - 27, 59, 23, 33, 35, 31, 31, 37, - 38, 39, 32, 23, 32, 27, 37, 36, - 31, 40, 25, 27, 38, 31, 36, 28, - 31, 36, 25, 45, 3, 34, 38, 39, - 40, 38, 30, 32, 19, 24, 25, 26, - 45, 20, 24, 33, 33, 31, 41, 34, - 39, 47, 40, 58, 59, 41, 33, 3, - 17, 61, 42, 30, 26, 29, 36, 61, - 33, 37, 62, 28, 25, 38, 25, 38, - 17, 23, 34, 33, 21, 33, 49, 27, - 32, 23, 27, 22, 24, 22, 39, 43, - 27, 37, 6, 42, 47, 26, 30, 31, - 41, 39, 33, 22, 45, 36, 32, 45, - 19, 22, 30, 5, 5, 17, 29, 22, - 31, 31, 43, 37, 27, 32, 32, 32, - 33, 34, 43, 35, 29, 26, 22, 32, - 19, 32, 25, 31, 41, 49, 28, 34, - 28, 39, 34, 19, 37, 38, 29, 21, - 36, 42, 24, 48, 16, 28, 49, 22, - 34, 31, 38, 39, 44, 11, 35, 30, - 33, 33, 23, 28, 33, 46, 15, 13, - 24, 41, 24, 34, 34, 30, 26, 24, - 14, 60, 21, 29, 39, 23, 35, 37, - 63, 45, 33, 34, 47, 41, 22, 42, - 35, 35, 23, 32, 35, 43, 32, 7, - 31, 41, 20, 31, 16, 13, 63, 25, - 30, 32, 35, 30, 30, 31, 42, 47, - 39, 38, 40, 40, 51, 55, 56, 18, - 21, 39, 39, 33, 17, 41, 23, 24, - 43, 25, 31, 20, 19, 45, 1, 34, - 31, 22, 35, 15, 46, 46, 35, 31, - 28, 29, 29, 23, 41, 27, 14, 53, - 53, 27, 24, 32, 57, 32, 17, 42, - 37, 29, 33, 1, 25, 32, 32, 63, - 26, 40, 44, 36, 31, 39, 20, 20, - 44, 23, 33, 34, 35, 33, 33, 28, - 41, 23, 41, 41, 29, 25, 26, 49, - 29, 24, 37, 49, 50, 51, 51, 26, - 39, 25, 26, 15, 39, 18, 42, 17, - 4, 31, 32, 32, 60, 1, 42, 32, - 0, 12, 19, 35, 21, 41, 17, 26, - 20, 45, 46, 32, 37, 22, 47, 29, - 31, 27, 29, 30, 21, 33, 35, 18, - 25, 33, 50, 51, 42, 2, 15, 51, - 53, 33, 25, 29, 55, 37, 38, 33, - 38, 59, 38, 33, 39, 13, 32, 40, - 61, 61, 32, 9, 44, 3, 31, 29, - 25, 31, 27, 23, 9, 25, 9, 29, - 20, 30, 30, 42, 18, 28, 25, 28, - 28, 21, 29, 43, 29, 43, 26, 44, - 44, 21, 38, 21, 24, 45, 45, 35, - 39, 22, 35, 36, 34, 34, 45, 34, - 29, 31, 46, 25, 46, 16, 17, 31, - 20, 32, 47, 47, 47, 32, 49, 49, - 49, 31, 1, 27, 28, 39, 39, 21, - 36, 23, 51, 2, 40, 51, 32, 53, - 24, 30, 24, 30, 21, 40, 57, 57, - 31, 41, 58, 32, 12, 4, 32, 34, - 59, 31, 32, 13, 9, 35, 26, 35, - 37, 61, 37, 63, 26, 29, 41, 38, - 23, 20, 41, 26, 41, 42, 42, 42, - 26, 26, 26, 26, 1, 26, 37, 37, - 37, 23, 34, 42, 27, 43, 34, 27, - 31, 24, 33, 16, 3, 31, 24, 33, - 24, 4, 44, 44, 11, 44, 31, 13, - 13, 44, 45, 13, 25, 22, 38, 26, - 38, 38, 39, 32, 30, 39, 30, 22, - 32, 26, 30, 47, 47, 47, 19, 47, - 30, 31, 35, 8, 23, 47, 47, 27, - 35, 47, 31, 48, 35, 19, 36, 49, - 49, 33, 31, 39, 27, 39, 49, 49, - 50, 50, 50, 39, 31, 51, 51, 39, - 28, 33, 33, 21, 40, 31, 52, 53, - 40, 53, 9, 33, 31, 53, 54, 54, - 54, 55, 55, 34, 15, 56, 25, 56, - 21, 21, 40, 40, 25, 40, 58, 36, - 5, 41, 41, 12, 60, 41, 41, 37, - 22, 61, 18, 29, 29, 30, 61, 30, - 61, 62, 62, 30, 30, 63, 18, 13, - 30, 23, 19, 20, 20, 41, 13, 2, - 5, 5, 1, 5, 32, 6, 32, 35, - 20, 35, 27, 35, 35, 36, 36, 13, - 36, 41, 41, 41, 3, 30, 42, 27, - 20, 30, 27, 28, 30, 21, 33, 33, - 14, 24, 30, 42, 24, 33, 25, 42, - 43, 14, 43, 43, 14, 43, 7, 36, - 37, 37, 37, 37, 7, 14, 25, 43, - 43, 44, 15, 37, 7, 7, 3, 1, - 8, 15, 15, 8, 44, 44, 44, 45, - 45, 45, 45, 8, 8, 45, 21, 45, - 28, 28, 28, 21, 28, 28, 22, 37, - 46, 46, 37, 8, 29, 37, 29, 22, - 46, 37, 22, 29, 47, 47, 38, 38, - 16, 38, 38, 33, 38, 22, 47, 47, - 29, 25, 16, 0, 48, 1, 34, 48, - 48, 34, 25, 26, 26, 49, 49, 26, - 1, 49, 4, 26, 4, 49, 1, 9, - 49, 49, 49, 10, 49, 17, 38, 17, - 17, 50, 38, 50, 50, 22, 38, 51, - 38, 38, 51, 39, 39, 18, 22, 39, - 51, 22, 52, 52, 52, 39, 53, 53, - 10, 23, 18, 29, 10, 53, 29, 54, - 11, 54, 11, 11, 55, 1, 18, 55, - 55, 55, 55, 55, 55, 29, 34, 18, - 29, 56, 56, 34, 57, 34, 34, 29, - 29, 57, 57, 35, 35, 35, 35, 35, - 39, 35, 59, 59, 18, 59, 39, 30, - 18, 40, 60, 60, 61, 30, 18, 61, - 61, 19, 19, -}; - -static const uint8_t table0_mvy[1099] = { - 32, 31, 32, 33, 32, 31, 31, 33, - 33, 34, 32, 30, 32, 35, 34, 31, - 32, 29, 33, 30, 32, 34, 33, 31, - 30, 35, 31, 31, 29, 33, 35, 30, - 29, 33, 34, 34, 30, 32, 32, 36, - 29, 32, 35, 32, 28, 32, 32, 27, - 35, 37, 34, 29, 30, 36, 35, 34, - 25, 30, 29, 35, 33, 31, 31, 32, - 31, 28, 39, 28, 29, 37, 31, 33, - 27, 36, 28, 36, 37, 33, 33, 31, - 27, 32, 31, 38, 26, 25, 25, 33, - 39, 31, 34, 30, 32, 32, 32, 34, - 36, 32, 28, 33, 30, 38, 37, 27, - 33, 28, 32, 37, 35, 38, 29, 34, - 27, 29, 29, 32, 32, 34, 35, 3, - 26, 36, 31, 38, 30, 26, 35, 34, - 37, 26, 25, 32, 32, 39, 23, 37, - 32, 32, 29, 32, 29, 36, 29, 30, - 41, 31, 30, 21, 39, 25, 34, 38, - 32, 35, 39, 32, 33, 33, 32, 27, - 29, 25, 28, 27, 26, 31, 30, 35, - 24, 24, 31, 34, 32, 30, 35, 40, - 28, 38, 5, 35, 29, 36, 36, 32, - 38, 30, 33, 31, 35, 26, 23, 38, - 32, 41, 28, 25, 37, 40, 37, 39, - 32, 36, 33, 39, 25, 26, 28, 31, - 28, 42, 23, 31, 33, 31, 39, 1, - 59, 22, 27, 4, 33, 34, 33, 24, - 41, 3, 35, 41, 41, 28, 36, 36, - 28, 33, 35, 21, 23, 21, 22, 37, - 27, 27, 43, 29, 60, 39, 27, 25, - 59, 34, 27, 27, 26, 40, 37, 27, - 61, 26, 39, 33, 31, 22, 37, 25, - 30, 25, 24, 61, 31, 34, 25, 38, - 32, 32, 30, 3, 61, 43, 29, 23, - 28, 32, 28, 32, 31, 34, 5, 33, - 32, 33, 33, 42, 37, 23, 38, 31, - 40, 26, 32, 26, 37, 38, 36, 24, - 29, 30, 20, 22, 29, 24, 32, 41, - 2, 34, 25, 33, 29, 31, 39, 35, - 36, 24, 32, 30, 33, 27, 44, 60, - 30, 36, 19, 34, 31, 24, 16, 35, - 32, 38, 21, 33, 31, 31, 21, 35, - 5, 17, 29, 38, 38, 18, 58, 19, - 43, 41, 30, 41, 43, 39, 29, 7, - 29, 17, 28, 19, 28, 31, 25, 19, - 40, 26, 21, 33, 39, 23, 40, 30, - 39, 34, 35, 32, 32, 24, 33, 30, - 40, 47, 39, 37, 32, 33, 24, 23, - 45, 47, 27, 23, 42, 32, 32, 33, - 36, 37, 37, 17, 18, 22, 40, 38, - 32, 31, 35, 24, 17, 25, 17, 23, - 33, 34, 51, 42, 31, 36, 36, 29, - 21, 22, 37, 44, 43, 25, 47, 33, - 45, 27, 31, 58, 31, 32, 31, 38, - 43, 20, 47, 45, 54, 1, 26, 34, - 38, 14, 22, 24, 33, 34, 32, 32, - 37, 21, 23, 49, 35, 23, 28, 39, - 39, 23, 55, 33, 30, 30, 63, 16, - 42, 28, 13, 33, 33, 35, 19, 46, - 43, 17, 19, 36, 39, 24, 31, 32, - 33, 26, 28, 62, 33, 63, 33, 39, - 19, 49, 17, 31, 43, 13, 15, 29, - 25, 35, 33, 23, 49, 41, 28, 29, - 34, 38, 7, 61, 11, 50, 13, 41, - 19, 47, 25, 26, 15, 42, 41, 29, - 45, 27, 17, 35, 32, 29, 32, 24, - 13, 26, 26, 31, 24, 33, 28, 30, - 31, 11, 45, 46, 33, 33, 35, 57, - 32, 32, 35, 45, 34, 11, 37, 42, - 39, 37, 31, 49, 21, 27, 29, 47, - 53, 40, 51, 16, 26, 1, 40, 30, - 41, 44, 34, 25, 27, 31, 35, 35, - 31, 15, 49, 1, 35, 40, 5, 58, - 21, 29, 22, 59, 45, 31, 9, 26, - 9, 29, 11, 32, 30, 3, 13, 20, - 18, 20, 11, 3, 29, 40, 31, 53, - 30, 17, 20, 37, 31, 42, 47, 47, - 54, 38, 9, 34, 13, 37, 21, 25, - 27, 43, 42, 45, 40, 25, 27, 46, - 22, 25, 53, 20, 2, 14, 39, 15, - 22, 44, 34, 21, 38, 33, 27, 48, - 34, 52, 35, 47, 49, 54, 2, 13, - 23, 52, 29, 45, 22, 49, 54, 21, - 40, 42, 31, 30, 29, 34, 0, 25, - 23, 51, 24, 59, 28, 38, 29, 31, - 2, 13, 31, 8, 31, 33, 12, 45, - 41, 7, 14, 30, 25, 18, 43, 20, - 43, 35, 44, 1, 49, 42, 42, 18, - 41, 38, 41, 44, 53, 11, 20, 25, - 45, 46, 47, 48, 39, 52, 46, 49, - 63, 55, 44, 38, 13, 13, 57, 22, - 51, 16, 12, 28, 35, 57, 25, 20, - 26, 28, 28, 29, 32, 31, 62, 34, - 35, 35, 19, 49, 48, 39, 40, 18, - 43, 46, 11, 6, 48, 19, 49, 41, - 10, 23, 58, 17, 21, 23, 34, 30, - 60, 0, 44, 34, 26, 37, 46, 43, - 49, 59, 4, 34, 59, 37, 22, 25, - 28, 46, 6, 40, 59, 42, 36, 61, - 28, 30, 31, 43, 10, 22, 23, 47, - 20, 52, 55, 36, 25, 16, 1, 11, - 27, 29, 5, 63, 18, 41, 31, 34, - 38, 1, 5, 13, 28, 31, 17, 38, - 39, 41, 36, 37, 22, 39, 33, 43, - 43, 15, 17, 49, 30, 21, 22, 20, - 10, 17, 25, 54, 57, 3, 34, 8, - 36, 25, 31, 14, 15, 19, 29, 25, - 18, 39, 53, 22, 27, 20, 29, 33, - 41, 42, 35, 62, 50, 29, 53, 50, - 35, 55, 42, 61, 63, 4, 7, 42, - 21, 46, 47, 49, 27, 46, 17, 55, - 41, 50, 63, 4, 56, 18, 8, 10, - 18, 51, 63, 36, 55, 18, 5, 55, - 9, 29, 17, 21, 30, 27, 1, 59, - 7, 11, 12, 15, 5, 42, 24, 41, - 43, 7, 27, 22, 25, 31, 30, 37, - 22, 39, 53, 29, 36, 37, 48, 0, - 5, 13, 17, 31, 32, 26, 46, 28, - 44, 45, 46, 53, 49, 51, 3, 41, - 3, 22, 42, 33, 5, 45, 7, 22, - 40, 53, 24, 14, 25, 27, 10, 12, - 34, 16, 17, 53, 20, 26, 39, 45, - 18, 45, 35, 33, 31, 49, 4, 39, - 42, 11, 51, 5, 13, 26, 27, 17, - 52, 30, 0, 22, 12, 34, 62, 36, - 38, 41, 47, 30, 63, 38, 41, 43, - 59, 33, 45, 37, 38, 40, 47, 24, - 48, 49, 30, 1, 10, 22, 49, 15, - 39, 59, 31, 32, 33, 18, 13, 15, - 31, 21, 27, 44, 42, 39, 46, 17, - 26, 32, 30, 31, 0, 30, 34, 9, - 12, 13, 25, 31, 32, 55, 43, 35, - 61, 33, 35, 46, 25, 47, 48, 62, - 63, 38, 61, 1, 2, 5, 7, 9, - 46, 10, 34, 35, 36, 55, 51, 7, - 40, 23, 34, 37, 5, 13, 42, 18, - 25, 27, 28, -}; - -static const uint16_t table1_mv_code[1100] = { - 0x0000, 0x0007, 0x0009, 0x000f, 0x000a, 0x0011, 0x001a, 0x001c, - 0x0011, 0x0031, 0x0025, 0x002d, 0x002f, 0x006f, 0x0075, 0x0041, - 0x004c, 0x004e, 0x005c, 0x0060, 0x0062, 0x0066, 0x0068, 0x0069, - 0x006b, 0x00a6, 0x00c1, 0x00cb, 0x00cc, 0x00ce, 0x00da, 0x00e8, - 0x00ee, 0x0087, 0x0090, 0x009e, 0x009f, 0x00ba, 0x00ca, 0x00d8, - 0x00db, 0x00df, 0x0104, 0x0109, 0x010c, 0x0143, 0x0145, 0x014a, - 0x0156, 0x015c, 0x01b3, 0x01d3, 0x01da, 0x0103, 0x0109, 0x010b, - 0x0122, 0x0127, 0x0134, 0x0161, 0x0164, 0x0176, 0x0184, 0x018d, - 0x018e, 0x018f, 0x0190, 0x0193, 0x0196, 0x019d, 0x019e, 0x019f, - 0x01a9, 0x01b2, 0x01b4, 0x01ba, 0x01bb, 0x01bc, 0x0201, 0x0202, - 0x0205, 0x0207, 0x020d, 0x0210, 0x0211, 0x0215, 0x021b, 0x021f, - 0x0281, 0x0285, 0x0290, 0x029c, 0x029d, 0x02a2, 0x02a7, 0x02a8, - 0x02aa, 0x02b0, 0x02b1, 0x02b4, 0x02bc, 0x02bf, 0x0320, 0x0326, - 0x0327, 0x0329, 0x032a, 0x0336, 0x0360, 0x0362, 0x0363, 0x0372, - 0x03b2, 0x03bc, 0x03bd, 0x0203, 0x0205, 0x021a, 0x0249, 0x024a, - 0x024c, 0x02c7, 0x02ca, 0x02ce, 0x02ef, 0x030d, 0x0322, 0x0325, - 0x0338, 0x0373, 0x037a, 0x0409, 0x0415, 0x0416, 0x0418, 0x0428, - 0x042d, 0x042f, 0x0434, 0x0508, 0x0509, 0x0510, 0x0511, 0x051c, - 0x051e, 0x0524, 0x0541, 0x0543, 0x0546, 0x0547, 0x054d, 0x0557, - 0x055f, 0x056a, 0x056c, 0x056d, 0x056f, 0x0576, 0x0577, 0x057a, - 0x057b, 0x057c, 0x057d, 0x0600, 0x0601, 0x0603, 0x0614, 0x0616, - 0x0617, 0x061c, 0x061f, 0x0642, 0x0648, 0x0649, 0x064a, 0x064b, - 0x0657, 0x0668, 0x0669, 0x066b, 0x066e, 0x067f, 0x06c2, 0x06c8, - 0x06cb, 0x06de, 0x06df, 0x06e2, 0x06e3, 0x06ef, 0x0748, 0x074b, - 0x076e, 0x076f, 0x077c, 0x0409, 0x0423, 0x0428, 0x0429, 0x042a, - 0x042b, 0x0432, 0x0433, 0x0496, 0x049a, 0x04d5, 0x04db, 0x0581, - 0x0582, 0x058b, 0x058c, 0x058d, 0x0598, 0x0599, 0x059a, 0x059e, - 0x05dd, 0x0619, 0x0632, 0x0633, 0x0648, 0x0672, 0x06a1, 0x06a2, - 0x06a3, 0x06af, 0x06e2, 0x06e3, 0x06e4, 0x0800, 0x0801, 0x0802, - 0x0803, 0x081a, 0x081b, 0x0829, 0x082f, 0x0832, 0x083e, 0x083f, - 0x0852, 0x0853, 0x0858, 0x086b, 0x0877, 0x0878, 0x0879, 0x087a, - 0x087b, 0x0a00, 0x0a01, 0x0a0d, 0x0a0e, 0x0a0f, 0x0a24, 0x0a37, - 0x0a3a, 0x0a3b, 0x0a3e, 0x0a46, 0x0a47, 0x0a4a, 0x0a4b, 0x0a5f, - 0x0a79, 0x0a7a, 0x0a7b, 0x0a80, 0x0a81, 0x0a84, 0x0a85, 0x0a99, - 0x0aa5, 0x0aa6, 0x0ab8, 0x0aba, 0x0abb, 0x0abc, 0x0abd, 0x0ac8, - 0x0ace, 0x0acf, 0x0ad7, 0x0adc, 0x0aeb, 0x0c04, 0x0c25, 0x0c26, - 0x0c27, 0x0c2a, 0x0c2b, 0x0c3a, 0x0c3b, 0x0c3c, 0x0c3d, 0x0ca0, - 0x0cad, 0x0cd4, 0x0cd5, 0x0cfc, 0x0cfd, 0x0d86, 0x0d92, 0x0d93, - 0x0d94, 0x0d95, 0x0db0, 0x0db8, 0x0db9, 0x0dba, 0x0dbb, 0x0dc0, - 0x0dc2, 0x0dc3, 0x0dda, 0x0ddb, 0x0ddc, 0x0ddd, 0x0e92, 0x0e93, - 0x0e94, 0x0e95, 0x0ec7, 0x0ecc, 0x0ece, 0x0ecf, 0x0ed8, 0x0ed9, - 0x0eda, 0x0edb, 0x0808, 0x0809, 0x080a, 0x0810, 0x0811, 0x0844, - 0x0845, 0x0861, 0x0862, 0x0863, 0x086c, 0x0922, 0x0923, 0x092e, - 0x092f, 0x0936, 0x0937, 0x09b1, 0x09b2, 0x09b3, 0x09b4, 0x09b5, - 0x09b8, 0x09b9, 0x09ba, 0x09bb, 0x09bc, 0x09bd, 0x09be, 0x09bf, - 0x0b00, 0x0b15, 0x0b2c, 0x0b2d, 0x0b2e, 0x0b2f, 0x0b36, 0x0bb9, - 0x0c28, 0x0c2a, 0x0c2b, 0x0c2c, 0x0c2d, 0x0c2e, 0x0c2f, 0x0c30, - 0x0c31, 0x0c38, 0x0c60, 0x0c61, 0x0c62, 0x0c63, 0x0c8d, 0x0c8e, - 0x0c8f, 0x0c92, 0x0cbe, 0x0cbf, 0x0ce6, 0x0ce7, 0x0d40, 0x0d41, - 0x0d57, 0x0d58, 0x0d59, 0x0d5a, 0x0d5b, 0x0d5c, 0x0d5d, 0x0d98, - 0x0d99, 0x0d9a, 0x0d9b, 0x0d9c, 0x0d9d, 0x0dad, 0x0dae, 0x0daf, - 0x0dc0, 0x0dc1, 0x0dc2, 0x0dc3, 0x0dca, 0x0dcb, 0x0dec, 0x0ded, - 0x0dee, 0x0def, 0x1018, 0x1022, 0x1023, 0x1030, 0x1031, 0x1032, - 0x1033, 0x1050, 0x1051, 0x105c, 0x1074, 0x1075, 0x1076, 0x1077, - 0x1078, 0x1079, 0x107a, 0x107b, 0x10b2, 0x10b3, 0x10b8, 0x10b9, - 0x10ba, 0x10bb, 0x10d4, 0x10ea, 0x10eb, 0x10ec, 0x10ed, 0x1404, - 0x1405, 0x1406, 0x1407, 0x1410, 0x1411, 0x1412, 0x1413, 0x1414, - 0x1415, 0x1416, 0x1417, 0x1418, 0x1419, 0x1466, 0x1467, 0x1468, - 0x1469, 0x146a, 0x146b, 0x146c, 0x146d, 0x147e, 0x147f, 0x1488, - 0x1489, 0x148a, 0x148b, 0x14b6, 0x14b7, 0x14b8, 0x14b9, 0x14ba, - 0x14bb, 0x14bc, 0x14bd, 0x14f0, 0x14f1, 0x14f8, 0x14f9, 0x14fa, - 0x14fb, 0x14fc, 0x14fd, 0x14fe, 0x14ff, 0x152a, 0x152b, 0x152c, - 0x152d, 0x152e, 0x152f, 0x1530, 0x1531, 0x1548, 0x1549, 0x154e, - 0x154f, 0x1558, 0x1559, 0x155a, 0x155b, 0x1572, 0x159a, 0x159b, - 0x15ac, 0x15ba, 0x15bb, 0x15d0, 0x15d1, 0x15d2, 0x15d3, 0x15d4, - 0x15d5, 0x181d, 0x181e, 0x181f, 0x1840, 0x1841, 0x1842, 0x1843, - 0x1844, 0x1845, 0x1846, 0x1847, 0x1848, 0x1849, 0x1861, 0x1862, - 0x1863, 0x1864, 0x1865, 0x1866, 0x1867, 0x1868, 0x1869, 0x186a, - 0x186b, 0x186c, 0x186d, 0x186e, 0x191b, 0x191c, 0x191d, 0x191e, - 0x191f, 0x1942, 0x1943, 0x1944, 0x1945, 0x1946, 0x1947, 0x1958, - 0x1959, 0x19ed, 0x19ee, 0x19ef, 0x19f0, 0x19f1, 0x19f2, 0x19f3, - 0x19f4, 0x19f5, 0x19f6, 0x19f7, 0x1b0e, 0x1b0f, 0x1b62, 0x1b63, - 0x1b64, 0x1b65, 0x1b66, 0x1b67, 0x1b68, 0x1b69, 0x1b6a, 0x1b6b, - 0x1b6c, 0x1b6d, 0x1b6e, 0x1b6f, 0x1b82, 0x1ba8, 0x1ba9, 0x1baa, - 0x1bab, 0x1bac, 0x1bad, 0x1bae, 0x1baf, 0x1bb0, 0x1bb1, 0x1bb2, - 0x1bb3, 0x1d80, 0x1d81, 0x1d82, 0x1d83, 0x1d84, 0x1d85, 0x1d86, - 0x1d87, 0x1d88, 0x1d89, 0x1d8a, 0x1d8b, 0x1d8c, 0x1d8d, 0x1007, - 0x1008, 0x1009, 0x100a, 0x100b, 0x100c, 0x100d, 0x100e, 0x100f, - 0x1016, 0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, - 0x1087, 0x10c0, 0x123a, 0x123b, 0x123c, 0x123d, 0x123e, 0x123f, - 0x1240, 0x1241, 0x1242, 0x1243, 0x1350, 0x1352, 0x1353, 0x1358, - 0x1359, 0x135a, 0x135b, 0x135c, 0x135d, 0x135e, 0x135f, 0x1360, - 0x1361, 0x1602, 0x1603, 0x160c, 0x160d, 0x160e, 0x160f, 0x1620, - 0x1621, 0x1622, 0x1623, 0x1624, 0x1625, 0x1626, 0x1627, 0x1628, - 0x1629, 0x166e, 0x166f, 0x167c, 0x167d, 0x167e, 0x167f, 0x1770, - 0x1771, 0x1852, 0x1853, 0x1872, 0x1873, 0x1874, 0x1875, 0x1876, - 0x1877, 0x1878, 0x1879, 0x187a, 0x187b, 0x187c, 0x187d, 0x187e, - 0x187f, 0x1918, 0x1919, 0x1926, 0x1927, 0x1970, 0x1971, 0x1972, - 0x1973, 0x1974, 0x1975, 0x1976, 0x1977, 0x1978, 0x1979, 0x197a, - 0x197b, 0x1aa0, 0x1aa1, 0x1aa2, 0x1aa3, 0x1aa4, 0x1aa5, 0x1aa6, - 0x1aa7, 0x1aa8, 0x1aa9, 0x1aaa, 0x1aab, 0x1aac, 0x1aad, 0x1b3c, - 0x1b3d, 0x1b3e, 0x1b3f, 0x1b50, 0x1b51, 0x1b52, 0x1b53, 0x1b54, - 0x1b55, 0x1b56, 0x1b57, 0x1b58, 0x1b59, 0x2032, 0x2033, 0x2034, - 0x2035, 0x2036, 0x2037, 0x2038, 0x2039, 0x203a, 0x203b, 0x203c, - 0x203d, 0x203e, 0x203f, 0x2040, 0x2041, 0x2042, 0x2043, 0x20ba, - 0x20bb, 0x20cc, 0x20cd, 0x20ce, 0x20cf, 0x20e0, 0x20e1, 0x20e2, - 0x20e3, 0x20e4, 0x20e5, 0x20e6, 0x20e7, 0x21aa, 0x21ab, 0x21c0, - 0x21c1, 0x21c2, 0x21c3, 0x21c4, 0x21c5, 0x21c6, 0x21c7, 0x21c8, - 0x21c9, 0x21ca, 0x21cb, 0x21cc, 0x21cd, 0x21ce, 0x21cf, 0x21d0, - 0x21d1, 0x21d2, 0x21d3, 0x2894, 0x2895, 0x2896, 0x2897, 0x2898, - 0x2899, 0x289a, 0x289b, 0x289c, 0x289d, 0x289e, 0x289f, 0x28c0, - 0x28c1, 0x28c2, 0x28c3, 0x28c4, 0x28c5, 0x28c6, 0x28c7, 0x28c8, - 0x28c9, 0x28ca, 0x28cb, 0x2930, 0x2931, 0x2932, 0x2933, 0x2934, - 0x2935, 0x2936, 0x2937, 0x2938, 0x2939, 0x293a, 0x293b, 0x293c, - 0x293d, 0x293e, 0x293f, 0x2960, 0x2961, 0x2962, 0x2963, 0x2964, - 0x2965, 0x2966, 0x2967, 0x2968, 0x2969, 0x296a, 0x296b, 0x2a40, - 0x2a41, 0x2a42, 0x2a43, 0x2a44, 0x2a45, 0x2a46, 0x2a47, 0x2a48, - 0x2a49, 0x2a4a, 0x2a4b, 0x2a4c, 0x2a4d, 0x2a4e, 0x2a4f, 0x2a50, - 0x2a51, 0x2a52, 0x2a53, 0x2ae6, 0x2ae7, 0x2b24, 0x2b25, 0x2b26, - 0x2b27, 0x2b28, 0x2b29, 0x2b2a, 0x2b2b, 0x2b2c, 0x2b2d, 0x2b2e, - 0x2b2f, 0x2b30, 0x2b31, 0x2b32, 0x2b33, 0x2b5a, 0x2b5b, 0x3014, - 0x3015, 0x3016, 0x3017, 0x3020, 0x3021, 0x3022, 0x3023, 0x3024, - 0x3025, 0x3026, 0x3027, 0x3028, 0x3029, 0x302a, 0x302b, 0x302c, - 0x302d, 0x302e, 0x302f, 0x3030, 0x3031, 0x3032, 0x3033, 0x3034, - 0x3035, 0x3036, 0x3037, 0x3038, 0x3039, 0x30c0, 0x30c1, 0x30de, - 0x30df, 0x3218, 0x3219, 0x321a, 0x321b, 0x321c, 0x321d, 0x321e, - 0x321f, 0x3220, 0x3221, 0x3222, 0x3223, 0x3224, 0x3225, 0x3226, - 0x3227, 0x3228, 0x3229, 0x322a, 0x322b, 0x322c, 0x322d, 0x322e, - 0x322f, 0x3230, 0x3231, 0x3232, 0x3233, 0x3234, 0x3235, 0x3378, - 0x3379, 0x337a, 0x337b, 0x337c, 0x337d, 0x337e, 0x337f, 0x33c0, - 0x33c1, 0x33c2, 0x33c3, 0x33c4, 0x33c5, 0x33c6, 0x33c7, 0x33c8, - 0x33c9, 0x33ca, 0x33cb, 0x33cc, 0x33cd, 0x33ce, 0x33cf, 0x33d0, - 0x33d1, 0x33d2, 0x33d3, 0x33d4, 0x33d5, 0x33d6, 0x33d7, 0x33d8, - 0x33d9, 0x3706, 0x3707, 0x3730, 0x3731, 0x3732, 0x3733, 0x3734, - 0x3735, 0x3736, 0x3737, 0x3738, 0x3739, 0x373a, 0x373b, 0x373c, - 0x373d, 0x373e, 0x373f, 0x3740, 0x3741, 0x3742, 0x3743, 0x3744, - 0x3745, 0x3746, 0x3747, 0x3748, 0x3749, 0x374a, 0x374b, 0x374c, - 0x374d, 0x374e, 0x374f, 0x3b34, 0x3b35, 0x3b36, 0x3b37, 0x3be8, - 0x3be9, 0x3bea, 0x3beb, 0x3bec, 0x3bed, 0x3bee, 0x3bef, 0x3bf0, - 0x3bf1, 0x3bf2, 0x3bf3, 0x3bf4, 0x3bf5, 0x3bf6, 0x3bf7, 0x3bf8, - 0x3bf9, 0x3bfa, 0x3bfb, 0x3bfc, 0x3bfd, 0x3bfe, 0x3bff, 0x2000, - 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, - 0x2009, 0x200a, 0x200b, 0x200c, 0x200d, 0x202e, 0x202f, 0x2182, - 0x2183, 0x21b4, 0x21b5, 0x21b6, 0x21b7, 0x21b8, 0x21b9, 0x21ba, - 0x21bb, 0x21bc, 0x21bd, 0x21be, 0x21bf, 0x2460, 0x2461, 0x2462, - 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, 0x2468, 0x2469, 0x246a, - 0x246b, 0x246c, 0x246d, 0x246e, 0x246f, 0x2470, 0x2471, 0x2472, - 0x2473, 0x26a2, 0x26a3, 0x000b, -}; - -static const uint8_t table1_mv_bits[1100] = { - 2, 4, 4, 4, 5, 5, 5, 5, - 6, 6, 7, 7, 7, 7, 7, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 4, -}; - -static const uint8_t table1_mvx[1099] = { - 32, 31, 32, 31, 33, 32, 33, 33, - 31, 34, 30, 32, 32, 34, 35, 32, - 34, 33, 29, 30, 30, 32, 31, 31, - 33, 35, 35, 33, 31, 29, 29, 33, - 34, 30, 31, 28, 36, 30, 34, 32, - 32, 37, 32, 32, 25, 27, 39, 32, - 32, 32, 38, 35, 36, 32, 37, 61, - 26, 32, 34, 35, 3, 35, 27, 28, - 29, 34, 28, 37, 31, 36, 32, 27, - 31, 30, 29, 39, 33, 29, 33, 35, - 25, 25, 29, 33, 31, 31, 31, 33, - 32, 30, 32, 32, 41, 39, 33, 36, - 32, 28, 34, 36, 38, 24, 60, 31, - 23, 28, 32, 33, 59, 32, 40, 30, - 5, 34, 32, 38, 32, 30, 43, 4, - 32, 32, 42, 31, 31, 32, 26, 38, - 26, 22, 21, 37, 61, 63, 37, 31, - 32, 33, 2, 1, 23, 33, 41, 27, - 35, 30, 38, 23, 33, 3, 28, 34, - 34, 27, 41, 29, 39, 35, 36, 29, - 32, 27, 30, 32, 24, 61, 37, 26, - 59, 25, 35, 27, 36, 37, 30, 31, - 34, 40, 3, 28, 34, 39, 32, 31, - 32, 30, 24, 28, 35, 36, 26, 32, - 31, 33, 29, 33, 39, 25, 30, 24, - 35, 59, 29, 34, 25, 30, 21, 35, - 43, 40, 32, 29, 5, 28, 31, 62, - 33, 33, 25, 31, 21, 31, 43, 31, - 34, 33, 20, 40, 39, 31, 31, 57, - 38, 32, 42, 33, 32, 31, 32, 29, - 30, 44, 5, 31, 22, 34, 36, 17, - 38, 58, 38, 35, 32, 60, 35, 24, - 32, 38, 16, 45, 42, 32, 31, 29, - 4, 30, 17, 40, 46, 48, 63, 32, - 42, 19, 41, 22, 28, 36, 45, 33, - 33, 32, 29, 7, 41, 42, 18, 33, - 33, 32, 22, 37, 1, 26, 22, 23, - 49, 28, 26, 27, 32, 33, 27, 23, - 28, 36, 15, 6, 34, 27, 31, 26, - 23, 2, 33, 32, 34, 41, 28, 32, - 41, 0, 36, 38, 34, 31, 47, 32, - 17, 31, 39, 33, 37, 51, 30, 47, - 32, 50, 32, 19, 63, 30, 25, 27, - 33, 62, 24, 31, 27, 30, 37, 31, - 45, 32, 39, 20, 46, 47, 35, 19, - 34, 1, 49, 21, 21, 14, 51, 26, - 23, 31, 36, 35, 58, 29, 29, 21, - 20, 42, 13, 28, 12, 40, 31, 33, - 39, 60, 32, 44, 33, 31, 28, 37, - 29, 32, 30, 49, 43, 28, 39, 25, - 32, 48, 2, 15, 20, 25, 31, 28, - 21, 24, 25, 15, 31, 17, 37, 43, - 18, 32, 33, 24, 33, 36, 13, 33, - 31, 39, 11, 31, 33, 32, 39, 37, - 32, 32, 29, 17, 44, 46, 36, 35, - 26, 37, 58, 32, 34, 38, 8, 38, - 38, 22, 29, 25, 16, 35, 32, 35, - 33, 43, 18, 46, 38, 50, 33, 18, - 53, 60, 13, 32, 36, 33, 51, 36, - 43, 45, 27, 42, 29, 24, 30, 25, - 31, 52, 31, 35, 38, 9, 22, 34, - 4, 17, 28, 55, 42, 25, 17, 20, - 47, 34, 33, 16, 40, 25, 16, 30, - 53, 29, 10, 11, 14, 26, 33, 4, - 35, 44, 26, 16, 31, 26, 34, 38, - 29, 31, 30, 24, 22, 61, 32, 9, - 45, 34, 31, 19, 9, 31, 46, 31, - 35, 54, 29, 57, 30, 50, 3, 31, - 63, 34, 47, 41, 51, 18, 31, 14, - 37, 38, 31, 24, 32, 31, 50, 33, - 31, 54, 27, 9, 33, 23, 19, 32, - 29, 29, 33, 28, 47, 49, 30, 47, - 33, 27, 25, 54, 44, 45, 50, 58, - 51, 48, 33, 59, 33, 34, 57, 13, - 26, 33, 13, 48, 30, 11, 7, 56, - 34, 55, 26, 0, 26, 35, 1, 51, - 33, 53, 31, 45, 12, 29, 29, 51, - 31, 48, 2, 6, 34, 30, 28, 33, - 60, 40, 27, 46, 31, 9, 35, 29, - 31, 39, 55, 46, 19, 37, 62, 34, - 30, 16, 19, 49, 41, 41, 39, 37, - 14, 5, 13, 35, 55, 30, 40, 40, - 42, 8, 20, 25, 45, 35, 33, 36, - 54, 38, 27, 37, 62, 40, 15, 59, - 49, 31, 29, 34, 34, 39, 24, 29, - 25, 29, 21, 29, 10, 61, 33, 49, - 35, 34, 3, 38, 39, 29, 7, 41, - 1, 35, 4, 23, 15, 23, 11, 37, - 28, 35, 30, 30, 24, 1, 43, 56, - 8, 34, 42, 24, 45, 30, 20, 23, - 8, 38, 22, 33, 17, 52, 34, 22, - 53, 43, 44, 1, 27, 31, 41, 43, - 41, 30, 31, 36, 30, 5, 55, 31, - 33, 30, 40, 23, 15, 29, 34, 34, - 59, 34, 30, 11, 13, 38, 5, 0, - 30, 42, 5, 30, 29, 34, 10, 44, - 30, 63, 35, 12, 3, 26, 15, 17, - 25, 34, 43, 39, 34, 56, 29, 23, - 30, 12, 30, 10, 35, 9, 24, 58, - 10, 12, 54, 33, 37, 20, 41, 35, - 29, 18, 61, 30, 40, 24, 39, 53, - 62, 26, 29, 33, 34, 53, 49, 21, - 27, 11, 63, 20, 26, 23, 7, 13, - 6, 47, 29, 30, 9, 51, 22, 34, - 21, 25, 33, 56, 57, 30, 38, 51, - 51, 38, 63, 28, 40, 35, 33, 18, - 33, 33, 24, 58, 58, 34, 49, 29, - 43, 4, 1, 4, 42, 35, 35, 30, - 17, 5, 56, 61, 25, 37, 36, 55, - 28, 35, 29, 50, 48, 52, 2, 42, - 34, 40, 46, 46, 43, 35, 29, 48, - 20, 29, 31, 41, 7, 30, 35, 19, - 14, 21, 8, 39, 39, 40, 46, 55, - 34, 6, 30, 34, 37, 25, 37, 33, - 22, 44, 52, 17, 35, 29, 36, 35, - 40, 37, 28, 30, 50, 14, 28, 55, - 6, 23, 19, 14, 30, 3, 30, 28, - 28, 61, 61, 47, 45, 48, 40, 40, - 34, 34, 25, 30, 29, 35, 4, 26, - 53, 50, 26, 41, 27, 59, 27, 38, - 39, 3, 50, 43, 47, 23, 33, 55, - 35, 21, 23, 35, 61, 33, 46, 52, - 35, 34, 24, 30, 43, 16, 37, 21, - 2, 24, 45, 34, 30, 55, 55, 1, - 29, 29, 26, 28, 25, 31, 36, 22, - 17, 30, 52, 2, 44, 44, 57, 26, - 62, 41, 39, 57, 26, 46, 49, 11, - 16, 19, 5, 59, 38, 39, 58, 38, - 25, 49, 50, 22, 28, 59, 9, 59, - 7, 28, 55, 17, 4, 35, 50, 21, - 29, 44, 47, 18, 24, 19, 25, 42, - 35, 3, 51, 35, 16, 35, 30, 63, - 57, 39, 39, 25, 35, 38, 9, 16, - 36, 45, 31, 60, 14, 34, 42, 24, - 0, 37, 18, 61, 57, 37, 28, 53, - 20, 46, 14, 47, 38, 38, 38, 9, - 34, 39, 43, 17, 39, 59, 5, 27, - 0, 12, 27, -}; - -static const uint8_t table1_mvy[1099] = { - 32, 32, 31, 31, 32, 33, 31, 33, - 33, 32, 32, 30, 34, 31, 32, 29, - 33, 30, 32, 33, 31, 35, 34, 30, - 34, 31, 33, 29, 29, 31, 33, 35, - 30, 30, 35, 32, 32, 34, 34, 28, - 25, 32, 36, 27, 32, 32, 32, 37, - 39, 3, 32, 30, 31, 26, 31, 32, - 32, 38, 29, 29, 32, 34, 31, 31, - 34, 35, 33, 33, 28, 33, 1, 33, - 27, 29, 30, 31, 28, 29, 37, 35, - 31, 33, 35, 27, 36, 37, 25, 25, - 61, 35, 4, 5, 32, 33, 36, 30, - 23, 30, 28, 34, 31, 32, 32, 39, - 32, 34, 21, 39, 32, 59, 32, 28, - 32, 36, 60, 33, 24, 36, 32, 32, - 41, 2, 32, 38, 26, 22, 33, 30, - 31, 32, 32, 30, 31, 32, 29, 3, - 40, 38, 32, 32, 33, 26, 31, 34, - 28, 38, 34, 31, 3, 31, 35, 38, - 27, 35, 33, 28, 29, 27, 29, 27, - 43, 29, 37, 63, 31, 33, 34, 30, - 31, 30, 37, 30, 35, 35, 26, 41, - 37, 31, 33, 28, 26, 30, 42, 24, - 7, 27, 33, 29, 36, 28, 34, 57, - 23, 41, 36, 23, 35, 34, 25, 30, - 25, 33, 25, 25, 29, 24, 33, 39, - 33, 33, 0, 37, 31, 36, 21, 32, - 61, 24, 35, 61, 31, 5, 31, 59, - 39, 21, 32, 30, 34, 22, 40, 32, - 29, 16, 31, 5, 62, 2, 20, 39, - 39, 32, 33, 1, 31, 24, 36, 32, - 36, 32, 28, 26, 6, 31, 38, 34, - 58, 35, 32, 33, 33, 17, 43, 26, - 31, 40, 31, 34, 32, 32, 31, 19, - 30, 32, 29, 33, 38, 38, 32, 59, - 40, 18, 38, 32, 35, 34, 32, 17, - 1, 15, 30, 28, 31, 28, 34, 29, - 32, 27, 35, 27, 49, 22, 37, 34, - 37, 26, 32, 32, 22, 28, 45, 29, - 30, 31, 43, 46, 41, 30, 26, 13, - 34, 32, 27, 38, 42, 42, 33, 47, - 33, 60, 27, 42, 25, 32, 22, 32, - 48, 32, 45, 33, 33, 41, 27, 25, - 19, 31, 35, 19, 36, 42, 27, 17, - 31, 44, 28, 33, 33, 31, 23, 31, - 40, 33, 31, 34, 30, 32, 33, 36, - 35, 47, 37, 41, 31, 23, 41, 29, - 30, 35, 32, 25, 32, 28, 58, 2, - 37, 33, 14, 33, 49, 20, 39, 36, - 21, 9, 23, 33, 35, 24, 39, 37, - 11, 33, 30, 31, 31, 28, 51, 40, - 35, 29, 25, 33, 46, 35, 37, 30, - 30, 8, 63, 28, 15, 40, 33, 45, - 49, 25, 32, 4, 47, 51, 36, 39, - 53, 10, 24, 29, 30, 31, 25, 40, - 38, 38, 33, 56, 23, 27, 32, 37, - 26, 29, 43, 36, 33, 24, 55, 43, - 9, 29, 34, 34, 24, 33, 18, 33, - 33, 30, 31, 50, 24, 60, 30, 39, - 34, 30, 39, 28, 22, 38, 2, 26, - 63, 32, 57, 21, 39, 33, 28, 18, - 30, 34, 22, 33, 29, 41, 30, 34, - 35, 21, 13, 34, 35, 39, 30, 46, - 32, 42, 32, 31, 33, 26, 11, 33, - 22, 31, 25, 31, 53, 27, 43, 25, - 40, 50, 21, 36, 38, 30, 12, 31, - 34, 20, 15, 29, 32, 62, 30, 13, - 17, 32, 19, 31, 20, 31, 30, 7, - 1, 17, 34, 37, 31, 31, 44, 34, - 26, 40, 16, 37, 52, 48, 30, 20, - 18, 33, 38, 29, 7, 25, 30, 54, - 45, 47, 46, 41, 29, 29, 16, 30, - 14, 26, 38, 34, 34, 29, 34, 30, - 29, 30, 57, 30, 4, 46, 33, 29, - 39, 44, 30, 31, 50, 33, 31, 32, - 19, 32, 40, 31, 37, 47, 1, 35, - 16, 31, 0, 35, 33, 1, 17, 34, - 9, 34, 33, 31, 49, 43, 42, 51, - 34, 29, 23, 29, 14, 30, 45, 49, - 11, 24, 31, 28, 35, 41, 30, 44, - 18, 29, 34, 35, 36, 25, 26, 21, - 31, 30, 34, 19, 34, 44, 36, 38, - 25, 31, 28, 23, 37, 3, 55, 41, - 30, 22, 41, 24, 33, 26, 35, 35, - 30, 55, 51, 47, 48, 38, 24, 15, - 21, 50, 25, 46, 30, 29, 10, 34, - 42, 45, 29, 42, 22, 3, 33, 27, - 34, 1, 34, 28, 34, 36, 35, 23, - 23, 13, 58, 3, 26, 63, 25, 31, - 34, 61, 38, 39, 25, 61, 29, 37, - 30, 41, 26, 48, 28, 33, 50, 35, - 30, 37, 29, 29, 40, 6, 39, 28, - 28, 19, 8, 22, 45, 34, 35, 10, - 58, 17, 37, 39, 30, 18, 54, 14, - 29, 16, 59, 30, 35, 23, 35, 30, - 47, 36, 29, 55, 20, 12, 31, 35, - 14, 29, 18, 34, 34, 24, 29, 26, - 22, 2, 27, 23, 8, 30, 55, 38, - 60, 31, 4, 34, 49, 34, 27, 34, - 33, 30, 31, 54, 42, 35, 38, 46, - 44, 26, 27, 9, 39, 25, 21, 29, - 28, 42, 13, 0, 5, 34, 37, 28, - 24, 29, 63, 26, 22, 27, 29, 25, - 33, 25, 61, 0, 35, 25, 36, 15, - 27, 40, 53, 33, 3, 10, 16, 37, - 38, 18, 30, 46, 27, 9, 6, 29, - 62, 8, 42, 28, 29, 3, 25, 16, - 26, 29, 35, 28, 27, 51, 61, 48, - 37, 9, 34, 7, 49, 45, 20, 29, - 21, 5, 5, 29, 28, 34, 29, 24, - 10, 24, 35, 36, 38, 55, 11, 36, - 38, 53, 54, 26, 30, 49, 20, 27, - 30, 39, 33, 41, 49, 22, 38, 38, - 4, 30, 8, 9, 3, 24, 22, 50, - 37, 36, 31, 27, 2, 9, 42, 63, - 25, 19, 44, 1, 28, 28, 48, 30, - 34, 41, 41, 38, 12, 27, 15, 0, - 16, 34, 35, 38, 28, 29, 40, 42, - 51, 52, 45, 54, 59, 59, 42, 44, - 37, 26, 46, 24, 15, 39, 22, 46, - 19, 35, 38, 17, 37, 23, 52, 55, - 50, 37, 26, 11, 37, 12, 24, 30, - 16, 13, 22, 13, 36, 35, 40, 41, - 34, 41, 26, 53, 51, 5, 21, 30, - 2, 63, 41, 20, 1, 56, 21, 24, - 25, 5, 28, 35, 26, 28, 30, 18, - 29, 23, 40, 34, 20, 42, 39, 34, - 28, 61, 38, 27, 62, 9, 36, 17, - 9, 49, 24, 25, 54, 34, 39, 37, - 3, 1, 25, 38, 38, 44, 35, 36, - 12, 60, 36, 38, 40, 25, 43, 39, - 53, 28, 39, 57, 46, 10, 52, 27, - 35, 42, 45, 59, 15, 60, 38, 24, - 23, 39, 12, 29, 24, 0, 20, 16, - 28, 43, 35, 28, 1, 49, 4, 21, - 42, 39, 29, 3, 44, 21, 53, 55, - 11, 5, 3, 39, 53, 28, 25, 19, - 34, 28, 21, -}; - -MVTable ff_mv_tables[2] = { - { table0_mv_code, - table0_mv_bits, - table0_mvx, - table0_mvy, }, - { table1_mv_code, - table1_mv_bits, - table1_mvx, - table1_mvy, } -}; - const uint8_t ff_v2_mb_type[8][2] = { { 1, 1 }, { 0, 2 }, { 3, 3 }, { 9, 5 }, { 5, 4 }, { 0x21, 7 }, { 0x20, 7 }, { 0x11, 6 }, diff --git a/libavcodec/msmpeg4data.h b/libavcodec/msmpeg4data.h index 2217b5ea48..13267d25c1 100644 --- a/libavcodec/msmpeg4data.h +++ b/libavcodec/msmpeg4data.h @@ -35,16 +35,6 @@ #include "libavutil/attributes_internal.h" #include "rl.h" -#include "vlc.h" - -/* motion vector table */ -typedef struct MVTable { - const uint16_t *table_mv_code; - const uint8_t *table_mv_bits; - const uint8_t *table_mvx; - const uint8_t *table_mvy; - const VLCElem *vlc; /* decoding: vlc */ -} MVTable; FF_VISIBILITY_PUSH_HIDDEN #define NB_RL_TABLES 6 @@ -64,7 +54,6 @@ extern const uint16_t ff_msmp4_mv_table0[MSMPEG4_MV_TABLES_NB_ELEMS]; extern const uint8_t ff_msmp4_mv_table0_lens[MSMPEG4_MV_TABLES_NB_ELEMS]; extern const uint16_t ff_msmp4_mv_table1[MSMPEG4_MV_TABLES_NB_ELEMS]; extern const uint8_t ff_msmp4_mv_table1_lens[MSMPEG4_MV_TABLES_NB_ELEMS]; -extern MVTable ff_mv_tables[2]; extern const uint8_t ff_v2_mb_type[8][2]; extern const uint8_t ff_v2_intra_cbpc[4][2]; diff --git a/libavcodec/msmpeg4enc.c b/libavcodec/msmpeg4enc.c index 5ce54a8d16..0ab2e473aa 100644 --- a/libavcodec/msmpeg4enc.c +++ b/libavcodec/msmpeg4enc.c @@ -55,11 +55,10 @@ static uint8_t rl_length[NB_RL_TABLES][MAX_LEVEL+1][MAX_RUN+1][2]; static uint32_t mv_vector_tables[2][4096]; /* build the table which associate a (x,y) motion vector to a vlc */ -static av_cold void init_mv_table(const MVTable *tab, uint32_t mv_vector_table[4096], +static av_cold void init_mv_table(const uint16_t mv_table[], const uint8_t mv_table_lens[], + uint32_t mv_vector_table[4096], unsigned escape_code, int escape_length) { - int i, x, y; - for (int i = 0; i < 4096; i++) { // Initialize to the table to "escaped". This code is equivalent to // the following double loop (with x and y ranging over 0..63): @@ -67,11 +66,16 @@ static av_cold void init_mv_table(const MVTable *tab, uint32_t mv_vector_table[4 mv_vector_table[i] = (escape_code << 20) | (i << 8) | escape_length; } - for (i = 0; i < MSMPEG4_MV_TABLES_NB_ELEMS - 1; i++) { - x = tab->table_mvx[i]; - y = tab->table_mvy[i]; - mv_vector_table[(x << 6) | y] = (tab->table_mv_code[i] << 8) | tab->table_mv_bits[i]; + for (uint32_t i = 0, code = 0; i < MSMPEG4_MV_TABLES_NB_ELEMS; i++) { + int sym = mv_table[i]; + int len = mv_table_lens[i]; + int x = sym >> 8; + int y = sym & 0xFF; + // We ignore the escape value here and restore it after the loop. + mv_vector_table[(x << 6) | y] = (code >> (24 - len)) | len; + code += 1U << (32 - len); } + mv_vector_table[0] = (escape_code << 20) | escape_length; } void ff_msmpeg4_code012(PutBitContext *pb, int n) @@ -128,8 +132,10 @@ static int get_size_of_code(const RLTable *rl, int last, int run, static av_cold void msmpeg4_encode_init_static(void) { - init_mv_table(&ff_mv_tables[0], mv_vector_tables[0], 0x0000, 8 + 12); - init_mv_table(&ff_mv_tables[1], mv_vector_tables[1], 0x000b, 4 + 12); + init_mv_table(ff_msmp4_mv_table0, ff_msmp4_mv_table0_lens, + mv_vector_tables[0], 0x0000, 8 + 12); + init_mv_table(ff_msmp4_mv_table1, ff_msmp4_mv_table1_lens, + mv_vector_tables[1], 0x000b, 4 + 12); for (int i = 0; i < NB_RL_TABLES; i++) { for (int level = 1; level <= MAX_LEVEL; level++) { -- 2.45.2 [-- Attachment #48: 0047-avcodec-mpegvideo-Move-MSMPEG4-fields-to-MSMPEG4-con.patch --] [-- Type: text/x-patch, Size: 47297 bytes --] From 2f66421c3470639904baed80a25094d73c2abc19 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Tue, 18 Mar 2025 13:21:23 +0100 Subject: [PATCH 47/77] avcodec/mpegvideo: Move MSMPEG4 fields to MSMPEG4 contexts Several fields are not used by any generic code and can therefore be moved to more specialized contexts. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpegvideo.h | 7 -- libavcodec/msmpeg4dec.c | 145 +++++++++++++++++++++------------------- libavcodec/msmpeg4dec.h | 12 +++- libavcodec/msmpeg4enc.c | 89 ++++++++++++------------ libavcodec/msmpeg4enc.h | 16 ++++- libavcodec/vaapi_vc1.c | 4 +- libavcodec/vc1.c | 12 ++-- libavcodec/vc1.h | 4 ++ libavcodec/vc1_block.c | 26 +++---- libavcodec/wmv2dec.c | 72 +++++++++++--------- libavcodec/wmv2enc.c | 33 ++++----- 11 files changed, 227 insertions(+), 193 deletions(-) diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 136b9b18a7..39ca4b3d1a 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -372,11 +372,6 @@ typedef struct MpegEncContext { int esc_pos; /* MSMPEG4 specific */ - int mv_table_index; - int rl_table_index; - int rl_chroma_table_index; - int dc_table_index; - int use_skip_mb_code; int slice_height; ///< in macroblocks int first_slice_line; ///< used in MPEG-4 too to handle resync markers int flipflop_rounding; @@ -389,9 +384,7 @@ typedef struct MpegEncContext { MSMP4_WMV2, MSMP4_VC1, ///< for VC1 (image), WMV3 (image) and MSS2. } msmpeg4_version; - int per_mb_rl_table; int esc3_level_length; - int esc3_run_length; int inter_intra_pred; int mspel; diff --git a/libavcodec/msmpeg4dec.c b/libavcodec/msmpeg4dec.c index b60e218f6a..df67d43542 100644 --- a/libavcodec/msmpeg4dec.c +++ b/libavcodec/msmpeg4dec.c @@ -107,11 +107,12 @@ static int msmpeg4v2_decode_motion(MpegEncContext * s, int pred, int f_code) static int msmpeg4v12_decode_mb(MpegEncContext *s, int16_t block[6][64]) { + MSMP4DecContext *const ms = mpv_to_msmpeg4(s); int cbp, code, i; uint32_t * const mb_type_ptr = &s->cur_pic.mb_type[s->mb_x + s->mb_y*s->mb_stride]; if (s->pict_type == AV_PICTURE_TYPE_P) { - if (s->use_skip_mb_code) { + if (ms->use_skip_mb_code) { if (get_bits1(&s->gb)) { /* skip mb */ s->mb_intra = 0; @@ -198,7 +199,7 @@ static int msmpeg4v12_decode_mb(MpegEncContext *s, int16_t block[6][64]) s->bdsp.clear_blocks(s->block[0]); for (i = 0; i < 6; i++) { - if (ff_msmpeg4_decode_block(s, block[i], i, (cbp >> (5 - i)) & 1, NULL) < 0) + if (ff_msmpeg4_decode_block(ms, block[i], i, (cbp >> (5 - i)) & 1, NULL) < 0) { av_log(s->avctx, AV_LOG_ERROR, "\nerror while decoding block: %d x %d (%d)\n", s->mb_x, s->mb_y, i); return -1; @@ -209,6 +210,7 @@ static int msmpeg4v12_decode_mb(MpegEncContext *s, int16_t block[6][64]) static int msmpeg4v34_decode_mb(MpegEncContext *s, int16_t block[6][64]) { + MSMP4DecContext *const ms = mpv_to_msmpeg4(s); int cbp, code, i; uint8_t *coded_val; uint32_t * const mb_type_ptr = &s->cur_pic.mb_type[s->mb_x + s->mb_y*s->mb_stride]; @@ -217,7 +219,7 @@ static int msmpeg4v34_decode_mb(MpegEncContext *s, int16_t block[6][64]) return AVERROR_INVALIDDATA; if (s->pict_type == AV_PICTURE_TYPE_P) { - if (s->use_skip_mb_code) { + if (ms->use_skip_mb_code) { if (get_bits1(&s->gb)) { /* skip mb */ s->mb_intra = 0; @@ -257,12 +259,12 @@ static int msmpeg4v34_decode_mb(MpegEncContext *s, int16_t block[6][64]) if (!s->mb_intra) { int mx, my; - if(s->per_mb_rl_table && cbp){ - s->rl_table_index = decode012(&s->gb); - s->rl_chroma_table_index = s->rl_table_index; + if (ms->per_mb_rl_table && cbp) { + ms->rl_table_index = decode012(&s->gb); + ms->rl_chroma_table_index = ms->rl_table_index; } ff_h263_pred_motion(s, 0, 0, &mx, &my); - ff_msmpeg4_decode_motion(s, &mx, &my); + ff_msmpeg4_decode_motion(ms, &mx, &my); s->mv_dir = MV_DIR_FORWARD; s->mv_type = MV_TYPE_16X16; s->mv[0][0][0] = mx; @@ -279,15 +281,15 @@ static int msmpeg4v34_decode_mb(MpegEncContext *s, int16_t block[6][64]) ff_dlog(s->avctx, "%d%d %d %d/", s->ac_pred, s->h263_aic_dir, s->mb_x, s->mb_y); } - if(s->per_mb_rl_table && cbp){ - s->rl_table_index = decode012(&s->gb); - s->rl_chroma_table_index = s->rl_table_index; + if (ms->per_mb_rl_table && cbp) { + ms->rl_table_index = decode012(&s->gb); + ms->rl_chroma_table_index = ms->rl_table_index; } } s->bdsp.clear_blocks(s->block[0]); for (i = 0; i < 6; i++) { - if (ff_msmpeg4_decode_block(s, block[i], i, (cbp >> (5 - i)) & 1, NULL) < 0) + if (ff_msmpeg4_decode_block(ms, block[i], i, (cbp >> (5 - i)) & 1, NULL) < 0) { av_log(s->avctx, AV_LOG_ERROR, "\nerror while decoding block: %d x %d (%d)\n", s->mb_x, s->mb_y, i); return -1; @@ -443,31 +445,31 @@ int ff_msmpeg4_decode_picture_header(MpegEncContext * s) switch(s->msmpeg4_version){ case MSMP4_V1: case MSMP4_V2: - s->rl_chroma_table_index = 2; - s->rl_table_index = 2; + ms->rl_chroma_table_index = 2; + ms->rl_table_index = 2; - s->dc_table_index = 0; //not used + ms->dc_table_index = 0; //not used break; case MSMP4_V3: - s->rl_chroma_table_index = decode012(&s->gb); - s->rl_table_index = decode012(&s->gb); + ms->rl_chroma_table_index = decode012(&s->gb); + ms->rl_table_index = decode012(&s->gb); - s->dc_table_index = get_bits1(&s->gb); + ms->dc_table_index = get_bits1(&s->gb); break; case MSMP4_WMV1: ff_msmpeg4_decode_ext_header(s, (2+5+5+17+7)/8); if (ms->bit_rate > MBAC_BITRATE) - s->per_mb_rl_table = get_bits1(&s->gb); + ms->per_mb_rl_table = get_bits1(&s->gb); else - s->per_mb_rl_table = 0; + ms->per_mb_rl_table = 0; - if(!s->per_mb_rl_table){ - s->rl_chroma_table_index = decode012(&s->gb); - s->rl_table_index = decode012(&s->gb); + if (!ms->per_mb_rl_table) { + ms->rl_chroma_table_index = decode012(&s->gb); + ms->rl_table_index = decode012(&s->gb); } - s->dc_table_index = get_bits1(&s->gb); + ms->dc_table_index = get_bits1(&s->gb); s->inter_intra_pred= 0; break; } @@ -475,49 +477,49 @@ int ff_msmpeg4_decode_picture_header(MpegEncContext * s) if(s->avctx->debug&FF_DEBUG_PICT_INFO) av_log(s->avctx, AV_LOG_DEBUG, "qscale:%d rlc:%d rl:%d dc:%d mbrl:%d slice:%d \n", s->qscale, - s->rl_chroma_table_index, - s->rl_table_index, - s->dc_table_index, - s->per_mb_rl_table, + ms->rl_chroma_table_index, + ms->rl_table_index, + ms->dc_table_index, + ms->per_mb_rl_table, s->slice_height); } else { switch(s->msmpeg4_version){ case MSMP4_V1: case MSMP4_V2: if (s->msmpeg4_version == MSMP4_V1) - s->use_skip_mb_code = 1; + ms->use_skip_mb_code = 1; else - s->use_skip_mb_code = get_bits1(&s->gb); - s->rl_table_index = 2; - s->rl_chroma_table_index = s->rl_table_index; - s->dc_table_index = 0; //not used - s->mv_table_index = 0; + ms->use_skip_mb_code = get_bits1(&s->gb); + ms->rl_table_index = 2; + ms->rl_chroma_table_index = ms->rl_table_index; + ms->dc_table_index = 0; //not used + ms->mv_table_index = 0; break; case MSMP4_V3: - s->use_skip_mb_code = get_bits1(&s->gb); - s->rl_table_index = decode012(&s->gb); - s->rl_chroma_table_index = s->rl_table_index; + ms->use_skip_mb_code = get_bits1(&s->gb); + ms->rl_table_index = decode012(&s->gb); + ms->rl_chroma_table_index = ms->rl_table_index; - s->dc_table_index = get_bits1(&s->gb); + ms->dc_table_index = get_bits1(&s->gb); - s->mv_table_index = get_bits1(&s->gb); + ms->mv_table_index = get_bits1(&s->gb); break; case MSMP4_WMV1: - s->use_skip_mb_code = get_bits1(&s->gb); + ms->use_skip_mb_code = get_bits1(&s->gb); if (ms->bit_rate > MBAC_BITRATE) - s->per_mb_rl_table = get_bits1(&s->gb); + ms->per_mb_rl_table = get_bits1(&s->gb); else - s->per_mb_rl_table = 0; + ms->per_mb_rl_table = 0; - if(!s->per_mb_rl_table){ - s->rl_table_index = decode012(&s->gb); - s->rl_chroma_table_index = s->rl_table_index; + if (!ms->per_mb_rl_table) { + ms->rl_table_index = decode012(&s->gb); + ms->rl_chroma_table_index = ms->rl_table_index; } - s->dc_table_index = get_bits1(&s->gb); + ms->dc_table_index = get_bits1(&s->gb); - s->mv_table_index = get_bits1(&s->gb); + ms->mv_table_index = get_bits1(&s->gb); s->inter_intra_pred = s->width*s->height < 320*240 && ms->bit_rate <= II_BITRATE; break; @@ -525,12 +527,12 @@ int ff_msmpeg4_decode_picture_header(MpegEncContext * s) if(s->avctx->debug&FF_DEBUG_PICT_INFO) av_log(s->avctx, AV_LOG_DEBUG, "skip:%d rl:%d rlc:%d dc:%d mv:%d mbrl:%d qp:%d \n", - s->use_skip_mb_code, - s->rl_table_index, - s->rl_chroma_table_index, - s->dc_table_index, - s->mv_table_index, - s->per_mb_rl_table, + ms->use_skip_mb_code, + ms->rl_table_index, + ms->rl_chroma_table_index, + ms->dc_table_index, + ms->mv_table_index, + ms->per_mb_rl_table, s->qscale); if(s->flipflop_rounding){ @@ -542,8 +544,8 @@ int ff_msmpeg4_decode_picture_header(MpegEncContext * s) ff_dlog(s->avctx, "%d %d %d %d %d\n", s->pict_type, ms->bit_rate, s->inter_intra_pred, s->width, s->height); - s->esc3_level_length= 0; - s->esc3_run_length= 0; + ms->esc3_level_length = 0; + ms->esc3_run_length = 0; return 0; } @@ -577,8 +579,9 @@ int ff_msmpeg4_decode_ext_header(MpegEncContext * s, int buf_size) return 0; } -static int msmpeg4_decode_dc(MpegEncContext * s, int n, int *dir_ptr) +static int msmpeg4_decode_dc(MSMP4DecContext *const ms, int n, int *dir_ptr) { + MpegEncContext *const s = &ms->m; int level, pred; if (s->msmpeg4_version <= MSMP4_V2) { @@ -594,7 +597,7 @@ static int msmpeg4_decode_dc(MpegEncContext * s, int n, int *dir_ptr) } level-=256; } else { - level = get_vlc2(&s->gb, ff_msmp4_dc_vlc[s->dc_table_index][n >= 4], + level = get_vlc2(&s->gb, ff_msmp4_dc_vlc[ms->dc_table_index][n >= 4], MSMP4_DC_VLC_BITS, 3); if (level == DC_MAX) { @@ -630,9 +633,10 @@ static int msmpeg4_decode_dc(MpegEncContext * s, int n, int *dir_ptr) return level; } -int ff_msmpeg4_decode_block(MpegEncContext * s, int16_t * block, +int ff_msmpeg4_decode_block(MSMP4DecContext *const ms, int16_t * block, int n, int coded, const uint8_t *scan_table) { + MpegEncContext *const s = &ms->m; int level, i, last, run, run_diff; int dc_pred_dir = -1; //unused but its passed around, so it needs to be initialized const RLTable *rl; @@ -644,20 +648,20 @@ int ff_msmpeg4_decode_block(MpegEncContext * s, int16_t * block, qadd=0; /* DC coef */ - level = msmpeg4_decode_dc(s, n, &dc_pred_dir); + level = msmpeg4_decode_dc(ms, n, &dc_pred_dir); if (level < 0){ av_log(s->avctx, AV_LOG_ERROR, "dc overflow- block: %d qscale: %d//\n", n, s->qscale); if(s->inter_intra_pred) level=0; } if (n < 4) { - rl = &ff_rl_table[s->rl_table_index]; + rl = &ff_rl_table[ms->rl_table_index]; if(level > 256*s->y_dc_scale){ av_log(s->avctx, AV_LOG_ERROR, "dc overflow+ L qscale: %d//\n", s->qscale); if(!s->inter_intra_pred) return -1; } } else { - rl = &ff_rl_table[3 + s->rl_chroma_table_index]; + rl = &ff_rl_table[3 + ms->rl_chroma_table_index]; if(level > 256*s->c_dc_scale){ av_log(s->avctx, AV_LOG_ERROR, "dc overflow+ C qscale: %d//\n", s->qscale); if(!s->inter_intra_pred) return -1; @@ -683,7 +687,7 @@ int ff_msmpeg4_decode_block(MpegEncContext * s, int16_t * block, qmul = s->qscale << 1; qadd = (s->qscale - 1) | 1; i = -1; - rl = &ff_rl_table[3 + s->rl_table_index]; + rl = &ff_rl_table[3 + ms->rl_table_index]; if (s->msmpeg4_version == MSMP4_V2) run_diff = 0; @@ -721,7 +725,7 @@ int ff_msmpeg4_decode_block(MpegEncContext * s, int16_t * block, }else{ int sign; last= SHOW_UBITS(re, &s->gb, 1); SKIP_BITS(re, &s->gb, 1); - if(!s->esc3_level_length){ + if (!ms->esc3_level_length) { int ll; ff_dlog(s->avctx, "ESC-3 %X at %d %d\n", show_bits(&s->gb, 24), s->mb_x, s->mb_y); @@ -739,18 +743,18 @@ int ff_msmpeg4_decode_block(MpegEncContext * s, int16_t * block, if(ll<8) SKIP_BITS(re, &s->gb, 1); } - s->esc3_level_length= ll; - s->esc3_run_length= SHOW_UBITS(re, &s->gb, 2) + 3; SKIP_BITS(re, &s->gb, 2); + ms->esc3_level_length = ll; + ms->esc3_run_length = SHOW_UBITS(re, &s->gb, 2) + 3; SKIP_BITS(re, &s->gb, 2); UPDATE_CACHE(re, &s->gb); } - run= SHOW_UBITS(re, &s->gb, s->esc3_run_length); - SKIP_BITS(re, &s->gb, s->esc3_run_length); + run = SHOW_UBITS(re, &s->gb, ms->esc3_run_length); + SKIP_BITS(re, &s->gb, ms->esc3_run_length); sign= SHOW_UBITS(re, &s->gb, 1); SKIP_BITS(re, &s->gb, 1); - level= SHOW_UBITS(re, &s->gb, s->esc3_level_length); - SKIP_BITS(re, &s->gb, s->esc3_level_length); + level = SHOW_UBITS(re, &s->gb, ms->esc3_level_length); + SKIP_BITS(re, &s->gb, ms->esc3_level_length); if(sign) level= -level; } @@ -814,9 +818,10 @@ int ff_msmpeg4_decode_block(MpegEncContext * s, int16_t * block, return 0; } -void ff_msmpeg4_decode_motion(MpegEncContext *s, int *mx_ptr, int *my_ptr) +void ff_msmpeg4_decode_motion(MSMP4DecContext *const ms, int *mx_ptr, int *my_ptr) { - const VLCElem *const mv_vlc = mv_tables[s->mv_table_index]; + const VLCElem *const mv_vlc = mv_tables[ms->mv_table_index]; + MpegEncContext *const s = &ms->m; int sym, mx, my; sym = get_vlc2(&s->gb, mv_vlc, MV_VLC_BITS, 2); diff --git a/libavcodec/msmpeg4dec.h b/libavcodec/msmpeg4dec.h index 47c4495f1d..b04331fd47 100644 --- a/libavcodec/msmpeg4dec.h +++ b/libavcodec/msmpeg4dec.h @@ -31,6 +31,14 @@ typedef struct MSMP4DecContext { MpegEncContext m; int bit_rate; + int mv_table_index; + int rl_table_index; + int rl_chroma_table_index; + int dc_table_index; + int use_skip_mb_code; + int per_mb_rl_table; + int esc3_level_length; + int esc3_run_length; } MSMP4DecContext; static inline MSMP4DecContext *mpv_to_msmpeg4(MpegEncContext *s) @@ -45,8 +53,8 @@ extern VLCElem ff_inter_intra_vlc[8]; int ff_msmpeg4_decode_init(AVCodecContext *avctx); int ff_msmpeg4_decode_picture_header(MpegEncContext *s); int ff_msmpeg4_decode_ext_header(MpegEncContext *s, int buf_size); -void ff_msmpeg4_decode_motion(MpegEncContext * s, int *mx_ptr, int *my_ptr); -int ff_msmpeg4_decode_block(MpegEncContext * s, int16_t * block, +void ff_msmpeg4_decode_motion(MSMP4DecContext *ms, int *mx_ptr, int *my_ptr); +int ff_msmpeg4_decode_block(MSMP4DecContext *ms, int16_t * block, int n, int coded, const uint8_t *scan_table); #endif diff --git a/libavcodec/msmpeg4enc.c b/libavcodec/msmpeg4enc.c index 0ab2e473aa..78197756ae 100644 --- a/libavcodec/msmpeg4enc.c +++ b/libavcodec/msmpeg4enc.c @@ -200,15 +200,15 @@ static void find_best_tables(MSMPEG4EncContext *ms) memset(ms->ac_stats, 0, sizeof(ms->ac_stats)); - s->rl_table_index = best; - s->rl_chroma_table_index= chroma_best; + ms->rl_table_index = best; + ms->rl_chroma_table_index = chroma_best; if(s->pict_type != s->last_non_b_pict_type){ - s->rl_table_index= 2; + ms->rl_table_index = 2; if(s->pict_type==AV_PICTURE_TYPE_I) - s->rl_chroma_table_index= 1; + ms->rl_chroma_table_index = 1; else - s->rl_chroma_table_index= 2; + ms->rl_chroma_table_index = 2; } } @@ -226,14 +226,14 @@ static int msmpeg4_encode_picture_header(MPVMainEncContext *const m) put_bits(&s->pb, 5, s->qscale); if (s->msmpeg4_version <= MSMP4_V2) { - s->rl_table_index = 2; - s->rl_chroma_table_index = 2; + ms->rl_table_index = 2; + ms->rl_chroma_table_index = 2; } - s->dc_table_index = 1; - s->mv_table_index = 1; /* only if P-frame */ - s->use_skip_mb_code = 1; /* only if P-frame */ - s->per_mb_rl_table = 0; + ms->dc_table_index = 1; + ms->mv_table_index = 1; /* only if P-frame */ + ms->use_skip_mb_code = 1; /* only if P-frame */ + ms->per_mb_rl_table = 0; if (s->msmpeg4_version == MSMP4_WMV1) s->inter_intra_pred = s->width * s->height < 320*240 && m->bit_rate <= II_BITRATE && @@ -248,35 +248,35 @@ static int msmpeg4_encode_picture_header(MPVMainEncContext *const m) if (s->msmpeg4_version == MSMP4_WMV1) { ff_msmpeg4_encode_ext_header(s); if (m->bit_rate > MBAC_BITRATE) - put_bits(&s->pb, 1, s->per_mb_rl_table); + put_bits(&s->pb, 1, ms->per_mb_rl_table); } if (s->msmpeg4_version > MSMP4_V2) { - if(!s->per_mb_rl_table){ - ff_msmpeg4_code012(&s->pb, s->rl_chroma_table_index); - ff_msmpeg4_code012(&s->pb, s->rl_table_index); + if (!ms->per_mb_rl_table){ + ff_msmpeg4_code012(&s->pb, ms->rl_chroma_table_index); + ff_msmpeg4_code012(&s->pb, ms->rl_table_index); } - put_bits(&s->pb, 1, s->dc_table_index); + put_bits(&s->pb, 1, ms->dc_table_index); } } else { - put_bits(&s->pb, 1, s->use_skip_mb_code); + put_bits(&s->pb, 1, ms->use_skip_mb_code); if (s->msmpeg4_version == MSMP4_WMV1 && m->bit_rate > MBAC_BITRATE) - put_bits(&s->pb, 1, s->per_mb_rl_table); + put_bits(&s->pb, 1, ms->per_mb_rl_table); if (s->msmpeg4_version > MSMP4_V2) { - if(!s->per_mb_rl_table) - ff_msmpeg4_code012(&s->pb, s->rl_table_index); + if (!ms->per_mb_rl_table) + ff_msmpeg4_code012(&s->pb, ms->rl_table_index); - put_bits(&s->pb, 1, s->dc_table_index); + put_bits(&s->pb, 1, ms->dc_table_index); - put_bits(&s->pb, 1, s->mv_table_index); + put_bits(&s->pb, 1, ms->mv_table_index); } } - s->esc3_level_length= 0; - s->esc3_run_length= 0; + s->esc3_level_length = 0; + ms->esc3_run_length = 0; return 0; } @@ -308,10 +308,11 @@ FF_ENABLE_DEPRECATION_WARNINGS av_assert0(!s->flipflop_rounding); } -void ff_msmpeg4_encode_motion(MpegEncContext * s, +void ff_msmpeg4_encode_motion(MSMPEG4EncContext *const ms, int mx, int my) { - const uint32_t *const mv_vector_table = mv_vector_tables[s->mv_table_index]; + MpegEncContext *const s = &ms->m.s; + const uint32_t *const mv_vector_table = mv_vector_tables[ms->mv_table_index]; uint32_t code; /* modulo encoding */ @@ -382,6 +383,7 @@ static void msmpeg4_encode_mb(MpegEncContext *const s, int16_t block[][64], int motion_x, int motion_y) { + MSMPEG4EncContext *const ms = mpv_to_msmpeg4(s); int cbp, coded_cbp, i; int pred_x, pred_y; @@ -394,7 +396,7 @@ static void msmpeg4_encode_mb(MpegEncContext *const s, if (s->block_last_index[i] >= 0) cbp |= 1 << (5 - i); } - if (s->use_skip_mb_code && (cbp | motion_x | motion_y) == 0) { + if (ms->use_skip_mb_code && (cbp | motion_x | motion_y) == 0) { /* skip macroblock */ put_bits(&s->pb, 1, 1); s->last_bits++; @@ -402,7 +404,7 @@ static void msmpeg4_encode_mb(MpegEncContext *const s, return; } - if (s->use_skip_mb_code) + if (ms->use_skip_mb_code) put_bits(&s->pb, 1, 0); /* mb coded */ if (s->msmpeg4_version <= MSMP4_V2) { @@ -430,8 +432,8 @@ static void msmpeg4_encode_mb(MpegEncContext *const s, /* motion vector */ ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y); - ff_msmpeg4_encode_motion(s, motion_x - pred_x, - motion_y - pred_y); + ff_msmpeg4_encode_motion(ms, motion_x - pred_x, + motion_y - pred_y); } s->mv_bits += get_bits_diff(s); @@ -452,7 +454,7 @@ static void msmpeg4_encode_mb(MpegEncContext *const s, put_bits(&s->pb, ff_v2_intra_cbpc[cbp&3][1], ff_v2_intra_cbpc[cbp&3][0]); } else { - if (s->use_skip_mb_code) + if (ms->use_skip_mb_code) put_bits(&s->pb, 1, 0); /* mb coded */ put_bits(&s->pb, ff_v2_mb_type[(cbp&3) + 4][1], @@ -479,7 +481,7 @@ static void msmpeg4_encode_mb(MpegEncContext *const s, put_bits(&s->pb, ff_msmp4_mb_i_table[coded_cbp][1], ff_msmp4_mb_i_table[coded_cbp][0]); } else { - if (s->use_skip_mb_code) + if (ms->use_skip_mb_code) put_bits(&s->pb, 1, 0); /* mb coded */ put_bits(&s->pb, ff_table_mb_non_intra[cbp][1], @@ -501,8 +503,9 @@ static void msmpeg4_encode_mb(MpegEncContext *const s, } } -static void msmpeg4_encode_dc(MpegEncContext * s, int level, int n, int *dir_ptr) +static void msmpeg4_encode_dc(MSMPEG4EncContext *const ms, int level, int n, int *dir_ptr) { + MpegEncContext *const s = &ms->m.s; int sign, code; int pred; @@ -539,8 +542,8 @@ static void msmpeg4_encode_dc(MpegEncContext * s, int level, int n, int *dir_ptr if (code > DC_MAX) code = DC_MAX; - put_bits(&s->pb, ff_msmp4_dc_tables[s->dc_table_index][n >= 4][code][1], - ff_msmp4_dc_tables[s->dc_table_index][n >= 4][code][0]); + put_bits(&s->pb, ff_msmp4_dc_tables[ms->dc_table_index][n >= 4][code][1], + ff_msmp4_dc_tables[ms->dc_table_index][n >= 4][code][0]); if (code == DC_MAX) put_bits(&s->pb, 8, level); @@ -563,18 +566,18 @@ void ff_msmpeg4_encode_block(MpegEncContext * s, int16_t * block, int n) const uint8_t *scantable; if (s->mb_intra) { - msmpeg4_encode_dc(s, block[0], n, &dc_pred_dir); + msmpeg4_encode_dc(ms, block[0], n, &dc_pred_dir); i = 1; if (n < 4) { - rl = &ff_rl_table[s->rl_table_index]; + rl = &ff_rl_table[ms->rl_table_index]; } else { - rl = &ff_rl_table[3 + s->rl_chroma_table_index]; + rl = &ff_rl_table[3 + ms->rl_chroma_table_index]; } run_diff = s->msmpeg4_version >= MSMP4_WMV1; scantable= s->intra_scantable.permutated; } else { i = 0; - rl = &ff_rl_table[3 + s->rl_table_index]; + rl = &ff_rl_table[3 + ms->rl_table_index]; run_diff = s->msmpeg4_version > MSMP4_V2; scantable= s->inter_scantable.permutated; } @@ -635,16 +638,16 @@ void ff_msmpeg4_encode_block(MpegEncContext * s, int16_t * block, int n) put_bits(&s->pb, 1, 0); put_bits(&s->pb, 1, last); if (s->msmpeg4_version >= MSMP4_WMV1) { - if(s->esc3_level_length==0){ - s->esc3_level_length=8; - s->esc3_run_length= 6; + if (s->esc3_level_length == 0) { + s->esc3_level_length = 8; + ms->esc3_run_length = 6; //ESCLVLSZ + ESCRUNSZ if(s->qscale<8) put_bits(&s->pb, 6, 3); else put_bits(&s->pb, 8, 3); } - put_bits(&s->pb, s->esc3_run_length, run); + put_bits(&s->pb, ms->esc3_run_length, run); put_bits(&s->pb, 1, sign); put_bits(&s->pb, s->esc3_level_length, level); }else{ diff --git a/libavcodec/msmpeg4enc.h b/libavcodec/msmpeg4enc.h index dde1fb6b93..bce1265bb5 100644 --- a/libavcodec/msmpeg4enc.h +++ b/libavcodec/msmpeg4enc.h @@ -29,15 +29,29 @@ typedef struct MSMPEG4EncContext { MPVMainEncContext m; + int mv_table_index; + int rl_table_index; + int rl_chroma_table_index; + int dc_table_index; + int use_skip_mb_code; + int per_mb_rl_table; + int esc3_run_length; + /** [mb_intra][isChroma][level][run][last] */ unsigned ac_stats[2][2][MAX_LEVEL + 1][MAX_RUN + 1][2]; } MSMPEG4EncContext; +static inline MSMPEG4EncContext *mpv_to_msmpeg4(MpegEncContext *s) +{ + // Only legal because no MSMPEG-4 decoder uses slice-threading. + return (MSMPEG4EncContext*)s; +} + void ff_msmpeg4_encode_init(MPVMainEncContext *m); void ff_msmpeg4_encode_ext_header(MpegEncContext *s); void ff_msmpeg4_encode_block(MpegEncContext * s, int16_t * block, int n); void ff_msmpeg4_handle_slices(MpegEncContext *s); -void ff_msmpeg4_encode_motion(MpegEncContext * s, int mx, int my); +void ff_msmpeg4_encode_motion(MSMPEG4EncContext *ms, int mx, int my); void ff_msmpeg4_code012(PutBitContext *pb, int n); diff --git a/libavcodec/vaapi_vc1.c b/libavcodec/vaapi_vc1.c index 6c25fdb5fa..f2285c396b 100644 --- a/libavcodec/vaapi_vc1.c +++ b/libavcodec/vaapi_vc1.c @@ -343,7 +343,7 @@ static int vaapi_vc1_start_frame(AVCodecContext *avctx, .mv_fields.bits = { .mv_mode = vc1_get_MVMODE(v), .mv_mode2 = vc1_get_MVMODE2(v), - .mv_table = (v->fcm == PROGRESSIVE ? s->mv_table_index : v->imvtab), + .mv_table = (v->fcm == PROGRESSIVE ? v->mv_table_index : v->imvtab), .two_mv_block_pattern_table = v->twomvbptab, .four_mv_switch = v->fourmvswitch, .four_mv_block_pattern_table = v->fourmvbptab, @@ -371,7 +371,7 @@ static int vaapi_vc1_start_frame(AVCodecContext *avctx, .frame_level_transform_type = vc1_get_TTFRM(v), .transform_ac_codingset_idx1 = v->c_ac_table_index, .transform_ac_codingset_idx2 = v->y_ac_table_index, - .intra_transform_dc_table = v->s.dc_table_index, + .intra_transform_dc_table = v->dc_table_index, }, }; diff --git a/libavcodec/vc1.c b/libavcodec/vc1.c index dec3e16ea2..1d642cc7f6 100644 --- a/libavcodec/vc1.c +++ b/libavcodec/vc1.c @@ -765,7 +765,7 @@ int ff_vc1_parse_frame_header(VC1Context *v, GetBitContext* gb) return AVERROR_INVALIDDATA; /* Hopefully this is correct for P-frames */ - v->s.mv_table_index = get_bits(gb, 2); //but using ff_vc1_ tables + v->mv_table_index = get_bits(gb, 2); //but using ff_vc1_ tables v->cbptab = get_bits(gb, 2); v->cbpcy_vlc = ff_vc1_cbpcy_p_vlc[v->cbptab]; @@ -804,7 +804,7 @@ int ff_vc1_parse_frame_header(VC1Context *v, GetBitContext* gb) av_log(v->s.avctx, AV_LOG_DEBUG, "MB Skip plane encoding: " "Imode: %i, Invert: %i\n", status>>1, status&1); - v->s.mv_table_index = get_bits(gb, 2); + v->mv_table_index = get_bits(gb, 2); v->cbptab = get_bits(gb, 2); v->cbpcy_vlc = ff_vc1_cbpcy_p_vlc[v->cbptab]; @@ -833,7 +833,7 @@ int ff_vc1_parse_frame_header(VC1Context *v, GetBitContext* gb) v->y_ac_table_index = decode012(gb); } /* DC Syntax */ - v->s.dc_table_index = get_bits1(gb); + v->dc_table_index = get_bits1(gb); } if (v->s.pict_type == AV_PICTURE_TYPE_BI) { @@ -1158,7 +1158,7 @@ int ff_vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb) "Imode: %i, Invert: %i\n", status>>1, status&1); /* Hopefully this is correct for P-frames */ - v->s.mv_table_index = get_bits(gb, 2); //but using ff_vc1_ tables + v->mv_table_index = get_bits(gb, 2); //but using ff_vc1_ tables v->cbptab = get_bits(gb, 2); v->cbpcy_vlc = ff_vc1_cbpcy_p_vlc[v->cbptab]; } else if (v->fcm == ILACE_FRAME) { // frame interlaced @@ -1295,7 +1295,7 @@ int ff_vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb) return -1; av_log(v->s.avctx, AV_LOG_DEBUG, "MB Skip plane encoding: " "Imode: %i, Invert: %i\n", status>>1, status&1); - v->s.mv_table_index = get_bits(gb, 2); + v->mv_table_index = get_bits(gb, 2); v->cbptab = get_bits(gb, 2); v->cbpcy_vlc = ff_vc1_cbpcy_p_vlc[v->cbptab]; } @@ -1330,7 +1330,7 @@ int ff_vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb) } /* DC Syntax */ - v->s.dc_table_index = get_bits1(gb); + v->dc_table_index = get_bits1(gb); if ((v->s.pict_type == AV_PICTURE_TYPE_I || v->s.pict_type == AV_PICTURE_TYPE_BI) && v->dquant) { av_log(v->s.avctx, AV_LOG_DEBUG, "VOP DQuant info\n"); diff --git a/libavcodec/vc1.h b/libavcodec/vc1.h index b7339bcd5f..e8762350a2 100644 --- a/libavcodec/vc1.h +++ b/libavcodec/vc1.h @@ -246,6 +246,7 @@ typedef struct VC1Context{ uint8_t dqsbedge; uint8_t dqbilevel; //@} + int dc_table_index; /** AC coding set indexes * @see 8.1.1.10, p(1)10 */ @@ -253,6 +254,8 @@ typedef struct VC1Context{ int c_ac_table_index; ///< Chroma index from ACFRM element int y_ac_table_index; ///< Luma index from AC2FRM element //@} + int esc3_level_length; + int esc3_run_length; int ttfrm; ///< Transform type info present at frame level uint8_t ttmbf; ///< Transform type flag int *ttblk_base, *ttblk; ///< Transform type at the block level @@ -282,6 +285,7 @@ typedef struct VC1Context{ uint8_t pquantizer; ///< Uniform (over sequence) quantizer in use const VLCElem *cbpcy_vlc; ///< CBPCY VLC table int tt_index; ///< Index for Transform Type tables (to decode TTMB) + int mv_table_index; uint8_t* mv_type_mb_plane; ///< bitplane for mv_type == (4MV) uint8_t* direct_mb_plane; ///< bitplane for "direct" MBs uint8_t* forward_mb_plane; ///< bitplane for "forward" MBs diff --git a/libavcodec/vc1_block.c b/libavcodec/vc1_block.c index 26adfbca1d..1661fdd742 100644 --- a/libavcodec/vc1_block.c +++ b/libavcodec/vc1_block.c @@ -227,7 +227,7 @@ static void vc1_put_blocks_clamped(VC1Context *v, int put_signed) * @param _dmv_y Vertical differential for decoded MV */ #define GET_MVDATA(_dmv_x, _dmv_y) \ - index = 1 + get_vlc2(gb, ff_vc1_mv_diff_vlc[s->mv_table_index], \ + index = 1 + get_vlc2(gb, ff_vc1_mv_diff_vlc[v->mv_table_index], \ VC1_MV_DIFF_VLC_BITS, 2); \ if (index > 36) { \ mb_has_coeffs = 1; \ @@ -549,19 +549,19 @@ static int vc1_decode_ac_coeff(VC1Context *v, int *last, int *skip, sign = get_bits1(gb); } else { lst = get_bits1(gb); - if (v->s.esc3_level_length == 0) { + if (v->esc3_level_length == 0) { if (v->pq < 8 || v->dquantfrm) { // table 59 - v->s.esc3_level_length = get_bits(gb, 3); - if (!v->s.esc3_level_length) - v->s.esc3_level_length = get_bits(gb, 2) + 8; + v->esc3_level_length = get_bits(gb, 3); + if (!v->esc3_level_length) + v->esc3_level_length = get_bits(gb, 2) + 8; } else { // table 60 - v->s.esc3_level_length = get_unary(gb, 1, 6) + 2; + v->esc3_level_length = get_unary(gb, 1, 6) + 2; } - v->s.esc3_run_length = 3 + get_bits(gb, 2); + v->esc3_run_length = 3 + get_bits(gb, 2); } - run = get_bits(gb, v->s.esc3_run_length); + run = get_bits(gb, v->esc3_run_length); sign = get_bits1(gb); - level = get_bits(gb, v->s.esc3_level_length); + level = get_bits(gb, v->esc3_level_length); } } @@ -590,7 +590,7 @@ static int vc1_decode_i_block(VC1Context *v, int16_t block[64], int n, int dcdiff, scale; /* Get DC differential */ - dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_vlc[s->dc_table_index][n >= 4], + dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_vlc[v->dc_table_index][n >= 4], MSMP4_DC_VLC_BITS, 3); if (dcdiff) { const int m = (v->pq == 1 || v->pq == 2) ? 3 - v->pq : 0; @@ -723,7 +723,7 @@ static int vc1_decode_i_block_adv(VC1Context *v, int16_t block[64], int n, int quant = FFABS(mquant); /* Get DC differential */ - dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_vlc[s->dc_table_index][n >= 4], + dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_vlc[v->dc_table_index][n >= 4], MSMP4_DC_VLC_BITS, 3); if (dcdiff) { const int m = (quant == 1 || quant == 2) ? 3 - quant : 0; @@ -911,7 +911,7 @@ static int vc1_decode_intra_block(VC1Context *v, int16_t block[64], int n, s->y_dc_scale = ff_wmv3_dc_scale_table[quant]; /* Get DC differential */ - dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_vlc[s->dc_table_index][n >= 4], + dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_vlc[v->dc_table_index][n >= 4], MSMP4_DC_VLC_BITS, 3); if (dcdiff) { const int m = (quant == 1 || quant == 2) ? 3 - quant : 0; @@ -2946,7 +2946,7 @@ static void vc1_decode_skip_blocks(VC1Context *v) void ff_vc1_decode_blocks(VC1Context *v) { - v->s.esc3_level_length = 0; + v->esc3_level_length = 0; if (v->x8_type) { ff_intrax8_decode_picture(&v->x8, v->s.cur_pic.ptr, &v->s.gb, &v->s.mb_x, &v->s.mb_y, diff --git a/libavcodec/wmv2dec.c b/libavcodec/wmv2dec.c index 02c3dc2535..964d6a4c06 100644 --- a/libavcodec/wmv2dec.c +++ b/libavcodec/wmv2dec.c @@ -248,16 +248,16 @@ int ff_wmv2_decode_secondary_picture_header(MpegEncContext *s) if (!w->j_type) { if (w->per_mb_rl_bit) - s->per_mb_rl_table = get_bits1(&s->gb); + w->ms.per_mb_rl_table = get_bits1(&s->gb); else - s->per_mb_rl_table = 0; + w->ms.per_mb_rl_table = 0; - if (!s->per_mb_rl_table) { - s->rl_chroma_table_index = decode012(&s->gb); - s->rl_table_index = decode012(&s->gb); + if (!w->ms.per_mb_rl_table) { + w->ms.rl_chroma_table_index = decode012(&s->gb); + w->ms.rl_table_index = decode012(&s->gb); } - s->dc_table_index = get_bits1(&s->gb); + w->ms.dc_table_index = get_bits1(&s->gb); // at minimum one bit per macroblock is required at least in a valid frame, // we discard frames much smaller than this. Frames smaller than 1/8 of the @@ -272,8 +272,8 @@ int ff_wmv2_decode_secondary_picture_header(MpegEncContext *s) if (s->avctx->debug & FF_DEBUG_PICT_INFO) { av_log(s->avctx, AV_LOG_DEBUG, "qscale:%d rlc:%d rl:%d dc:%d mbrl:%d j_type:%d \n", - s->qscale, s->rl_chroma_table_index, s->rl_table_index, - s->dc_table_index, s->per_mb_rl_table, w->j_type); + s->qscale, w->ms.rl_chroma_table_index, w->ms.rl_table_index, + w->ms.dc_table_index, w->ms.per_mb_rl_table, w->j_type); } } else { int cbp_index; @@ -298,20 +298,20 @@ int ff_wmv2_decode_secondary_picture_header(MpegEncContext *s) } if (w->per_mb_rl_bit) - s->per_mb_rl_table = get_bits1(&s->gb); + w->ms.per_mb_rl_table = get_bits1(&s->gb); else - s->per_mb_rl_table = 0; + w->ms.per_mb_rl_table = 0; - if (!s->per_mb_rl_table) { - s->rl_table_index = decode012(&s->gb); - s->rl_chroma_table_index = s->rl_table_index; + if (!w->ms.per_mb_rl_table) { + w->ms.rl_table_index = decode012(&s->gb); + w->ms.rl_chroma_table_index = w->ms.rl_table_index; } if (get_bits_left(&s->gb) < 2) return AVERROR_INVALIDDATA; - s->dc_table_index = get_bits1(&s->gb); - s->mv_table_index = get_bits1(&s->gb); + w->ms.dc_table_index = get_bits1(&s->gb); + w->ms.mv_table_index = get_bits1(&s->gb); s->inter_intra_pred = 0; // (s->width * s->height < 320 * 240 && w->ms.bit_rate <= II_BITRATE); s->no_rounding ^= 1; @@ -320,15 +320,15 @@ int ff_wmv2_decode_secondary_picture_header(MpegEncContext *s) av_log(s->avctx, AV_LOG_DEBUG, "rl:%d rlc:%d dc:%d mv:%d mbrl:%d qp:%d mspel:%d " "per_mb_abt:%d abt_type:%d cbp:%d ii:%d\n", - s->rl_table_index, s->rl_chroma_table_index, - s->dc_table_index, s->mv_table_index, - s->per_mb_rl_table, s->qscale, s->mspel, + w->ms.rl_table_index, w->ms.rl_chroma_table_index, + w->ms.dc_table_index, w->ms.mv_table_index, + w->ms.per_mb_rl_table, s->qscale, s->mspel, w->per_mb_abt, w->abt_type, w->cbp_table_index, s->inter_intra_pred); } } - s->esc3_level_length = 0; - s->esc3_run_length = 0; + w->ms.esc3_level_length = 0; + w->ms.esc3_run_length = 0; if (w->j_type) { ff_intrax8_decode_picture(&w->x8, s->cur_pic.ptr, @@ -349,7 +349,7 @@ static inline void wmv2_decode_motion(WMV2DecContext *w, int *mx_ptr, int *my_pt { MpegEncContext *const s = &w->ms.m; - ff_msmpeg4_decode_motion(s, mx_ptr, my_ptr); + ff_msmpeg4_decode_motion(&w->ms, mx_ptr, my_ptr); if ((((*mx_ptr) | (*my_ptr)) & 1) && s->mspel) w->common.hshift = get_bits1(&s->gb); @@ -423,19 +423,23 @@ static inline int wmv2_decode_inter_block(WMV2DecContext *w, int16_t *block, sub_cbp = sub_cbp_table[decode012(&s->gb)]; - if (sub_cbp & 1) - if ((ret = ff_msmpeg4_decode_block(s, block, n, 1, scantable)) < 0) + if (sub_cbp & 1) { + ret = ff_msmpeg4_decode_block(&w->ms, block, n, 1, scantable); + if (ret < 0) return ret; + } - if (sub_cbp & 2) - if ((ret = ff_msmpeg4_decode_block(s, w->abt_block2[n], n, 1, scantable)) < 0) + if (sub_cbp & 2) { + ret = ff_msmpeg4_decode_block(&w->ms, w->abt_block2[n], n, 1, scantable); + if (ret < 0) return ret; + } s->block_last_index[n] = 63; return 0; } else { - return ff_msmpeg4_decode_block(s, block, n, 1, + return ff_msmpeg4_decode_block(&w->ms, block, n, 1, s->inter_scantable.permutated); } } @@ -445,6 +449,7 @@ static int wmv2_decode_mb(MpegEncContext *s, int16_t block[6][64]) /* The following is only allowed because this encoder * does not use slice threading. */ WMV2DecContext *const w = (WMV2DecContext *) s; + MSMP4DecContext *const ms = &w->ms; int cbp, code, i, ret; uint8_t *coded_val; @@ -498,9 +503,9 @@ static int wmv2_decode_mb(MpegEncContext *s, int16_t block[6][64]) if (cbp) { s->bdsp.clear_blocks(s->block[0]); - if (s->per_mb_rl_table) { - s->rl_table_index = decode012(&s->gb); - s->rl_chroma_table_index = s->rl_table_index; + if (ms->per_mb_rl_table) { + ms->rl_table_index = decode012(&s->gb); + ms->rl_chroma_table_index = ms->rl_table_index; } if (w->abt_flag && w->per_mb_abt) { @@ -539,14 +544,15 @@ static int wmv2_decode_mb(MpegEncContext *s, int16_t block[6][64]) ff_dlog(s->avctx, "%d%d %d %d/", s->ac_pred, s->h263_aic_dir, s->mb_x, s->mb_y); } - if (s->per_mb_rl_table && cbp) { - s->rl_table_index = decode012(&s->gb); - s->rl_chroma_table_index = s->rl_table_index; + if (ms->per_mb_rl_table && cbp) { + ms->rl_table_index = decode012(&s->gb); + ms->rl_chroma_table_index = ms->rl_table_index; } s->bdsp.clear_blocks(s->block[0]); for (i = 0; i < 6; i++) { - if ((ret = ff_msmpeg4_decode_block(s, block[i], i, (cbp >> (5 - i)) & 1, NULL)) < 0) { + ret = ff_msmpeg4_decode_block(ms, block[i], i, (cbp >> (5 - i)) & 1, NULL); + if (ret < 0) { av_log(s->avctx, AV_LOG_ERROR, "\nerror while decoding intra block: %d x %d (%d)\n", s->mb_x, s->mb_y, i); diff --git a/libavcodec/wmv2enc.c b/libavcodec/wmv2enc.c index 6eda38d05f..81b0ace053 100644 --- a/libavcodec/wmv2enc.c +++ b/libavcodec/wmv2enc.c @@ -75,6 +75,7 @@ static int encode_ext_header(WMV2EncContext *w) static int wmv2_encode_picture_header(MPVMainEncContext *const m) { WMV2EncContext *const w = (WMV2EncContext *) m; + MSMPEG4EncContext *const ms = &w->msmpeg4; MpegEncContext *const s = &m->s; put_bits(&s->pb, 1, s->pict_type - 1); @@ -82,9 +83,9 @@ static int wmv2_encode_picture_header(MPVMainEncContext *const m) put_bits(&s->pb, 7, 0); put_bits(&s->pb, 5, s->qscale); - s->dc_table_index = 1; - s->mv_table_index = 1; /* only if P-frame */ - s->per_mb_rl_table = 0; + ms->dc_table_index = 1; + ms->mv_table_index = 1; /* only if P-frame */ + ms->per_mb_rl_table = 0; s->mspel = 0; w->per_mb_abt = 0; w->abt_type = 0; @@ -98,14 +99,14 @@ static int wmv2_encode_picture_header(MPVMainEncContext *const m) put_bits(&s->pb, 1, w->j_type); if (w->per_mb_rl_bit) - put_bits(&s->pb, 1, s->per_mb_rl_table); + put_bits(&s->pb, 1, ms->per_mb_rl_table); - if (!s->per_mb_rl_table) { - ff_msmpeg4_code012(&s->pb, s->rl_chroma_table_index); - ff_msmpeg4_code012(&s->pb, s->rl_table_index); + if (!ms->per_mb_rl_table) { + ff_msmpeg4_code012(&s->pb, ms->rl_chroma_table_index); + ff_msmpeg4_code012(&s->pb, ms->rl_table_index); } - put_bits(&s->pb, 1, s->dc_table_index); + put_bits(&s->pb, 1, ms->dc_table_index); s->inter_intra_pred = 0; } else { @@ -126,19 +127,19 @@ static int wmv2_encode_picture_header(MPVMainEncContext *const m) } if (w->per_mb_rl_bit) - put_bits(&s->pb, 1, s->per_mb_rl_table); + put_bits(&s->pb, 1, ms->per_mb_rl_table); - if (!s->per_mb_rl_table) { - ff_msmpeg4_code012(&s->pb, s->rl_table_index); - s->rl_chroma_table_index = s->rl_table_index; + if (!ms->per_mb_rl_table) { + ff_msmpeg4_code012(&s->pb, ms->rl_table_index); + ms->rl_chroma_table_index = ms->rl_table_index; } - put_bits(&s->pb, 1, s->dc_table_index); - put_bits(&s->pb, 1, s->mv_table_index); + put_bits(&s->pb, 1, ms->dc_table_index); + put_bits(&s->pb, 1, ms->mv_table_index); s->inter_intra_pred = 0; // (s->width * s->height < 320 * 240 && m->bit_rate <= II_BITRATE); } s->esc3_level_length = 0; - s->esc3_run_length = 0; + ms->esc3_run_length = 0; return 0; } @@ -170,7 +171,7 @@ static void wmv2_encode_mb(MpegEncContext *const s, int16_t block[][64], s->misc_bits += get_bits_diff(s); /* motion vector */ ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y); - ff_msmpeg4_encode_motion(s, motion_x - pred_x, + ff_msmpeg4_encode_motion(&w->msmpeg4, motion_x - pred_x, motion_y - pred_y); s->mv_bits += get_bits_diff(s); } else { -- 2.45.2 [-- Attachment #49: 0048-avcodec-mpegvideo-Move-allocating-encoder-buffers-to.patch --] [-- Type: text/x-patch, Size: 5931 bytes --] From 0faa3cf487081776a9b577b0fdfb20c4d9494ca7 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Tue, 25 Oct 2022 18:27:17 +0200 Subject: [PATCH 48/77] avcodec/mpegvideo: Move allocating encoder buffers to mpegvideoenc.c dct_error_sum and me.map are allocated per slice-context and therefore their allocation has not been moved to mpegvideoenc.c in 0154fb43e328b13da8943e66b38dc1b5ab9315af. This commit changes this by allocating them jointly and moving said allocations to mpegvideo_enc.c like the other encoder-only buffers. The buffers are suitably aligned to ensure that no false sharing occurs. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpegvideo.c | 17 ------------ libavcodec/mpegvideo_enc.c | 54 ++++++++++++++++++++++++++++++++++++++ libavcodec/mpegvideoenc.h | 3 +++ 3 files changed, 57 insertions(+), 17 deletions(-) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index bc367fba07..8055e6c0e2 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -351,17 +351,6 @@ av_cold void ff_mpv_idct_init(MpegEncContext *s) static av_cold int init_duplicate_context(MpegEncContext *s) { - if (s->encoding) { - s->me.map = av_mallocz(2 * ME_MAP_SIZE * sizeof(*s->me.map)); - if (!s->me.map) - return AVERROR(ENOMEM); - s->me.score_map = s->me.map + ME_MAP_SIZE; - - if (s->noise_reduction) { - if (!FF_ALLOCZ_TYPED_ARRAY(s->dct_error_sum, 2)) - return AVERROR(ENOMEM); - } - } if (!FF_ALLOCZ_TYPED_ARRAY(s->blocks, 1 + s->encoding)) return AVERROR(ENOMEM); s->block = s->blocks[0]; @@ -420,9 +409,6 @@ static av_cold void free_duplicate_context(MpegEncContext *s) s->sc.obmc_scratchpad = NULL; s->sc.linesize = 0; - av_freep(&s->dct_error_sum); - av_freep(&s->me.map); - s->me.score_map = NULL; av_freep(&s->blocks); av_freep(&s->ac_val_base); s->block = NULL; @@ -646,9 +632,6 @@ static void clear_context(MpegEncContext *s) memset(s->thread_context, 0, sizeof(s->thread_context)); - s->me.map = NULL; - s->me.score_map = NULL; - s->dct_error_sum = NULL; s->block = NULL; s->blocks = NULL; s->ac_val_base = NULL; diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 116c974098..f6bd9be56b 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -33,6 +33,7 @@ #include "config_components.h" +#include <assert.h> #include <stdint.h> #include "libavutil/emms.h" @@ -420,6 +421,53 @@ static av_cold int init_matrices(MPVMainEncContext *const m, AVCodecContext *avc return 0; } +static av_cold int init_buffers(MPVMainEncContext *const m, AVCodecContext *avctx) +{ + MpegEncContext *const s = &m->s; + // Align the following per-thread buffers to avoid false sharing. + enum { +#ifndef _MSC_VER + /// The number is supposed to match/exceed the cache-line size. + ALIGN = FFMAX(128, _Alignof(max_align_t)), +#else + ALIGN = 128, +#endif + ME_MAP_ALLOC_SIZE = FFALIGN(2 * ME_MAP_SIZE * sizeof(*s->me.map), ALIGN), + DCT_ERROR_SIZE = FFALIGN(2 * sizeof(*s->dct_error_sum), ALIGN), + }; + static_assert(FFMAX(ME_MAP_ALLOC_SIZE, DCT_ERROR_SIZE) * MAX_THREADS + ALIGN - 1 <= SIZE_MAX, + "Need checks for potential overflow."); + unsigned nb_slices = s->slice_context_count; + char *dct_error = NULL, *me_map; + + if (s->noise_reduction) { + dct_error = av_mallocz(ALIGN - 1 + nb_slices * DCT_ERROR_SIZE); + if (!dct_error) + return AVERROR(ENOMEM); + m->dct_error_sum_base = dct_error; + dct_error += FFALIGN((uintptr_t)dct_error, ALIGN) - (uintptr_t)dct_error; + } + me_map = av_mallocz(ALIGN - 1 + nb_slices * ME_MAP_ALLOC_SIZE); + if (!me_map) + return AVERROR(ENOMEM); + m->me_map_base = me_map; + me_map += FFALIGN((uintptr_t)me_map, ALIGN) - (uintptr_t)me_map; + + for (unsigned i = 0; i < nb_slices; ++i) { + MpegEncContext *const s2 = s->thread_context[i]; + + if (dct_error) { + s2->dct_error_sum = (void*)dct_error; + dct_error += DCT_ERROR_SIZE; + } + s2->me.map = (uint32_t*)me_map; + s2->me.score_map = s2->me.map + ME_MAP_SIZE; + me_map += ME_MAP_ALLOC_SIZE; + } + + return 0; +} + /* init video encoder */ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) { @@ -923,6 +971,10 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) if (ret < 0) return ret; + ret = init_buffers(m, avctx); + if (ret < 0) + return ret; + /* Allocate MV tables; the MV and MB tables will be copied * to slice contexts by ff_update_duplicate_context(). */ mv_table_size = (s->mb_height + 2) * s->mb_stride + 1; @@ -1067,6 +1119,8 @@ av_cold int ff_mpv_encode_end(AVCodecContext *avctx) av_freep(&s->b_field_mv_table_base); av_freep(&s->b_field_select_table[0][0]); av_freep(&s->p_field_select_table[0]); + av_freep(&m->dct_error_sum_base); + av_freep(&m->me_map_base); av_freep(&s->mb_type); av_freep(&s->lambda_table); diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h index 57b91d169a..dfd86d76cc 100644 --- a/libavcodec/mpegvideoenc.h +++ b/libavcodec/mpegvideoenc.h @@ -98,6 +98,9 @@ typedef struct MPVMainEncContext { int64_t mb_var_sum; ///< sum of MB variance for current frame int64_t mc_mb_var_sum; ///< motion compensated MB variance for current frame + + char *me_map_base; ///< backs MotionEstContext.(map|score_map) + char *dct_error_sum_base; ///< backs dct_error_sum } MPVMainEncContext; static inline const MPVMainEncContext *slice_to_mainenc(const MpegEncContext *s) -- 2.45.2 [-- Attachment #50: 0049-avcodec-mpegvideo-Move-encoder-only-base-arrays-to-M.patch --] [-- Type: text/x-patch, Size: 9430 bytes --] From 1c0ec9ed6a7234fefabda44086f85ca4ca2db31d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sun, 16 Mar 2025 09:02:05 +0100 Subject: [PATCH 49/77] avcodec/mpegvideo: Move encoder-only base arrays to MPVMainEncContext Also allocate them jointly (thereby reducing the number of base arrays considerably) and already set them on all slice contexts; don't rely on ff_update_duplicate_context(). Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpegvideo.h | 9 +--- libavcodec/mpegvideo_enc.c | 92 +++++++++++++++++--------------------- libavcodec/mpegvideoenc.h | 1 + 3 files changed, 43 insertions(+), 59 deletions(-) diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 39ca4b3d1a..609052786e 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -207,14 +207,7 @@ typedef struct MpegEncContext { H263DSPContext h263dsp; int f_code; ///< forward MV resolution int b_code; ///< backward MV resolution for B-frames (MPEG-4) - int16_t (*p_mv_table_base)[2]; - int16_t (*b_forw_mv_table_base)[2]; - int16_t (*b_back_mv_table_base)[2]; - int16_t (*b_bidir_forw_mv_table_base)[2]; - int16_t (*b_bidir_back_mv_table_base)[2]; - int16_t (*b_direct_mv_table_base)[2]; int16_t (*p_field_mv_table_base)[2]; - int16_t (*b_field_mv_table_base)[2]; int16_t (*p_mv_table)[2]; ///< MV table (1MV per MB) P-frame encoding int16_t (*b_forw_mv_table)[2]; ///< MV table (1MV per MB) forward mode B-frame encoding int16_t (*b_back_mv_table)[2]; ///< MV table (1MV per MB) backward mode B-frame encoding @@ -224,7 +217,7 @@ typedef struct MpegEncContext { int16_t (*p_field_mv_table[2][2])[2]; ///< MV table (2MV per MB) interlaced P-frame encoding int16_t (*b_field_mv_table[2][2][2])[2];///< MV table (4MV per MB) interlaced B-frame encoding uint8_t (*p_field_select_table[2]); ///< Only the first element is allocated - uint8_t (*b_field_select_table[2][2]); ///< Only the first element is allocated + uint8_t (*b_field_select_table[2][2]); ///< allocated jointly with p_field_select_table /* The following fields are encoder-only */ uint16_t *mb_var; ///< Table for MB variances diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index f6bd9be56b..2331bbbb06 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -437,8 +437,10 @@ static av_cold int init_buffers(MPVMainEncContext *const m, AVCodecContext *avct }; static_assert(FFMAX(ME_MAP_ALLOC_SIZE, DCT_ERROR_SIZE) * MAX_THREADS + ALIGN - 1 <= SIZE_MAX, "Need checks for potential overflow."); - unsigned nb_slices = s->slice_context_count; + unsigned nb_slices = s->slice_context_count, mv_table_size; char *dct_error = NULL, *me_map; + int nb_mv_tables = 6; + int16_t (*mv_table)[2]; if (s->noise_reduction) { dct_error = av_mallocz(ALIGN - 1 + nb_slices * DCT_ERROR_SIZE); @@ -453,8 +455,23 @@ static av_cold int init_buffers(MPVMainEncContext *const m, AVCodecContext *avct m->me_map_base = me_map; me_map += FFALIGN((uintptr_t)me_map, ALIGN) - (uintptr_t)me_map; + mv_table_size = (s->mb_height + 2) * s->mb_stride + 1; + if (s->codec_id == AV_CODEC_ID_MPEG4 || + (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)) { + nb_mv_tables += 8; + if (!ALLOCZ_ARRAYS(s->p_field_select_table[0], 2 * (2 + 4), mv_table_size)) + return AVERROR(ENOMEM); + } + + mv_table = av_calloc(mv_table_size, nb_mv_tables * sizeof(*mv_table)); + if (!mv_table) + return AVERROR(ENOMEM); + m->mv_table_base = mv_table; + mv_table += s->mb_stride + 1; + for (unsigned i = 0; i < nb_slices; ++i) { MpegEncContext *const s2 = s->thread_context[i]; + int16_t (*tmp_mv_table)[2] = mv_table; if (dct_error) { s2->dct_error_sum = (void*)dct_error; @@ -463,6 +480,27 @@ static av_cold int init_buffers(MPVMainEncContext *const m, AVCodecContext *avct s2->me.map = (uint32_t*)me_map; s2->me.score_map = s2->me.map + ME_MAP_SIZE; me_map += ME_MAP_ALLOC_SIZE; + + s2->p_mv_table = tmp_mv_table; + s2->b_forw_mv_table = tmp_mv_table += mv_table_size; + s2->b_back_mv_table = tmp_mv_table += mv_table_size; + s2->b_bidir_forw_mv_table = tmp_mv_table += mv_table_size; + s2->b_bidir_back_mv_table = tmp_mv_table += mv_table_size; + s2->b_direct_mv_table = tmp_mv_table += mv_table_size; + + if (s->p_field_select_table[0]) { // MPEG-4 or INTERLACED_ME above + uint8_t *field_select = s->p_field_select_table[0]; + s2->p_field_select_table[0] = field_select; + s2->p_field_select_table[1] = field_select += 2 * mv_table_size; + + for (int j = 0; j < 2; j++) { + for (int k = 0; k < 2; k++) { + for (int l = 0; l < 2; l++) + s2->b_field_mv_table[j][k][l] = tmp_mv_table += mv_table_size; + s2->b_field_select_table[j][k] = field_select += 2 * mv_table_size; + } + } + } } return 0; @@ -475,7 +513,7 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) MpegEncContext *const s = &m->s; AVCPBProperties *cpb_props; int i, ret; - int mb_array_size, mv_table_size; + int mb_array_size; mpv_encode_defaults(m); @@ -975,23 +1013,6 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) if (ret < 0) return ret; - /* Allocate MV tables; the MV and MB tables will be copied - * to slice contexts by ff_update_duplicate_context(). */ - mv_table_size = (s->mb_height + 2) * s->mb_stride + 1; - if (!FF_ALLOCZ_TYPED_ARRAY(s->p_mv_table_base, mv_table_size) || - !FF_ALLOCZ_TYPED_ARRAY(s->b_forw_mv_table_base, mv_table_size) || - !FF_ALLOCZ_TYPED_ARRAY(s->b_back_mv_table_base, mv_table_size) || - !FF_ALLOCZ_TYPED_ARRAY(s->b_bidir_forw_mv_table_base, mv_table_size) || - !FF_ALLOCZ_TYPED_ARRAY(s->b_bidir_back_mv_table_base, mv_table_size) || - !FF_ALLOCZ_TYPED_ARRAY(s->b_direct_mv_table_base, mv_table_size)) - return AVERROR(ENOMEM); - s->p_mv_table = s->p_mv_table_base + s->mb_stride + 1; - s->b_forw_mv_table = s->b_forw_mv_table_base + s->mb_stride + 1; - s->b_back_mv_table = s->b_back_mv_table_base + s->mb_stride + 1; - s->b_bidir_forw_mv_table = s->b_bidir_forw_mv_table_base + s->mb_stride + 1; - s->b_bidir_back_mv_table = s->b_bidir_back_mv_table_base + s->mb_stride + 1; - s->b_direct_mv_table = s->b_direct_mv_table_base + s->mb_stride + 1; - /* Allocate MB type table */ mb_array_size = s->mb_stride * s->mb_height; if (!FF_ALLOCZ_TYPED_ARRAY(s->mb_type, mb_array_size) || @@ -1001,30 +1022,6 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) !(s->mb_mean = av_mallocz(mb_array_size))) return AVERROR(ENOMEM); - if (s->codec_id == AV_CODEC_ID_MPEG4 || - (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)) { - int16_t (*tmp1)[2]; - uint8_t *tmp2; - if (!(tmp1 = ALLOCZ_ARRAYS(s->b_field_mv_table_base, 8, mv_table_size)) || - !(tmp2 = ALLOCZ_ARRAYS(s->b_field_select_table[0][0], 2 * 4, mv_table_size)) || - !ALLOCZ_ARRAYS(s->p_field_select_table[0], 2 * 2, mv_table_size)) - return AVERROR(ENOMEM); - - s->p_field_select_table[1] = s->p_field_select_table[0] + 2 * mv_table_size; - tmp1 += s->mb_stride + 1; - - for (int i = 0; i < 2; i++) { - for (int j = 0; j < 2; j++) { - for (int k = 0; k < 2; k++) { - s->b_field_mv_table[i][j][k] = tmp1; - tmp1 += mv_table_size; - } - s->b_field_select_table[i][j] = tmp2; - tmp2 += 2 * mv_table_size; - } - } - } - if (s->noise_reduction) { if (!FF_ALLOCZ_TYPED_ARRAY(s->dct_offset, 2)) return AVERROR(ENOMEM); @@ -1110,14 +1107,7 @@ av_cold int ff_mpv_encode_end(AVCodecContext *avctx) av_freep(&avctx->stats_out); - av_freep(&s->p_mv_table_base); - av_freep(&s->b_forw_mv_table_base); - av_freep(&s->b_back_mv_table_base); - av_freep(&s->b_bidir_forw_mv_table_base); - av_freep(&s->b_bidir_back_mv_table_base); - av_freep(&s->b_direct_mv_table_base); - av_freep(&s->b_field_mv_table_base); - av_freep(&s->b_field_select_table[0][0]); + av_freep(&m->mv_table_base); av_freep(&s->p_field_select_table[0]); av_freep(&m->dct_error_sum_base); av_freep(&m->me_map_base); diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h index dfd86d76cc..6097ea7a9c 100644 --- a/libavcodec/mpegvideoenc.h +++ b/libavcodec/mpegvideoenc.h @@ -101,6 +101,7 @@ typedef struct MPVMainEncContext { char *me_map_base; ///< backs MotionEstContext.(map|score_map) char *dct_error_sum_base; ///< backs dct_error_sum + int16_t (*mv_table_base)[2]; } MPVMainEncContext; static inline const MPVMainEncContext *slice_to_mainenc(const MpegEncContext *s) -- 2.45.2 [-- Attachment #51: 0050-avcodec-mpegvideo_enc-Don-t-allocate-B-frame-bufs-wi.patch --] [-- Type: text/x-patch, Size: 3036 bytes --] From faf62fc8fb7c5a3462655872274b4cd66a755d9b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sun, 16 Mar 2025 09:18:41 +0100 Subject: [PATCH 50/77] avcodec/mpegvideo_enc: Don't allocate B-frame bufs without B frames (Checking in the same way for intra_only is not straightforward, because at least p_mv_table is written to even in intra_only mode.) Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpegvideo_enc.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 2331bbbb06..680ce7d153 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -439,7 +439,7 @@ static av_cold int init_buffers(MPVMainEncContext *const m, AVCodecContext *avct "Need checks for potential overflow."); unsigned nb_slices = s->slice_context_count, mv_table_size; char *dct_error = NULL, *me_map; - int nb_mv_tables = 6; + int has_b_frames = !!m->max_b_frames, nb_mv_tables = 1 + 5 * has_b_frames; int16_t (*mv_table)[2]; if (s->noise_reduction) { @@ -458,8 +458,8 @@ static av_cold int init_buffers(MPVMainEncContext *const m, AVCodecContext *avct mv_table_size = (s->mb_height + 2) * s->mb_stride + 1; if (s->codec_id == AV_CODEC_ID_MPEG4 || (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)) { - nb_mv_tables += 8; - if (!ALLOCZ_ARRAYS(s->p_field_select_table[0], 2 * (2 + 4), mv_table_size)) + nb_mv_tables += 8 * has_b_frames; + if (!ALLOCZ_ARRAYS(s->p_field_select_table[0], 2 * (2 + 4 * has_b_frames), mv_table_size)) return AVERROR(ENOMEM); } @@ -482,17 +482,20 @@ static av_cold int init_buffers(MPVMainEncContext *const m, AVCodecContext *avct me_map += ME_MAP_ALLOC_SIZE; s2->p_mv_table = tmp_mv_table; + if (has_b_frames) { s2->b_forw_mv_table = tmp_mv_table += mv_table_size; s2->b_back_mv_table = tmp_mv_table += mv_table_size; s2->b_bidir_forw_mv_table = tmp_mv_table += mv_table_size; s2->b_bidir_back_mv_table = tmp_mv_table += mv_table_size; s2->b_direct_mv_table = tmp_mv_table += mv_table_size; + } if (s->p_field_select_table[0]) { // MPEG-4 or INTERLACED_ME above uint8_t *field_select = s->p_field_select_table[0]; s2->p_field_select_table[0] = field_select; s2->p_field_select_table[1] = field_select += 2 * mv_table_size; + if (has_b_frames) { for (int j = 0; j < 2; j++) { for (int k = 0; k < 2; k++) { for (int l = 0; l < 2; l++) @@ -500,6 +503,7 @@ static av_cold int init_buffers(MPVMainEncContext *const m, AVCodecContext *avct s2->b_field_select_table[j][k] = field_select += 2 * mv_table_size; } } + } } } -- 2.45.2 [-- Attachment #52: 0051-avcodec-mpegvideo_enc-Reindent-after-the-previous-co.patch --] [-- Type: text/x-patch, Size: 2546 bytes --] From c7e7076efbd4cc121ce55a6316cd4016e6cfbff9 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sun, 16 Mar 2025 09:39:37 +0100 Subject: [PATCH 51/77] avcodec/mpegvideo_enc: Reindent after the previous commit Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpegvideo_enc.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 680ce7d153..85d6b1faff 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -483,11 +483,11 @@ static av_cold int init_buffers(MPVMainEncContext *const m, AVCodecContext *avct s2->p_mv_table = tmp_mv_table; if (has_b_frames) { - s2->b_forw_mv_table = tmp_mv_table += mv_table_size; - s2->b_back_mv_table = tmp_mv_table += mv_table_size; - s2->b_bidir_forw_mv_table = tmp_mv_table += mv_table_size; - s2->b_bidir_back_mv_table = tmp_mv_table += mv_table_size; - s2->b_direct_mv_table = tmp_mv_table += mv_table_size; + s2->b_forw_mv_table = tmp_mv_table += mv_table_size; + s2->b_back_mv_table = tmp_mv_table += mv_table_size; + s2->b_bidir_forw_mv_table = tmp_mv_table += mv_table_size; + s2->b_bidir_back_mv_table = tmp_mv_table += mv_table_size; + s2->b_direct_mv_table = tmp_mv_table += mv_table_size; } if (s->p_field_select_table[0]) { // MPEG-4 or INTERLACED_ME above @@ -496,14 +496,14 @@ static av_cold int init_buffers(MPVMainEncContext *const m, AVCodecContext *avct s2->p_field_select_table[1] = field_select += 2 * mv_table_size; if (has_b_frames) { - for (int j = 0; j < 2; j++) { - for (int k = 0; k < 2; k++) { - for (int l = 0; l < 2; l++) - s2->b_field_mv_table[j][k][l] = tmp_mv_table += mv_table_size; - s2->b_field_select_table[j][k] = field_select += 2 * mv_table_size; + for (int j = 0; j < 2; j++) { + for (int k = 0; k < 2; k++) { + for (int l = 0; l < 2; l++) + s2->b_field_mv_table[j][k][l] = tmp_mv_table += mv_table_size; + s2->b_field_select_table[j][k] = field_select += 2 * mv_table_size; + } } } - } } } -- 2.45.2 [-- Attachment #53: 0052-avcodec-mpegvideo_enc-Move-allocating-remaining-buff.patch --] [-- Type: text/x-patch, Size: 4288 bytes --] From 0f97322ab966d1265e4cf7e07ade68c3bf73ebb9 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sun, 16 Mar 2025 10:21:30 +0100 Subject: [PATCH 52/77] avcodec/mpegvideo_enc: Move allocating remaining buffers to init_buffers Also allocate mb_type, mc_mb_var, mb_var and mb_mean jointly while just at it. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpegvideo_enc.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 85d6b1faff..0c2ed2e931 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -437,12 +437,14 @@ static av_cold int init_buffers(MPVMainEncContext *const m, AVCodecContext *avct }; static_assert(FFMAX(ME_MAP_ALLOC_SIZE, DCT_ERROR_SIZE) * MAX_THREADS + ALIGN - 1 <= SIZE_MAX, "Need checks for potential overflow."); - unsigned nb_slices = s->slice_context_count, mv_table_size; + unsigned nb_slices = s->slice_context_count, mv_table_size, mb_array_size; char *dct_error = NULL, *me_map; int has_b_frames = !!m->max_b_frames, nb_mv_tables = 1 + 5 * has_b_frames; int16_t (*mv_table)[2]; if (s->noise_reduction) { + if (!FF_ALLOCZ_TYPED_ARRAY(s->dct_offset, 2)) + return AVERROR(ENOMEM); dct_error = av_mallocz(ALIGN - 1 + nb_slices * DCT_ERROR_SIZE); if (!dct_error) return AVERROR(ENOMEM); @@ -455,6 +457,14 @@ static av_cold int init_buffers(MPVMainEncContext *const m, AVCodecContext *avct m->me_map_base = me_map; me_map += FFALIGN((uintptr_t)me_map, ALIGN) - (uintptr_t)me_map; + /* Allocate MB type table */ + mb_array_size = s->mb_stride * s->mb_height; + s->mb_type = av_calloc(mb_array_size, 3 * sizeof(*s->mb_type) + sizeof(*s->mb_mean)); + if (!s->mb_type) + return AVERROR(ENOMEM); + if (!FF_ALLOCZ_TYPED_ARRAY(s->lambda_table, mb_array_size)) + return AVERROR(ENOMEM); + mv_table_size = (s->mb_height + 2) * s->mb_stride + 1; if (s->codec_id == AV_CODEC_ID_MPEG4 || (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)) { @@ -474,9 +484,17 @@ static av_cold int init_buffers(MPVMainEncContext *const m, AVCodecContext *avct int16_t (*tmp_mv_table)[2] = mv_table; if (dct_error) { + s2->dct_offset = s->dct_offset; s2->dct_error_sum = (void*)dct_error; dct_error += DCT_ERROR_SIZE; } + + s2->mb_type = s->mb_type; + s2->mc_mb_var = s2->mb_type + mb_array_size; + s2->mb_var = s2->mc_mb_var + mb_array_size; + s2->mb_mean = (uint8_t*)(s2->mb_var + mb_array_size); + s2->lambda_table = s->lambda_table; + s2->me.map = (uint32_t*)me_map; s2->me.score_map = s2->me.map + ME_MAP_SIZE; me_map += ME_MAP_ALLOC_SIZE; @@ -517,7 +535,6 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) MpegEncContext *const s = &m->s; AVCPBProperties *cpb_props; int i, ret; - int mb_array_size; mpv_encode_defaults(m); @@ -1017,20 +1034,6 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) if (ret < 0) return ret; - /* Allocate MB type table */ - mb_array_size = s->mb_stride * s->mb_height; - if (!FF_ALLOCZ_TYPED_ARRAY(s->mb_type, mb_array_size) || - !FF_ALLOCZ_TYPED_ARRAY(s->lambda_table, mb_array_size) || - !FF_ALLOCZ_TYPED_ARRAY(s->mc_mb_var, mb_array_size) || - !FF_ALLOCZ_TYPED_ARRAY(s->mb_var, mb_array_size) || - !(s->mb_mean = av_mallocz(mb_array_size))) - return AVERROR(ENOMEM); - - if (s->noise_reduction) { - if (!FF_ALLOCZ_TYPED_ARRAY(s->dct_offset, 2)) - return AVERROR(ENOMEM); - } - ff_dct_encode_init(s); if (s->mpeg_quant || s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { @@ -1122,9 +1125,6 @@ av_cold int ff_mpv_encode_end(AVCodecContext *avctx) av_freep(&s->q_intra_matrix); av_freep(&s->q_intra_matrix16); av_freep(&s->dct_offset); - av_freep(&s->mb_var); - av_freep(&s->mc_mb_var); - av_freep(&s->mb_mean); return 0; } -- 2.45.2 [-- Attachment #54: 0053-avcodec-mpegvideo-Move-noise_reduction-to-MPVMainEnc.patch --] [-- Type: text/x-patch, Size: 5083 bytes --] From 6204361baa5d94d66eced3e21ee2180ce561e8fd Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sun, 16 Mar 2025 10:30:48 +0100 Subject: [PATCH 53/77] avcodec/mpegvideo: Move noise_reduction to MPVMainEncContext Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpegvideo.h | 2 -- libavcodec/mpegvideo_enc.c | 19 +++++++++++-------- libavcodec/mpegvideoenc.h | 4 +++- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 609052786e..69efc81096 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -473,8 +473,6 @@ typedef struct MpegEncContext { int error_rate; - int noise_reduction; - int intra_penalty; } MpegEncContext; diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 0c2ed2e931..b32b8fe768 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -442,7 +442,7 @@ static av_cold int init_buffers(MPVMainEncContext *const m, AVCodecContext *avct int has_b_frames = !!m->max_b_frames, nb_mv_tables = 1 + 5 * has_b_frames; int16_t (*mv_table)[2]; - if (s->noise_reduction) { + if (m->noise_reduction) { if (!FF_ALLOCZ_TYPED_ARRAY(s->dct_offset, 2)) return AVERROR(ENOMEM); dct_error = av_mallocz(ALIGN - 1 + nb_slices * DCT_ERROR_SIZE); @@ -1877,8 +1877,9 @@ static void frame_end(MPVMainEncContext *const m) s->last_non_b_pict_type = s->pict_type; } -static void update_noise_reduction(MpegEncContext *s) +static void update_noise_reduction(MPVMainEncContext *const m) { + MpegEncContext *const s = &m->s; int intra, i; for (intra = 0; intra < 2; intra++) { @@ -1890,7 +1891,7 @@ static void update_noise_reduction(MpegEncContext *s) } for (i = 0; i < 64; i++) { - s->dct_offset[intra][i] = (s->noise_reduction * + s->dct_offset[intra][i] = (m->noise_reduction * s->dct_count[intra] + s->dct_error_sum[intra][i] / 2) / (s->dct_error_sum[intra][i] + 1); @@ -1898,8 +1899,10 @@ static void update_noise_reduction(MpegEncContext *s) } } -static void frame_start(MpegEncContext *s) +static void frame_start(MPVMainEncContext *const m) { + MpegEncContext *const s = &m->s; + s->cur_pic.ptr->f->pict_type = s->pict_type; if (s->pict_type != AV_PICTURE_TYPE_B) { @@ -1907,9 +1910,9 @@ static void frame_start(MpegEncContext *s) ff_mpv_replace_picture(&s->next_pic, &s->cur_pic); } + av_assert2(!!m->noise_reduction == !!s->dct_error_sum); if (s->dct_error_sum) { - av_assert2(s->noise_reduction && s->encoding); - update_noise_reduction(s); + update_noise_reduction(m); } } @@ -1959,7 +1962,7 @@ int ff_mpv_encode_picture(AVCodecContext *avctx, AVPacket *pkt, s->pict_type = s->new_pic->pict_type; //emms_c(); - frame_start(s); + frame_start(m); vbv_retry: ret = encode_picture(m, pkt); if (growing_buffer) { @@ -3598,7 +3601,7 @@ static void merge_context_after_encode(MpegEncContext *dst, MpegEncContext *src) MERGE(encoding_error[1]); MERGE(encoding_error[2]); - if (dst->noise_reduction){ + if (dst->dct_error_sum) { for(i=0; i<64; i++){ MERGE(dct_error_sum[0][i]); MERGE(dct_error_sum[1][i]); diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h index 6097ea7a9c..d101c92cbb 100644 --- a/libavcodec/mpegvideoenc.h +++ b/libavcodec/mpegvideoenc.h @@ -68,6 +68,8 @@ typedef struct MPVMainEncContext { int b_sensitivity; int brd_scale; + int noise_reduction; + float border_masking; int lmin, lmax; int vbv_ignore_qmax; @@ -199,7 +201,7 @@ FF_MPV_OPT_CMP_FUNC, \ {"skip_factor", "Frame skip factor", FF_MPV_MAIN_OFFSET(frame_skip_factor), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ {"skip_exp", "Frame skip exponent", FF_MPV_MAIN_OFFSET(frame_skip_exp), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ {"skip_cmp", "Frame skip compare function", FF_MPV_MAIN_OFFSET(frame_skip_cmp), AV_OPT_TYPE_INT, {.i64 = FF_CMP_DCTMAX }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, .unit = "cmp_func" }, \ -{"noise_reduction", "Noise reduction", FF_MPV_OFFSET(noise_reduction), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"noise_reduction", "Noise reduction", FF_MPV_MAIN_OFFSET(noise_reduction), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ {"ps", "RTP payload size in bytes", FF_MPV_OFFSET(rtp_payload_size), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ #define FF_MPV_COMMON_BFRAME_OPTS \ -- 2.45.2 [-- Attachment #55: 0054-avcodec-mpegvideo-Support-custom-slice-context-sizes.patch --] [-- Type: text/x-patch, Size: 1973 bytes --] From dd3a973dd2480a77f04673ff95ff4e8c2a7526c5 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sun, 16 Mar 2025 14:52:36 +0100 Subject: [PATCH 54/77] avcodec/mpegvideo: Support custom slice context sizes This is in preparation for adding a special slice context for the encoders and moving all the encoder-specific fields to it. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpegvideo.c | 3 ++- libavcodec/mpegvideo.h | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 8055e6c0e2..126fefa1be 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -375,6 +375,7 @@ static av_cold int init_duplicate_context(MpegEncContext *s) av_cold int ff_mpv_init_duplicate_contexts(MpegEncContext *s) { int nb_slices = s->slice_context_count, ret; + size_t slice_size = s->slice_ctx_size ? s->slice_ctx_size : sizeof(*s); s->parent = s; @@ -382,7 +383,7 @@ av_cold int ff_mpv_init_duplicate_contexts(MpegEncContext *s) * fields allocated in init_duplicate_context are NULL after * copying. This prevents double-frees upon allocation error. */ for (int i = 1; i < nb_slices; i++) { - s->thread_context[i] = av_memdup(s, sizeof(MpegEncContext)); + s->thread_context[i] = av_memdup(s, slice_size); if (!s->thread_context[i]) return AVERROR(ENOMEM); if ((ret = init_duplicate_context(s->thread_context[i])) < 0) diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 69efc81096..02894ce68f 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -469,6 +469,9 @@ typedef struct MpegEncContext { * a frame size change */ int context_reinit; + /// If set, ff_mpv_common_init() will allocate slice contexts of this size + unsigned slice_ctx_size; + ERContext er; int error_rate; -- 2.45.2 [-- Attachment #56: 0055-avcodec-mpegvideo-Move-last-pic-information-to-MPVMa.patch --] [-- Type: text/x-patch, Size: 6705 bytes --] From cb00bce3c7de503711cf83183ee8e8c44e48f168 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sat, 29 Jan 2022 05:25:25 +0100 Subject: [PATCH 55/77] avcodec/mpegvideo: Move last-pic information to MPVMainEncContext last_pict_type, last_non_b_pict_type and last_lambda_for are only used by the encoder's main thread. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpegvideo.h | 3 --- libavcodec/mpegvideo_enc.c | 16 ++++++++-------- libavcodec/mpegvideoenc.h | 3 +++ libavcodec/msmpeg4enc.c | 4 ++-- libavcodec/ratecontrol.c | 4 ++-- libavcodec/snowenc.c | 2 +- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 02894ce68f..c16fb1c703 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -185,10 +185,7 @@ typedef struct MpegEncContext { int adaptive_quant; ///< use adaptive quantization int dquant; ///< qscale difference to prev qscale int pict_type; ///< AV_PICTURE_TYPE_I, AV_PICTURE_TYPE_P, AV_PICTURE_TYPE_B, ... - int last_pict_type; //FIXME removes - int last_non_b_pict_type; ///< used for MPEG-4 gmc B-frames & ratecontrol int droppable; - int last_lambda_for[5]; ///< last lambda for a specific pict type int skipdct; ///< skip dct and code zero residual /* motion compensation */ diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index b32b8fe768..9f44c37b3d 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -1515,9 +1515,9 @@ static int estimate_best_b_count(MPVMainEncContext *const m) return AVERROR(ENOMEM); //emms_c(); - p_lambda = s->last_lambda_for[AV_PICTURE_TYPE_P]; + p_lambda = m->last_lambda_for[AV_PICTURE_TYPE_P]; //p_lambda * FFABS(s->avctx->b_quant_factor) + s->avctx->b_quant_offset; - b_lambda = s->last_lambda_for[AV_PICTURE_TYPE_B]; + b_lambda = m->last_lambda_for[AV_PICTURE_TYPE_B]; if (!b_lambda) // FIXME we should do this somewhere else b_lambda = p_lambda; lambda2 = (b_lambda * b_lambda + (1 << FF_LAMBDA_SHIFT) / 2) >> @@ -1871,10 +1871,10 @@ static void frame_end(MPVMainEncContext *const m) emms_c(); - s->last_pict_type = s->pict_type; - s->last_lambda_for [s->pict_type] = s->cur_pic.ptr->f->quality; + m->last_pict_type = s->pict_type; + m->last_lambda_for[s->pict_type] = s->cur_pic.ptr->f->quality; if (s->pict_type!= AV_PICTURE_TYPE_B) - s->last_non_b_pict_type = s->pict_type; + m->last_non_b_pict_type = s->pict_type; } static void update_noise_reduction(MPVMainEncContext *const m) @@ -3702,9 +3702,9 @@ static int encode_picture(MPVMainEncContext *const m, const AVPacket *pkt) ff_get_2pass_fcode(m); } else if (!(s->avctx->flags & AV_CODEC_FLAG_QSCALE)) { if(s->pict_type==AV_PICTURE_TYPE_B) - s->lambda= s->last_lambda_for[s->pict_type]; + s->lambda = m->last_lambda_for[s->pict_type]; else - s->lambda= s->last_lambda_for[s->last_non_b_pict_type]; + s->lambda = m->last_lambda_for[m->last_non_b_pict_type]; update_qscale(m); } @@ -3735,7 +3735,7 @@ static int encode_picture(MPVMainEncContext *const m, const AVPacket *pkt) s->lambda = (s->lambda * s->me_penalty_compensation + 128) >> 8; s->lambda2 = (s->lambda2 * (int64_t) s->me_penalty_compensation + 128) >> 8; if (s->pict_type != AV_PICTURE_TYPE_B) { - if ((s->me_pre && s->last_non_b_pict_type == AV_PICTURE_TYPE_I) || + if ((s->me_pre && m->last_non_b_pict_type == AV_PICTURE_TYPE_I) || s->me_pre == 2) { s->avctx->execute(s->avctx, pre_estimate_motion_thread, &s->thread_context[0], NULL, context_count, sizeof(void*)); } diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h index d101c92cbb..7054881c05 100644 --- a/libavcodec/mpegvideoenc.h +++ b/libavcodec/mpegvideoenc.h @@ -96,6 +96,9 @@ typedef struct MPVMainEncContext { int stuffing_bits; ///< bits used for stuffing int next_lambda; ///< next lambda used for retrying to encode a frame int fixed_qscale; ///< fixed qscale if non zero + int last_lambda_for[5]; ///< last lambda for a specific pict type + int last_pict_type; //FIXME removes + int last_non_b_pict_type; ///< used for MPEG-4 gmc B-frames & ratecontrol RateControlContext rc_context; ///< contains stuff only accessed in ratecontrol.c int64_t mb_var_sum; ///< sum of MB variance for current frame diff --git a/libavcodec/msmpeg4enc.c b/libavcodec/msmpeg4enc.c index 78197756ae..bba0493f01 100644 --- a/libavcodec/msmpeg4enc.c +++ b/libavcodec/msmpeg4enc.c @@ -203,8 +203,8 @@ static void find_best_tables(MSMPEG4EncContext *ms) ms->rl_table_index = best; ms->rl_chroma_table_index = chroma_best; - if(s->pict_type != s->last_non_b_pict_type){ - ms->rl_table_index = 2; + if (s->pict_type != ms->m.last_non_b_pict_type) { + ms->rl_table_index= 2; if(s->pict_type==AV_PICTURE_TYPE_I) ms->rl_chroma_table_index = 1; else diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c index 0d2bf8fb30..b131f61b70 100644 --- a/libavcodec/ratecontrol.c +++ b/libavcodec/ratecontrol.c @@ -940,10 +940,10 @@ float ff_rate_estimate_qscale(MPVMainEncContext *const m, int dry_run) /* update predictors */ if (picture_number > 2 && !dry_run) { const int64_t last_var = - s->last_pict_type == AV_PICTURE_TYPE_I ? rcc->last_mb_var_sum + m->last_pict_type == AV_PICTURE_TYPE_I ? rcc->last_mb_var_sum : rcc->last_mc_mb_var_sum; av_assert1(m->frame_bits >= m->stuffing_bits); - update_predictor(&rcc->pred[s->last_pict_type], + update_predictor(&rcc->pred[m->last_pict_type], rcc->last_qscale, sqrt(last_var), m->frame_bits - m->stuffing_bits); diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c index b4a329158f..e6cf2a290c 100644 --- a/libavcodec/snowenc.c +++ b/libavcodec/snowenc.c @@ -2058,7 +2058,7 @@ redo_frame: } if(avctx->flags&AV_CODEC_FLAG_PASS1) ff_write_pass1_stats(&enc->m); - mpv->last_pict_type = mpv->pict_type; + enc->m.last_pict_type = mpv->pict_type; emms_c(); -- 2.45.2 [-- Attachment #57: 0056-avcodec-h261-ituh263-enc-Don-t-set-ptr_lastgob-unnec.patch --] [-- Type: text/x-patch, Size: 1567 bytes --] From fb595f470839cb25414e1c2b3f47ee371cd809ef Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Sun, 16 Mar 2025 15:52:29 +0100 Subject: [PATCH 56/77] avcodec/{h261,ituh263}enc: Don't set ptr_lastgob unnecessarily It will be overwritten later in encode_thread() anyway. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/h261enc.c | 3 --- libavcodec/ituh263enc.c | 2 -- 2 files changed, 5 deletions(-) diff --git a/libavcodec/h261enc.c b/libavcodec/h261enc.c index 81711b3a16..da8736a78c 100644 --- a/libavcodec/h261enc.c +++ b/libavcodec/h261enc.c @@ -74,9 +74,6 @@ static int h261_encode_picture_header(MPVMainEncContext *const m) align_put_bits(&s->pb); - /* Update the pointer to last GOB */ - s->ptr_lastgob = put_bits_ptr(&s->pb); - put_bits(&s->pb, 20, 0x10); /* PSC */ temp_ref = s->picture_number * 30000LL * s->avctx->time_base.num / diff --git a/libavcodec/ituh263enc.c b/libavcodec/ituh263enc.c index deaf7dc5c6..5a2af09b18 100644 --- a/libavcodec/ituh263enc.c +++ b/libavcodec/ituh263enc.c @@ -249,8 +249,6 @@ static int h263_encode_picture_header(MPVMainEncContext *const m) align_put_bits(&s->pb); - /* Update the pointer to last GOB */ - s->ptr_lastgob = put_bits_ptr(&s->pb); put_bits(&s->pb, 22, 0x20); /* PSC */ temp_ref= s->picture_number * (int64_t)coded_frame_rate * s->avctx->time_base.num / //FIXME use timestamp (coded_frame_rate_base * (int64_t)s->avctx->time_base.den); -- 2.45.2 [-- Attachment #58: 0057-avcodec-mpegvideoenc-Remove-declaration-of-inexisten.patch --] [-- Type: text/x-patch, Size: 1173 bytes --] From ec4ea816a792349a0e88c58a329704d045724367 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Tue, 18 Mar 2025 15:06:07 +0100 Subject: [PATCH 57/77] avcodec/mpegvideoenc: Remove declaration of inexistent function ff_MPV_encode_init_x86() has been renamed to ff_dct_encode_init_x86() in 6b33e918996e8a4e40071cb0a273c23de22ce1fc in FFmpeg; libav renamed it to ff_mpv_encode_init_x86() in commit 6b33e918996e8a4e40071cb0a273c23de22ce1fc. This hasn't been noticed in c1df467d73ee8c6e792ec27c126c5f0e2bc1af9d when merging. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpegvideoenc.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h index 7054881c05..a082830ab1 100644 --- a/libavcodec/mpegvideoenc.h +++ b/libavcodec/mpegvideoenc.h @@ -226,7 +226,6 @@ FF_MPV_OPT_CMP_FUNC, \ extern const AVClass ff_mpv_enc_class; int ff_mpv_encode_init(AVCodecContext *avctx); -void ff_mpv_encode_init_x86(MpegEncContext *s); int ff_mpv_encode_end(AVCodecContext *avctx); int ff_mpv_encode_picture(AVCodecContext *avctx, AVPacket *pkt, -- 2.45.2 [-- Attachment #59: 0058-avcodec-mpegvideo_enc-Call-ff_mpv_common_init-later.patch --] [-- Type: text/x-patch, Size: 2545 bytes --] From 2b38ab06b0fc8a778b10842eda2b37cd173d8639 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Tue, 18 Mar 2025 16:29:07 +0100 Subject: [PATCH 58/77] avcodec/mpegvideo_enc: Call ff_mpv_common_init() later Namely after the main slice context has already been initialized, so that this initialized state is directly copied to the newly created slice contexts without relying on it being copied by ff_update_duplicate_context(). This is in preparation for further commits. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpegvideo_enc.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 9f44c37b3d..f9b8d96c83 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -1011,9 +1011,6 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) /* init */ ff_mpv_idct_init(s); - if ((ret = ff_mpv_common_init(s)) < 0) - return ret; - ff_fdctdsp_init(&s->fdsp, avctx); ff_mpegvideoencdsp_init(&s->mpvencdsp, avctx); ff_pixblockdsp_init(&s->pdsp, avctx); @@ -1030,10 +1027,6 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) if (ret < 0) return ret; - ret = init_buffers(m, avctx); - if (ret < 0) - return ret; - ff_dct_encode_init(s); if (s->mpeg_quant || s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { @@ -1047,13 +1040,6 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) s->dct_unquantize_inter = s->dct_unquantize_mpeg1_inter; } - if (s->slice_context_count > 1) { - s->rtp_mode = 1; - - if (avctx->codec_id == AV_CODEC_ID_H263P) - s->h263_slice_structured = 1; - } - if (CONFIG_H263_ENCODER && s->out_format == FMT_H263) { ff_h263_encode_init(m); #if CONFIG_MSMPEG4ENC @@ -1062,6 +1048,23 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) #endif } + ret = ff_mpv_common_init(s); + if (ret < 0) + return ret; + + if (s->slice_context_count > 1) { + for (int i = 0; i < s->slice_context_count; ++i) { + s->thread_context[i]->rtp_mode = 1; + + if (avctx->codec_id == AV_CODEC_ID_H263P) + s->thread_context[i]->h263_slice_structured = 1; + } + } + + ret = init_buffers(m, avctx); + if (ret < 0) + return ret; + ret = ff_rate_control_init(m); if (ret < 0) return ret; -- 2.45.2 [-- Attachment #60: 0059-avcodec-mpeg4videoenc-Move-initializations-before-ff.patch --] [-- Type: text/x-patch, Size: 3892 bytes --] From 925461e15f60a5b44fc59acfc790fcb5a6e9e12f Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Tue, 18 Mar 2025 18:32:18 +0100 Subject: [PATCH 59/77] avcodec/mpeg4videoenc: Move initializations before ff_mpv_encode_init() This avoids relying on ff_update_duplicate_context() to copy these fields to the slice contexts. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/ituh263enc.c | 9 +++++---- libavcodec/mpeg4videoenc.c | 26 +++++++++++++------------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/libavcodec/ituh263enc.c b/libavcodec/ituh263enc.c index 5a2af09b18..876e178070 100644 --- a/libavcodec/ituh263enc.c +++ b/libavcodec/ituh263enc.c @@ -826,6 +826,11 @@ av_cold void ff_h263_encode_init(MPVMainEncContext *const m) s->me.mv_penalty = ff_h263_get_mv_penalty(); // FIXME exact table for MSMPEG4 & H.263+ + ff_h263dsp_init(&s->h263dsp); + + if (s->codec_id == AV_CODEC_ID_MPEG4) + return; + s->intra_ac_vlc_length =s->inter_ac_vlc_length = uni_h263_inter_rl_len; s->intra_ac_vlc_last_length=s->inter_ac_vlc_last_length= uni_h263_inter_rl_len + 128*64; if(s->h263_aic){ @@ -842,8 +847,6 @@ av_cold void ff_h263_encode_init(MPVMainEncContext *const m) // use fcodes >1 only for MPEG-4 & H.263 & H.263+ FIXME switch(s->codec_id){ - case AV_CODEC_ID_MPEG4: - break; case AV_CODEC_ID_H263P: if(s->umvplus) m->fcode_tab = umv_fcode_tab + MAX_MV; @@ -875,8 +878,6 @@ av_cold void ff_h263_encode_init(MPVMainEncContext *const m) m->encode_picture_header = h263_encode_picture_header; if (!s->encode_mb) s->encode_mb = h263_encode_mb; - - ff_h263dsp_init(&s->h263dsp); } void ff_h263_encode_mba(MpegEncContext *s) diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c index 4c31e7e9c8..ddb6958229 100644 --- a/libavcodec/mpeg4videoenc.c +++ b/libavcodec/mpeg4videoenc.c @@ -1305,6 +1305,19 @@ static av_cold int encode_init(AVCodecContext *avctx) m->encode_picture_header = mpeg4_encode_picture_header; s->encode_mb = mpeg4_encode_mb; + m->fcode_tab = fcode_tab + MAX_MV; + + s->min_qcoeff = -2048; + s->max_qcoeff = 2047; + s->intra_ac_vlc_length = uni_mpeg4_intra_rl_len; + s->intra_ac_vlc_last_length = uni_mpeg4_intra_rl_len + 128 * 64; + s->inter_ac_vlc_length = uni_mpeg4_inter_rl_len; + s->inter_ac_vlc_last_length = uni_mpeg4_inter_rl_len + 128 * 64; + s->luma_dc_vlc_length = uni_DCtab_lum_len; + s->ac_esc_length = 7 + 2 + 1 + 6 + 1 + 12 + 1; + s->y_dc_scale_table = ff_mpeg4_y_dc_scale_table; + s->c_dc_scale_table = ff_mpeg4_c_dc_scale_table; + ff_qpeldsp_init(&s->qdsp); if ((ret = ff_mpv_encode_init(avctx)) < 0) return ret; @@ -1322,19 +1335,6 @@ static av_cold int encode_init(AVCodecContext *avctx) m4->time_increment_bits = av_log2(avctx->time_base.den - 1) + 1; - m->fcode_tab = fcode_tab + MAX_MV; - - s->min_qcoeff = -2048; - s->max_qcoeff = 2047; - s->intra_ac_vlc_length = uni_mpeg4_intra_rl_len; - s->intra_ac_vlc_last_length = uni_mpeg4_intra_rl_len + 128 * 64; - s->inter_ac_vlc_length = uni_mpeg4_inter_rl_len; - s->inter_ac_vlc_last_length = uni_mpeg4_inter_rl_len + 128 * 64; - s->luma_dc_vlc_length = uni_DCtab_lum_len; - s->ac_esc_length = 7 + 2 + 1 + 6 + 1 + 12 + 1; - s->y_dc_scale_table = ff_mpeg4_y_dc_scale_table; - s->c_dc_scale_table = ff_mpeg4_c_dc_scale_table; - if (s->avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { s->avctx->extradata = av_malloc(1024); if (!s->avctx->extradata) -- 2.45.2 [-- Attachment #61: 0060-avcodec-mpegvideo-Move-me_pre-me_penalty_compensatio.patch --] [-- Type: text/x-patch, Size: 4171 bytes --] From f2ed672f2ef4f157a60ad15cc6833a9f9d56108c Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Wed, 19 Mar 2025 00:39:31 +0100 Subject: [PATCH 60/77] avcodec/mpegvideo: Move me_pre, me_penalty_compensation to MPVMainEncCtx Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/mpegvideo.h | 2 -- libavcodec/mpegvideo_enc.c | 8 ++++---- libavcodec/mpegvideoenc.h | 7 +++++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index c16fb1c703..1ff2924052 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -223,8 +223,6 @@ typedef struct MpegEncContext { uint64_t encoding_error[MPV_MAX_PLANES]; int motion_est; ///< ME algorithm - int me_penalty_compensation; - int me_pre; ///< prepass for motion estimation int mv_dir; #define MV_DIR_FORWARD 1 #define MV_DIR_BACKWARD 2 diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index f9b8d96c83..33241d6cb0 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -3735,11 +3735,11 @@ static int encode_picture(MPVMainEncContext *const m, const AVPacket *pkt) /* Estimate motion for every MB */ if(s->pict_type != AV_PICTURE_TYPE_I){ - s->lambda = (s->lambda * s->me_penalty_compensation + 128) >> 8; - s->lambda2 = (s->lambda2 * (int64_t) s->me_penalty_compensation + 128) >> 8; + s->lambda = (s->lambda * m->me_penalty_compensation + 128) >> 8; + s->lambda2 = (s->lambda2 * (int64_t) m->me_penalty_compensation + 128) >> 8; if (s->pict_type != AV_PICTURE_TYPE_B) { - if ((s->me_pre && m->last_non_b_pict_type == AV_PICTURE_TYPE_I) || - s->me_pre == 2) { + if ((m->me_pre && m->last_non_b_pict_type == AV_PICTURE_TYPE_I) || + m->me_pre == 2) { s->avctx->execute(s->avctx, pre_estimate_motion_thread, &s->thread_context[0], NULL, context_count, sizeof(void*)); } } diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h index a082830ab1..37e1546b50 100644 --- a/libavcodec/mpegvideoenc.h +++ b/libavcodec/mpegvideoenc.h @@ -101,6 +101,9 @@ typedef struct MPVMainEncContext { int last_non_b_pict_type; ///< used for MPEG-4 gmc B-frames & ratecontrol RateControlContext rc_context; ///< contains stuff only accessed in ratecontrol.c + int me_penalty_compensation; + int me_pre; ///< prepass for motion estimation + int64_t mb_var_sum; ///< sum of MB variance for current frame int64_t mc_mb_var_sum; ///< motion compensated MB variance for current frame @@ -218,8 +221,8 @@ FF_MPV_OPT_CMP_FUNC, \ { "zero", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_ZERO }, 0, 0, FF_MPV_OPT_FLAGS, .unit = "motion_est" }, \ { "epzs", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_EPZS }, 0, 0, FF_MPV_OPT_FLAGS, .unit = "motion_est" }, \ { "xone", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_XONE }, 0, 0, FF_MPV_OPT_FLAGS, .unit = "motion_est" }, \ -{"mepc", "Motion estimation bitrate penalty compensation (1.0 = 256)", FF_MPV_OFFSET(me_penalty_compensation), AV_OPT_TYPE_INT, {.i64 = 256 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ -{"mepre", "pre motion estimation", FF_MPV_OFFSET(me_pre), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"mepc", "Motion estimation bitrate penalty compensation (1.0 = 256)", FF_MPV_MAIN_OFFSET(me_penalty_compensation), AV_OPT_TYPE_INT, {.i64 = 256 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"mepre", "pre motion estimation", FF_MPV_MAIN_OFFSET(me_pre), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ {"intra_penalty", "Penalty for intra blocks in block decision", FF_MPV_OFFSET(intra_penalty), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX/2, FF_MPV_OPT_FLAGS }, \ {"sc_threshold", "Scene change threshold", FF_MPV_MAIN_OFFSET(scenechange_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ -- 2.45.2 [-- Attachment #62: 0061-avcodec-mpegvideo-Move-motion_est-to-MotionEstContex.patch --] [-- Type: text/x-patch, Size: 6387 bytes --] From 62330ba619b526ff730457e5f6084b91433425ff Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Wed, 19 Mar 2025 00:48:33 +0100 Subject: [PATCH 61/77] avcodec/mpegvideo: Move motion_est to MotionEstContext Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/motion_est.c | 7 ++++--- libavcodec/motion_est.h | 1 + libavcodec/mpegvideo.h | 1 - libavcodec/mpegvideoenc.h | 2 +- libavcodec/snowenc.c | 2 +- libavcodec/svq1enc.c | 5 +---- 6 files changed, 8 insertions(+), 10 deletions(-) diff --git a/libavcodec/motion_est.c b/libavcodec/motion_est.c index 7c08fe53eb..88164de6a5 100644 --- a/libavcodec/motion_est.c +++ b/libavcodec/motion_est.c @@ -919,7 +919,7 @@ void ff_estimate_p_frame_motion(MpegEncContext * s, s->mb_var [s->mb_stride * mb_y + mb_x] = (varc+128)>>8; c->mb_var_sum_temp += (varc+128)>>8; - if (s->motion_est != FF_ME_ZERO) { + if (c->motion_est != FF_ME_ZERO) { const int mot_stride = s->b8_stride; const int mot_xy = s->block_index[0]; @@ -1127,7 +1127,7 @@ static int estimate_motion_b(MpegEncContext *s, int mb_x, int mb_y, get_limits(s, 16*mb_x, 16*mb_y, 1); - if (s->motion_est != FF_ME_ZERO) { + if (c->motion_est != FF_ME_ZERO) { P_LEFT[0] = mv_table[mot_xy - 1][0]; P_LEFT[1] = mv_table[mot_xy - 1][1]; @@ -1599,8 +1599,9 @@ void ff_estimate_b_frame_motion(MpegEncContext * s, int ff_get_best_fcode(MPVMainEncContext *const m, const int16_t (*mv_table)[2], int type) { MpegEncContext *const s = &m->s; + MotionEstContext *const c = &s->me; - if (s->motion_est != FF_ME_ZERO) { + if (c->motion_est != FF_ME_ZERO) { int score[8]; int i, y, range= s->avctx->me_range ? s->avctx->me_range : (INT_MAX/2); const uint8_t * fcode_tab = m->fcode_tab; diff --git a/libavcodec/motion_est.h b/libavcodec/motion_est.h index d8a2cab3a0..5fa96161c6 100644 --- a/libavcodec/motion_est.h +++ b/libavcodec/motion_est.h @@ -48,6 +48,7 @@ typedef struct MPVMainEncContext MPVMainEncContext; */ typedef struct MotionEstContext { AVCodecContext *avctx; + int motion_est; ///< ME algorithm int skip; ///< set if ME is skipped for the current MB int co_located_mv[4][2]; ///< mv from last P-frame for direct mode ME int direct_basis_mv[4][2]; diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 1ff2924052..85227fdb8f 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -222,7 +222,6 @@ typedef struct MpegEncContext { uint8_t *mb_mean; ///< Table for MB luminance uint64_t encoding_error[MPV_MAX_PLANES]; - int motion_est; ///< ME algorithm int mv_dir; #define MV_DIR_FORWARD 1 #define MV_DIR_BACKWARD 2 diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h index 37e1546b50..bc8a3e80d5 100644 --- a/libavcodec/mpegvideoenc.h +++ b/libavcodec/mpegvideoenc.h @@ -217,7 +217,7 @@ FF_MPV_OPT_CMP_FUNC, \ #define FF_MPV_COMMON_MOTION_EST_OPTS \ { "mv0", "always try a mb with mv=<0,0>", 0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_MV0 }, 0, 0, FF_MPV_OPT_FLAGS, .unit = "mpv_flags" },\ -{"motion_est", "motion estimation algorithm", FF_MPV_OFFSET(motion_est), AV_OPT_TYPE_INT, {.i64 = FF_ME_EPZS }, FF_ME_ZERO, FF_ME_XONE, FF_MPV_OPT_FLAGS, .unit = "motion_est" }, \ +{"motion_est", "motion estimation algorithm", FF_MPV_OFFSET(me.motion_est), AV_OPT_TYPE_INT, {.i64 = FF_ME_EPZS }, FF_ME_ZERO, FF_ME_XONE, FF_MPV_OPT_FLAGS, .unit = "motion_est" }, \ { "zero", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_ZERO }, 0, 0, FF_MPV_OPT_FLAGS, .unit = "motion_est" }, \ { "epzs", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_EPZS }, 0, 0, FF_MPV_OPT_FLAGS, .unit = "motion_est" }, \ { "xone", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_XONE }, 0, 0, FF_MPV_OPT_FLAGS, .unit = "motion_est" }, \ diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c index e6cf2a290c..fc2a56a808 100644 --- a/libavcodec/snowenc.c +++ b/libavcodec/snowenc.c @@ -1866,7 +1866,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, mpv->b8_stride = 2 * mpv->mb_width + 1; mpv->f_code = 1; mpv->pict_type = pic->pict_type; - mpv->motion_est = enc->motion_est; + mpv->me.motion_est = enc->motion_est; mpv->me.scene_change_score = 0; mpv->me.dia_size = avctx->dia_size; mpv->quarter_sample = (s->avctx->flags & AV_CODEC_FLAG_QPEL)!=0; diff --git a/libavcodec/svq1enc.c b/libavcodec/svq1enc.c index 40e3fd0045..652dc11b03 100644 --- a/libavcodec/svq1enc.c +++ b/libavcodec/svq1enc.c @@ -96,8 +96,6 @@ typedef struct SVQ1EncContext { uint8_t *scratchbuf; - int motion_est; - SVQ1EncDSPContext svq1encdsp; } SVQ1EncContext; @@ -339,7 +337,6 @@ static int svq1_encode_plane(SVQ1EncContext *s, int plane, s->m.b8_stride = 2 * s->m.mb_width + 1; s->m.f_code = 1; s->m.pict_type = s->pict_type; - s->m.motion_est = s->motion_est; s->m.me.scene_change_score = 0; // s->m.out_format = FMT_H263; // s->m.unrestricted_mv = 1; @@ -719,7 +716,7 @@ static int svq1_encode_frame(AVCodecContext *avctx, AVPacket *pkt, #define OFFSET(x) offsetof(struct SVQ1EncContext, x) #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { - { "motion-est", "Motion estimation algorithm", OFFSET(motion_est), AV_OPT_TYPE_INT, { .i64 = FF_ME_EPZS }, FF_ME_ZERO, FF_ME_XONE, VE, .unit = "motion-est"}, + { "motion-est", "Motion estimation algorithm", OFFSET(m.me.motion_est), AV_OPT_TYPE_INT, { .i64 = FF_ME_EPZS }, FF_ME_ZERO, FF_ME_XONE, VE, .unit = "motion-est"}, { "zero", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_ZERO }, 0, 0, FF_MPV_OPT_FLAGS, .unit = "motion-est" }, { "epzs", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_EPZS }, 0, 0, FF_MPV_OPT_FLAGS, .unit = "motion-est" }, { "xone", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_XONE }, 0, 0, FF_MPV_OPT_FLAGS, .unit = "motion-est" }, -- 2.45.2 [-- Attachment #63: 0062-avcodec-motion_est-Don-t-use-MpegEncContext.avctx.patch --] [-- Type: text/x-patch, Size: 6683 bytes --] From b6a01ec0933a169f204bb225091032b03d18e781 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Wed, 19 Mar 2025 01:26:18 +0100 Subject: [PATCH 62/77] avcodec/motion_est: Don't use MpegEncContext.avctx Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/motion_est.c | 29 +++++++++++++++-------------- libavcodec/motion_est_template.c | 2 +- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/libavcodec/motion_est.c b/libavcodec/motion_est.c index 88164de6a5..ffad3dbc79 100644 --- a/libavcodec/motion_est.c +++ b/libavcodec/motion_est.c @@ -372,7 +372,7 @@ void ff_me_init_pic(MpegEncContext *s) MotionEstContext * const c= &s->me; /*FIXME s->no_rounding b_type*/ - if (s->avctx->flags & AV_CODEC_FLAG_QPEL) { + if (c->avctx->flags & AV_CODEC_FLAG_QPEL) { c->qpel_avg = s->qdsp.avg_qpel_pixels_tab; if (s->no_rounding) c->qpel_put = s->qdsp.put_no_rnd_qpel_pixels_tab; @@ -984,7 +984,7 @@ void ff_estimate_p_frame_motion(MpegEncContext * s, mx *= 1 << shift; my *= 1 << shift; } - if ((s->avctx->flags & AV_CODEC_FLAG_4MV) + if ((c->avctx->flags & AV_CODEC_FLAG_4MV) && !c->skip && varc>50<<8 && vard>10<<8){ if(h263_mv4_search(s, mx, my, shift) < INT_MAX) mb_type|=CANDIDATE_MB_TYPE_INTER4V; @@ -992,7 +992,7 @@ void ff_estimate_p_frame_motion(MpegEncContext * s, set_p_mv_tables(s, mx, my, 0); }else set_p_mv_tables(s, mx, my, 1); - if ((s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) + if ((c->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) && !c->skip){ //FIXME varc/d checks if(interlaced_search(s, 0, s->p_field_mv_table, s->p_field_select_table, mx, my, 0) < INT_MAX) mb_type |= CANDIDATE_MB_TYPE_INTER_I; @@ -1005,7 +1005,7 @@ void ff_estimate_p_frame_motion(MpegEncContext * s, if(c->avctx->me_sub_cmp != c->avctx->mb_cmp && !c->skip) dmin= get_mb_score(s, mx, my, 0, 0, 0, 16, 1); - if ((s->avctx->flags & AV_CODEC_FLAG_4MV) + if ((c->avctx->flags & AV_CODEC_FLAG_4MV) && !c->skip && varc>50<<8 && vard>10<<8){ int dmin4= h263_mv4_search(s, mx, my, shift); if(dmin4 < dmin){ @@ -1013,7 +1013,7 @@ void ff_estimate_p_frame_motion(MpegEncContext * s, dmin=dmin4; } } - if ((s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) + if ((c->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) && !c->skip){ //FIXME varc/d checks int dmin_i= interlaced_search(s, 0, s->p_field_mv_table, s->p_field_select_table, mx, my, 0); if(dmin_i < dmin){ @@ -1269,10 +1269,10 @@ static inline int bidir_refine(MpegEncContext * s, int mb_x, int mb_y) pred_bx, pred_by, 0, 16); - if(s->avctx->bidir_refine){ + if (c->avctx->bidir_refine) { int end; static const uint8_t limittab[5]={0,8,32,64,80}; - const int limit= limittab[s->avctx->bidir_refine]; + const int limit = limittab[c->avctx->bidir_refine]; static const int8_t vect[][4]={ { 0, 0, 0, 1}, { 0, 0, 0,-1}, { 0, 0, 1, 0}, { 0, 0,-1, 0}, { 0, 1, 0, 0}, { 0,-1, 0, 0}, { 1, 0, 0, 0}, {-1, 0, 0, 0}, @@ -1526,13 +1526,13 @@ void ff_estimate_b_frame_motion(MpegEncContext * s, c->skip=0; bmin = estimate_motion_b(s, mb_x, mb_y, s->b_back_mv_table, 2, s->b_code) + 2 * c->mb_penalty_factor; - ff_dlog(s->avctx, " %d %d ", s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1]); + ff_dlog(c->avctx, " %d %d ", s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1]); c->skip=0; fbmin= bidir_refine(s, mb_x, mb_y) + c->mb_penalty_factor; - ff_dlog(s->avctx, "%d %d %d %d\n", dmin, fmin, bmin, fbmin); + ff_dlog(c->avctx, "%d %d %d %d\n", dmin, fmin, bmin, fbmin); - if (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) { + if (c->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) { //FIXME mb type penalty c->skip=0; c->current_mv_penalty= c->mv_penalty[s->f_code] + MAX_DMV; @@ -1603,14 +1603,15 @@ int ff_get_best_fcode(MPVMainEncContext *const m, const int16_t (*mv_table)[2], if (c->motion_est != FF_ME_ZERO) { int score[8]; - int i, y, range= s->avctx->me_range ? s->avctx->me_range : (INT_MAX/2); + int i, y, range = c->avctx->me_range ? c->avctx->me_range : (INT_MAX/2); const uint8_t * fcode_tab = m->fcode_tab; int best_fcode=-1; int best_score=-10000000; if (s->msmpeg4_version != MSMP4_UNUSED) range= FFMIN(range, 16); - else if(s->codec_id == AV_CODEC_ID_MPEG2VIDEO && s->avctx->strict_std_compliance >= FF_COMPLIANCE_NORMAL) + else if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO && + c->avctx->strict_std_compliance >= FF_COMPLIANCE_NORMAL) range= FFMIN(range, 256); for(i=0; i<8; i++) score[i]= s->mb_num*(8-i); @@ -1661,11 +1662,11 @@ void ff_fix_long_p_mvs(MpegEncContext * s, int type) range = (((s->out_format == FMT_MPEG1 || s->msmpeg4_version != MSMP4_UNUSED) ? 8 : 16) << f_code); av_assert0(range <= 16 || s->msmpeg4_version == MSMP4_UNUSED); - av_assert0(range <=256 || !(s->codec_id == AV_CODEC_ID_MPEG2VIDEO && s->avctx->strict_std_compliance >= FF_COMPLIANCE_NORMAL)); + av_assert0(range <=256 || !(s->codec_id == AV_CODEC_ID_MPEG2VIDEO && c->avctx->strict_std_compliance >= FF_COMPLIANCE_NORMAL)); if(c->avctx->me_range && range > c->avctx->me_range) range= c->avctx->me_range; - if (s->avctx->flags & AV_CODEC_FLAG_4MV) { + if (c->avctx->flags & AV_CODEC_FLAG_4MV) { const int wrap= s->b8_stride; /* clip / convert to intra 8x8 type MVs */ diff --git a/libavcodec/motion_est_template.c b/libavcodec/motion_est_template.c index b2701aa32e..5498f9c982 100644 --- a/libavcodec/motion_est_template.c +++ b/libavcodec/motion_est_template.c @@ -906,7 +906,7 @@ static av_always_inline int epzs_motion_search_internal(MpegEncContext * s, int CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16, (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16) }else{ - if(dmin<((h*h*s->avctx->mv0_threshold)>>8) + if (dmin < ((h * h * c->avctx->mv0_threshold) >> 8) && ( P_LEFT[0] |P_LEFT[1] |P_TOP[0] |P_TOP[1] |P_TOPRIGHT[0]|P_TOPRIGHT[1])==0){ -- 2.45.2 [-- Attachment #64: 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".
next reply other threads:[~2025-03-19 21:19 UTC|newest] Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top 2025-03-19 21:18 Andreas Rheinhardt [this message] 2025-03-19 21:20 ` Andreas Rheinhardt 2025-03-22 0:34 ` Michael Niedermayer 2025-03-22 13:16 ` Andreas Rheinhardt
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=AS8P250MB0744A8DBC25ABEC4F82344B58FD92@AS8P250MB0744.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