From 881a5e047dc78ec9ab771817497dffec503d77ee Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Sun, 1 Jan 2012 20:24:24 +0100 Subject: mpegenc: use avctx->slices as number of slices Adds a new member to MpegEncContext to hold the number of used slice contexts. Fixes segfaults with '-threads 17 -thread_type slice' and fate-vsynth{1,2}-mpeg{2,4}thread{,_ilace} with --disable-pthreads. --- libavcodec/h264.c | 9 ++++---- libavcodec/mpeg12.c | 4 +++- libavcodec/mpegvideo.c | 53 ++++++++++++++++++++++++---------------------- libavcodec/mpegvideo.h | 1 + libavcodec/mpegvideo_enc.c | 5 +++-- libavcodec/options.c | 2 +- tests/codec-regression.sh | 6 +++--- 7 files changed, 43 insertions(+), 37 deletions(-) diff --git a/libavcodec/h264.c b/libavcodec/h264.c index 2bde0fec2a..316a57d75e 100644 --- a/libavcodec/h264.c +++ b/libavcodec/h264.c @@ -1280,7 +1280,6 @@ int ff_h264_frame_start(H264Context *h){ MpegEncContext * const s = &h->s; int i; const int pixel_shift = h->pixel_shift; - int thread_count = (s->avctx->active_thread_type & FF_THREAD_SLICE) ? s->avctx->thread_count : 1; if(MPV_frame_start(s, s->avctx) < 0) return -1; @@ -1309,7 +1308,7 @@ int ff_h264_frame_start(H264Context *h){ /* can't be in alloc_tables because linesize isn't known there. * FIXME: redo bipred weight to not require extra buffer? */ - for(i = 0; i < thread_count; i++) + for(i = 0; i < s->slice_context_count; i++) if(h->thread_context[i] && !h->thread_context[i]->s.obmc_scratchpad) h->thread_context[i]->s.obmc_scratchpad = av_malloc(16*6*s->linesize); @@ -2826,7 +2825,7 @@ static int decode_slice_header(H264Context *h, H264Context *h0){ return -1; } } else { - for(i = 1; i < s->avctx->thread_count; i++) { + for(i = 1; i < s->slice_context_count; i++) { H264Context *c; c = h->thread_context[i] = av_malloc(sizeof(H264Context)); memcpy(c, h->s.thread_context[i], sizeof(MpegEncContext)); @@ -2839,7 +2838,7 @@ static int decode_slice_header(H264Context *h, H264Context *h0){ clone_tables(c, h, i); } - for(i = 0; i < s->avctx->thread_count; i++) + for(i = 0; i < s->slice_context_count; i++) if (context_init(h->thread_context[i]) < 0) { av_log(h->s.avctx, AV_LOG_ERROR, "context_init() failed.\n"); return -1; @@ -3742,7 +3741,7 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size){ int nals_needed=0; ///< number of NALs that need decoding before the next frame thread starts int nal_index; - h->max_contexts = (HAVE_THREADS && (s->avctx->active_thread_type&FF_THREAD_SLICE)) ? avctx->thread_count : 1; + h->max_contexts = s->slice_context_count; if(!(s->flags2 & CODEC_FLAG2_CHUNKS)){ h->current_slice = 0; if (!s->first_field) diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c index 48860cf33a..2019512839 100644 --- a/libavcodec/mpeg12.c +++ b/libavcodec/mpeg12.c @@ -2428,7 +2428,9 @@ static int decode_chunks(AVCodecContext *avctx, } if (HAVE_THREADS && (avctx->active_thread_type & FF_THREAD_SLICE)) { - int threshold= (s2->mb_height * s->slice_count + avctx->thread_count / 2) / avctx->thread_count; + int threshold = (s2->mb_height * s->slice_count + + s2->slice_context_count / 2) / + s2->slice_context_count; if (threshold <= mb_y) { MpegEncContext *thread_context = s2->thread_context[s->slice_count]; diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 214b64ec3b..a2aa257f89 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -637,6 +637,8 @@ void MPV_common_defaults(MpegEncContext *s) s->picture_range_start = 0; s->picture_range_end = MAX_PICTURE_COUNT; + + s->slice_context_count = 1; } /** @@ -655,11 +657,13 @@ void MPV_decode_defaults(MpegEncContext *s) */ av_cold int MPV_common_init(MpegEncContext *s) { - int y_size, c_size, yc_size, i, mb_array_size, mv_table_size, x, y, - threads = (s->encoding || - (HAVE_THREADS && - s->avctx->active_thread_type & FF_THREAD_SLICE)) ? - s->avctx->thread_count : 1; + int y_size, c_size, yc_size, i, mb_array_size, mv_table_size, x, y; + int nb_slices = (HAVE_THREADS && + s->avctx->active_thread_type & FF_THREAD_SLICE) ? + s->avctx->thread_count : 1; + + if (s->encoding && s->avctx->slices) + nb_slices = s->avctx->slices; if (s->codec_id == CODEC_ID_MPEG2VIDEO && !s->progressive_sequence) s->mb_height = (s->height + 31) / 32 * 2; @@ -672,14 +676,15 @@ av_cold int MPV_common_init(MpegEncContext *s) return -1; } - if ((s->encoding || (s->avctx->active_thread_type & FF_THREAD_SLICE)) && - (s->avctx->thread_count > MAX_THREADS || - (s->avctx->thread_count > s->mb_height && s->mb_height))) { - int max_threads = FFMIN(MAX_THREADS, s->mb_height); - av_log(s->avctx, AV_LOG_WARNING, - "too many threads (%d), reducing to %d\n", - s->avctx->thread_count, max_threads); - threads = max_threads; + 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; } if ((s->width || s->height) && @@ -885,22 +890,19 @@ av_cold int MPV_common_init(MpegEncContext *s) s->thread_context[0] = s; if (s->width && s->height) { - if (s->encoding || (HAVE_THREADS && - s->avctx->active_thread_type&FF_THREAD_SLICE)) { - for (i = 1; i < threads; i++) { + 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 < threads; i++) { + 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) + s->avctx->thread_count / 2) / - s->avctx->thread_count; + (s->mb_height * (i) + nb_slices / 2) / nb_slices; s->thread_context[i]->end_mb_y = - (s->mb_height * (i + 1) + s->avctx->thread_count / 2) / - s->avctx->thread_count; + (s->mb_height * (i + 1) + nb_slices / 2) / nb_slices; } } else { if (init_duplicate_context(s, s) < 0) @@ -908,6 +910,7 @@ av_cold int MPV_common_init(MpegEncContext *s) s->start_mb_y = 0; s->end_mb_y = s->mb_height; } + s->slice_context_count = nb_slices; } return 0; @@ -921,14 +924,14 @@ void MPV_common_end(MpegEncContext *s) { int i, j, k; - if (s->encoding || (HAVE_THREADS && - s->avctx->active_thread_type & FF_THREAD_SLICE)) { - for (i = 0; i < s->avctx->thread_count; i++) { + 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->avctx->thread_count; i++) { + for (i = 1; i < s->slice_context_count; i++) { av_freep(&s->thread_context[i]); } + s->slice_context_count = 1; } else free_duplicate_context(s); av_freep(&s->parse_context.buffer); diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 6483893c1a..3473e6d8f7 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -268,6 +268,7 @@ typedef struct MpegEncContext { int start_mb_y; ///< start mb_y of this thread (so current thread should process start_mb_y <= row < end_mb_y) int end_mb_y; ///< end mb_y of this thread (so current thread should process start_mb_y <= row < end_mb_y) struct MpegEncContext *thread_context[MAX_THREADS]; + int slice_context_count; ///< number of used thread_contexts /** * copy of the previous picture structure. diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index af303d80cd..84a5cdaac8 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -1428,7 +1428,8 @@ int MPV_encode_picture(AVCodecContext *avctx, { MpegEncContext *s = avctx->priv_data; AVFrame *pic_arg = data; - int i, stuffing_count, context_count = avctx->thread_count; + int i, stuffing_count; + int context_count = s->slice_context_count; for (i = 0; i < context_count; i++) { int start_y = s->thread_context[i]->start_mb_y; @@ -3059,7 +3060,7 @@ static int encode_picture(MpegEncContext *s, int picture_number) { int i; int bits; - int context_count = s->avctx->thread_count; + int context_count = s->slice_context_count; s->picture_number = picture_number; diff --git a/libavcodec/options.c b/libavcodec/options.c index 4ac92fd29e..a99aed7ad1 100644 --- a/libavcodec/options.c +++ b/libavcodec/options.c @@ -506,7 +506,7 @@ static const AVOption options[]={ {"cholesky", NULL, 0, AV_OPT_TYPE_CONST, {.dbl = AV_LPC_TYPE_CHOLESKY }, INT_MIN, INT_MAX, A|E, "lpc_type"}, {"lpc_passes", "deprecated, use flac-specific options", OFFSET(lpc_passes), AV_OPT_TYPE_INT, {.dbl = -1 }, INT_MIN, INT_MAX, A|E}, #endif -{"slices", "number of slices, used in parallelized decoding", OFFSET(slices), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, V|E}, +{"slices", "number of slices, used in parallelized encoding", OFFSET(slices), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, V|E}, {"thread_type", "select multithreading type", OFFSET(thread_type), AV_OPT_TYPE_FLAGS, {.dbl = FF_THREAD_SLICE|FF_THREAD_FRAME }, 0, INT_MAX, V|E|D, "thread_type"}, {"slice", NULL, 0, AV_OPT_TYPE_CONST, {.dbl = FF_THREAD_SLICE }, INT_MIN, INT_MAX, V|E|D, "thread_type"}, {"frame", NULL, 0, AV_OPT_TYPE_CONST, {.dbl = FF_THREAD_FRAME }, INT_MIN, INT_MAX, V|E|D, "thread_type"}, diff --git a/tests/codec-regression.sh b/tests/codec-regression.sh index e20bf6420d..220593b17f 100755 --- a/tests/codec-regression.sh +++ b/tests/codec-regression.sh @@ -62,13 +62,13 @@ fi if [ -n "$do_mpeg2thread" ] ; then # mpeg2 encoding interlaced -do_video_encoding mpeg2thread.mpg "-qscale 10 -vcodec mpeg2video -f mpeg1video -bf 2 -flags +ildct+ilme -threads 2" +do_video_encoding mpeg2thread.mpg "-qscale 10 -vcodec mpeg2video -f mpeg1video -bf 2 -flags +ildct+ilme -threads 2 -slices 2" do_video_decoding fi if [ -n "$do_mpeg2thread_ilace" ]; then # mpeg2 encoding interlaced using intra vlc -do_video_encoding mpeg2threadivlc.mpg "-qscale 10 -vcodec mpeg2video -f mpeg1video -bf 2 -flags +ildct+ilme -flags2 +ivlc -threads 2" +do_video_encoding mpeg2threadivlc.mpg "-qscale 10 -vcodec mpeg2video -f mpeg1video -bf 2 -flags +ildct+ilme -flags2 +ivlc -threads 2 -slices 2" do_video_decoding fi @@ -143,7 +143,7 @@ do_video_decoding fi if [ -n "$do_mpeg4thread" ] ; then -do_video_encoding mpeg4-thread.avi "-b 500k -flags +mv4+part+aic -trellis 1 -mbd bits -ps 200 -bf 2 -an -vcodec mpeg4 -threads 2" +do_video_encoding mpeg4-thread.avi "-b 500k -flags +mv4+part+aic -trellis 1 -mbd bits -ps 200 -bf 2 -an -vcodec mpeg4 -threads 2 -slices 2" do_video_decoding fi -- cgit v1.2.3