Mercurial > libavcodec.hg
annotate dnxhddec.c @ 12266:48d6738904a9 libavcodec
Fix SPLATB_REG mess. Used to be a if/elseif/elseif/elseif spaghetti, so this
splits it into small optimization-specific macros which are selected for each
DSP function. The advantage of this approach is that the sse4 functions now
use the ssse3 codepath also without needing an explicit sse4 codepath.
author | rbultje |
---|---|
date | Sat, 24 Jul 2010 19:33:05 +0000 |
parents | 8a4984c5cacc |
children | 914f484bb476 |
rev | line source |
---|---|
4687 | 1 /* |
2 * VC3/DNxHD decoder. | |
8629
04423b2f6e0b
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
8291
diff
changeset
|
3 * Copyright (c) 2007 SmartJog S.A., Baptiste Coudurier <baptiste dot coudurier at smartjog dot com> |
4687 | 4 * |
5 * This file is part of FFmpeg. | |
6 * | |
7 * FFmpeg is free software; you can redistribute it and/or | |
8 * modify it under the terms of the GNU Lesser General Public | |
9 * License as published by the Free Software Foundation; either | |
10 * version 2.1 of the License, or (at your option) any later version. | |
11 * | |
12 * FFmpeg is distributed in the hope that it will be useful, | |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Lesser General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Lesser General Public | |
18 * License along with FFmpeg; if not, write to the Free Software | |
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
20 */ | |
21 | |
22 //#define TRACE | |
23 //#define DEBUG | |
24 | |
25 #include "avcodec.h" | |
9428 | 26 #include "get_bits.h" |
4687 | 27 #include "dnxhddata.h" |
28 #include "dsputil.h" | |
29 | |
30 typedef struct { | |
31 AVCodecContext *avctx; | |
32 AVFrame picture; | |
33 GetBitContext gb; | |
34 int cid; ///< compression id | |
35 unsigned int width, height; | |
36 unsigned int mb_width, mb_height; | |
37 uint32_t mb_scan_index[68]; /* max for 1080p */ | |
38 int cur_field; ///< current interlaced field | |
39 VLC ac_vlc, dc_vlc, run_vlc; | |
40 int last_dc[3]; | |
41 DSPContext dsp; | |
11369 | 42 DECLARE_ALIGNED(16, DCTELEM, blocks)[8][64]; |
10093 | 43 ScanTable scantable; |
4687 | 44 const CIDEntry *cid_table; |
45 } DNXHDContext; | |
46 | |
47 #define DNXHD_VLC_BITS 9 | |
5794
8412118b41d3
preliminary 10 bit depth decoding support, still miss generic api to export picture, working on it
bcoudurier
parents:
5793
diff
changeset
|
48 #define DNXHD_DC_VLC_BITS 7 |
4687 | 49 |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6448
diff
changeset
|
50 static av_cold int dnxhd_decode_init(AVCodecContext *avctx) |
4687 | 51 { |
52 DNXHDContext *ctx = avctx->priv_data; | |
53 | |
54 ctx->avctx = avctx; | |
55 dsputil_init(&ctx->dsp, avctx); | |
56 avctx->coded_frame = &ctx->picture; | |
57 ctx->picture.type = FF_I_TYPE; | |
58 return 0; | |
59 } | |
60 | |
61 static int dnxhd_init_vlc(DNXHDContext *ctx, int cid) | |
62 { | |
63 if (!ctx->cid_table) { | |
64 int index; | |
65 | |
5473 | 66 if ((index = ff_dnxhd_get_cid_table(cid)) < 0) { |
4687 | 67 av_log(ctx->avctx, AV_LOG_ERROR, "unsupported cid %d\n", cid); |
68 return -1; | |
69 } | |
5473 | 70 ctx->cid_table = &ff_dnxhd_cid_table[index]; |
4687 | 71 init_vlc(&ctx->ac_vlc, DNXHD_VLC_BITS, 257, |
5465 | 72 ctx->cid_table->ac_bits, 1, 1, |
73 ctx->cid_table->ac_codes, 2, 2, 0); | |
5794
8412118b41d3
preliminary 10 bit depth decoding support, still miss generic api to export picture, working on it
bcoudurier
parents:
5793
diff
changeset
|
74 init_vlc(&ctx->dc_vlc, DNXHD_DC_VLC_BITS, ctx->cid_table->bit_depth+4, |
5465 | 75 ctx->cid_table->dc_bits, 1, 1, |
76 ctx->cid_table->dc_codes, 1, 1, 0); | |
4687 | 77 init_vlc(&ctx->run_vlc, DNXHD_VLC_BITS, 62, |
5465 | 78 ctx->cid_table->run_bits, 1, 1, |
79 ctx->cid_table->run_codes, 2, 2, 0); | |
4687 | 80 |
81 ff_init_scantable(ctx->dsp.idct_permutation, &ctx->scantable, ff_zigzag_direct); | |
82 } | |
83 return 0; | |
84 } | |
85 | |
6233 | 86 static int dnxhd_decode_header(DNXHDContext *ctx, const uint8_t *buf, int buf_size, int first_field) |
4687 | 87 { |
88 static const uint8_t header_prefix[] = { 0x00, 0x00, 0x02, 0x80, 0x01 }; | |
89 int i; | |
90 | |
91 if (buf_size < 0x280) | |
92 return -1; | |
93 | |
94 if (memcmp(buf, header_prefix, 5)) { | |
95 av_log(ctx->avctx, AV_LOG_ERROR, "error in header\n"); | |
96 return -1; | |
97 } | |
5468 | 98 if (buf[5] & 2) { /* interlaced */ |
99 ctx->cur_field = buf[5] & 1; | |
4687 | 100 ctx->picture.interlaced_frame = 1; |
6212 | 101 ctx->picture.top_field_first = first_field ^ ctx->cur_field; |
5468 | 102 av_log(ctx->avctx, AV_LOG_DEBUG, "interlaced %d, cur field %d\n", buf[5] & 3, ctx->cur_field); |
4687 | 103 } |
104 | |
105 ctx->height = AV_RB16(buf + 0x18); | |
106 ctx->width = AV_RB16(buf + 0x1a); | |
107 | |
4688
1cefcd7da878
10l, fix debug, dprintf does not have log level
bcoudurier
parents:
4687
diff
changeset
|
108 dprintf(ctx->avctx, "width %d, heigth %d\n", ctx->width, ctx->height); |
4687 | 109 |
5791 | 110 if (buf[0x21] & 0x40) { |
4687 | 111 av_log(ctx->avctx, AV_LOG_ERROR, "10 bit per component\n"); |
112 return -1; | |
113 } | |
114 | |
115 ctx->cid = AV_RB32(buf + 0x28); | |
4688
1cefcd7da878
10l, fix debug, dprintf does not have log level
bcoudurier
parents:
4687
diff
changeset
|
116 dprintf(ctx->avctx, "compression id %d\n", ctx->cid); |
4687 | 117 |
118 if (dnxhd_init_vlc(ctx, ctx->cid) < 0) | |
119 return -1; | |
120 | |
5464 | 121 if (buf_size < ctx->cid_table->coding_unit_size) { |
4687 | 122 av_log(ctx->avctx, AV_LOG_ERROR, "incorrect frame size\n"); |
123 return -1; | |
124 } | |
125 | |
126 ctx->mb_width = ctx->width>>4; | |
127 ctx->mb_height = buf[0x16d]; | |
128 | |
11424 | 129 dprintf(ctx->avctx, "mb width %d, mb height %d\n", ctx->mb_width, ctx->mb_height); |
130 | |
131 if ((ctx->height+15)>>4 == ctx->mb_height && ctx->picture.interlaced_frame) | |
132 ctx->height <<= 1; | |
133 | |
134 if (ctx->mb_height > 68 || | |
135 (ctx->mb_height<<ctx->picture.interlaced_frame) > (ctx->height+15)>>4) { | |
136 av_log(ctx->avctx, AV_LOG_ERROR, "mb height too big: %d\n", ctx->mb_height); | |
4687 | 137 return -1; |
138 } | |
139 | |
140 for (i = 0; i < ctx->mb_height; i++) { | |
141 ctx->mb_scan_index[i] = AV_RB32(buf + 0x170 + (i<<2)); | |
4688
1cefcd7da878
10l, fix debug, dprintf does not have log level
bcoudurier
parents:
4687
diff
changeset
|
142 dprintf(ctx->avctx, "mb scan index %d\n", ctx->mb_scan_index[i]); |
4687 | 143 if (buf_size < ctx->mb_scan_index[i] + 0x280) { |
144 av_log(ctx->avctx, AV_LOG_ERROR, "invalid mb scan index\n"); | |
145 return -1; | |
146 } | |
147 } | |
148 | |
149 return 0; | |
150 } | |
151 | |
152 static int dnxhd_decode_dc(DNXHDContext *ctx) | |
153 { | |
154 int len; | |
155 | |
156 len = get_vlc2(&ctx->gb, ctx->dc_vlc.table, DNXHD_DC_VLC_BITS, 1); | |
157 return len ? get_xbits(&ctx->gb, len) : 0; | |
158 } | |
159 | |
160 static void dnxhd_decode_dct_block(DNXHDContext *ctx, DCTELEM *block, int n, int qscale) | |
161 { | |
162 int i, j, index, index2; | |
163 int level, component, sign; | |
164 const uint8_t *weigth_matrix; | |
165 | |
166 if (n&2) { | |
167 component = 1 + (n&1); | |
5795 | 168 weigth_matrix = ctx->cid_table->chroma_weight; |
4687 | 169 } else { |
170 component = 0; | |
5795 | 171 weigth_matrix = ctx->cid_table->luma_weight; |
4687 | 172 } |
173 | |
174 ctx->last_dc[component] += dnxhd_decode_dc(ctx); | |
175 block[0] = ctx->last_dc[component]; | |
176 //av_log(ctx->avctx, AV_LOG_DEBUG, "dc %d\n", block[0]); | |
177 for (i = 1; ; i++) { | |
178 index = get_vlc2(&ctx->gb, ctx->ac_vlc.table, DNXHD_VLC_BITS, 2); | |
179 //av_log(ctx->avctx, AV_LOG_DEBUG, "index %d\n", index); | |
5466 | 180 level = ctx->cid_table->ac_level[index]; |
4687 | 181 if (!level) { /* EOB */ |
182 //av_log(ctx->avctx, AV_LOG_DEBUG, "EOB\n"); | |
183 return; | |
184 } | |
185 sign = get_sbits(&ctx->gb, 1); | |
186 | |
5466 | 187 if (ctx->cid_table->ac_index_flag[index]) { |
188 level += get_bits(&ctx->gb, ctx->cid_table->index_bits)<<6; | |
4687 | 189 } |
190 | |
5466 | 191 if (ctx->cid_table->ac_run_flag[index]) { |
4687 | 192 index2 = get_vlc2(&ctx->gb, ctx->run_vlc.table, DNXHD_VLC_BITS, 2); |
5466 | 193 i += ctx->cid_table->run[index2]; |
4687 | 194 } |
195 | |
5792 | 196 if (i > 63) { |
197 av_log(ctx->avctx, AV_LOG_ERROR, "ac tex damaged %d, %d\n", n, i); | |
198 return; | |
199 } | |
200 | |
4687 | 201 j = ctx->scantable.permutated[i]; |
202 //av_log(ctx->avctx, AV_LOG_DEBUG, "j %d\n", j); | |
203 //av_log(ctx->avctx, AV_LOG_DEBUG, "level %d, weigth %d\n", level, weigth_matrix[i]); | |
204 level = (2*level+1) * qscale * weigth_matrix[i]; | |
5794
8412118b41d3
preliminary 10 bit depth decoding support, still miss generic api to export picture, working on it
bcoudurier
parents:
5793
diff
changeset
|
205 if (ctx->cid_table->bit_depth == 10) { |
8412118b41d3
preliminary 10 bit depth decoding support, still miss generic api to export picture, working on it
bcoudurier
parents:
5793
diff
changeset
|
206 if (weigth_matrix[i] != 8) |
8412118b41d3
preliminary 10 bit depth decoding support, still miss generic api to export picture, working on it
bcoudurier
parents:
5793
diff
changeset
|
207 level += 8; |
8412118b41d3
preliminary 10 bit depth decoding support, still miss generic api to export picture, working on it
bcoudurier
parents:
5793
diff
changeset
|
208 level >>= 4; |
8412118b41d3
preliminary 10 bit depth decoding support, still miss generic api to export picture, working on it
bcoudurier
parents:
5793
diff
changeset
|
209 } else { |
8412118b41d3
preliminary 10 bit depth decoding support, still miss generic api to export picture, working on it
bcoudurier
parents:
5793
diff
changeset
|
210 if (weigth_matrix[i] != 32) |
8412118b41d3
preliminary 10 bit depth decoding support, still miss generic api to export picture, working on it
bcoudurier
parents:
5793
diff
changeset
|
211 level += 32; |
8412118b41d3
preliminary 10 bit depth decoding support, still miss generic api to export picture, working on it
bcoudurier
parents:
5793
diff
changeset
|
212 level >>= 6; |
8412118b41d3
preliminary 10 bit depth decoding support, still miss generic api to export picture, working on it
bcoudurier
parents:
5793
diff
changeset
|
213 } |
4687 | 214 //av_log(NULL, AV_LOG_DEBUG, "i %d, j %d, end level %d\n", i, j, level); |
5793 | 215 block[j] = (level^sign) - sign; |
4687 | 216 } |
217 } | |
218 | |
219 static int dnxhd_decode_macroblock(DNXHDContext *ctx, int x, int y) | |
220 { | |
221 int dct_linesize_luma = ctx->picture.linesize[0]; | |
222 int dct_linesize_chroma = ctx->picture.linesize[1]; | |
223 uint8_t *dest_y, *dest_u, *dest_v; | |
224 int dct_offset; | |
225 int qscale, i; | |
226 | |
227 qscale = get_bits(&ctx->gb, 11); | |
228 skip_bits1(&ctx->gb); | |
229 //av_log(ctx->avctx, AV_LOG_DEBUG, "qscale %d\n", qscale); | |
230 | |
231 for (i = 0; i < 8; i++) { | |
8291 | 232 ctx->dsp.clear_block(ctx->blocks[i]); |
4687 | 233 dnxhd_decode_dct_block(ctx, ctx->blocks[i], i, qscale); |
234 } | |
5468 | 235 |
236 if (ctx->picture.interlaced_frame) { | |
237 dct_linesize_luma <<= 1; | |
238 dct_linesize_chroma <<= 1; | |
239 } | |
240 | |
4687 | 241 dest_y = ctx->picture.data[0] + ((y * dct_linesize_luma) << 4) + (x << 4); |
242 dest_u = ctx->picture.data[1] + ((y * dct_linesize_chroma) << 4) + (x << 3); | |
243 dest_v = ctx->picture.data[2] + ((y * dct_linesize_chroma) << 4) + (x << 3); | |
244 | |
5468 | 245 if (ctx->cur_field) { |
246 dest_y += ctx->picture.linesize[0]; | |
247 dest_u += ctx->picture.linesize[1]; | |
248 dest_v += ctx->picture.linesize[2]; | |
249 } | |
250 | |
4687 | 251 dct_offset = dct_linesize_luma << 3; |
252 ctx->dsp.idct_put(dest_y, dct_linesize_luma, ctx->blocks[0]); | |
253 ctx->dsp.idct_put(dest_y + 8, dct_linesize_luma, ctx->blocks[1]); | |
254 ctx->dsp.idct_put(dest_y + dct_offset, dct_linesize_luma, ctx->blocks[4]); | |
255 ctx->dsp.idct_put(dest_y + dct_offset + 8, dct_linesize_luma, ctx->blocks[5]); | |
256 | |
257 if (!(ctx->avctx->flags & CODEC_FLAG_GRAY)) { | |
258 dct_offset = dct_linesize_chroma << 3; | |
259 ctx->dsp.idct_put(dest_u, dct_linesize_chroma, ctx->blocks[2]); | |
260 ctx->dsp.idct_put(dest_v, dct_linesize_chroma, ctx->blocks[3]); | |
261 ctx->dsp.idct_put(dest_u + dct_offset, dct_linesize_chroma, ctx->blocks[6]); | |
262 ctx->dsp.idct_put(dest_v + dct_offset, dct_linesize_chroma, ctx->blocks[7]); | |
263 } | |
264 | |
265 return 0; | |
266 } | |
267 | |
6233 | 268 static int dnxhd_decode_macroblocks(DNXHDContext *ctx, const uint8_t *buf, int buf_size) |
4687 | 269 { |
270 int x, y; | |
271 for (y = 0; y < ctx->mb_height; y++) { | |
5463 | 272 ctx->last_dc[0] = |
273 ctx->last_dc[1] = | |
5794
8412118b41d3
preliminary 10 bit depth decoding support, still miss generic api to export picture, working on it
bcoudurier
parents:
5793
diff
changeset
|
274 ctx->last_dc[2] = 1<<(ctx->cid_table->bit_depth+2); // for levels +2^(bitdepth-1) |
4687 | 275 init_get_bits(&ctx->gb, buf + ctx->mb_scan_index[y], (buf_size - ctx->mb_scan_index[y]) << 3); |
276 for (x = 0; x < ctx->mb_width; x++) { | |
277 //START_TIMER; | |
278 dnxhd_decode_macroblock(ctx, x, y); | |
279 //STOP_TIMER("decode macroblock"); | |
280 } | |
281 } | |
282 return 0; | |
283 } | |
284 | |
285 static int dnxhd_decode_frame(AVCodecContext *avctx, void *data, int *data_size, | |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8629
diff
changeset
|
286 AVPacket *avpkt) |
4687 | 287 { |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8629
diff
changeset
|
288 const uint8_t *buf = avpkt->data; |
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8629
diff
changeset
|
289 int buf_size = avpkt->size; |
4687 | 290 DNXHDContext *ctx = avctx->priv_data; |
291 AVFrame *picture = data; | |
5468 | 292 int first_field = 1; |
4687 | 293 |
4688
1cefcd7da878
10l, fix debug, dprintf does not have log level
bcoudurier
parents:
4687
diff
changeset
|
294 dprintf(avctx, "frame size %d\n", buf_size); |
4687 | 295 |
5468 | 296 decode_coding_unit: |
297 if (dnxhd_decode_header(ctx, buf, buf_size, first_field) < 0) | |
4687 | 298 return -1; |
299 | |
11424 | 300 if ((avctx->width || avctx->height) && |
301 (ctx->width != avctx->width || ctx->height != avctx->height)) { | |
302 av_log(avctx, AV_LOG_WARNING, "frame size changed: %dx%d -> %dx%d\n", | |
303 avctx->width, avctx->height, ctx->width, ctx->height); | |
304 first_field = 1; | |
305 } | |
306 | |
4687 | 307 avctx->pix_fmt = PIX_FMT_YUV422P; |
308 if (avcodec_check_dimensions(avctx, ctx->width, ctx->height)) | |
309 return -1; | |
310 avcodec_set_dimensions(avctx, ctx->width, ctx->height); | |
311 | |
5468 | 312 if (first_field) { |
5469 | 313 if (ctx->picture.data[0]) |
314 avctx->release_buffer(avctx, &ctx->picture); | |
315 if (avctx->get_buffer(avctx, &ctx->picture) < 0) { | |
316 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
317 return -1; | |
318 } | |
5468 | 319 } |
4687 | 320 |
321 dnxhd_decode_macroblocks(ctx, buf + 0x280, buf_size - 0x280); | |
322 | |
5468 | 323 if (first_field && ctx->picture.interlaced_frame) { |
324 buf += ctx->cid_table->coding_unit_size; | |
325 buf_size -= ctx->cid_table->coding_unit_size; | |
326 first_field = 0; | |
327 goto decode_coding_unit; | |
328 } | |
329 | |
4687 | 330 *picture = ctx->picture; |
331 *data_size = sizeof(AVPicture); | |
4721 | 332 return buf_size; |
4687 | 333 } |
334 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6448
diff
changeset
|
335 static av_cold int dnxhd_decode_close(AVCodecContext *avctx) |
4687 | 336 { |
337 DNXHDContext *ctx = avctx->priv_data; | |
338 | |
5467 | 339 if (ctx->picture.data[0]) |
4687 | 340 avctx->release_buffer(avctx, &ctx->picture); |
341 free_vlc(&ctx->ac_vlc); | |
342 free_vlc(&ctx->dc_vlc); | |
343 free_vlc(&ctx->run_vlc); | |
344 return 0; | |
345 } | |
346 | |
347 AVCodec dnxhd_decoder = { | |
348 "dnxhd", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
11424
diff
changeset
|
349 AVMEDIA_TYPE_VIDEO, |
4687 | 350 CODEC_ID_DNXHD, |
351 sizeof(DNXHDContext), | |
352 dnxhd_decode_init, | |
353 NULL, | |
354 dnxhd_decode_close, | |
355 dnxhd_decode_frame, | |
356 CODEC_CAP_DR1, | |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6710
diff
changeset
|
357 .long_name = NULL_IF_CONFIG_SMALL("VC3/DNxHD"), |
4687 | 358 }; |