summaryrefslogtreecommitdiff
path: root/libavcodec/vp8.c
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2011-10-30 01:33:41 +0200
committerMichael Niedermayer <michaelni@gmx.at>2011-10-30 01:33:41 +0200
commitd17e7070a099af04a1dc7bc9ddd82f67bfcf9827 (patch)
tree4be589d09939bead88ef3d4e1d5e90fe0348af6c /libavcodec/vp8.c
parent1af3571e05522df4e71a5b33de05bdb9e953a6c4 (diff)
parent7d1b17b83330aefe2f32a66fe84effe46ae51014 (diff)
Merge remote-tracking branch 'qatar/master'
* qatar/master: (51 commits) cin audio: use sign_extend() instead of casting to int16_t cin audio: restructure decoding loop to avoid a separate counter variable cin audio: use local variable for delta value cin audio: remove unneeded cast from void* cin audio: validate the channel count cin audio: remove unneeded AVCodecContext pointer from CinAudioContext dsicin: fix several audio-related fields in the CIN demuxer flacdec: use av_get_bytes_per_sample() to get sample size dca: handle errors from dca_decode_block() dca: return error if the frame header is invalid dca: return proper error codes instead of -1 utvideo: handle empty Huffman trees binkaudio: change short to int16_t binkaudio: only decode one block at a time. binkaudio: store interleaved overlap samples in BinkAudioContext. binkaudio: pre-calculate quantization factors binkaudio: add some buffer overread checks. atrac3: support float or int16 output using request_sample_fmt atrac3: add CODEC_CAP_SUBFRAMES capability atrac3: return appropriate error codes instead of -1 ... Conflicts: libavcodec/atrac1.c libavcodec/dca.c libavformat/mov.c Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec/vp8.c')
-rw-r--r--libavcodec/vp8.c48
1 files changed, 30 insertions, 18 deletions
diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c
index 9b07608078..37bdcf7525 100644
--- a/libavcodec/vp8.c
+++ b/libavcodec/vp8.c
@@ -50,7 +50,8 @@ static int vp8_alloc_frame(VP8Context *s, AVFrame *f)
int ret;
if ((ret = ff_thread_get_buffer(s->avctx, f)) < 0)
return ret;
- if (!s->maps_are_invalid && s->num_maps_to_be_freed) {
+ if (s->num_maps_to_be_freed) {
+ assert(!s->maps_are_invalid);
f->ref_index[0] = s->segmentation_maps[--s->num_maps_to_be_freed];
} else if (!(f->ref_index[0] = av_mallocz(s->mb_width * s->mb_height))) {
ff_thread_release_buffer(s->avctx, f);
@@ -59,39 +60,50 @@ static int vp8_alloc_frame(VP8Context *s, AVFrame *f)
return 0;
}
-static void vp8_release_frame(VP8Context *s, AVFrame *f, int is_close)
+static void vp8_release_frame(VP8Context *s, AVFrame *f, int prefer_delayed_free, int can_direct_free)
{
- if (!is_close) {
- if (f->ref_index[0]) {
- assert(s->num_maps_to_be_freed < FF_ARRAY_ELEMS(s->segmentation_maps));
- s->segmentation_maps[s->num_maps_to_be_freed++] = f->ref_index[0];
+ if (f->ref_index[0]) {
+ if (prefer_delayed_free) {
+ /* Upon a size change, we want to free the maps but other threads may still
+ * be using them, so queue them. Upon a seek, all threads are inactive so
+ * we want to cache one to prevent re-allocation in the next decoding
+ * iteration, but the rest we can free directly. */
+ int max_queued_maps = can_direct_free ? 1 : FF_ARRAY_ELEMS(s->segmentation_maps);
+ if (s->num_maps_to_be_freed < max_queued_maps) {
+ s->segmentation_maps[s->num_maps_to_be_freed++] = f->ref_index[0];
+ } else if (can_direct_free) /* vp8_decode_flush(), but our queue is full */ {
+ av_free(f->ref_index[0]);
+ } /* else: MEMLEAK (should never happen, but better that than crash) */
f->ref_index[0] = NULL;
+ } else /* vp8_decode_free() */ {
+ av_free(f->ref_index[0]);
}
- } else {
- av_freep(&f->ref_index[0]);
}
ff_thread_release_buffer(s->avctx, f);
}
-static void vp8_decode_flush_impl(AVCodecContext *avctx, int force, int is_close)
+static void vp8_decode_flush_impl(AVCodecContext *avctx,
+ int prefer_delayed_free, int can_direct_free, int free_mem)
{
VP8Context *s = avctx->priv_data;
int i;
- if (!avctx->is_copy || force) {
+ if (!avctx->is_copy) {
for (i = 0; i < 5; i++)
if (s->frames[i].data[0])
- vp8_release_frame(s, &s->frames[i], is_close);
+ vp8_release_frame(s, &s->frames[i], prefer_delayed_free, can_direct_free);
}
memset(s->framep, 0, sizeof(s->framep));
- free_buffers(s);
- s->maps_are_invalid = 1;
+ if (free_mem) {
+ free_buffers(s);
+ s->maps_are_invalid = 1;
+ }
}
static void vp8_decode_flush(AVCodecContext *avctx)
{
- vp8_decode_flush_impl(avctx, 0, 0);
+ vp8_decode_flush_impl(avctx, 1, 1, 0);
}
static int update_dimensions(VP8Context *s, int width, int height)
@@ -101,7 +113,7 @@ static int update_dimensions(VP8Context *s, int width, int height)
if (av_image_check_size(width, height, 0, s->avctx))
return AVERROR_INVALIDDATA;
- vp8_decode_flush_impl(s->avctx, 1, 0);
+ vp8_decode_flush_impl(s->avctx, 1, 0, 1);
avcodec_set_dimensions(s->avctx, width, height);
}
@@ -1581,7 +1593,7 @@ static int vp8_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
&s->frames[i] != s->framep[VP56_FRAME_PREVIOUS] &&
&s->frames[i] != s->framep[VP56_FRAME_GOLDEN] &&
&s->frames[i] != s->framep[VP56_FRAME_GOLDEN2])
- vp8_release_frame(s, &s->frames[i], 0);
+ vp8_release_frame(s, &s->frames[i], 1, 0);
// find a free buffer
for (i = 0; i < 5; i++)
@@ -1597,7 +1609,7 @@ static int vp8_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
abort();
}
if (curframe->data[0])
- ff_thread_release_buffer(avctx, curframe);
+ vp8_release_frame(s, curframe, 1, 0);
curframe->key_frame = s->keyframe;
curframe->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
@@ -1778,7 +1790,7 @@ static av_cold int vp8_decode_init(AVCodecContext *avctx)
static av_cold int vp8_decode_free(AVCodecContext *avctx)
{
- vp8_decode_flush_impl(avctx, 0, 1);
+ vp8_decode_flush_impl(avctx, 0, 1, 1);
release_queued_segmaps(avctx->priv_data, 1);
return 0;
}