Mercurial > libavcodec.hg
annotate vp56.c @ 12494:94eaea836bf4 libavcodec
Check avctx width/height more thoroughly (e.g. all values 0 except width would
have been accepted before).
Also do not fail if they are invalid but instead override them to 0.
This allows decoding e.g. MPEG video when only the container values are corrupted.
For encoding a value of 0,0 of course makes no sense, but was allowed
through before and will be caught by an extra check in the encode function.
author | reimar |
---|---|
date | Wed, 15 Sep 2010 04:46:55 +0000 |
parents | 54583a14a995 |
children |
rev | line source |
---|---|
3695 | 1 /** |
11644
7dd2a45249a9
Remove explicit filename from Doxygen @file commands.
diego
parents:
11350
diff
changeset
|
2 * @file |
3695 | 3 * VP5 and VP6 compatible video decoder (common features) |
4 * | |
5 * Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.org> | |
6 * | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3715
diff
changeset
|
7 * This file is part of FFmpeg. |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3715
diff
changeset
|
8 * |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3715
diff
changeset
|
9 * FFmpeg is free software; you can redistribute it and/or |
3695 | 10 * modify it under the terms of the GNU Lesser General Public |
11 * License as published by the Free Software Foundation; either | |
12 * version 2.1 of the License, or (at your option) any later version. | |
13 * | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3715
diff
changeset
|
14 * FFmpeg is distributed in the hope that it will be useful, |
3695 | 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 * Lesser General Public License for more details. | |
18 * | |
19 * You should have received a copy of the GNU Lesser General Public | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3715
diff
changeset
|
20 * License along with FFmpeg; if not, write to the Free Software |
5215 | 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
3695 | 22 */ |
23 | |
24 #include "avcodec.h" | |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
25 #include "bytestream.h" |
3695 | 26 |
27 #include "vp56.h" | |
28 #include "vp56data.h" | |
29 | |
30 | |
12292 | 31 void ff_vp56_init_dequant(VP56Context *s, int quantizer) |
3695 | 32 { |
33 s->quantizer = quantizer; | |
34 s->dequant_dc = vp56_dc_dequant[quantizer] << 2; | |
35 s->dequant_ac = vp56_ac_dequant[quantizer] << 2; | |
11053
c57e72227d7d
Make VP5 and VP6 decoders output a qscale table to allow for more automatic
reimar
parents:
11050
diff
changeset
|
36 memset(s->qscale_table, quantizer, s->mb_width); |
3695 | 37 } |
38 | |
8299 | 39 static int vp56_get_vectors_predictors(VP56Context *s, int row, int col, |
40 VP56Frame ref_frame) | |
3695 | 41 { |
42 int nb_pred = 0; | |
8299 | 43 VP56mv vect[2] = {{0,0}, {0,0}}; |
3695 | 44 int pos, offset; |
8299 | 45 VP56mv mvp; |
3695 | 46 |
47 for (pos=0; pos<12; pos++) { | |
48 mvp.x = col + vp56_candidate_predictor_pos[pos][0]; | |
49 mvp.y = row + vp56_candidate_predictor_pos[pos][1]; | |
50 if (mvp.x < 0 || mvp.x >= s->mb_width || | |
51 mvp.y < 0 || mvp.y >= s->mb_height) | |
52 continue; | |
53 offset = mvp.x + s->mb_width*mvp.y; | |
54 | |
55 if (vp56_reference_frame[s->macroblocks[offset].type] != ref_frame) | |
56 continue; | |
3697 | 57 if ((s->macroblocks[offset].mv.x == vect[0].x && |
58 s->macroblocks[offset].mv.y == vect[0].y) || | |
3695 | 59 (s->macroblocks[offset].mv.x == 0 && |
60 s->macroblocks[offset].mv.y == 0)) | |
61 continue; | |
62 | |
3697 | 63 vect[nb_pred++] = s->macroblocks[offset].mv; |
3695 | 64 if (nb_pred > 1) { |
65 nb_pred = -1; | |
66 break; | |
67 } | |
68 s->vector_candidate_pos = pos; | |
69 } | |
70 | |
3697 | 71 s->vector_candidate[0] = vect[0]; |
72 s->vector_candidate[1] = vect[1]; | |
3695 | 73 |
74 return nb_pred+1; | |
75 } | |
76 | |
8299 | 77 static void vp56_parse_mb_type_models(VP56Context *s) |
3695 | 78 { |
8299 | 79 VP56RangeCoder *c = &s->c; |
8304 | 80 VP56Model *model = s->modelp; |
3695 | 81 int i, ctx, type; |
82 | |
83 for (ctx=0; ctx<3; ctx++) { | |
84 if (vp56_rac_get_prob(c, 174)) { | |
85 int idx = vp56_rac_gets(c, 4); | |
5711 | 86 memcpy(model->mb_types_stats[ctx], |
87 vp56_pre_def_mb_type_stats[idx][ctx], | |
88 sizeof(model->mb_types_stats[ctx])); | |
3695 | 89 } |
90 if (vp56_rac_get_prob(c, 254)) { | |
91 for (type=0; type<10; type++) { | |
92 for(i=0; i<2; i++) { | |
93 if (vp56_rac_get_prob(c, 205)) { | |
94 int delta, sign = vp56_rac_get(c); | |
95 | |
96 delta = vp56_rac_get_tree(c, vp56_pmbtm_tree, | |
97 vp56_mb_type_model_model); | |
98 if (!delta) | |
99 delta = 4 * vp56_rac_gets(c, 7); | |
5711 | 100 model->mb_types_stats[ctx][type][i] += (delta ^ -sign) + sign; |
3695 | 101 } |
102 } | |
103 } | |
104 } | |
105 } | |
106 | |
107 /* compute MB type probability tables based on previous MB type */ | |
108 for (ctx=0; ctx<3; ctx++) { | |
109 int p[10]; | |
110 | |
111 for (type=0; type<10; type++) | |
5711 | 112 p[type] = 100 * model->mb_types_stats[ctx][type][1]; |
3695 | 113 |
114 for (type=0; type<10; type++) { | |
115 int p02, p34, p0234, p17, p56, p89, p5689, p156789; | |
116 | |
117 /* conservative MB type probability */ | |
5711 | 118 model->mb_type[ctx][type][0] = 255 - (255 * model->mb_types_stats[ctx][type][0]) / (1 + model->mb_types_stats[ctx][type][0] + model->mb_types_stats[ctx][type][1]); |
3695 | 119 |
120 p[type] = 0; /* same MB type => weight is null */ | |
121 | |
122 /* binary tree parsing probabilities */ | |
123 p02 = p[0] + p[2]; | |
124 p34 = p[3] + p[4]; | |
125 p0234 = p02 + p34; | |
126 p17 = p[1] + p[7]; | |
127 p56 = p[5] + p[6]; | |
128 p89 = p[8] + p[9]; | |
129 p5689 = p56 + p89; | |
130 p156789 = p17 + p5689; | |
131 | |
5711 | 132 model->mb_type[ctx][type][1] = 1 + 255 * p0234/(1+p0234+p156789); |
133 model->mb_type[ctx][type][2] = 1 + 255 * p02 / (1+p0234); | |
134 model->mb_type[ctx][type][3] = 1 + 255 * p17 / (1+p156789); | |
135 model->mb_type[ctx][type][4] = 1 + 255 * p[0] / (1+p02); | |
136 model->mb_type[ctx][type][5] = 1 + 255 * p[3] / (1+p34); | |
137 model->mb_type[ctx][type][6] = 1 + 255 * p[1] / (1+p17); | |
138 model->mb_type[ctx][type][7] = 1 + 255 * p56 / (1+p5689); | |
139 model->mb_type[ctx][type][8] = 1 + 255 * p[5] / (1+p56); | |
140 model->mb_type[ctx][type][9] = 1 + 255 * p[8] / (1+p89); | |
3695 | 141 |
142 /* restore initial value */ | |
5711 | 143 p[type] = 100 * model->mb_types_stats[ctx][type][1]; |
3695 | 144 } |
145 } | |
146 } | |
147 | |
8299 | 148 static VP56mb vp56_parse_mb_type(VP56Context *s, |
8300 | 149 VP56mb prev_type, int ctx) |
3695 | 150 { |
5711 | 151 uint8_t *mb_type_model = s->modelp->mb_type[ctx][prev_type]; |
8299 | 152 VP56RangeCoder *c = &s->c; |
3695 | 153 |
154 if (vp56_rac_get_prob(c, mb_type_model[0])) | |
155 return prev_type; | |
156 else | |
157 return vp56_rac_get_tree(c, vp56_pmbt_tree, mb_type_model); | |
158 } | |
159 | |
8299 | 160 static void vp56_decode_4mv(VP56Context *s, int row, int col) |
3695 | 161 { |
8299 | 162 VP56mv mv = {0,0}; |
3695 | 163 int type[4]; |
164 int b; | |
165 | |
166 /* parse each block type */ | |
167 for (b=0; b<4; b++) { | |
168 type[b] = vp56_rac_gets(&s->c, 2); | |
169 if (type[b]) | |
170 type[b]++; /* only returns 0, 2, 3 or 4 (all INTER_PF) */ | |
171 } | |
172 | |
173 /* get vectors */ | |
174 for (b=0; b<4; b++) { | |
175 switch (type[b]) { | |
176 case VP56_MB_INTER_NOVEC_PF: | |
8299 | 177 s->mv[b] = (VP56mv) {0,0}; |
3695 | 178 break; |
179 case VP56_MB_INTER_DELTA_PF: | |
180 s->parse_vector_adjustment(s, &s->mv[b]); | |
181 break; | |
182 case VP56_MB_INTER_V1_PF: | |
183 s->mv[b] = s->vector_candidate[0]; | |
184 break; | |
185 case VP56_MB_INTER_V2_PF: | |
186 s->mv[b] = s->vector_candidate[1]; | |
187 break; | |
188 } | |
189 mv.x += s->mv[b].x; | |
190 mv.y += s->mv[b].y; | |
191 } | |
192 | |
193 /* this is the one selected for the whole MB for prediction */ | |
194 s->macroblocks[row * s->mb_width + col].mv = s->mv[3]; | |
195 | |
196 /* chroma vectors are average luma vectors */ | |
197 if (s->avctx->codec->id == CODEC_ID_VP5) { | |
198 s->mv[4].x = s->mv[5].x = RSHIFT(mv.x,2); | |
199 s->mv[4].y = s->mv[5].y = RSHIFT(mv.y,2); | |
200 } else { | |
8299 | 201 s->mv[4] = s->mv[5] = (VP56mv) {mv.x/4, mv.y/4}; |
3695 | 202 } |
203 } | |
204 | |
8299 | 205 static VP56mb vp56_decode_mv(VP56Context *s, int row, int col) |
3695 | 206 { |
8299 | 207 VP56mv *mv, vect = {0,0}; |
3695 | 208 int ctx, b; |
209 | |
210 ctx = vp56_get_vectors_predictors(s, row, col, VP56_FRAME_PREVIOUS); | |
211 s->mb_type = vp56_parse_mb_type(s, s->mb_type, ctx); | |
212 s->macroblocks[row * s->mb_width + col].type = s->mb_type; | |
213 | |
214 switch (s->mb_type) { | |
215 case VP56_MB_INTER_V1_PF: | |
216 mv = &s->vector_candidate[0]; | |
217 break; | |
218 | |
219 case VP56_MB_INTER_V2_PF: | |
220 mv = &s->vector_candidate[1]; | |
221 break; | |
222 | |
223 case VP56_MB_INTER_V1_GF: | |
224 vp56_get_vectors_predictors(s, row, col, VP56_FRAME_GOLDEN); | |
225 mv = &s->vector_candidate[0]; | |
226 break; | |
227 | |
228 case VP56_MB_INTER_V2_GF: | |
229 vp56_get_vectors_predictors(s, row, col, VP56_FRAME_GOLDEN); | |
230 mv = &s->vector_candidate[1]; | |
231 break; | |
232 | |
233 case VP56_MB_INTER_DELTA_PF: | |
3697 | 234 s->parse_vector_adjustment(s, &vect); |
235 mv = &vect; | |
3695 | 236 break; |
237 | |
238 case VP56_MB_INTER_DELTA_GF: | |
239 vp56_get_vectors_predictors(s, row, col, VP56_FRAME_GOLDEN); | |
3697 | 240 s->parse_vector_adjustment(s, &vect); |
241 mv = &vect; | |
3695 | 242 break; |
243 | |
244 case VP56_MB_INTER_4V: | |
245 vp56_decode_4mv(s, row, col); | |
246 return s->mb_type; | |
247 | |
248 default: | |
3697 | 249 mv = &vect; |
3695 | 250 break; |
251 } | |
252 | |
253 s->macroblocks[row*s->mb_width + col].mv = *mv; | |
254 | |
255 /* same vector for all blocks */ | |
256 for (b=0; b<6; b++) | |
257 s->mv[b] = *mv; | |
258 | |
259 return s->mb_type; | |
260 } | |
261 | |
8299 | 262 static void vp56_add_predictors_dc(VP56Context *s, VP56Frame ref_frame) |
3695 | 263 { |
264 int idx = s->scantable.permutated[0]; | |
5718
bb4293d858da
rename one variable to be consistent with the rest of the file
aurel
parents:
5717
diff
changeset
|
265 int b; |
3695 | 266 |
5718
bb4293d858da
rename one variable to be consistent with the rest of the file
aurel
parents:
5717
diff
changeset
|
267 for (b=0; b<6; b++) { |
8299 | 268 VP56RefDc *ab = &s->above_blocks[s->above_block_idx[b]]; |
269 VP56RefDc *lb = &s->left_block[vp56_b6to4[b]]; | |
3695 | 270 int count = 0; |
271 int dc = 0; | |
5719 | 272 int i; |
3695 | 273 |
274 if (ref_frame == lb->ref_frame) { | |
275 dc += lb->dc_coeff; | |
276 count++; | |
277 } | |
278 if (ref_frame == ab->ref_frame) { | |
279 dc += ab->dc_coeff; | |
280 count++; | |
281 } | |
5719 | 282 if (s->avctx->codec->id == CODEC_ID_VP5) |
283 for (i=0; i<2; i++) | |
284 if (count < 2 && ref_frame == ab[-1+2*i].ref_frame) { | |
285 dc += ab[-1+2*i].dc_coeff; | |
286 count++; | |
287 } | |
3695 | 288 if (count == 0) |
5718
bb4293d858da
rename one variable to be consistent with the rest of the file
aurel
parents:
5717
diff
changeset
|
289 dc = s->prev_dc[vp56_b2p[b]][ref_frame]; |
3695 | 290 else if (count == 2) |
291 dc /= 2; | |
292 | |
5718
bb4293d858da
rename one variable to be consistent with the rest of the file
aurel
parents:
5717
diff
changeset
|
293 s->block_coeff[b][idx] += dc; |
bb4293d858da
rename one variable to be consistent with the rest of the file
aurel
parents:
5717
diff
changeset
|
294 s->prev_dc[vp56_b2p[b]][ref_frame] = s->block_coeff[b][idx]; |
bb4293d858da
rename one variable to be consistent with the rest of the file
aurel
parents:
5717
diff
changeset
|
295 ab->dc_coeff = s->block_coeff[b][idx]; |
3695 | 296 ab->ref_frame = ref_frame; |
5718
bb4293d858da
rename one variable to be consistent with the rest of the file
aurel
parents:
5717
diff
changeset
|
297 lb->dc_coeff = s->block_coeff[b][idx]; |
3695 | 298 lb->ref_frame = ref_frame; |
5718
bb4293d858da
rename one variable to be consistent with the rest of the file
aurel
parents:
5717
diff
changeset
|
299 s->block_coeff[b][idx] *= s->dequant_dc; |
3695 | 300 } |
301 } | |
302 | |
8299 | 303 static void vp56_deblock_filter(VP56Context *s, uint8_t *yuv, |
3695 | 304 int stride, int dx, int dy) |
305 { | |
306 int t = vp56_filter_threshold[s->quantizer]; | |
11665 | 307 if (dx) s->vp56dsp.edge_filter_hor(yuv + 10-dx , stride, t); |
308 if (dy) s->vp56dsp.edge_filter_ver(yuv + stride*(10-dy), stride, t); | |
3695 | 309 } |
310 | |
8299 | 311 static void vp56_mc(VP56Context *s, int b, int plane, uint8_t *src, |
3695 | 312 int stride, int x, int y) |
313 { | |
4595 | 314 uint8_t *dst=s->framep[VP56_FRAME_CURRENT]->data[plane]+s->block_offset[b]; |
3695 | 315 uint8_t *src_block; |
316 int src_offset; | |
317 int overlap_offset = 0; | |
318 int mask = s->vp56_coord_div[b] - 1; | |
319 int deblock_filtering = s->deblock_filtering; | |
320 int dx; | |
321 int dy; | |
322 | |
323 if (s->avctx->skip_loop_filter >= AVDISCARD_ALL || | |
324 (s->avctx->skip_loop_filter >= AVDISCARD_NONKEY | |
4595 | 325 && !s->framep[VP56_FRAME_CURRENT]->key_frame)) |
3695 | 326 deblock_filtering = 0; |
327 | |
328 dx = s->mv[b].x / s->vp56_coord_div[b]; | |
329 dy = s->mv[b].y / s->vp56_coord_div[b]; | |
330 | |
331 if (b >= 4) { | |
332 x /= 2; | |
333 y /= 2; | |
334 } | |
335 x += dx - 2; | |
336 y += dy - 2; | |
337 | |
338 if (x<0 || x+12>=s->plane_width[plane] || | |
339 y<0 || y+12>=s->plane_height[plane]) { | |
340 ff_emulated_edge_mc(s->edge_emu_buffer, | |
341 src + s->block_offset[b] + (dy-2)*stride + (dx-2), | |
342 stride, 12, 12, x, y, | |
343 s->plane_width[plane], | |
344 s->plane_height[plane]); | |
345 src_block = s->edge_emu_buffer; | |
346 src_offset = 2 + 2*stride; | |
347 } else if (deblock_filtering) { | |
3715
cdaee53c5da1
replaces back some C code by dsp.put_pixels_tab[0][0] (revert r6231)
aurel
parents:
3706
diff
changeset
|
348 /* only need a 12x12 block, but there is no such dsp function, */ |
cdaee53c5da1
replaces back some C code by dsp.put_pixels_tab[0][0] (revert r6231)
aurel
parents:
3706
diff
changeset
|
349 /* so copy a 16x12 block */ |
cdaee53c5da1
replaces back some C code by dsp.put_pixels_tab[0][0] (revert r6231)
aurel
parents:
3706
diff
changeset
|
350 s->dsp.put_pixels_tab[0][0](s->edge_emu_buffer, |
cdaee53c5da1
replaces back some C code by dsp.put_pixels_tab[0][0] (revert r6231)
aurel
parents:
3706
diff
changeset
|
351 src + s->block_offset[b] + (dy-2)*stride + (dx-2), |
cdaee53c5da1
replaces back some C code by dsp.put_pixels_tab[0][0] (revert r6231)
aurel
parents:
3706
diff
changeset
|
352 stride, 12); |
3695 | 353 src_block = s->edge_emu_buffer; |
354 src_offset = 2 + 2*stride; | |
355 } else { | |
356 src_block = src; | |
357 src_offset = s->block_offset[b] + dy*stride + dx; | |
358 } | |
359 | |
360 if (deblock_filtering) | |
361 vp56_deblock_filter(s, src_block, stride, dx&7, dy&7); | |
362 | |
363 if (s->mv[b].x & mask) | |
364 overlap_offset += (s->mv[b].x > 0) ? 1 : -1; | |
365 if (s->mv[b].y & mask) | |
366 overlap_offset += (s->mv[b].y > 0) ? stride : -stride; | |
367 | |
368 if (overlap_offset) { | |
369 if (s->filter) | |
370 s->filter(s, dst, src_block, src_offset, src_offset+overlap_offset, | |
371 stride, s->mv[b], mask, s->filter_selection, b<4); | |
372 else | |
373 s->dsp.put_no_rnd_pixels_l2[1](dst, src_block+src_offset, | |
374 src_block+src_offset+overlap_offset, | |
375 stride, 8); | |
376 } else { | |
377 s->dsp.put_pixels_tab[1][0](dst, src_block+src_offset, stride, 8); | |
378 } | |
379 } | |
380 | |
8299 | 381 static void vp56_decode_mb(VP56Context *s, int row, int col, int is_alpha) |
3695 | 382 { |
383 AVFrame *frame_current, *frame_ref; | |
8299 | 384 VP56mb mb_type; |
385 VP56Frame ref_frame; | |
5717 | 386 int b, ab, b_max, plane, off; |
3695 | 387 |
4595 | 388 if (s->framep[VP56_FRAME_CURRENT]->key_frame) |
3695 | 389 mb_type = VP56_MB_INTRA; |
390 else | |
391 mb_type = vp56_decode_mv(s, row, col); | |
392 ref_frame = vp56_reference_frame[mb_type]; | |
393 | |
8288 | 394 s->dsp.clear_blocks(*s->block_coeff); |
3695 | 395 |
396 s->parse_coeff(s); | |
397 | |
398 vp56_add_predictors_dc(s, ref_frame); | |
399 | |
4595 | 400 frame_current = s->framep[VP56_FRAME_CURRENT]; |
401 frame_ref = s->framep[ref_frame]; | |
3695 | 402 |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
403 ab = 6*is_alpha; |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
404 b_max = 6 - 2*is_alpha; |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
405 |
3695 | 406 switch (mb_type) { |
407 case VP56_MB_INTRA: | |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
408 for (b=0; b<b_max; b++) { |
5717 | 409 plane = vp56_b2p[b+ab]; |
410 s->dsp.idct_put(frame_current->data[plane] + s->block_offset[b], | |
411 s->stride[plane], s->block_coeff[b]); | |
3695 | 412 } |
413 break; | |
414 | |
415 case VP56_MB_INTER_NOVEC_PF: | |
416 case VP56_MB_INTER_NOVEC_GF: | |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
417 for (b=0; b<b_max; b++) { |
5717 | 418 plane = vp56_b2p[b+ab]; |
3695 | 419 off = s->block_offset[b]; |
5717 | 420 s->dsp.put_pixels_tab[1][0](frame_current->data[plane] + off, |
421 frame_ref->data[plane] + off, | |
422 s->stride[plane], 8); | |
423 s->dsp.idct_add(frame_current->data[plane] + off, | |
424 s->stride[plane], s->block_coeff[b]); | |
3695 | 425 } |
426 break; | |
427 | |
428 case VP56_MB_INTER_DELTA_PF: | |
429 case VP56_MB_INTER_V1_PF: | |
430 case VP56_MB_INTER_V2_PF: | |
431 case VP56_MB_INTER_DELTA_GF: | |
432 case VP56_MB_INTER_4V: | |
433 case VP56_MB_INTER_V1_GF: | |
434 case VP56_MB_INTER_V2_GF: | |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
435 for (b=0; b<b_max; b++) { |
3695 | 436 int x_off = b==1 || b==3 ? 8 : 0; |
437 int y_off = b==2 || b==3 ? 8 : 0; | |
5717 | 438 plane = vp56_b2p[b+ab]; |
439 vp56_mc(s, b, plane, frame_ref->data[plane], s->stride[plane], | |
3695 | 440 16*col+x_off, 16*row+y_off); |
5717 | 441 s->dsp.idct_add(frame_current->data[plane] + s->block_offset[b], |
442 s->stride[plane], s->block_coeff[b]); | |
3695 | 443 } |
444 break; | |
445 } | |
446 } | |
447 | |
5708 | 448 static int vp56_size_changed(AVCodecContext *avctx) |
3695 | 449 { |
8299 | 450 VP56Context *s = avctx->priv_data; |
4595 | 451 int stride = s->framep[VP56_FRAME_CURRENT]->linesize[0]; |
3695 | 452 int i; |
453 | |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
454 s->plane_width[0] = s->plane_width[3] = avctx->coded_width; |
5708 | 455 s->plane_width[1] = s->plane_width[2] = avctx->coded_width/2; |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
456 s->plane_height[0] = s->plane_height[3] = avctx->coded_height; |
5708 | 457 s->plane_height[1] = s->plane_height[2] = avctx->coded_height/2; |
3695 | 458 |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
459 for (i=0; i<4; i++) |
4595 | 460 s->stride[i] = s->flip * s->framep[VP56_FRAME_CURRENT]->linesize[i]; |
3695 | 461 |
5708 | 462 s->mb_width = (avctx->coded_width +15) / 16; |
463 s->mb_height = (avctx->coded_height+15) / 16; | |
3695 | 464 |
465 if (s->mb_width > 1000 || s->mb_height > 1000) { | |
466 av_log(avctx, AV_LOG_ERROR, "picture too big\n"); | |
467 return -1; | |
468 } | |
469 | |
11053
c57e72227d7d
Make VP5 and VP6 decoders output a qscale table to allow for more automatic
reimar
parents:
11050
diff
changeset
|
470 s->qscale_table = av_realloc(s->qscale_table, s->mb_width); |
3695 | 471 s->above_blocks = av_realloc(s->above_blocks, |
472 (4*s->mb_width+6) * sizeof(*s->above_blocks)); | |
473 s->macroblocks = av_realloc(s->macroblocks, | |
474 s->mb_width*s->mb_height*sizeof(*s->macroblocks)); | |
3715
cdaee53c5da1
replaces back some C code by dsp.put_pixels_tab[0][0] (revert r6231)
aurel
parents:
3706
diff
changeset
|
475 av_free(s->edge_emu_buffer_alloc); |
cdaee53c5da1
replaces back some C code by dsp.put_pixels_tab[0][0] (revert r6231)
aurel
parents:
3706
diff
changeset
|
476 s->edge_emu_buffer_alloc = av_malloc(16*stride); |
3695 | 477 s->edge_emu_buffer = s->edge_emu_buffer_alloc; |
478 if (s->flip < 0) | |
479 s->edge_emu_buffer += 15 * stride; | |
480 | |
481 return 0; | |
482 } | |
483 | |
12292 | 484 int ff_vp56_decode_frame(AVCodecContext *avctx, void *data, int *data_size, |
12294 | 485 AVPacket *avpkt) |
3695 | 486 { |
9356
2983bd7deaf5
fix vp5/vp6 decoding by using new prototype for decode function
aurel
parents:
8782
diff
changeset
|
487 const uint8_t *buf = avpkt->data; |
8299 | 488 VP56Context *s = avctx->priv_data; |
4595 | 489 AVFrame *const p = s->framep[VP56_FRAME_CURRENT]; |
9356
2983bd7deaf5
fix vp5/vp6 decoding by using new prototype for decode function
aurel
parents:
8782
diff
changeset
|
490 int remaining_buf_size = avpkt->size; |
8782 | 491 int is_alpha, av_uninit(alpha_offset); |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
492 |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
493 if (s->has_alpha) { |
11050
170c9ce34d14
vp56: check buffer size to fix a potential segfault
aurel
parents:
10968
diff
changeset
|
494 if (remaining_buf_size < 3) |
170c9ce34d14
vp56: check buffer size to fix a potential segfault
aurel
parents:
10968
diff
changeset
|
495 return -1; |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
496 alpha_offset = bytestream_get_be24(&buf); |
6756
c00f5cad61cc
ensure vp56_decode_frame always return unchanged buf_size
aurel
parents:
6517
diff
changeset
|
497 remaining_buf_size -= 3; |
11050
170c9ce34d14
vp56: check buffer size to fix a potential segfault
aurel
parents:
10968
diff
changeset
|
498 if (remaining_buf_size < alpha_offset) |
170c9ce34d14
vp56: check buffer size to fix a potential segfault
aurel
parents:
10968
diff
changeset
|
499 return -1; |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
500 } |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
501 |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
502 for (is_alpha=0; is_alpha < 1+s->has_alpha; is_alpha++) { |
5715 | 503 int mb_row, mb_col, mb_row_flip, mb_offset = 0; |
504 int block, y, uv, stride_y, stride_uv; | |
505 int golden_frame = 0; | |
506 int res; | |
3695 | 507 |
5715 | 508 s->modelp = &s->models[is_alpha]; |
3695 | 509 |
6756
c00f5cad61cc
ensure vp56_decode_frame always return unchanged buf_size
aurel
parents:
6517
diff
changeset
|
510 res = s->parse_header(s, buf, remaining_buf_size, &golden_frame); |
5715 | 511 if (!res) |
512 return -1; | |
3695 | 513 |
5715 | 514 if (!is_alpha) { |
515 p->reference = 1; | |
516 if (avctx->get_buffer(avctx, p) < 0) { | |
517 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
518 return -1; | |
3695 | 519 } |
520 | |
5715 | 521 if (res == 2) |
522 if (vp56_size_changed(avctx)) { | |
523 avctx->release_buffer(avctx, p); | |
524 return -1; | |
525 } | |
526 } | |
527 | |
528 if (p->key_frame) { | |
529 p->pict_type = FF_I_TYPE; | |
530 s->default_models_init(s); | |
531 for (block=0; block<s->mb_height*s->mb_width; block++) | |
532 s->macroblocks[block].type = VP56_MB_INTRA; | |
533 } else { | |
534 p->pict_type = FF_P_TYPE; | |
535 vp56_parse_mb_type_models(s); | |
536 s->parse_vector_models(s); | |
537 s->mb_type = VP56_MB_INTER_NOVEC_PF; | |
538 } | |
539 | |
540 s->parse_coeff_models(s); | |
541 | |
542 memset(s->prev_dc, 0, sizeof(s->prev_dc)); | |
543 s->prev_dc[1][VP56_FRAME_CURRENT] = 128; | |
544 s->prev_dc[2][VP56_FRAME_CURRENT] = 128; | |
545 | |
546 for (block=0; block < 4*s->mb_width+6; block++) { | |
6795 | 547 s->above_blocks[block].ref_frame = VP56_FRAME_NONE; |
5715 | 548 s->above_blocks[block].dc_coeff = 0; |
549 s->above_blocks[block].not_null_dc = 0; | |
550 } | |
6795 | 551 s->above_blocks[2*s->mb_width + 2].ref_frame = VP56_FRAME_CURRENT; |
552 s->above_blocks[3*s->mb_width + 4].ref_frame = VP56_FRAME_CURRENT; | |
5715 | 553 |
554 stride_y = p->linesize[0]; | |
555 stride_uv = p->linesize[1]; | |
556 | |
557 if (s->flip < 0) | |
558 mb_offset = 7; | |
559 | |
560 /* main macroblocks loop */ | |
561 for (mb_row=0; mb_row<s->mb_height; mb_row++) { | |
562 if (s->flip < 0) | |
563 mb_row_flip = s->mb_height - mb_row - 1; | |
564 else | |
565 mb_row_flip = mb_row; | |
566 | |
567 for (block=0; block<4; block++) { | |
6795 | 568 s->left_block[block].ref_frame = VP56_FRAME_NONE; |
5715 | 569 s->left_block[block].dc_coeff = 0; |
570 s->left_block[block].not_null_dc = 0; | |
571 } | |
5716 | 572 memset(s->coeff_ctx, 0, sizeof(s->coeff_ctx)); |
5715 | 573 memset(s->coeff_ctx_last, 24, sizeof(s->coeff_ctx_last)); |
574 | |
575 s->above_block_idx[0] = 1; | |
576 s->above_block_idx[1] = 2; | |
577 s->above_block_idx[2] = 1; | |
578 s->above_block_idx[3] = 2; | |
579 s->above_block_idx[4] = 2*s->mb_width + 2 + 1; | |
580 s->above_block_idx[5] = 3*s->mb_width + 4 + 1; | |
581 | |
582 s->block_offset[s->frbi] = (mb_row_flip*16 + mb_offset) * stride_y; | |
583 s->block_offset[s->srbi] = s->block_offset[s->frbi] + 8*stride_y; | |
584 s->block_offset[1] = s->block_offset[0] + 8; | |
585 s->block_offset[3] = s->block_offset[2] + 8; | |
586 s->block_offset[4] = (mb_row_flip*8 + mb_offset) * stride_uv; | |
587 s->block_offset[5] = s->block_offset[4]; | |
588 | |
589 for (mb_col=0; mb_col<s->mb_width; mb_col++) { | |
590 vp56_decode_mb(s, mb_row, mb_col, is_alpha); | |
591 | |
592 for (y=0; y<4; y++) { | |
593 s->above_block_idx[y] += 2; | |
594 s->block_offset[y] += 16; | |
595 } | |
596 | |
597 for (uv=4; uv<6; uv++) { | |
598 s->above_block_idx[uv] += 1; | |
599 s->block_offset[uv] += 8; | |
600 } | |
3695 | 601 } |
602 } | |
603 | |
5715 | 604 if (p->key_frame || golden_frame) { |
605 if (s->framep[VP56_FRAME_GOLDEN]->data[0] && | |
606 s->framep[VP56_FRAME_GOLDEN] != s->framep[VP56_FRAME_GOLDEN2]) | |
607 avctx->release_buffer(avctx, s->framep[VP56_FRAME_GOLDEN]); | |
608 s->framep[VP56_FRAME_GOLDEN] = p; | |
609 } | |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
610 |
5715 | 611 if (s->has_alpha) { |
612 FFSWAP(AVFrame *, s->framep[VP56_FRAME_GOLDEN], | |
613 s->framep[VP56_FRAME_GOLDEN2]); | |
614 buf += alpha_offset; | |
6756
c00f5cad61cc
ensure vp56_decode_frame always return unchanged buf_size
aurel
parents:
6517
diff
changeset
|
615 remaining_buf_size -= alpha_offset; |
5715 | 616 } |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
617 } |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
618 |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
619 if (s->framep[VP56_FRAME_PREVIOUS] == s->framep[VP56_FRAME_GOLDEN] || |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
620 s->framep[VP56_FRAME_PREVIOUS] == s->framep[VP56_FRAME_GOLDEN2]) { |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
621 if (s->framep[VP56_FRAME_UNUSED] != s->framep[VP56_FRAME_GOLDEN] && |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
622 s->framep[VP56_FRAME_UNUSED] != s->framep[VP56_FRAME_GOLDEN2]) |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
623 FFSWAP(AVFrame *, s->framep[VP56_FRAME_PREVIOUS], |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
624 s->framep[VP56_FRAME_UNUSED]); |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
625 else |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
626 FFSWAP(AVFrame *, s->framep[VP56_FRAME_PREVIOUS], |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
627 s->framep[VP56_FRAME_UNUSED2]); |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
628 } else if (s->framep[VP56_FRAME_PREVIOUS]->data[0]) |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
629 avctx->release_buffer(avctx, s->framep[VP56_FRAME_PREVIOUS]); |
4595 | 630 FFSWAP(AVFrame *, s->framep[VP56_FRAME_CURRENT], |
631 s->framep[VP56_FRAME_PREVIOUS]); | |
3695 | 632 |
11053
c57e72227d7d
Make VP5 and VP6 decoders output a qscale table to allow for more automatic
reimar
parents:
11050
diff
changeset
|
633 p->qstride = 0; |
c57e72227d7d
Make VP5 and VP6 decoders output a qscale table to allow for more automatic
reimar
parents:
11050
diff
changeset
|
634 p->qscale_table = s->qscale_table; |
c57e72227d7d
Make VP5 and VP6 decoders output a qscale table to allow for more automatic
reimar
parents:
11050
diff
changeset
|
635 p->qscale_type = FF_QSCALE_TYPE_VP56; |
4596 | 636 *(AVFrame*)data = *p; |
637 *data_size = sizeof(AVFrame); | |
3695 | 638 |
9356
2983bd7deaf5
fix vp5/vp6 decoding by using new prototype for decode function
aurel
parents:
8782
diff
changeset
|
639 return avpkt->size; |
3695 | 640 } |
641 | |
12292 | 642 av_cold void ff_vp56_init(AVCodecContext *avctx, int flip, int has_alpha) |
3695 | 643 { |
8299 | 644 VP56Context *s = avctx->priv_data; |
3695 | 645 int i; |
646 | |
647 s->avctx = avctx; | |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
648 avctx->pix_fmt = has_alpha ? PIX_FMT_YUVA420P : PIX_FMT_YUV420P; |
3695 | 649 |
5708 | 650 if (avctx->idct_algo == FF_IDCT_AUTO) |
651 avctx->idct_algo = FF_IDCT_VP3; | |
652 dsputil_init(&s->dsp, avctx); | |
11665 | 653 ff_vp56dsp_init(&s->vp56dsp, avctx->codec->id); |
3695 | 654 ff_init_scantable(s->dsp.idct_permutation, &s->scantable,ff_zigzag_direct); |
655 | |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
656 for (i=0; i<4; i++) |
4595 | 657 s->framep[i] = &s->frames[i]; |
658 s->framep[VP56_FRAME_UNUSED] = s->framep[VP56_FRAME_GOLDEN]; | |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
659 s->framep[VP56_FRAME_UNUSED2] = s->framep[VP56_FRAME_GOLDEN2]; |
3695 | 660 s->edge_emu_buffer_alloc = NULL; |
661 | |
662 s->above_blocks = NULL; | |
663 s->macroblocks = NULL; | |
664 s->quantizer = -1; | |
665 s->deblock_filtering = 1; | |
666 | |
667 s->filter = NULL; | |
668 | |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
669 s->has_alpha = has_alpha; |
3695 | 670 if (flip) { |
671 s->flip = -1; | |
672 s->frbi = 2; | |
673 s->srbi = 0; | |
674 } else { | |
675 s->flip = 1; | |
676 s->frbi = 0; | |
677 s->srbi = 2; | |
678 } | |
679 } | |
680 | |
12292 | 681 av_cold int ff_vp56_free(AVCodecContext *avctx) |
3695 | 682 { |
8299 | 683 VP56Context *s = avctx->priv_data; |
3695 | 684 |
11053
c57e72227d7d
Make VP5 and VP6 decoders output a qscale table to allow for more automatic
reimar
parents:
11050
diff
changeset
|
685 av_freep(&s->qscale_table); |
10968
c1cccc058c7a
Use av_freep intead of av_free to free pointers in vp56 context.
reimar
parents:
9356
diff
changeset
|
686 av_freep(&s->above_blocks); |
c1cccc058c7a
Use av_freep intead of av_free to free pointers in vp56 context.
reimar
parents:
9356
diff
changeset
|
687 av_freep(&s->macroblocks); |
c1cccc058c7a
Use av_freep intead of av_free to free pointers in vp56 context.
reimar
parents:
9356
diff
changeset
|
688 av_freep(&s->edge_emu_buffer_alloc); |
5708 | 689 if (s->framep[VP56_FRAME_GOLDEN]->data[0]) |
4595 | 690 avctx->release_buffer(avctx, s->framep[VP56_FRAME_GOLDEN]); |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
691 if (s->framep[VP56_FRAME_GOLDEN2]->data[0]) |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
692 avctx->release_buffer(avctx, s->framep[VP56_FRAME_GOLDEN2]); |
4595 | 693 if (s->framep[VP56_FRAME_PREVIOUS]->data[0]) |
694 avctx->release_buffer(avctx, s->framep[VP56_FRAME_PREVIOUS]); | |
3695 | 695 return 0; |
696 } |