avcodec/ffv1dec: reorganize thread init/update
authorMichael Niedermayer <michaelni@gmx.at>
Sun, 1 Sep 2013 20:38:43 +0000 (22:38 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Sun, 1 Sep 2013 21:22:06 +0000 (23:22 +0200)
This moves some allocations to init, reducing possible failure modes in update.
Always copies from the previous context instead of just during init

Fixes Ticket2923

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
libavcodec/ffv1dec.c

index 70904ea..c600ce8 100644 (file)
@@ -942,7 +942,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac
 static int init_thread_copy(AVCodecContext *avctx)
 {
     FFV1Context *f = avctx->priv_data;
-    int i;
+    int i, ret;
 
     f->picture.f      = NULL;
     f->last_picture.f = NULL;
@@ -955,9 +955,43 @@ static int init_thread_copy(AVCodecContext *avctx)
                                          f->context_count[i] * sizeof(*f->initial_states[i]));
     }
 
+    f->picture.f      = av_frame_alloc();
+    f->last_picture.f = av_frame_alloc();
+
+    if ((ret = ffv1_init_slice_contexts(f)) < 0)
+        return ret;
+
     return 0;
 }
 
+static void copy_fields(FFV1Context *fsdst, FFV1Context *fssrc, FFV1Context *fsrc)
+{
+    fsdst->version             = fsrc->version;
+    fsdst->micro_version       = fsrc->micro_version;
+    fsdst->chroma_planes       = fsrc->chroma_planes;
+    fsdst->chroma_h_shift      = fsrc->chroma_h_shift;
+    fsdst->chroma_v_shift      = fsrc->chroma_v_shift;
+    fsdst->transparency        = fsrc->transparency;
+    fsdst->plane_count         = fsrc->plane_count;
+    fsdst->ac                  = fsrc->ac;
+    fsdst->colorspace          = fsrc->colorspace;
+
+    fsdst->ec                  = fsrc->ec;
+    fsdst->intra               = fsrc->intra;
+    fsdst->slice_damaged       = fssrc->slice_damaged;
+    fsdst->key_frame_ok        = fsrc->key_frame_ok;
+
+    fsdst->bits_per_raw_sample = fsrc->bits_per_raw_sample;
+    fsdst->packed_at_lsb       = fsrc->packed_at_lsb;
+    fsdst->slice_count         = fsrc->slice_count;
+    if (fsrc->version<3){
+        fsdst->slice_x             = fssrc->slice_x;
+        fsdst->slice_y             = fssrc->slice_y;
+        fsdst->slice_width         = fssrc->slice_width;
+        fsdst->slice_height        = fssrc->slice_height;
+    }
+}
+
 static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
 {
     FFV1Context *fsrc = src->priv_data;
@@ -967,33 +1001,30 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
     if (dst == src)
         return 0;
 
-    if (!fdst->picture.f) {
+    {
         FFV1Context bak = *fdst;
         memcpy(fdst, fsrc, sizeof(*fdst));
         memcpy(fdst->initial_states, bak.initial_states, sizeof(fdst->initial_states));
-
-        fdst->picture.f      = av_frame_alloc();
-        fdst->last_picture.f = av_frame_alloc();
-
-        if ((ret = ffv1_init_slice_contexts(fdst)) < 0)
-            return ret;
+        memcpy(fdst->slice_context,  bak.slice_context , sizeof(fdst->slice_context));
+        fdst->picture      = bak.picture;
+        fdst->last_picture = bak.last_picture;
+        for (i = 0; i<fdst->num_h_slices * fdst->num_v_slices; i++) {
+            FFV1Context *fssrc = fsrc->slice_context[i];
+            FFV1Context *fsdst = fdst->slice_context[i];
+            copy_fields(fsdst, fssrc, fsrc);
+        }
+        av_assert0(!fdst->plane[0].state);
+        av_assert0(!fdst->sample_buffer);
     }
 
     av_assert1(fdst->slice_count == fsrc->slice_count);
 
-    fdst->key_frame_ok = fsrc->key_frame_ok;
 
     ff_thread_release_buffer(dst, &fdst->picture);
     if (fsrc->picture.f->data[0]) {
         if ((ret = ff_thread_ref_frame(&fdst->picture, &fsrc->picture)) < 0)
             return ret;
     }
-    for (i = 0; i < fdst->slice_count; i++) {
-        FFV1Context *fsdst = fdst->slice_context[i];
-        FFV1Context *fssrc = fsrc->slice_context[i];
-
-        fsdst->slice_damaged = fssrc->slice_damaged;
-    }
 
     fdst->fsrc = fsrc;