+static void free_buffers(VP8Context *s)
+{
+ av_freep(&s->macroblocks_base);
+ av_freep(&s->filter_strength);
+ av_freep(&s->intra4x4_pred_mode_top);
+ av_freep(&s->top_nnz);
+ av_freep(&s->edge_emu_buffer);
+ av_freep(&s->top_border);
+
+ s->macroblocks = NULL;
+}
+
+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->num_maps_to_be_freed && !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);
+ return AVERROR(ENOMEM);
+ }
+ return 0;
+}
+
+static void vp8_release_frame(VP8Context *s, AVFrame *f, int prefer_delayed_free, int can_direct_free)
+{
+ 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]);
+ }
+ }
+ ff_thread_release_buffer(s->avctx, f);
+}
+
+static void vp8_decode_flush_impl(AVCodecContext *avctx,
+ int prefer_delayed_free, int can_direct_free, int free_mem)