]> git.sesse.net Git - ffmpeg/commitdiff
pthread/mpegvideo: detect and block attempts to init frames after setup.
authorMichael Niedermayer <michaelni@gmx.at>
Fri, 23 Mar 2012 23:20:05 +0000 (00:20 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Fri, 23 Mar 2012 23:32:18 +0000 (00:32 +0100)
This fixes race conditions that ultimately lead to memory corruption.

Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
libavcodec/internal.h
libavcodec/mpegvideo.c
libavcodec/pthread.c
libavcodec/utils.c

index fb2c0dbe56c7a03abb8ff8348e6407102b5efe25..dfef6eb31f405e11db4dcb7a5d7ef0e6de1a7789 100644 (file)
@@ -157,4 +157,6 @@ static av_always_inline int64_t ff_samples_to_time_base(AVCodecContext *avctx,
                         avctx->time_base);
 }
 
+int ff_thread_can_start_frame(AVCodecContext *avctx);
+
 #endif /* AVCODEC_INTERNAL_H */
index 62670a6f5ec1ebb013df793e2e747570ddbf42d2..017bbdfba152de198faa817bef9708c52a379235 100644 (file)
@@ -1134,6 +1134,11 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
     assert(s->last_picture_ptr == NULL || s->out_format != FMT_H264 ||
            s->codec_id == CODEC_ID_SVQ3);
 
+    if (!ff_thread_can_start_frame(avctx)) {
+        av_log(avctx, AV_LOG_ERROR, "Attempt to start a frame outside SETUP state\n");
+        return -1;
+    }
+
     /* mark & release old frames */
     if (s->out_format != FMT_H264 || s->codec_id == CODEC_ID_SVQ3) {
         if (s->pict_type != AV_PICTURE_TYPE_B && s->last_picture_ptr &&
index 7834922f9f4911330b503a29504ae45eefcae5c4..d8f8858c1e27fcaa009f92222e7696d5ce7c6a28 100644 (file)
@@ -932,6 +932,17 @@ static int *allocate_progress(PerThreadContext *p)
     return p->progress[i];
 }
 
+int ff_thread_can_start_frame(AVCodecContext *avctx)
+{
+    PerThreadContext *p = avctx->thread_opaque;
+    if ((avctx->active_thread_type&FF_THREAD_FRAME) && p->state != STATE_SETTING_UP &&
+        (avctx->codec->update_thread_context || (!avctx->thread_safe_callbacks &&
+                avctx->get_buffer != avcodec_default_get_buffer))) {
+        return 0;
+    }
+    return 1;
+}
+
 int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f)
 {
     PerThreadContext *p = avctx->thread_opaque;
index e918024ca5626796d1dc690488b0f88781ac05cf..58435d43aa1c673134589f664ccbde70ab7dc42f 100644 (file)
@@ -2285,6 +2285,11 @@ void ff_thread_await_progress(AVFrame *f, int progress, int field)
 {
 }
 
+int ff_thread_can_start_frame(AVCodecContext *avctx)
+{
+    return 1;
+}
+
 #endif
 
 enum AVMediaType avcodec_get_type(enum CodecID codec_id)