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