diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 1fae5fbeb0..60abe08d7a 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -444,7 +444,65 @@ static av_cold int init_matrices(MPVMainEncContext *const m, AVCodecContext *avc return 0; } -static av_cold int init_buffers(MPVMainEncContext *const m, AVCodecContext *avctx) +static av_cold int init_buffers(MPVMainEncContext *const m) +{ + MPVEncContext *const s = &m->s; + int has_b_frames = !!m->max_b_frames; + int16_t (*mv_table)[2]; + + /* Allocate MB type table */ + unsigned mb_array_size = s->c.mb_stride * s->c.mb_height; + s->mb_type = av_calloc(mb_array_size, 3 * sizeof(*s->mb_type) + sizeof(*s->mb_mean)); + if (!s->mb_type) + return AVERROR(ENOMEM); + s->mc_mb_var = s->mb_type + mb_array_size; + s->mb_var = s->mc_mb_var + mb_array_size; + s->mb_mean = (uint8_t*)(s->mb_var + mb_array_size); + + if (!FF_ALLOCZ_TYPED_ARRAY(s->lambda_table, mb_array_size)) + return AVERROR(ENOMEM); + + unsigned mv_table_size = (s->c.mb_height + 2) * s->c.mb_stride + 1; + unsigned nb_mv_tables = 1 + 5 * has_b_frames; + if (s->c.codec_id == AV_CODEC_ID_MPEG4 || + (s->c.avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)) { + nb_mv_tables += 8 * has_b_frames; + s->p_field_select_table[0] = av_calloc(mv_table_size, 2 * (2 + 4 * has_b_frames)); + if (!s->p_field_select_table[0]) + return AVERROR(ENOMEM); + s->p_field_select_table[1] = s->p_field_select_table[0] + 2 * mv_table_size; + } + + mv_table = av_calloc(mv_table_size, nb_mv_tables * sizeof(*mv_table)); + if (!mv_table) + return AVERROR(ENOMEM); + m->mv_table_base = mv_table; + mv_table += s->c.mb_stride + 1; + + s->p_mv_table = mv_table; + if (has_b_frames) { + s->b_forw_mv_table = mv_table += mv_table_size; + s->b_back_mv_table = mv_table += mv_table_size; + s->b_bidir_forw_mv_table = mv_table += mv_table_size; + s->b_bidir_back_mv_table = mv_table += mv_table_size; + s->b_direct_mv_table = mv_table += mv_table_size; + + if (s->p_field_select_table[1]) { // MPEG-4 or INTERLACED_ME above + uint8_t *field_select = s->p_field_select_table[1]; + for (int j = 0; j < 2; j++) { + for (int k = 0; k < 2; k++) { + for (int l = 0; l < 2; l++) + s->b_field_mv_table[j][k][l] = mv_table += mv_table_size; + s->b_field_select_table[j][k] = field_select += 2 * mv_table_size; + } + } + } + } + + return 0; +} + +static av_cold int init_slice_buffers(MPVMainEncContext *const m) { MPVEncContext *const s = &m->s; // Align the following per-thread buffers to avoid false sharing. @@ -459,85 +517,26 @@ static av_cold int init_buffers(MPVMainEncContext *const m, AVCodecContext *avct }; static_assert(DCT_ERROR_SIZE * MAX_THREADS + ALIGN - 1 <= SIZE_MAX, "Need checks for potential overflow."); - unsigned nb_slices = s->c.slice_context_count, mv_table_size, mb_array_size; - char *dct_error = NULL; - int has_b_frames = !!m->max_b_frames, nb_mv_tables = 1 + 5 * has_b_frames; - int16_t (*mv_table)[2]; + unsigned nb_slices = s->c.slice_context_count; - if (m->noise_reduction) { - if (!FF_ALLOCZ_TYPED_ARRAY(s->dct_offset, 2)) - return AVERROR(ENOMEM); - dct_error = av_mallocz(ALIGN - 1 + nb_slices * DCT_ERROR_SIZE); - if (!dct_error) - return AVERROR(ENOMEM); - m->dct_error_sum_base = dct_error; - dct_error += FFALIGN((uintptr_t)dct_error, ALIGN) - (uintptr_t)dct_error; - } + if (!m->noise_reduction) + return 0; - /* Allocate MB type table */ - mb_array_size = s->c.mb_stride * s->c.mb_height; - s->mb_type = av_calloc(mb_array_size, 3 * sizeof(*s->mb_type) + sizeof(*s->mb_mean)); - if (!s->mb_type) + if (!FF_ALLOCZ_TYPED_ARRAY(s->dct_offset, 2)) return AVERROR(ENOMEM); - if (!FF_ALLOCZ_TYPED_ARRAY(s->lambda_table, mb_array_size)) + char *dct_error = av_mallocz(ALIGN - 1 + nb_slices * DCT_ERROR_SIZE); + if (!dct_error) return AVERROR(ENOMEM); - - mv_table_size = (s->c.mb_height + 2) * s->c.mb_stride + 1; - if (s->c.codec_id == AV_CODEC_ID_MPEG4 || - (s->c.avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)) { - nb_mv_tables += 8 * has_b_frames; - if (!ALLOCZ_ARRAYS(s->p_field_select_table[0], 2 * (2 + 4 * has_b_frames), mv_table_size)) - 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->c.mb_stride + 1; + m->dct_error_sum_base = dct_error; + dct_error += FFALIGN((uintptr_t)dct_error, ALIGN) - (uintptr_t)dct_error; for (unsigned i = 0; i < nb_slices; ++i) { MPVEncContext *const s2 = s->c.enc_contexts[i]; - int16_t (*tmp_mv_table)[2] = mv_table; - if (dct_error) { - s2->dct_offset = s->dct_offset; - s2->dct_error_sum = (void*)dct_error; - dct_error += DCT_ERROR_SIZE; - } - - s2->mb_type = s->mb_type; - s2->mc_mb_var = s2->mb_type + mb_array_size; - s2->mb_var = s2->mc_mb_var + mb_array_size; - s2->mb_mean = (uint8_t*)(s2->mb_var + mb_array_size); - s2->lambda_table = s->lambda_table; - - s2->p_mv_table = tmp_mv_table; - if (has_b_frames) { - s2->b_forw_mv_table = tmp_mv_table += mv_table_size; - s2->b_back_mv_table = tmp_mv_table += mv_table_size; - s2->b_bidir_forw_mv_table = tmp_mv_table += mv_table_size; - s2->b_bidir_back_mv_table = tmp_mv_table += mv_table_size; - s2->b_direct_mv_table = tmp_mv_table += mv_table_size; - } - - if (s->p_field_select_table[0]) { // MPEG-4 or INTERLACED_ME above - uint8_t *field_select = s->p_field_select_table[0]; - s2->p_field_select_table[0] = field_select; - s2->p_field_select_table[1] = field_select += 2 * mv_table_size; - - if (has_b_frames) { - for (int j = 0; j < 2; j++) { - for (int k = 0; k < 2; k++) { - for (int l = 0; l < 2; l++) - s2->b_field_mv_table[j][k][l] = tmp_mv_table += mv_table_size; - s2->b_field_select_table[j][k] = field_select += 2 * mv_table_size; - } - } - } - } + s2->dct_offset = s->dct_offset; + s2->dct_error_sum = (void*)dct_error; + dct_error += DCT_ERROR_SIZE; } - return 0; } @@ -1059,20 +1058,19 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) ret = ff_mpv_common_init(&s->c); if (ret < 0) return ret; + ret = init_buffers(m); + if (ret < 0) + return ret; + if (s->c.slice_context_count > 1) { + s->rtp_mode = 1; + if (avctx->codec_id == AV_CODEC_ID_H263P) + s->c.h263_slice_structured = 1; + } ret = ff_mpv_init_duplicate_contexts(&s->c); if (ret < 0) return ret; - if (s->c.slice_context_count > 1) { - for (int i = 0; i < s->c.slice_context_count; ++i) { - s->c.enc_contexts[i]->rtp_mode = 1; - - if (avctx->codec_id == AV_CODEC_ID_H263P) - s->c.enc_contexts[i]->c.h263_slice_structured = 1; - } - } - - ret = init_buffers(m, avctx); + ret = init_slice_buffers(m); if (ret < 0) return ret;