summaryrefslogtreecommitdiff
path: root/libavcodec/vp3.c
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2012-11-21 21:34:46 +0100
committerAnton Khirnov <anton@khirnov.net>2013-03-08 07:38:30 +0100
commit759001c534287a96dc96d1e274665feb7059145d (patch)
tree6ace9560c20aa30db92067c5b45d7bd86e458d10 /libavcodec/vp3.c
parent6e7b50b4270116ded8b874d76cb7c5b1a0341827 (diff)
lavc decoders: work with refcounted frames.
Diffstat (limited to 'libavcodec/vp3.c')
-rw-r--r--libavcodec/vp3.c172
1 files changed, 103 insertions, 69 deletions
diff --git a/libavcodec/vp3.c b/libavcodec/vp3.c
index f46ac32a9a..3d55c784aa 100644
--- a/libavcodec/vp3.c
+++ b/libavcodec/vp3.c
@@ -131,9 +131,9 @@ 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;
DSPContext dsp;
VideoDSPContext vdsp;
@@ -261,19 +261,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);
}
@@ -292,6 +284,12 @@ static av_cold int vp3_decode_end(AVCodecContext *avctx)
av_freep(&s->motion_val[1]);
av_freep(&s->edge_emu_buffer);
+ /* 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;
@@ -308,8 +306,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;
}
@@ -1290,8 +1286,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;
@@ -1420,14 +1416,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);
}
/**
@@ -1436,7 +1432,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;
@@ -1469,10 +1465,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 +1653,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
@@ -1821,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:
@@ -1835,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)
@@ -1864,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, current_frame);
+ 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);
@@ -1887,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++) {
@@ -1905,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,
@@ -1918,7 +1949,7 @@ static int vp3_decode_frame(AVCodecContext *avctx,
int buf_size = avpkt->size;
Vp3DecodeContext *s = avctx->priv_data;
GetBitContext gb;
- int i;
+ int i, ret;
init_get_bits(&gb, buf, buf_size * 8);
@@ -1960,15 +1991,14 @@ 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;
- 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;
+ 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)
@@ -1989,17 +2019,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);
}
}
@@ -2033,7 +2063,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;
@@ -2047,11 +2077,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;
@@ -2059,7 +2093,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;
}
@@ -2113,7 +2147,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