mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-07-02 05:56:46 +08:00
avcodec/mpegvideo: Allocate ac_val jointly
They are currently allocated separately per slice; allocating them jointly allows to avoid saving them in ff_update_duplicate_context(). The way it is done also avoids allocating ac_val for encoders that don't need it (e.g. H.263 or H.263+ with AIC). This entailed moving setting nb_slices to ff_mpv_init_context_frame() which is called from ff_mpv_common_frame_size_change(). The resultant nb_slices will always be one when called from a decoder using ff_mpv_common_frame_size_change(). Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This commit is contained in:
@ -120,18 +120,6 @@ static av_cold int init_duplicate_context(MpegEncContext *s)
|
||||
return AVERROR(ENOMEM);
|
||||
s->block = s->blocks[0];
|
||||
|
||||
if (s->out_format == FMT_H263) {
|
||||
int mb_height = s->msmpeg4_version == MSMP4_VC1 ?
|
||||
FFALIGN(s->mb_height, 2) : s->mb_height;
|
||||
int y_size = s->b8_stride * (2 * mb_height + 1);
|
||||
int c_size = s->mb_stride * (mb_height + 1);
|
||||
int yc_size = y_size + 2 * c_size;
|
||||
/* ac values */
|
||||
if (!FF_ALLOCZ_TYPED_ARRAY(s->ac_val_base, yc_size))
|
||||
return AVERROR(ENOMEM);
|
||||
s->ac_val = s->ac_val_base + s->b8_stride + 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -171,7 +159,6 @@ static av_cold void free_duplicate_context(MpegEncContext *s)
|
||||
s->sc.linesize = 0;
|
||||
|
||||
av_freep(&s->blocks);
|
||||
av_freep(&s->ac_val_base);
|
||||
s->block = NULL;
|
||||
}
|
||||
|
||||
@ -192,7 +179,6 @@ static void backup_duplicate_context(MpegEncContext *bak, MpegEncContext *src)
|
||||
COPY(block);
|
||||
COPY(start_mb_y);
|
||||
COPY(end_mb_y);
|
||||
COPY(ac_val_base);
|
||||
COPY(ac_val);
|
||||
#undef COPY
|
||||
}
|
||||
@ -245,15 +231,34 @@ static av_cold void free_buffer_pools(BufferPoolContext *pools)
|
||||
|
||||
av_cold int ff_mpv_init_context_frame(MpegEncContext *s)
|
||||
{
|
||||
int nb_slices = (HAVE_THREADS &&
|
||||
s->avctx->active_thread_type & FF_THREAD_SLICE) ?
|
||||
s->avctx->thread_count : 1;
|
||||
BufferPoolContext *const pools = &s->buffer_pools;
|
||||
int y_size, c_size, yc_size, i, mb_array_size, mv_table_size, x, y;
|
||||
int mb_height;
|
||||
|
||||
if (s->encoding && s->avctx->slices)
|
||||
nb_slices = s->avctx->slices;
|
||||
|
||||
if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO && !s->progressive_sequence)
|
||||
s->mb_height = (s->height + 31) / 32 * 2;
|
||||
else
|
||||
s->mb_height = (s->height + 15) / 16;
|
||||
|
||||
if (nb_slices > MAX_THREADS || (nb_slices > s->mb_height && s->mb_height)) {
|
||||
int max_slices;
|
||||
if (s->mb_height)
|
||||
max_slices = FFMIN(MAX_THREADS, s->mb_height);
|
||||
else
|
||||
max_slices = MAX_THREADS;
|
||||
av_log(s->avctx, AV_LOG_WARNING, "too many threads/slices (%d),"
|
||||
" reducing to %d\n", nb_slices, max_slices);
|
||||
nb_slices = max_slices;
|
||||
}
|
||||
|
||||
s->slice_context_count = nb_slices;
|
||||
|
||||
/* VC-1 can change from being progressive to interlaced on a per-frame
|
||||
* basis. We therefore allocate certain buffers so big that they work
|
||||
* in both instances. */
|
||||
@ -332,6 +337,14 @@ av_cold int ff_mpv_init_context_frame(MpegEncContext *s)
|
||||
}
|
||||
|
||||
if (s->h263_pred || s->h263_aic || !s->encoding) {
|
||||
size_t allslice_yc_size = yc_size * (s->encoding ? nb_slices : 1);
|
||||
if (s->out_format == FMT_H263) {
|
||||
/* ac values */
|
||||
if (!FF_ALLOCZ_TYPED_ARRAY(s->ac_val_base, allslice_yc_size))
|
||||
return AVERROR(ENOMEM);
|
||||
s->ac_val = s->ac_val_base + s->b8_stride + 1;
|
||||
}
|
||||
|
||||
/* dc values */
|
||||
// MN: we need these for error resilience of intra-frames
|
||||
// Allocating them unconditionally for decoders also means
|
||||
@ -381,14 +394,8 @@ av_cold int ff_mpv_init_context_frame(MpegEncContext *s)
|
||||
*/
|
||||
av_cold int ff_mpv_common_init(MpegEncContext *s)
|
||||
{
|
||||
int nb_slices = (HAVE_THREADS &&
|
||||
s->avctx->active_thread_type & FF_THREAD_SLICE) ?
|
||||
s->avctx->thread_count : 1;
|
||||
int ret;
|
||||
|
||||
if (s->encoding && s->avctx->slices)
|
||||
nb_slices = s->avctx->slices;
|
||||
|
||||
if (s->avctx->pix_fmt == AV_PIX_FMT_NONE) {
|
||||
av_log(s->avctx, AV_LOG_ERROR,
|
||||
"decoding to AV_PIX_FMT_NONE is not supported.\n");
|
||||
@ -411,20 +418,8 @@ av_cold int ff_mpv_common_init(MpegEncContext *s)
|
||||
if ((ret = ff_mpv_init_context_frame(s)))
|
||||
goto fail;
|
||||
|
||||
if (nb_slices > MAX_THREADS || (nb_slices > s->mb_height && s->mb_height)) {
|
||||
int max_slices;
|
||||
if (s->mb_height)
|
||||
max_slices = FFMIN(MAX_THREADS, s->mb_height);
|
||||
else
|
||||
max_slices = MAX_THREADS;
|
||||
av_log(s->avctx, AV_LOG_WARNING, "too many threads/slices (%d),"
|
||||
" reducing to %d\n", nb_slices, max_slices);
|
||||
nb_slices = max_slices;
|
||||
}
|
||||
|
||||
s->context_initialized = 1;
|
||||
s->thread_context[0] = s;
|
||||
s->slice_context_count = nb_slices;
|
||||
|
||||
// if (s->width && s->height) {
|
||||
if (!s->encoding) {
|
||||
@ -450,6 +445,7 @@ av_cold void ff_mpv_free_context_frame(MpegEncContext *s)
|
||||
for (int j = 0; j < 2; j++)
|
||||
s->p_field_mv_table[i][j] = NULL;
|
||||
|
||||
av_freep(&s->ac_val_base);
|
||||
av_freep(&s->dc_val_base);
|
||||
av_freep(&s->coded_block_base);
|
||||
av_freep(&s->mbintra_table);
|
||||
|
@ -518,24 +518,36 @@ static av_cold int init_slice_buffers(MPVMainEncContext *const m)
|
||||
static_assert(DCT_ERROR_SIZE * MAX_THREADS + ALIGN - 1 <= SIZE_MAX,
|
||||
"Need checks for potential overflow.");
|
||||
unsigned nb_slices = s->c.slice_context_count;
|
||||
char *dct_error = NULL;
|
||||
|
||||
if (!m->noise_reduction)
|
||||
return 0;
|
||||
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 (!FF_ALLOCZ_TYPED_ARRAY(s->dct_offset, 2))
|
||||
return AVERROR(ENOMEM);
|
||||
char *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;
|
||||
const int y_size = s->c.b8_stride * (2 * s->c.mb_height + 1);
|
||||
const int c_size = s->c.mb_stride * (s->c.mb_height + 1);
|
||||
const int yc_size = y_size + 2 * c_size;
|
||||
ptrdiff_t offset = 0;
|
||||
|
||||
for (unsigned i = 0; i < nb_slices; ++i) {
|
||||
MPVEncContext *const s2 = s->c.enc_contexts[i];
|
||||
|
||||
s2->dct_offset = s->dct_offset;
|
||||
s2->dct_error_sum = (void*)dct_error;
|
||||
dct_error += DCT_ERROR_SIZE;
|
||||
if (dct_error) {
|
||||
s2->dct_offset = s->dct_offset;
|
||||
s2->dct_error_sum = (void*)dct_error;
|
||||
dct_error += DCT_ERROR_SIZE;
|
||||
}
|
||||
|
||||
if (s2->c.ac_val) {
|
||||
s2->c.ac_val += offset;
|
||||
offset += yc_size;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user