Merge commit '759001c534287a96dc96d1e274665feb7059145d'
[ffmpeg.git] / libavcodec / vp3.c
index 00a77e9..a77bf8f 100644 (file)
@@ -135,10 +135,11 @@ typedef struct Vp3DecodeContext {
     int version;
     int width, height;
     int chroma_x_shift, chroma_y_shift;
-    AVFrame golden_frame;
-    AVFrame last_frame;
-    AVFrame current_frame;
+    ThreadFrame golden_frame;
+    ThreadFrame last_frame;
+    ThreadFrame current_frame;
     int keyframe;
+    uint8_t idct_permutation[64];
     DSPContext dsp;
     VideoDSPContext vdsp;
     VP3DSPContext vp3dsp;
@@ -265,19 +266,11 @@ static void vp3_decode_flush(AVCodecContext *avctx)
 {
     Vp3DecodeContext *s = avctx->priv_data;
 
-    if (s->golden_frame.data[0]) {
-        if (s->golden_frame.data[0] == s->last_frame.data[0])
-            memset(&s->last_frame, 0, sizeof(AVFrame));
-        if (s->current_frame.data[0] == s->golden_frame.data[0])
-            memset(&s->current_frame, 0, sizeof(AVFrame));
+    if (s->golden_frame.f)
         ff_thread_release_buffer(avctx, &s->golden_frame);
-    }
-    if (s->last_frame.data[0]) {
-        if (s->current_frame.data[0] == s->last_frame.data[0])
-            memset(&s->current_frame, 0, sizeof(AVFrame));
+    if (s->last_frame.f)
         ff_thread_release_buffer(avctx, &s->last_frame);
-    }
-    if (s->current_frame.data[0])
+    if (s->current_frame.f)
         ff_thread_release_buffer(avctx, &s->current_frame);
 }
 
@@ -298,6 +291,12 @@ static av_cold int vp3_decode_end(AVCodecContext *avctx)
 
     s->theora_tables = 0;
 
+    /* release all frames */
+    vp3_decode_flush(avctx);
+    av_frame_free(&s->current_frame.f);
+    av_frame_free(&s->last_frame.f);
+    av_frame_free(&s->golden_frame.f);
+
     if (avctx->internal->is_copy)
         return 0;
 
@@ -314,8 +313,6 @@ static av_cold int vp3_decode_end(AVCodecContext *avctx)
     ff_free_vlc(&s->mode_code_vlc);
     ff_free_vlc(&s->motion_vector_vlc);
 
-    /* release all frames */
-    vp3_decode_flush(avctx);
 
     return 0;
 }
@@ -384,7 +381,7 @@ static void init_dequantizer(Vp3DecodeContext *s, int qpi)
                 int qmin= 8<<(inter + !i);
                 int qscale= i ? ac_scale_factor : dc_scale_factor;
 
-                s->qmat[qpi][inter][plane][s->dsp.idct_permutation[i]]= av_clip((qscale * coeff)/100 * 4, qmin, 4096);
+                s->qmat[qpi][inter][plane][s->idct_permutation[i]]= av_clip((qscale * coeff)/100 * 4, qmin, 4096);
             }
             // all DC coefficients use the same quant so as not to interfere with DC prediction
             s->qmat[qpi][inter][plane][0] = s->qmat[0][inter][plane][0];
@@ -1296,8 +1293,8 @@ static void apply_loop_filter(Vp3DecodeContext *s, int plane, int ystart, int ye
     int width           = s->fragment_width[!!plane];
     int height          = s->fragment_height[!!plane];
     int fragment        = s->fragment_start        [plane] + ystart * width;
-    int stride          = s->current_frame.linesize[plane];
-    uint8_t *plane_data = s->current_frame.data    [plane];
+    int stride          = s->current_frame.f->linesize[plane];
+    uint8_t *plane_data = s->current_frame.f->data    [plane];
     if (!s->flipped_image) stride = -stride;
     plane_data += s->data_offset[plane] + 8*ystart*stride;
 
@@ -1426,14 +1423,14 @@ static void vp3_draw_horiz_band(Vp3DecodeContext *s, int y)
     }
 
     cy = y >> s->chroma_y_shift;
-    offset[0] = s->current_frame.linesize[0]*y;
-    offset[1] = s->current_frame.linesize[1]*cy;
-    offset[2] = s->current_frame.linesize[2]*cy;
+    offset[0] = s->current_frame.f->linesize[0]*y;
+    offset[1] = s->current_frame.f->linesize[1]*cy;
+    offset[2] = s->current_frame.f->linesize[2]*cy;
     for (i = 3; i < AV_NUM_DATA_POINTERS; i++)
         offset[i] = 0;
 
     emms_c();
-    s->avctx->draw_horiz_band(s->avctx, &s->current_frame, offset, y, 3, h);
+    s->avctx->draw_horiz_band(s->avctx, s->current_frame.f, offset, y, 3, h);
 }
 
 /**
@@ -1442,7 +1439,7 @@ static void vp3_draw_horiz_band(Vp3DecodeContext *s, int y)
  */
 static void await_reference_row(Vp3DecodeContext *s, Vp3Fragment *fragment, int motion_y, int y)
 {
-    AVFrame *ref_frame;
+    ThreadFrame *ref_frame;
     int ref_row;
     int border = motion_y&1;
 
@@ -1475,10 +1472,10 @@ static void render_slice(Vp3DecodeContext *s, int slice)
         return;
 
     for (plane = 0; plane < 3; plane++) {
-        uint8_t *output_plane = s->current_frame.data    [plane] + s->data_offset[plane];
-        uint8_t *  last_plane = s->   last_frame.data    [plane] + s->data_offset[plane];
-        uint8_t *golden_plane = s-> golden_frame.data    [plane] + s->data_offset[plane];
-        int stride            = s->current_frame.linesize[plane];
+        uint8_t *output_plane = s->current_frame.f->data    [plane] + s->data_offset[plane];
+        uint8_t *  last_plane = s->   last_frame.f->data    [plane] + s->data_offset[plane];
+        uint8_t *golden_plane = s-> golden_frame.f->data    [plane] + s->data_offset[plane];
+        int stride            = s->current_frame.f->linesize[plane];
         int plane_width       = s->width  >> (plane && s->chroma_x_shift);
         int plane_height      = s->height >> (plane && s->chroma_y_shift);
         int8_t (*motion_val)[2] = s->motion_val[!!plane];
@@ -1657,14 +1654,36 @@ static av_cold int allocate_tables(AVCodecContext *avctx)
     return 0;
 }
 
+static av_cold int init_frames(Vp3DecodeContext *s)
+{
+    s->current_frame.f = av_frame_alloc();
+    s->last_frame.f    = av_frame_alloc();
+    s->golden_frame.f  = av_frame_alloc();
+
+    if (!s->current_frame.f || !s->last_frame.f || !s->golden_frame.f) {
+        av_frame_free(&s->current_frame.f);
+        av_frame_free(&s->last_frame.f);
+        av_frame_free(&s->golden_frame.f);
+        return AVERROR(ENOMEM);
+    }
+
+    return 0;
+}
+
 static av_cold int vp3_decode_init(AVCodecContext *avctx)
 {
     Vp3DecodeContext *s = avctx->priv_data;
-    int i, inter, plane;
+    int i, inter, plane, ret;
     int c_width;
     int c_height;
     int y_fragment_count, c_fragment_count;
 
+    ret = init_frames(s);
+    if (ret < 0)
+        return ret;
+
+    avctx->internal->allocate_progress = 1;
+
     if (avctx->codec_tag == MKTAG('V','P','3','0'))
         s->version = 0;
     else
@@ -1680,8 +1699,8 @@ static av_cold int vp3_decode_init(AVCodecContext *avctx)
     ff_videodsp_init(&s->vdsp, 8);
     ff_vp3dsp_init(&s->vp3dsp, avctx->flags);
 
-    ff_init_scantable_permutation(s->dsp.idct_permutation, s->vp3dsp.idct_perm);
-    ff_init_scantable(s->dsp.idct_permutation, &s->scantable, ff_zigzag_direct);
+    ff_init_scantable_permutation(s->idct_permutation, s->vp3dsp.idct_perm);
+    ff_init_scantable(s->idct_permutation, &s->scantable, ff_zigzag_direct);
 
     /* initialize to an impossible value which will force a recalculation
      * in the first frame decode */
@@ -1820,12 +1839,6 @@ static av_cold int vp3_decode_init(AVCodecContext *avctx)
         &motion_vector_vlc_table[0][1], 2, 1,
         &motion_vector_vlc_table[0][0], 2, 1, 0);
 
-    for (i = 0; i < 3; i++) {
-        s->current_frame.data[i] = NULL;
-        s->last_frame.data[i] = NULL;
-        s->golden_frame.data[i] = NULL;
-    }
-
     return allocate_tables(avctx);
 
 vlc_fail:
@@ -1834,26 +1847,44 @@ vlc_fail:
 }
 
 /// Release and shuffle frames after decode finishes
-static void update_frames(AVCodecContext *avctx)
+static int update_frames(AVCodecContext *avctx)
 {
     Vp3DecodeContext *s = avctx->priv_data;
+    int ret = 0;
 
-    /* release the last frame, if it is allocated and if it is not the
-     * golden frame */
-    if (s->last_frame.data[0] && s->last_frame.type != FF_BUFFER_TYPE_COPY)
-        ff_thread_release_buffer(avctx, &s->last_frame);
 
     /* shuffle frames (last = current) */
-    s->last_frame= s->current_frame;
+    ff_thread_release_buffer(avctx, &s->last_frame);
+    ret = ff_thread_ref_frame(&s->last_frame, &s->current_frame);
+    if (ret < 0)
+        goto fail;
 
     if (s->keyframe) {
-        if (s->golden_frame.data[0])
-            ff_thread_release_buffer(avctx, &s->golden_frame);
-        s->golden_frame = s->current_frame;
-        s->last_frame.type = FF_BUFFER_TYPE_COPY;
+        ff_thread_release_buffer(avctx, &s->golden_frame);
+        ret = ff_thread_ref_frame(&s->golden_frame, &s->current_frame);
     }
 
-    s->current_frame.data[0]= NULL; /* ensure that we catch any access to this released frame */
+fail:
+    ff_thread_release_buffer(avctx, &s->current_frame);
+    return ret;
+}
+
+static int ref_frame(Vp3DecodeContext *s, ThreadFrame *dst, ThreadFrame *src)
+{
+    ff_thread_release_buffer(s->avctx, dst);
+    if (src->f->data[0])
+        return ff_thread_ref_frame(dst, src);
+    return 0;
+}
+
+static int ref_frames(Vp3DecodeContext *dst, Vp3DecodeContext *src)
+{
+    int ret;
+    if ((ret = ref_frame(dst, &dst->current_frame, &src->current_frame)) < 0 ||
+        (ret = ref_frame(dst, &dst->golden_frame,  &src->golden_frame)) < 0  ||
+        (ret = ref_frame(dst, &dst->last_frame,    &src->last_frame)) < 0)
+        return ret;
+    return 0;
 }
 
 static int vp3_update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
@@ -1863,17 +1894,17 @@ static int vp3_update_thread_context(AVCodecContext *dst, const AVCodecContext *
 
 #define copy_fields(to, from, start_field, end_field) memcpy(&to->start_field, &from->start_field, (char*)&to->end_field - (char*)&to->start_field)
 
-    if (!s1->current_frame.data[0]
+    if (!s1->current_frame.f->data[0]
         ||s->width != s1->width
         ||s->height!= s1->height) {
         if (s != s1)
-            copy_fields(s, s1, golden_frame, keyframe);
+            ref_frames(s, s1);
         return -1;
     }
 
     if (s != s1) {
         // init tables if the first frame hasn't been decoded
-        if (!s->current_frame.data[0]) {
+        if (!s->current_frame.f->data[0]) {
             int y_fragment_count, c_fragment_count;
             s->avctx = dst;
             err = allocate_tables(dst);
@@ -1886,7 +1917,10 @@ static int vp3_update_thread_context(AVCodecContext *dst, const AVCodecContext *
         }
 
         // copy previous frame data
-        copy_fields(s, s1, golden_frame, dsp);
+        if ((err = ref_frames(s, s1)) < 0)
+            return err;
+
+        s->keyframe = s1->keyframe;
 
         // copy qscale data if necessary
         for (i = 0; i < 3; i++) {
@@ -1904,9 +1938,7 @@ static int vp3_update_thread_context(AVCodecContext *dst, const AVCodecContext *
 #undef copy_fields
     }
 
-    update_frames(dst);
-
-    return 0;
+    return update_frames(dst);
 }
 
 static int vp3_decode_frame(AVCodecContext *avctx,
@@ -1917,8 +1949,7 @@ static int vp3_decode_frame(AVCodecContext *avctx,
     int buf_size = avpkt->size;
     Vp3DecodeContext *s = avctx->priv_data;
     GetBitContext gb;
-    int i;
-    int ret;
+    int i, ret;
 
     init_get_bits(&gb, buf, buf_size * 8);
 
@@ -1991,16 +2022,15 @@ static int vp3_decode_frame(AVCodecContext *avctx,
     if (avctx->skip_frame >= AVDISCARD_NONKEY && !s->keyframe)
         return buf_size;
 
-    s->current_frame.reference = 3;
-    s->current_frame.pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
-    s->current_frame.key_frame = s->keyframe;
-    if (ff_thread_get_buffer(avctx, &s->current_frame) < 0) {
+    s->current_frame.f->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
+    s->current_frame.f->key_frame = s->keyframe;
+    if (ff_thread_get_buffer(avctx, &s->current_frame, AV_GET_BUFFER_FLAG_REF) < 0) {
         av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
         goto error;
     }
 
     if (!s->edge_emu_buffer)
-        s->edge_emu_buffer = av_malloc(9*FFABS(s->current_frame.linesize[0]));
+        s->edge_emu_buffer = av_malloc(9*FFABS(s->current_frame.f->linesize[0]));
 
     if (s->keyframe) {
         if (!s->theora)
@@ -2021,17 +2051,17 @@ static int vp3_decode_frame(AVCodecContext *avctx,
             skip_bits(&gb, 2); /* reserved? */
         }
     } else {
-        if (!s->golden_frame.data[0]) {
+        if (!s->golden_frame.f->data[0]) {
             av_log(s->avctx, AV_LOG_WARNING, "vp3: first frame not a keyframe\n");
 
-            s->golden_frame.reference = 3;
-            s->golden_frame.pict_type = AV_PICTURE_TYPE_I;
-            if (ff_thread_get_buffer(avctx, &s->golden_frame) < 0) {
+            s->golden_frame.f->pict_type = AV_PICTURE_TYPE_I;
+            if (ff_thread_get_buffer(avctx, &s->golden_frame, AV_GET_BUFFER_FLAG_REF) < 0) {
                 av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
                 goto error;
             }
-            s->last_frame = s->golden_frame;
-            s->last_frame.type = FF_BUFFER_TYPE_COPY;
+            ff_thread_release_buffer(avctx, &s->last_frame);
+            if ((ret = ff_thread_ref_frame(&s->last_frame, &s->golden_frame)) < 0)
+                goto error;
             ff_thread_report_progress(&s->last_frame, INT_MAX, 0);
         }
     }
@@ -2065,7 +2095,7 @@ static int vp3_decode_frame(AVCodecContext *avctx,
         if (s->flipped_image)
             s->data_offset[i] = 0;
         else
-            s->data_offset[i] = (height-1) * s->current_frame.linesize[i];
+            s->data_offset[i] = (height-1) * s->current_frame.f->linesize[i];
     }
 
     s->last_slice_end = 0;
@@ -2079,11 +2109,15 @@ static int vp3_decode_frame(AVCodecContext *avctx,
     }
     vp3_draw_horiz_band(s, s->avctx->height);
 
+    if ((ret = av_frame_ref(data, s->current_frame.f)) < 0)
+        return ret;
     *got_frame = 1;
-    *(AVFrame*)data= s->current_frame;
 
-    if (!HAVE_THREADS || !(s->avctx->active_thread_type&FF_THREAD_FRAME))
-        update_frames(avctx);
+    if (!HAVE_THREADS || !(s->avctx->active_thread_type&FF_THREAD_FRAME)) {
+        ret = update_frames(avctx);
+        if (ret < 0)
+            return ret;
+    }
 
     return buf_size;
 
@@ -2091,7 +2125,7 @@ error:
     ff_thread_report_progress(&s->current_frame, INT_MAX, 0);
 
     if (!HAVE_THREADS || !(s->avctx->active_thread_type&FF_THREAD_FRAME))
-        avctx->release_buffer(avctx, &s->current_frame);
+        av_frame_unref(s->current_frame.f);
 
     return -1;
 }
@@ -2145,7 +2179,7 @@ static int vp3_init_thread_copy(AVCodecContext *avctx)
     s->motion_val[1]          = NULL;
     s->edge_emu_buffer        = NULL;
 
-    return 0;
+    return init_frames(s);
 }
 
 #if CONFIG_THEORA_DECODER