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.
tags/n0.10
| @@ -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) | |||
| @@ -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]; | |||
| @@ -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); | |||
| @@ -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. | |||
| @@ -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; | |||
| @@ -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"}, | |||
| @@ -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 | |||