1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-12-23 12:43:46 +02:00

mpegvideo: add reinit function for frame parameter changes

This is mainly required for frame parameter changes during frame based
multithreading but single threaded usage profits too from avoiding
ff_MPV_common_end()/ff_MPV_common_init() cycles.
This commit is contained in:
Janne Grunau 2012-09-05 20:40:12 +02:00
parent 1b3439b305
commit 435c0b87d2
2 changed files with 101 additions and 4 deletions

View File

@ -1001,6 +1001,77 @@ static int free_context_frame(MpegEncContext *s)
return 0; return 0;
} }
int ff_MPV_common_frame_size_change(MpegEncContext *s)
{
int i, err = 0;
if (s->slice_context_count > 1) {
for (i = 0; i < s->slice_context_count; i++) {
free_duplicate_context(s->thread_context[i]);
}
for (i = 1; i < s->slice_context_count; i++) {
av_freep(&s->thread_context[i]);
}
} else
free_duplicate_context(s);
free_context_frame(s);
if (s->picture)
for (i = 0; i < s->picture_count; i++) {
s->picture[i].needs_realloc = 1;
}
s->last_picture_ptr =
s->next_picture_ptr =
s->current_picture_ptr = NULL;
// init
if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO && !s->progressive_sequence)
s->mb_height = (s->height + 31) / 32 * 2;
else if (s->codec_id != AV_CODEC_ID_H264)
s->mb_height = (s->height + 15) / 16;
if ((s->width || s->height) &&
av_image_check_size(s->width, s->height, 0, s->avctx))
return AVERROR_INVALIDDATA;
if ((err = init_context_frame(s)))
goto fail;
s->thread_context[0] = s;
if (s->width && s->height) {
int nb_slices = s->slice_context_count;
if (nb_slices > 1) {
for (i = 1; i < nb_slices; i++) {
s->thread_context[i] = av_malloc(sizeof(MpegEncContext));
memcpy(s->thread_context[i], s, sizeof(MpegEncContext));
}
for (i = 0; i < nb_slices; i++) {
if (init_duplicate_context(s->thread_context[i], s) < 0)
goto fail;
s->thread_context[i]->start_mb_y =
(s->mb_height * (i) + nb_slices / 2) / nb_slices;
s->thread_context[i]->end_mb_y =
(s->mb_height * (i + 1) + nb_slices / 2) / nb_slices;
}
} else {
if (init_duplicate_context(s, s) < 0)
goto fail;
s->start_mb_y = 0;
s->end_mb_y = s->mb_height;
}
s->slice_context_count = nb_slices;
}
return 0;
fail:
ff_MPV_common_end(s);
return err;
}
/* init common structure for both encoder and decoder */ /* init common structure for both encoder and decoder */
void ff_MPV_common_end(MpegEncContext *s) void ff_MPV_common_end(MpegEncContext *s)
{ {
@ -1155,7 +1226,17 @@ void ff_release_unused_pictures(MpegEncContext*s, int remove_current)
} }
} }
int ff_find_unused_picture(MpegEncContext *s, int shared) static inline int pic_is_unused(MpegEncContext *s, Picture *pic)
{
if (pic->f.data[0] == NULL)
return 1;
if (pic->needs_realloc)
if (!pic->owner2 || pic->owner2 == s)
return 1;
return 0;
}
static int find_unused_picture(MpegEncContext *s, int shared)
{ {
int i; int i;
@ -1166,11 +1247,11 @@ int ff_find_unused_picture(MpegEncContext *s, int shared)
} }
} else { } else {
for (i = s->picture_range_start; i < s->picture_range_end; i++) { for (i = s->picture_range_start; i < s->picture_range_end; i++) {
if (s->picture[i].f.data[0] == NULL && s->picture[i].f.type != 0) if (pic_is_unused(s, &s->picture[i]) && s->picture[i].f.type != 0)
return i; // FIXME return i; // FIXME
} }
for (i = s->picture_range_start; i < s->picture_range_end; i++) { for (i = s->picture_range_start; i < s->picture_range_end; i++) {
if (s->picture[i].f.data[0] == NULL) if (pic_is_unused(s, &s->picture[i]))
return i; return i;
} }
} }
@ -1178,6 +1259,20 @@ int ff_find_unused_picture(MpegEncContext *s, int shared)
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
} }
int ff_find_unused_picture(MpegEncContext *s, int shared)
{
int ret = find_unused_picture(s, shared);
if (ret >= 0 && ret < s->picture_range_end) {
if (s->picture[ret].needs_realloc) {
s->picture[ret].needs_realloc = 0;
free_picture(s, &s->picture[ret]);
avcodec_get_frame_defaults(&s->picture[ret].f);
}
}
return ret;
}
static void update_noise_reduction(MpegEncContext *s) static void update_noise_reduction(MpegEncContext *s)
{ {
int intra, i; int intra, i;
@ -1225,7 +1320,7 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
if (s->picture[i].owner2 == s && s->picture[i].f.data[0] && if (s->picture[i].owner2 == s && s->picture[i].f.data[0] &&
&s->picture[i] != s->last_picture_ptr && &s->picture[i] != s->last_picture_ptr &&
&s->picture[i] != s->next_picture_ptr && &s->picture[i] != s->next_picture_ptr &&
s->picture[i].f.reference) { s->picture[i].f.reference && !s->picture[i].needs_realloc) {
if (!(avctx->active_thread_type & FF_THREAD_FRAME)) if (!(avctx->active_thread_type & FF_THREAD_FRAME))
av_log(avctx, AV_LOG_ERROR, av_log(avctx, AV_LOG_ERROR,
"releasing zombie picture\n"); "releasing zombie picture\n");

View File

@ -139,6 +139,7 @@ typedef struct Picture{
int32_t *mb_cmp_score; ///< Table for MB cmp scores, for mb decision FIXME remove int32_t *mb_cmp_score; ///< Table for MB cmp scores, for mb decision FIXME remove
int b_frame_score; /* */ int b_frame_score; /* */
struct MpegEncContext *owner2; ///< pointer to the MpegEncContext that allocated this picture struct MpegEncContext *owner2; ///< pointer to the MpegEncContext that allocated this picture
int needs_realloc; ///< Picture needs to be reallocated (eg due to a frame size change)
} Picture; } Picture;
/** /**
@ -748,6 +749,7 @@ void ff_MPV_common_defaults(MpegEncContext *s);
void ff_MPV_decode_defaults(MpegEncContext *s); void ff_MPV_decode_defaults(MpegEncContext *s);
int ff_MPV_common_init(MpegEncContext *s); int ff_MPV_common_init(MpegEncContext *s);
int ff_MPV_common_frame_size_change(MpegEncContext *s);
void ff_MPV_common_end(MpegEncContext *s); void ff_MPV_common_end(MpegEncContext *s);
void ff_MPV_decode_mb(MpegEncContext *s, DCTELEM block[12][64]); void ff_MPV_decode_mb(MpegEncContext *s, DCTELEM block[12][64]);
int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx); int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx);