mpegenc: use avctx->slices as number of slices
authorJanne Grunau <janne-libav@jannau.net>
Sun, 1 Jan 2012 19:24:24 +0000 (20:24 +0100)
committerJanne Grunau <janne-libav@jannau.net>
Mon, 2 Jan 2012 18:20:23 +0000 (19:20 +0100)
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
libavcodec/mpeg12.c
libavcodec/mpegvideo.c
libavcodec/mpegvideo.h
libavcodec/mpegvideo_enc.c
libavcodec/options.c
tests/codec-regression.sh

index 2bde0fe..316a57d 100644 (file)
@@ -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)
index 48860cf..2019512 100644 (file)
@@ -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];
 
index 214b64e..a2aa257 100644 (file)
@@ -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);
index 6483893..3473e6d 100644 (file)
@@ -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.
index af303d8..84a5cda 100644 (file)
@@ -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;
 
index 4ac92fd..a99aed7 100644 (file)
@@ -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"},
index e20bf64..220593b 100755 (executable)
@@ -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