Commit 881a5e04 authored by Janne Grunau's avatar Janne Grunau

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.
parent 26480821
...@@ -1280,7 +1280,6 @@ int ff_h264_frame_start(H264Context *h){ ...@@ -1280,7 +1280,6 @@ int ff_h264_frame_start(H264Context *h){
MpegEncContext * const s = &h->s; MpegEncContext * const s = &h->s;
int i; int i;
const int pixel_shift = h->pixel_shift; 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) if(MPV_frame_start(s, s->avctx) < 0)
return -1; return -1;
...@@ -1309,7 +1308,7 @@ int ff_h264_frame_start(H264Context *h){ ...@@ -1309,7 +1308,7 @@ int ff_h264_frame_start(H264Context *h){
/* can't be in alloc_tables because linesize isn't known there. /* can't be in alloc_tables because linesize isn't known there.
* FIXME: redo bipred weight to not require extra buffer? */ * 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) 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); 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){ ...@@ -2826,7 +2825,7 @@ static int decode_slice_header(H264Context *h, H264Context *h0){
return -1; return -1;
} }
} else { } else {
for(i = 1; i < s->avctx->thread_count; i++) { for(i = 1; i < s->slice_context_count; i++) {
H264Context *c; H264Context *c;
c = h->thread_context[i] = av_malloc(sizeof(H264Context)); c = h->thread_context[i] = av_malloc(sizeof(H264Context));
memcpy(c, h->s.thread_context[i], sizeof(MpegEncContext)); memcpy(c, h->s.thread_context[i], sizeof(MpegEncContext));
...@@ -2839,7 +2838,7 @@ static int decode_slice_header(H264Context *h, H264Context *h0){ ...@@ -2839,7 +2838,7 @@ static int decode_slice_header(H264Context *h, H264Context *h0){
clone_tables(c, h, i); 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) { if (context_init(h->thread_context[i]) < 0) {
av_log(h->s.avctx, AV_LOG_ERROR, "context_init() failed.\n"); av_log(h->s.avctx, AV_LOG_ERROR, "context_init() failed.\n");
return -1; return -1;
...@@ -3742,7 +3741,7 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size){ ...@@ -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 nals_needed=0; ///< number of NALs that need decoding before the next frame thread starts
int nal_index; 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)){ if(!(s->flags2 & CODEC_FLAG2_CHUNKS)){
h->current_slice = 0; h->current_slice = 0;
if (!s->first_field) if (!s->first_field)
......
...@@ -2428,7 +2428,9 @@ static int decode_chunks(AVCodecContext *avctx, ...@@ -2428,7 +2428,9 @@ static int decode_chunks(AVCodecContext *avctx,
} }
if (HAVE_THREADS && (avctx->active_thread_type & FF_THREAD_SLICE)) { 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) { if (threshold <= mb_y) {
MpegEncContext *thread_context = s2->thread_context[s->slice_count]; MpegEncContext *thread_context = s2->thread_context[s->slice_count];
......
...@@ -637,6 +637,8 @@ void MPV_common_defaults(MpegEncContext *s) ...@@ -637,6 +637,8 @@ void MPV_common_defaults(MpegEncContext *s)
s->picture_range_start = 0; s->picture_range_start = 0;
s->picture_range_end = MAX_PICTURE_COUNT; s->picture_range_end = MAX_PICTURE_COUNT;
s->slice_context_count = 1;
} }
/** /**
...@@ -655,11 +657,13 @@ void MPV_decode_defaults(MpegEncContext *s) ...@@ -655,11 +657,13 @@ void MPV_decode_defaults(MpegEncContext *s)
*/ */
av_cold int MPV_common_init(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, int y_size, c_size, yc_size, i, mb_array_size, mv_table_size, x, y;
threads = (s->encoding || int nb_slices = (HAVE_THREADS &&
(HAVE_THREADS && s->avctx->active_thread_type & FF_THREAD_SLICE) ?
s->avctx->active_thread_type & FF_THREAD_SLICE)) ? s->avctx->thread_count : 1;
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) if (s->codec_id == CODEC_ID_MPEG2VIDEO && !s->progressive_sequence)
s->mb_height = (s->height + 31) / 32 * 2; s->mb_height = (s->height + 31) / 32 * 2;
...@@ -672,14 +676,15 @@ av_cold int MPV_common_init(MpegEncContext *s) ...@@ -672,14 +676,15 @@ av_cold int MPV_common_init(MpegEncContext *s)
return -1; return -1;
} }
if ((s->encoding || (s->avctx->active_thread_type & FF_THREAD_SLICE)) && if (nb_slices > MAX_THREADS || (nb_slices > s->mb_height && s->mb_height)) {
(s->avctx->thread_count > MAX_THREADS || int max_slices;
(s->avctx->thread_count > s->mb_height && s->mb_height))) { if (s->mb_height)
int max_threads = FFMIN(MAX_THREADS, s->mb_height); max_slices = FFMIN(MAX_THREADS, s->mb_height);
av_log(s->avctx, AV_LOG_WARNING, else
"too many threads (%d), reducing to %d\n", max_slices = MAX_THREADS;
s->avctx->thread_count, max_threads); av_log(s->avctx, AV_LOG_WARNING, "too many threads/slices (%d),"
threads = max_threads; " reducing to %d\n", nb_slices, max_slices);
nb_slices = max_slices;
} }
if ((s->width || s->height) && if ((s->width || s->height) &&
...@@ -885,22 +890,19 @@ av_cold int MPV_common_init(MpegEncContext *s) ...@@ -885,22 +890,19 @@ av_cold int MPV_common_init(MpegEncContext *s)
s->thread_context[0] = s; s->thread_context[0] = s;
if (s->width && s->height) { if (s->width && s->height) {
if (s->encoding || (HAVE_THREADS && if (nb_slices > 1) {
s->avctx->active_thread_type&FF_THREAD_SLICE)) { for (i = 1; i < nb_slices; i++) {
for (i = 1; i < threads; i++) {
s->thread_context[i] = av_malloc(sizeof(MpegEncContext)); s->thread_context[i] = av_malloc(sizeof(MpegEncContext));
memcpy(s->thread_context[i], s, 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) if (init_duplicate_context(s->thread_context[i], s) < 0)
goto fail; goto fail;
s->thread_context[i]->start_mb_y = s->thread_context[i]->start_mb_y =
(s->mb_height * (i) + s->avctx->thread_count / 2) / (s->mb_height * (i) + nb_slices / 2) / nb_slices;
s->avctx->thread_count;
s->thread_context[i]->end_mb_y = s->thread_context[i]->end_mb_y =
(s->mb_height * (i + 1) + s->avctx->thread_count / 2) / (s->mb_height * (i + 1) + nb_slices / 2) / nb_slices;
s->avctx->thread_count;
} }
} else { } else {
if (init_duplicate_context(s, s) < 0) if (init_duplicate_context(s, s) < 0)
...@@ -908,6 +910,7 @@ av_cold int MPV_common_init(MpegEncContext *s) ...@@ -908,6 +910,7 @@ av_cold int MPV_common_init(MpegEncContext *s)
s->start_mb_y = 0; s->start_mb_y = 0;
s->end_mb_y = s->mb_height; s->end_mb_y = s->mb_height;
} }
s->slice_context_count = nb_slices;
} }
return 0; return 0;
...@@ -921,14 +924,14 @@ void MPV_common_end(MpegEncContext *s) ...@@ -921,14 +924,14 @@ void MPV_common_end(MpegEncContext *s)
{ {
int i, j, k; int i, j, k;
if (s->encoding || (HAVE_THREADS && if (s->slice_context_count > 1) {
s->avctx->active_thread_type & FF_THREAD_SLICE)) { for (i = 0; i < s->slice_context_count; i++) {
for (i = 0; i < s->avctx->thread_count; i++) {
free_duplicate_context(s->thread_context[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]); av_freep(&s->thread_context[i]);
} }
s->slice_context_count = 1;
} else free_duplicate_context(s); } else free_duplicate_context(s);
av_freep(&s->parse_context.buffer); av_freep(&s->parse_context.buffer);
......
...@@ -268,6 +268,7 @@ typedef struct MpegEncContext { ...@@ -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 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) 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]; struct MpegEncContext *thread_context[MAX_THREADS];
int slice_context_count; ///< number of used thread_contexts
/** /**
* copy of the previous picture structure. * copy of the previous picture structure.
......
...@@ -1428,7 +1428,8 @@ int MPV_encode_picture(AVCodecContext *avctx, ...@@ -1428,7 +1428,8 @@ int MPV_encode_picture(AVCodecContext *avctx,
{ {
MpegEncContext *s = avctx->priv_data; MpegEncContext *s = avctx->priv_data;
AVFrame *pic_arg = 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++) { for (i = 0; i < context_count; i++) {
int start_y = s->thread_context[i]->start_mb_y; int start_y = s->thread_context[i]->start_mb_y;
...@@ -3059,7 +3060,7 @@ static int encode_picture(MpegEncContext *s, int picture_number) ...@@ -3059,7 +3060,7 @@ static int encode_picture(MpegEncContext *s, int picture_number)
{ {
int i; int i;
int bits; int bits;
int context_count = s->avctx->thread_count; int context_count = s->slice_context_count;
s->picture_number = picture_number; s->picture_number = picture_number;
......
...@@ -506,7 +506,7 @@ static const AVOption options[]={ ...@@ -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"}, {"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}, {"lpc_passes", "deprecated, use flac-specific options", OFFSET(lpc_passes), AV_OPT_TYPE_INT, {.dbl = -1 }, INT_MIN, INT_MAX, A|E},
#endif #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"}, {"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"}, {"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"}, {"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 ...@@ -62,13 +62,13 @@ fi
if [ -n "$do_mpeg2thread" ] ; then if [ -n "$do_mpeg2thread" ] ; then
# mpeg2 encoding interlaced # 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 do_video_decoding
fi fi
if [ -n "$do_mpeg2thread_ilace" ]; then if [ -n "$do_mpeg2thread_ilace" ]; then
# mpeg2 encoding interlaced using intra vlc # 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 do_video_decoding
fi fi
...@@ -143,7 +143,7 @@ do_video_decoding ...@@ -143,7 +143,7 @@ do_video_decoding
fi fi
if [ -n "$do_mpeg4thread" ] ; then 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 do_video_decoding
fi fi
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment