Mercurial > libavcodec.hg
annotate vp56.c @ 11352:6e0af2cfdcfe libavcodec
Do MC and IDCT in coding (hilbert) order
This increases the slice size to 64 pixels, due to having to decode an
entire chroma superblock row per slice.
This can be up to 6% slower depending on clip and CPU, but is necessary
for future optimizations that gain significantly more than was lost.
author | conrad |
---|---|
date | Wed, 03 Mar 2010 23:27:40 +0000 |
parents | 7d9a1a807e91 |
children | 7dd2a45249a9 |
rev | line source |
---|---|
3695 | 1 /** |
8718
e9d9d946f213
Use full internal pathname in doxygen @file directives.
diego
parents:
8329
diff
changeset
|
2 * @file libavcodec/vp56.c |
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 | |
8299 | 31 void 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_edge_filter(VP56Context *s, uint8_t *yuv, |
3695 | 304 int pix_inc, int line_inc, int t) |
305 { | |
306 int pix2_inc = 2 * pix_inc; | |
307 int i, v; | |
308 | |
309 for (i=0; i<12; i++) { | |
310 v = (yuv[-pix2_inc] + 3*(yuv[0]-yuv[-pix_inc]) - yuv[pix_inc] + 4) >>3; | |
311 v = s->adjust(v, t); | |
4594 | 312 yuv[-pix_inc] = av_clip_uint8(yuv[-pix_inc] + v); |
313 yuv[0] = av_clip_uint8(yuv[0] - v); | |
3695 | 314 yuv += line_inc; |
315 } | |
316 } | |
317 | |
8299 | 318 static void vp56_deblock_filter(VP56Context *s, uint8_t *yuv, |
3695 | 319 int stride, int dx, int dy) |
320 { | |
321 int t = vp56_filter_threshold[s->quantizer]; | |
322 if (dx) vp56_edge_filter(s, yuv + 10-dx , 1, stride, t); | |
323 if (dy) vp56_edge_filter(s, yuv + stride*(10-dy), stride, 1, t); | |
324 } | |
325 | |
8299 | 326 static void vp56_mc(VP56Context *s, int b, int plane, uint8_t *src, |
3695 | 327 int stride, int x, int y) |
328 { | |
4595 | 329 uint8_t *dst=s->framep[VP56_FRAME_CURRENT]->data[plane]+s->block_offset[b]; |
3695 | 330 uint8_t *src_block; |
331 int src_offset; | |
332 int overlap_offset = 0; | |
333 int mask = s->vp56_coord_div[b] - 1; | |
334 int deblock_filtering = s->deblock_filtering; | |
335 int dx; | |
336 int dy; | |
337 | |
338 if (s->avctx->skip_loop_filter >= AVDISCARD_ALL || | |
339 (s->avctx->skip_loop_filter >= AVDISCARD_NONKEY | |
4595 | 340 && !s->framep[VP56_FRAME_CURRENT]->key_frame)) |
3695 | 341 deblock_filtering = 0; |
342 | |
343 dx = s->mv[b].x / s->vp56_coord_div[b]; | |
344 dy = s->mv[b].y / s->vp56_coord_div[b]; | |
345 | |
346 if (b >= 4) { | |
347 x /= 2; | |
348 y /= 2; | |
349 } | |
350 x += dx - 2; | |
351 y += dy - 2; | |
352 | |
353 if (x<0 || x+12>=s->plane_width[plane] || | |
354 y<0 || y+12>=s->plane_height[plane]) { | |
355 ff_emulated_edge_mc(s->edge_emu_buffer, | |
356 src + s->block_offset[b] + (dy-2)*stride + (dx-2), | |
357 stride, 12, 12, x, y, | |
358 s->plane_width[plane], | |
359 s->plane_height[plane]); | |
360 src_block = s->edge_emu_buffer; | |
361 src_offset = 2 + 2*stride; | |
362 } 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
|
363 /* 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
|
364 /* 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
|
365 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
|
366 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
|
367 stride, 12); |
3695 | 368 src_block = s->edge_emu_buffer; |
369 src_offset = 2 + 2*stride; | |
370 } else { | |
371 src_block = src; | |
372 src_offset = s->block_offset[b] + dy*stride + dx; | |
373 } | |
374 | |
375 if (deblock_filtering) | |
376 vp56_deblock_filter(s, src_block, stride, dx&7, dy&7); | |
377 | |
378 if (s->mv[b].x & mask) | |
379 overlap_offset += (s->mv[b].x > 0) ? 1 : -1; | |
380 if (s->mv[b].y & mask) | |
381 overlap_offset += (s->mv[b].y > 0) ? stride : -stride; | |
382 | |
383 if (overlap_offset) { | |
384 if (s->filter) | |
385 s->filter(s, dst, src_block, src_offset, src_offset+overlap_offset, | |
386 stride, s->mv[b], mask, s->filter_selection, b<4); | |
387 else | |
388 s->dsp.put_no_rnd_pixels_l2[1](dst, src_block+src_offset, | |
389 src_block+src_offset+overlap_offset, | |
390 stride, 8); | |
391 } else { | |
392 s->dsp.put_pixels_tab[1][0](dst, src_block+src_offset, stride, 8); | |
393 } | |
394 } | |
395 | |
8299 | 396 static void vp56_decode_mb(VP56Context *s, int row, int col, int is_alpha) |
3695 | 397 { |
398 AVFrame *frame_current, *frame_ref; | |
8299 | 399 VP56mb mb_type; |
400 VP56Frame ref_frame; | |
5717 | 401 int b, ab, b_max, plane, off; |
3695 | 402 |
4595 | 403 if (s->framep[VP56_FRAME_CURRENT]->key_frame) |
3695 | 404 mb_type = VP56_MB_INTRA; |
405 else | |
406 mb_type = vp56_decode_mv(s, row, col); | |
407 ref_frame = vp56_reference_frame[mb_type]; | |
408 | |
8288 | 409 s->dsp.clear_blocks(*s->block_coeff); |
3695 | 410 |
411 s->parse_coeff(s); | |
412 | |
413 vp56_add_predictors_dc(s, ref_frame); | |
414 | |
4595 | 415 frame_current = s->framep[VP56_FRAME_CURRENT]; |
416 frame_ref = s->framep[ref_frame]; | |
3695 | 417 |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
418 ab = 6*is_alpha; |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
419 b_max = 6 - 2*is_alpha; |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
420 |
3695 | 421 switch (mb_type) { |
422 case VP56_MB_INTRA: | |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
423 for (b=0; b<b_max; b++) { |
5717 | 424 plane = vp56_b2p[b+ab]; |
425 s->dsp.idct_put(frame_current->data[plane] + s->block_offset[b], | |
426 s->stride[plane], s->block_coeff[b]); | |
3695 | 427 } |
428 break; | |
429 | |
430 case VP56_MB_INTER_NOVEC_PF: | |
431 case VP56_MB_INTER_NOVEC_GF: | |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
432 for (b=0; b<b_max; b++) { |
5717 | 433 plane = vp56_b2p[b+ab]; |
3695 | 434 off = s->block_offset[b]; |
5717 | 435 s->dsp.put_pixels_tab[1][0](frame_current->data[plane] + off, |
436 frame_ref->data[plane] + off, | |
437 s->stride[plane], 8); | |
438 s->dsp.idct_add(frame_current->data[plane] + off, | |
439 s->stride[plane], s->block_coeff[b]); | |
3695 | 440 } |
441 break; | |
442 | |
443 case VP56_MB_INTER_DELTA_PF: | |
444 case VP56_MB_INTER_V1_PF: | |
445 case VP56_MB_INTER_V2_PF: | |
446 case VP56_MB_INTER_DELTA_GF: | |
447 case VP56_MB_INTER_4V: | |
448 case VP56_MB_INTER_V1_GF: | |
449 case VP56_MB_INTER_V2_GF: | |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
450 for (b=0; b<b_max; b++) { |
3695 | 451 int x_off = b==1 || b==3 ? 8 : 0; |
452 int y_off = b==2 || b==3 ? 8 : 0; | |
5717 | 453 plane = vp56_b2p[b+ab]; |
454 vp56_mc(s, b, plane, frame_ref->data[plane], s->stride[plane], | |
3695 | 455 16*col+x_off, 16*row+y_off); |
5717 | 456 s->dsp.idct_add(frame_current->data[plane] + s->block_offset[b], |
457 s->stride[plane], s->block_coeff[b]); | |
3695 | 458 } |
459 break; | |
460 } | |
461 } | |
462 | |
5708 | 463 static int vp56_size_changed(AVCodecContext *avctx) |
3695 | 464 { |
8299 | 465 VP56Context *s = avctx->priv_data; |
4595 | 466 int stride = s->framep[VP56_FRAME_CURRENT]->linesize[0]; |
3695 | 467 int i; |
468 | |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
469 s->plane_width[0] = s->plane_width[3] = avctx->coded_width; |
5708 | 470 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
|
471 s->plane_height[0] = s->plane_height[3] = avctx->coded_height; |
5708 | 472 s->plane_height[1] = s->plane_height[2] = avctx->coded_height/2; |
3695 | 473 |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
474 for (i=0; i<4; i++) |
4595 | 475 s->stride[i] = s->flip * s->framep[VP56_FRAME_CURRENT]->linesize[i]; |
3695 | 476 |
5708 | 477 s->mb_width = (avctx->coded_width +15) / 16; |
478 s->mb_height = (avctx->coded_height+15) / 16; | |
3695 | 479 |
480 if (s->mb_width > 1000 || s->mb_height > 1000) { | |
481 av_log(avctx, AV_LOG_ERROR, "picture too big\n"); | |
482 return -1; | |
483 } | |
484 | |
11053
c57e72227d7d
Make VP5 and VP6 decoders output a qscale table to allow for more automatic
reimar
parents:
11050
diff
changeset
|
485 s->qscale_table = av_realloc(s->qscale_table, s->mb_width); |
3695 | 486 s->above_blocks = av_realloc(s->above_blocks, |
487 (4*s->mb_width+6) * sizeof(*s->above_blocks)); | |
488 s->macroblocks = av_realloc(s->macroblocks, | |
489 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
|
490 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
|
491 s->edge_emu_buffer_alloc = av_malloc(16*stride); |
3695 | 492 s->edge_emu_buffer = s->edge_emu_buffer_alloc; |
493 if (s->flip < 0) | |
494 s->edge_emu_buffer += 15 * stride; | |
495 | |
496 return 0; | |
497 } | |
498 | |
499 int vp56_decode_frame(AVCodecContext *avctx, void *data, int *data_size, | |
9356
2983bd7deaf5
fix vp5/vp6 decoding by using new prototype for decode function
aurel
parents:
8782
diff
changeset
|
500 AVPacket *avpkt) |
3695 | 501 { |
9356
2983bd7deaf5
fix vp5/vp6 decoding by using new prototype for decode function
aurel
parents:
8782
diff
changeset
|
502 const uint8_t *buf = avpkt->data; |
8299 | 503 VP56Context *s = avctx->priv_data; |
4595 | 504 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
|
505 int remaining_buf_size = avpkt->size; |
8782 | 506 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
|
507 |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
508 if (s->has_alpha) { |
11050
170c9ce34d14
vp56: check buffer size to fix a potential segfault
aurel
parents:
10968
diff
changeset
|
509 if (remaining_buf_size < 3) |
170c9ce34d14
vp56: check buffer size to fix a potential segfault
aurel
parents:
10968
diff
changeset
|
510 return -1; |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
511 alpha_offset = bytestream_get_be24(&buf); |
6756
c00f5cad61cc
ensure vp56_decode_frame always return unchanged buf_size
aurel
parents:
6517
diff
changeset
|
512 remaining_buf_size -= 3; |
11050
170c9ce34d14
vp56: check buffer size to fix a potential segfault
aurel
parents:
10968
diff
changeset
|
513 if (remaining_buf_size < alpha_offset) |
170c9ce34d14
vp56: check buffer size to fix a potential segfault
aurel
parents:
10968
diff
changeset
|
514 return -1; |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
515 } |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
516 |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
517 for (is_alpha=0; is_alpha < 1+s->has_alpha; is_alpha++) { |
5715 | 518 int mb_row, mb_col, mb_row_flip, mb_offset = 0; |
519 int block, y, uv, stride_y, stride_uv; | |
520 int golden_frame = 0; | |
521 int res; | |
3695 | 522 |
5715 | 523 s->modelp = &s->models[is_alpha]; |
3695 | 524 |
6756
c00f5cad61cc
ensure vp56_decode_frame always return unchanged buf_size
aurel
parents:
6517
diff
changeset
|
525 res = s->parse_header(s, buf, remaining_buf_size, &golden_frame); |
5715 | 526 if (!res) |
527 return -1; | |
3695 | 528 |
5715 | 529 if (!is_alpha) { |
530 p->reference = 1; | |
531 if (avctx->get_buffer(avctx, p) < 0) { | |
532 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
533 return -1; | |
3695 | 534 } |
535 | |
5715 | 536 if (res == 2) |
537 if (vp56_size_changed(avctx)) { | |
538 avctx->release_buffer(avctx, p); | |
539 return -1; | |
540 } | |
541 } | |
542 | |
543 if (p->key_frame) { | |
544 p->pict_type = FF_I_TYPE; | |
545 s->default_models_init(s); | |
546 for (block=0; block<s->mb_height*s->mb_width; block++) | |
547 s->macroblocks[block].type = VP56_MB_INTRA; | |
548 } else { | |
549 p->pict_type = FF_P_TYPE; | |
550 vp56_parse_mb_type_models(s); | |
551 s->parse_vector_models(s); | |
552 s->mb_type = VP56_MB_INTER_NOVEC_PF; | |
553 } | |
554 | |
555 s->parse_coeff_models(s); | |
556 | |
557 memset(s->prev_dc, 0, sizeof(s->prev_dc)); | |
558 s->prev_dc[1][VP56_FRAME_CURRENT] = 128; | |
559 s->prev_dc[2][VP56_FRAME_CURRENT] = 128; | |
560 | |
561 for (block=0; block < 4*s->mb_width+6; block++) { | |
6795 | 562 s->above_blocks[block].ref_frame = VP56_FRAME_NONE; |
5715 | 563 s->above_blocks[block].dc_coeff = 0; |
564 s->above_blocks[block].not_null_dc = 0; | |
565 } | |
6795 | 566 s->above_blocks[2*s->mb_width + 2].ref_frame = VP56_FRAME_CURRENT; |
567 s->above_blocks[3*s->mb_width + 4].ref_frame = VP56_FRAME_CURRENT; | |
5715 | 568 |
569 stride_y = p->linesize[0]; | |
570 stride_uv = p->linesize[1]; | |
571 | |
572 if (s->flip < 0) | |
573 mb_offset = 7; | |
574 | |
575 /* main macroblocks loop */ | |
576 for (mb_row=0; mb_row<s->mb_height; mb_row++) { | |
577 if (s->flip < 0) | |
578 mb_row_flip = s->mb_height - mb_row - 1; | |
579 else | |
580 mb_row_flip = mb_row; | |
581 | |
582 for (block=0; block<4; block++) { | |
6795 | 583 s->left_block[block].ref_frame = VP56_FRAME_NONE; |
5715 | 584 s->left_block[block].dc_coeff = 0; |
585 s->left_block[block].not_null_dc = 0; | |
586 } | |
5716 | 587 memset(s->coeff_ctx, 0, sizeof(s->coeff_ctx)); |
5715 | 588 memset(s->coeff_ctx_last, 24, sizeof(s->coeff_ctx_last)); |
589 | |
590 s->above_block_idx[0] = 1; | |
591 s->above_block_idx[1] = 2; | |
592 s->above_block_idx[2] = 1; | |
593 s->above_block_idx[3] = 2; | |
594 s->above_block_idx[4] = 2*s->mb_width + 2 + 1; | |
595 s->above_block_idx[5] = 3*s->mb_width + 4 + 1; | |
596 | |
597 s->block_offset[s->frbi] = (mb_row_flip*16 + mb_offset) * stride_y; | |
598 s->block_offset[s->srbi] = s->block_offset[s->frbi] + 8*stride_y; | |
599 s->block_offset[1] = s->block_offset[0] + 8; | |
600 s->block_offset[3] = s->block_offset[2] + 8; | |
601 s->block_offset[4] = (mb_row_flip*8 + mb_offset) * stride_uv; | |
602 s->block_offset[5] = s->block_offset[4]; | |
603 | |
604 for (mb_col=0; mb_col<s->mb_width; mb_col++) { | |
605 vp56_decode_mb(s, mb_row, mb_col, is_alpha); | |
606 | |
607 for (y=0; y<4; y++) { | |
608 s->above_block_idx[y] += 2; | |
609 s->block_offset[y] += 16; | |
610 } | |
611 | |
612 for (uv=4; uv<6; uv++) { | |
613 s->above_block_idx[uv] += 1; | |
614 s->block_offset[uv] += 8; | |
615 } | |
3695 | 616 } |
617 } | |
618 | |
5715 | 619 if (p->key_frame || golden_frame) { |
620 if (s->framep[VP56_FRAME_GOLDEN]->data[0] && | |
621 s->framep[VP56_FRAME_GOLDEN] != s->framep[VP56_FRAME_GOLDEN2]) | |
622 avctx->release_buffer(avctx, s->framep[VP56_FRAME_GOLDEN]); | |
623 s->framep[VP56_FRAME_GOLDEN] = p; | |
624 } | |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
625 |
5715 | 626 if (s->has_alpha) { |
627 FFSWAP(AVFrame *, s->framep[VP56_FRAME_GOLDEN], | |
628 s->framep[VP56_FRAME_GOLDEN2]); | |
629 buf += alpha_offset; | |
6756
c00f5cad61cc
ensure vp56_decode_frame always return unchanged buf_size
aurel
parents:
6517
diff
changeset
|
630 remaining_buf_size -= alpha_offset; |
5715 | 631 } |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
632 } |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
633 |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
634 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
|
635 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
|
636 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
|
637 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
|
638 FFSWAP(AVFrame *, s->framep[VP56_FRAME_PREVIOUS], |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
639 s->framep[VP56_FRAME_UNUSED]); |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
640 else |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
641 FFSWAP(AVFrame *, s->framep[VP56_FRAME_PREVIOUS], |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
642 s->framep[VP56_FRAME_UNUSED2]); |
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
643 } 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
|
644 avctx->release_buffer(avctx, s->framep[VP56_FRAME_PREVIOUS]); |
4595 | 645 FFSWAP(AVFrame *, s->framep[VP56_FRAME_CURRENT], |
646 s->framep[VP56_FRAME_PREVIOUS]); | |
3695 | 647 |
11053
c57e72227d7d
Make VP5 and VP6 decoders output a qscale table to allow for more automatic
reimar
parents:
11050
diff
changeset
|
648 p->qstride = 0; |
c57e72227d7d
Make VP5 and VP6 decoders output a qscale table to allow for more automatic
reimar
parents:
11050
diff
changeset
|
649 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
|
650 p->qscale_type = FF_QSCALE_TYPE_VP56; |
4596 | 651 *(AVFrame*)data = *p; |
652 *data_size = sizeof(AVFrame); | |
3695 | 653 |
9356
2983bd7deaf5
fix vp5/vp6 decoding by using new prototype for decode function
aurel
parents:
8782
diff
changeset
|
654 return avpkt->size; |
3695 | 655 } |
656 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6297
diff
changeset
|
657 av_cold void vp56_init(AVCodecContext *avctx, int flip, int has_alpha) |
3695 | 658 { |
8299 | 659 VP56Context *s = avctx->priv_data; |
3695 | 660 int i; |
661 | |
662 s->avctx = avctx; | |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
663 avctx->pix_fmt = has_alpha ? PIX_FMT_YUVA420P : PIX_FMT_YUV420P; |
3695 | 664 |
5708 | 665 if (avctx->idct_algo == FF_IDCT_AUTO) |
666 avctx->idct_algo = FF_IDCT_VP3; | |
667 dsputil_init(&s->dsp, avctx); | |
3695 | 668 ff_init_scantable(s->dsp.idct_permutation, &s->scantable,ff_zigzag_direct); |
669 | |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
670 for (i=0; i<4; i++) |
4595 | 671 s->framep[i] = &s->frames[i]; |
672 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
|
673 s->framep[VP56_FRAME_UNUSED2] = s->framep[VP56_FRAME_GOLDEN2]; |
3695 | 674 s->edge_emu_buffer_alloc = NULL; |
675 | |
676 s->above_blocks = NULL; | |
677 s->macroblocks = NULL; | |
678 s->quantizer = -1; | |
679 s->deblock_filtering = 1; | |
680 | |
681 s->filter = NULL; | |
682 | |
5714
314be1cfdcb0
add a new vp6a codec (add alpha plan support to vp6)
aurel
parents:
5711
diff
changeset
|
683 s->has_alpha = has_alpha; |
3695 | 684 if (flip) { |
685 s->flip = -1; | |
686 s->frbi = 2; | |
687 s->srbi = 0; | |
688 } else { | |
689 s->flip = 1; | |
690 s->frbi = 0; | |
691 s->srbi = 2; | |
692 } | |
693 } | |
694 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6297
diff
changeset
|
695 av_cold int vp56_free(AVCodecContext *avctx) |
3695 | 696 { |
8299 | 697 VP56Context *s = avctx->priv_data; |
3695 | 698 |
11053
c57e72227d7d
Make VP5 and VP6 decoders output a qscale table to allow for more automatic
reimar
parents:
11050
diff
changeset
|
699 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
|
700 av_freep(&s->above_blocks); |
c1cccc058c7a
Use av_freep intead of av_free to free pointers in vp56 context.
reimar
parents:
9356
diff
changeset
|
701 av_freep(&s->macroblocks); |
c1cccc058c7a
Use av_freep intead of av_free to free pointers in vp56 context.
reimar
parents:
9356
diff
changeset
|
702 av_freep(&s->edge_emu_buffer_alloc); |
5708 | 703 if (s->framep[VP56_FRAME_GOLDEN]->data[0]) |
4595 | 704 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
|
705 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
|
706 avctx->release_buffer(avctx, s->framep[VP56_FRAME_GOLDEN2]); |
4595 | 707 if (s->framep[VP56_FRAME_PREVIOUS]->data[0]) |
708 avctx->release_buffer(avctx, s->framep[VP56_FRAME_PREVIOUS]); | |
3695 | 709 return 0; |
710 } |