OLD | NEW |
(Empty) | |
| 1 diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c |
| 2 index 7442b99..447bdb5 100644 |
| 3 --- a/libavcodec/vp8.c |
| 4 +++ b/libavcodec/vp8.c |
| 5 @@ -41,24 +41,57 @@ static void free_buffers(VP8Context *s) |
| 6 av_freep(&s->top_nnz); |
| 7 av_freep(&s->edge_emu_buffer); |
| 8 av_freep(&s->top_border); |
| 9 - av_freep(&s->segmentation_map); |
| 10 |
| 11 s->macroblocks = NULL; |
| 12 } |
| 13 |
| 14 -static void vp8_decode_flush(AVCodecContext *avctx) |
| 15 +static int vp8_alloc_frame(VP8Context *s, AVFrame *f) |
| 16 +{ |
| 17 + int ret; |
| 18 + if ((ret = ff_thread_get_buffer(s->avctx, f)) < 0) |
| 19 + return ret; |
| 20 + if (!s->maps_are_invalid && s->num_maps_to_be_freed) { |
| 21 + f->ref_index[0] = s->segmentation_maps[--s->num_maps_to_be_freed]; |
| 22 + } else if (!(f->ref_index[0] = av_mallocz(s->mb_width * s->mb_height))) { |
| 23 + ff_thread_release_buffer(s->avctx, f); |
| 24 + return AVERROR(ENOMEM); |
| 25 + } |
| 26 + return 0; |
| 27 +} |
| 28 + |
| 29 +static void vp8_release_frame(VP8Context *s, AVFrame *f, int is_close) |
| 30 +{ |
| 31 + if (!is_close) { |
| 32 + if (f->ref_index[0]) { |
| 33 + assert(s->num_maps_to_be_freed < FF_ARRAY_ELEMS(s->segmentation_map
s)); |
| 34 + s->segmentation_maps[s->num_maps_to_be_freed++] = f->ref_index[0]; |
| 35 + f->ref_index[0] = NULL; |
| 36 + } |
| 37 + } else { |
| 38 + av_freep(&f->ref_index[0]); |
| 39 + } |
| 40 + ff_thread_release_buffer(s->avctx, f); |
| 41 +} |
| 42 + |
| 43 +static void vp8_decode_flush_impl(AVCodecContext *avctx, int force, int is_clos
e) |
| 44 { |
| 45 VP8Context *s = avctx->priv_data; |
| 46 int i; |
| 47 |
| 48 - if (!avctx->is_copy) { |
| 49 + if (!avctx->is_copy || force) { |
| 50 for (i = 0; i < 5; i++) |
| 51 if (s->frames[i].data[0]) |
| 52 - ff_thread_release_buffer(avctx, &s->frames[i]); |
| 53 + vp8_release_frame(s, &s->frames[i], is_close); |
| 54 } |
| 55 memset(s->framep, 0, sizeof(s->framep)); |
| 56 |
| 57 free_buffers(s); |
| 58 + s->maps_are_invalid = 1; |
| 59 +} |
| 60 + |
| 61 +static void vp8_decode_flush(AVCodecContext *avctx) |
| 62 +{ |
| 63 + vp8_decode_flush_impl(avctx, 0, 0); |
| 64 } |
| 65 |
| 66 static int update_dimensions(VP8Context *s, int width, int height) |
| 67 @@ -68,7 +101,7 @@ static int update_dimensions(VP8Context *s, int width, int he
ight) |
| 68 if (av_image_check_size(width, height, 0, s->avctx)) |
| 69 return AVERROR_INVALIDDATA; |
| 70 |
| 71 - vp8_decode_flush(s->avctx); |
| 72 + vp8_decode_flush_impl(s->avctx, 1, 0); |
| 73 |
| 74 avcodec_set_dimensions(s->avctx, width, height); |
| 75 } |
| 76 @@ -81,10 +114,9 @@ static int update_dimensions(VP8Context *s, int width, int h
eight) |
| 77 s->intra4x4_pred_mode_top = av_mallocz(s->mb_width*4); |
| 78 s->top_nnz = av_mallocz(s->mb_width*sizeof(*s->top_nnz)); |
| 79 s->top_border = av_mallocz((s->mb_width+1)*sizeof(*s->top_bord
er)); |
| 80 - s->segmentation_map = av_mallocz(s->mb_width*s->mb_height); |
| 81 |
| 82 if (!s->macroblocks_base || !s->filter_strength || !s->intra4x4_pred_mode_t
op || |
| 83 - !s->top_nnz || !s->top_border || !s->segmentation_map) |
| 84 + !s->top_nnz || !s->top_border) |
| 85 return AVERROR(ENOMEM); |
| 86 |
| 87 s->macroblocks = s->macroblocks_base + 1; |
| 88 @@ -1508,6 +1540,14 @@ static void filter_mb_row_simple(VP8Context *s, AVFrame *
curframe, int mb_y) |
| 89 } |
| 90 } |
| 91 |
| 92 +static void release_queued_segmaps(VP8Context *s, int is_close) |
| 93 +{ |
| 94 + int leave_behind = is_close ? 0 : !s->maps_are_invalid; |
| 95 + while (s->num_maps_to_be_freed > leave_behind) |
| 96 + av_freep(&s->segmentation_maps[--s->num_maps_to_be_freed]); |
| 97 + s->maps_are_invalid = 0; |
| 98 +} |
| 99 + |
| 100 static int vp8_decode_frame(AVCodecContext *avctx, void *data, int *data_size, |
| 101 AVPacket *avpkt) |
| 102 { |
| 103 @@ -1516,6 +1556,8 @@ static int vp8_decode_frame(AVCodecContext *avctx, void *d
ata, int *data_size, |
| 104 enum AVDiscard skip_thresh; |
| 105 AVFrame *av_uninit(curframe), *prev_frame = s->framep[VP56_FRAME_CURRENT]; |
| 106 |
| 107 + release_queued_segmaps(s, 0); |
| 108 + |
| 109 if ((ret = decode_frame_header(s, avpkt->data, avpkt->size)) < 0) |
| 110 return ret; |
| 111 |
| 112 @@ -1538,7 +1580,7 @@ static int vp8_decode_frame(AVCodecContext *avctx, void *d
ata, int *data_size, |
| 113 &s->frames[i] != s->framep[VP56_FRAME_PREVIOUS] && |
| 114 &s->frames[i] != s->framep[VP56_FRAME_GOLDEN] && |
| 115 &s->frames[i] != s->framep[VP56_FRAME_GOLDEN2]) |
| 116 - ff_thread_release_buffer(avctx, &s->frames[i]); |
| 117 + vp8_release_frame(s, &s->frames[i], 0); |
| 118 |
| 119 // find a free buffer |
| 120 for (i = 0; i < 5; i++) |
| 121 @@ -1559,8 +1601,7 @@ static int vp8_decode_frame(AVCodecContext *avctx, void *d
ata, int *data_size, |
| 122 curframe->key_frame = s->keyframe; |
| 123 curframe->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; |
| 124 curframe->reference = referenced ? 3 : 0; |
| 125 - curframe->ref_index[0] = s->segmentation_map; |
| 126 - if ((ret = ff_thread_get_buffer(avctx, curframe))) { |
| 127 + if ((ret = vp8_alloc_frame(s, curframe))) { |
| 128 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed!\n"); |
| 129 return ret; |
| 130 } |
| 131 @@ -1652,8 +1693,8 @@ static int vp8_decode_frame(AVCodecContext *avctx, void *d
ata, int *data_size, |
| 132 s->dsp.prefetch(dst[0] + (mb_x&3)*4*s->linesize + 64, s->linesize,
4); |
| 133 s->dsp.prefetch(dst[1] + (mb_x&7)*s->uvlinesize + 64, dst[2] - dst[
1], 2); |
| 134 |
| 135 - decode_mb_mode(s, mb, mb_x, mb_y, s->segmentation_map + mb_xy, |
| 136 - prev_frame ? prev_frame->ref_index[0] + mb_xy : NULL
); |
| 137 + decode_mb_mode(s, mb, mb_x, mb_y, curframe->ref_index[0] + mb_xy, |
| 138 + prev_frame && prev_frame->ref_index[0] ? prev_frame-
>ref_index[0] + mb_xy : NULL); |
| 139 |
| 140 prefetch_motion(s, mb, mb_x, mb_y, mb_xy, VP56_FRAME_PREVIOUS); |
| 141 |
| 142 @@ -1736,7 +1777,8 @@ static av_cold int vp8_decode_init(AVCodecContext *avctx) |
| 143 |
| 144 static av_cold int vp8_decode_free(AVCodecContext *avctx) |
| 145 { |
| 146 - vp8_decode_flush(avctx); |
| 147 + vp8_decode_flush_impl(avctx, 0, 1); |
| 148 + release_queued_segmaps(avctx->priv_data, 1); |
| 149 return 0; |
| 150 } |
| 151 |
| 152 diff --git a/libavcodec/vp8.h b/libavcodec/vp8.h |
| 153 index 5a96cd4..6cbdca2 100644 |
| 154 --- a/libavcodec/vp8.h |
| 155 +++ b/libavcodec/vp8.h |
| 156 @@ -130,7 +130,6 @@ typedef struct { |
| 157 |
| 158 uint8_t *intra4x4_pred_mode_top; |
| 159 uint8_t intra4x4_pred_mode_left[4]; |
| 160 - uint8_t *segmentation_map; |
| 161 |
| 162 /** |
| 163 * Macroblocks can have one of 4 different quants in a frame when |
| 164 @@ -237,6 +236,16 @@ typedef struct { |
| 165 H264PredContext hpc; |
| 166 vp8_mc_func put_pixels_tab[3][3][3]; |
| 167 AVFrame frames[5]; |
| 168 + |
| 169 + /** |
| 170 + * A list of segmentation_map buffers that are to be free()'ed in |
| 171 + * the next decoding iteration. We can't free() them right away |
| 172 + * because the map may still be used by subsequent decoding threads. |
| 173 + * Unused if frame threading is off. |
| 174 + */ |
| 175 + uint8_t *segmentation_maps[5]; |
| 176 + int num_maps_to_be_freed; |
| 177 + int maps_are_invalid; |
| 178 } VP8Context; |
| 179 |
| 180 #endif /* AVCODEC_VP8_H */ |
OLD | NEW |