Index: ffmpeg/source/patched-ffmpeg/libavcodec/vp8.c |
diff --git a/ffmpeg/source/patched-ffmpeg/libavcodec/vp8.c b/ffmpeg/source/patched-ffmpeg/libavcodec/vp8.c |
index 208f0bb0f8bd43bc772df07b54a954de8cb7054d..3880971729e4fedf2a68168111bf9ef71c953af8 100644 |
--- a/ffmpeg/source/patched-ffmpeg/libavcodec/vp8.c |
+++ b/ffmpeg/source/patched-ffmpeg/libavcodec/vp8.c |
@@ -41,24 +41,57 @@ static void free_buffers(VP8Context *s) |
av_freep(&s->top_nnz); |
av_freep(&s->edge_emu_buffer); |
av_freep(&s->top_border); |
- av_freep(&s->segmentation_map); |
s->macroblocks = NULL; |
} |
-static void vp8_decode_flush(AVCodecContext *avctx) |
+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) { |
+ 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); |
+ return AVERROR(ENOMEM); |
+ } |
+ return 0; |
+} |
+ |
+static void vp8_release_frame(VP8Context *s, AVFrame *f, int is_close) |
+{ |
+ 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]; |
+ f->ref_index[0] = NULL; |
+ } |
+ } 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) |
{ |
VP8Context *s = avctx->priv_data; |
int i; |
- if (!avctx->is_copy) { |
+ if (!avctx->is_copy || force) { |
for (i = 0; i < 5; i++) |
if (s->frames[i].data[0]) |
- ff_thread_release_buffer(avctx, &s->frames[i]); |
+ vp8_release_frame(s, &s->frames[i], is_close); |
} |
memset(s->framep, 0, sizeof(s->framep)); |
free_buffers(s); |
+ s->maps_are_invalid = 1; |
+} |
+ |
+static void vp8_decode_flush(AVCodecContext *avctx) |
+{ |
+ vp8_decode_flush_impl(avctx, 0, 0); |
} |
static int update_dimensions(VP8Context *s, int width, int height) |
@@ -68,7 +101,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(s->avctx); |
+ vp8_decode_flush_impl(s->avctx, 1, 0); |
avcodec_set_dimensions(s->avctx, width, height); |
} |
@@ -81,10 +114,9 @@ static int update_dimensions(VP8Context *s, int width, int height) |
s->intra4x4_pred_mode_top = av_mallocz(s->mb_width*4); |
s->top_nnz = av_mallocz(s->mb_width*sizeof(*s->top_nnz)); |
s->top_border = av_mallocz((s->mb_width+1)*sizeof(*s->top_border)); |
- s->segmentation_map = av_mallocz(s->mb_width*s->mb_height); |
if (!s->macroblocks_base || !s->filter_strength || !s->intra4x4_pred_mode_top || |
- !s->top_nnz || !s->top_border || !s->segmentation_map) |
+ !s->top_nnz || !s->top_border) |
return AVERROR(ENOMEM); |
s->macroblocks = s->macroblocks_base + 1; |
@@ -1507,6 +1539,14 @@ static void filter_mb_row_simple(VP8Context *s, AVFrame *curframe, int mb_y) |
} |
} |
+static void release_queued_segmaps(VP8Context *s, int is_close) |
+{ |
+ int leave_behind = is_close ? 0 : !s->maps_are_invalid; |
+ while (s->num_maps_to_be_freed > leave_behind) |
+ av_freep(&s->segmentation_maps[--s->num_maps_to_be_freed]); |
+ s->maps_are_invalid = 0; |
+} |
+ |
static int vp8_decode_frame(AVCodecContext *avctx, void *data, int *data_size, |
AVPacket *avpkt) |
{ |
@@ -1515,6 +1555,8 @@ static int vp8_decode_frame(AVCodecContext *avctx, void *data, int *data_size, |
enum AVDiscard skip_thresh; |
AVFrame *av_uninit(curframe), *prev_frame = s->framep[VP56_FRAME_CURRENT]; |
+ release_queued_segmaps(s, 0); |
+ |
if ((ret = decode_frame_header(s, avpkt->data, avpkt->size)) < 0) |
return ret; |
@@ -1537,7 +1579,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]) |
- ff_thread_release_buffer(avctx, &s->frames[i]); |
+ vp8_release_frame(s, &s->frames[i], 0); |
// find a free buffer |
for (i = 0; i < 5; i++) |
@@ -1558,8 +1600,7 @@ static int vp8_decode_frame(AVCodecContext *avctx, void *data, int *data_size, |
curframe->key_frame = s->keyframe; |
curframe->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; |
curframe->reference = referenced ? 3 : 0; |
- curframe->ref_index[0] = s->segmentation_map; |
- if ((ret = ff_thread_get_buffer(avctx, curframe))) { |
+ if ((ret = vp8_alloc_frame(s, curframe))) { |
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed!\n"); |
return ret; |
} |
@@ -1651,8 +1692,8 @@ static int vp8_decode_frame(AVCodecContext *avctx, void *data, int *data_size, |
s->dsp.prefetch(dst[0] + (mb_x&3)*4*s->linesize + 64, s->linesize, 4); |
s->dsp.prefetch(dst[1] + (mb_x&7)*s->uvlinesize + 64, dst[2] - dst[1], 2); |
- decode_mb_mode(s, mb, mb_x, mb_y, s->segmentation_map + mb_xy, |
- prev_frame ? prev_frame->ref_index[0] + mb_xy : NULL); |
+ decode_mb_mode(s, mb, mb_x, mb_y, curframe->ref_index[0] + mb_xy, |
+ prev_frame && prev_frame->ref_index[0] ? prev_frame->ref_index[0] + mb_xy : NULL); |
prefetch_motion(s, mb, mb_x, mb_y, mb_xy, VP56_FRAME_PREVIOUS); |
@@ -1735,7 +1776,8 @@ static av_cold int vp8_decode_init(AVCodecContext *avctx) |
static av_cold int vp8_decode_free(AVCodecContext *avctx) |
{ |
- vp8_decode_flush(avctx); |
+ vp8_decode_flush_impl(avctx, 0, 1); |
+ release_queued_segmaps(avctx->priv_data, 1); |
return 0; |
} |