Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(95)

Side by Side Diff: ffmpeg/patches/to_upstream/42_vp8_fix_segmentation_maps.patch

Issue 8341002: VP8: fix up handling of segmentation_maps in reference frames. (Closed) Base URL: svn://chrome-svn/chrome/trunk/deps/third_party
Patch Set: merge Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ffmpeg/patches/README ('k') | ffmpeg/source/patched-ffmpeg/libavcodec/vp8.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 */
OLDNEW
« no previous file with comments | « ffmpeg/patches/README ('k') | ffmpeg/source/patched-ffmpeg/libavcodec/vp8.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698