ffmpeg / libavcodec / dnxhddec.c @ 72415b2a
History | View | Annotate | Download (11.4 KB)
1 | 52b6bad2 | Baptiste Coudurier | /*
|
---|---|---|---|
2 | * VC3/DNxHD decoder.
|
||
3 | 406792e7 | Diego Biurrun | * Copyright (c) 2007 SmartJog S.A., Baptiste Coudurier <baptiste dot coudurier at smartjog dot com>
|
4 | 52b6bad2 | Baptiste Coudurier | *
|
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" |
||
26 | 9106a698 | Stefano Sabatini | #include "get_bits.h" |
27 | 52b6bad2 | Baptiste Coudurier | #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; |
||
42 | 84dc2d8a | Måns Rullgård | DECLARE_ALIGNED(16, DCTELEM, blocks)[8][64]; |
43 | 20e7c8ae | Måns Rullgård | ScanTable scantable; |
44 | 52b6bad2 | Baptiste Coudurier | const CIDEntry *cid_table;
|
45 | } DNXHDContext; |
||
46 | |||
47 | #define DNXHD_VLC_BITS 9 |
||
48 | cd52a9ca | Baptiste Coudurier | #define DNXHD_DC_VLC_BITS 7 |
49 | 52b6bad2 | Baptiste Coudurier | |
50 | 98a6fff9 | Zuxy Meng | static av_cold int dnxhd_decode_init(AVCodecContext *avctx) |
51 | 52b6bad2 | Baptiste Coudurier | { |
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 | |||
66 | d3dc629c | Baptiste Coudurier | if ((index = ff_dnxhd_get_cid_table(cid)) < 0) { |
67 | 52b6bad2 | Baptiste Coudurier | av_log(ctx->avctx, AV_LOG_ERROR, "unsupported cid %d\n", cid);
|
68 | return -1; |
||
69 | } |
||
70 | d3dc629c | Baptiste Coudurier | ctx->cid_table = &ff_dnxhd_cid_table[index]; |
71 | 52b6bad2 | Baptiste Coudurier | init_vlc(&ctx->ac_vlc, DNXHD_VLC_BITS, 257,
|
72 | 940e4bf9 | Baptiste Coudurier | ctx->cid_table->ac_bits, 1, 1, |
73 | ctx->cid_table->ac_codes, 2, 2, 0); |
||
74 | cd52a9ca | Baptiste Coudurier | init_vlc(&ctx->dc_vlc, DNXHD_DC_VLC_BITS, ctx->cid_table->bit_depth+4,
|
75 | 940e4bf9 | Baptiste Coudurier | ctx->cid_table->dc_bits, 1, 1, |
76 | ctx->cid_table->dc_codes, 1, 1, 0); |
||
77 | 52b6bad2 | Baptiste Coudurier | init_vlc(&ctx->run_vlc, DNXHD_VLC_BITS, 62,
|
78 | 940e4bf9 | Baptiste Coudurier | ctx->cid_table->run_bits, 1, 1, |
79 | ctx->cid_table->run_codes, 2, 2, 0); |
||
80 | 52b6bad2 | Baptiste Coudurier | |
81 | ff_init_scantable(ctx->dsp.idct_permutation, &ctx->scantable, ff_zigzag_direct); |
||
82 | } |
||
83 | return 0; |
||
84 | } |
||
85 | |||
86 | bd0e945f | Michael Niedermayer | static int dnxhd_decode_header(DNXHDContext *ctx, const uint8_t *buf, int buf_size, int first_field) |
87 | 52b6bad2 | Baptiste Coudurier | { |
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 | } |
||
98 | 6b259e43 | Baptiste Coudurier | if (buf[5] & 2) { /* interlaced */ |
99 | ctx->cur_field = buf[5] & 1; |
||
100 | 52b6bad2 | Baptiste Coudurier | ctx->picture.interlaced_frame = 1;
|
101 | bb41f2e7 | Baptiste Coudurier | ctx->picture.top_field_first = first_field ^ ctx->cur_field; |
102 | 6b259e43 | Baptiste Coudurier | av_log(ctx->avctx, AV_LOG_DEBUG, "interlaced %d, cur field %d\n", buf[5] & 3, ctx->cur_field); |
103 | 52b6bad2 | Baptiste Coudurier | } |
104 | |||
105 | ctx->height = AV_RB16(buf + 0x18);
|
||
106 | ctx->width = AV_RB16(buf + 0x1a);
|
||
107 | |||
108 | 8a0cdea1 | Baptiste Coudurier | dprintf(ctx->avctx, "width %d, heigth %d\n", ctx->width, ctx->height);
|
109 | 52b6bad2 | Baptiste Coudurier | |
110 | 42d1ffa3 | Baptiste Coudurier | if (buf[0x21] & 0x40) { |
111 | 52b6bad2 | Baptiste Coudurier | av_log(ctx->avctx, AV_LOG_ERROR, "10 bit per component\n");
|
112 | return -1; |
||
113 | } |
||
114 | |||
115 | ctx->cid = AV_RB32(buf + 0x28);
|
||
116 | 8a0cdea1 | Baptiste Coudurier | dprintf(ctx->avctx, "compression id %d\n", ctx->cid);
|
117 | 52b6bad2 | Baptiste Coudurier | |
118 | if (dnxhd_init_vlc(ctx, ctx->cid) < 0) |
||
119 | return -1; |
||
120 | |||
121 | 035bc647 | Baptiste Coudurier | if (buf_size < ctx->cid_table->coding_unit_size) {
|
122 | 52b6bad2 | Baptiste Coudurier | 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 | |||
129 | 1307463d | Baptiste Coudurier | 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);
|
||
137 | 52b6bad2 | Baptiste Coudurier | 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)); |
||
142 | 8a0cdea1 | Baptiste Coudurier | dprintf(ctx->avctx, "mb scan index %d\n", ctx->mb_scan_index[i]);
|
143 | 52b6bad2 | Baptiste Coudurier | 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); |
||
168 | 6cb1d361 | Baptiste Coudurier | weigth_matrix = ctx->cid_table->chroma_weight; |
169 | 52b6bad2 | Baptiste Coudurier | } else {
|
170 | component = 0;
|
||
171 | 6cb1d361 | Baptiste Coudurier | weigth_matrix = ctx->cid_table->luma_weight; |
172 | 52b6bad2 | Baptiste Coudurier | } |
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);
|
||
180 | 9a0a2c9f | Baptiste Coudurier | level = ctx->cid_table->ac_level[index]; |
181 | 52b6bad2 | Baptiste Coudurier | if (!level) { /* EOB */ |
182 | //av_log(ctx->avctx, AV_LOG_DEBUG, "EOB\n");
|
||
183 | return;
|
||
184 | } |
||
185 | sign = get_sbits(&ctx->gb, 1);
|
||
186 | |||
187 | 9a0a2c9f | Baptiste Coudurier | if (ctx->cid_table->ac_index_flag[index]) {
|
188 | level += get_bits(&ctx->gb, ctx->cid_table->index_bits)<<6;
|
||
189 | 52b6bad2 | Baptiste Coudurier | } |
190 | |||
191 | 9a0a2c9f | Baptiste Coudurier | if (ctx->cid_table->ac_run_flag[index]) {
|
192 | 52b6bad2 | Baptiste Coudurier | index2 = get_vlc2(&ctx->gb, ctx->run_vlc.table, DNXHD_VLC_BITS, 2);
|
193 | 9a0a2c9f | Baptiste Coudurier | i += ctx->cid_table->run[index2]; |
194 | 52b6bad2 | Baptiste Coudurier | } |
195 | |||
196 | a417d041 | Baptiste Coudurier | if (i > 63) { |
197 | av_log(ctx->avctx, AV_LOG_ERROR, "ac tex damaged %d, %d\n", n, i);
|
||
198 | return;
|
||
199 | } |
||
200 | |||
201 | 52b6bad2 | Baptiste Coudurier | 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]; |
||
205 | cd52a9ca | Baptiste Coudurier | if (ctx->cid_table->bit_depth == 10) { |
206 | if (weigth_matrix[i] != 8) |
||
207 | level += 8;
|
||
208 | level >>= 4;
|
||
209 | } else {
|
||
210 | if (weigth_matrix[i] != 32) |
||
211 | level += 32;
|
||
212 | level >>= 6;
|
||
213 | } |
||
214 | 52b6bad2 | Baptiste Coudurier | //av_log(NULL, AV_LOG_DEBUG, "i %d, j %d, end level %d\n", i, j, level);
|
215 | 5e301bbb | Baptiste Coudurier | block[j] = (level^sign) - sign; |
216 | 52b6bad2 | Baptiste Coudurier | } |
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++) { |
||
232 | af5e7fc9 | Baptiste Coudurier | ctx->dsp.clear_block(ctx->blocks[i]); |
233 | 52b6bad2 | Baptiste Coudurier | dnxhd_decode_dct_block(ctx, ctx->blocks[i], i, qscale); |
234 | } |
||
235 | 6b259e43 | Baptiste Coudurier | |
236 | if (ctx->picture.interlaced_frame) {
|
||
237 | dct_linesize_luma <<= 1;
|
||
238 | dct_linesize_chroma <<= 1;
|
||
239 | } |
||
240 | |||
241 | 52b6bad2 | Baptiste Coudurier | 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 | |||
245 | 6b259e43 | Baptiste Coudurier | 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 | |||
251 | 52b6bad2 | Baptiste Coudurier | 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 | |||
268 | bd0e945f | Michael Niedermayer | static int dnxhd_decode_macroblocks(DNXHDContext *ctx, const uint8_t *buf, int buf_size) |
269 | 52b6bad2 | Baptiste Coudurier | { |
270 | int x, y;
|
||
271 | for (y = 0; y < ctx->mb_height; y++) { |
||
272 | 36ebf912 | Baptiste Coudurier | ctx->last_dc[0] =
|
273 | ctx->last_dc[1] =
|
||
274 | cd52a9ca | Baptiste Coudurier | ctx->last_dc[2] = 1<<(ctx->cid_table->bit_depth+2); // for levels +2^(bitdepth-1) |
275 | 52b6bad2 | Baptiste Coudurier | 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, |
||
286 | 7a00bbad | Thilo Borgmann | AVPacket *avpkt) |
287 | 52b6bad2 | Baptiste Coudurier | { |
288 | 7a00bbad | Thilo Borgmann | const uint8_t *buf = avpkt->data;
|
289 | int buf_size = avpkt->size;
|
||
290 | 52b6bad2 | Baptiste Coudurier | DNXHDContext *ctx = avctx->priv_data; |
291 | AVFrame *picture = data; |
||
292 | 6b259e43 | Baptiste Coudurier | int first_field = 1; |
293 | 52b6bad2 | Baptiste Coudurier | |
294 | 8a0cdea1 | Baptiste Coudurier | dprintf(avctx, "frame size %d\n", buf_size);
|
295 | 52b6bad2 | Baptiste Coudurier | |
296 | 6b259e43 | Baptiste Coudurier | decode_coding_unit:
|
297 | if (dnxhd_decode_header(ctx, buf, buf_size, first_field) < 0) |
||
298 | 52b6bad2 | Baptiste Coudurier | return -1; |
299 | |||
300 | 1307463d | Baptiste Coudurier | 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 | |||
307 | 52b6bad2 | Baptiste Coudurier | 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 | |||
312 | 6b259e43 | Baptiste Coudurier | if (first_field) {
|
313 | 3c605485 | Baptiste Coudurier | 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 | } |
||
319 | 6b259e43 | Baptiste Coudurier | } |
320 | 52b6bad2 | Baptiste Coudurier | |
321 | dnxhd_decode_macroblocks(ctx, buf + 0x280, buf_size - 0x280); |
||
322 | |||
323 | 6b259e43 | Baptiste Coudurier | 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 | |||
330 | 52b6bad2 | Baptiste Coudurier | *picture = ctx->picture; |
331 | *data_size = sizeof(AVPicture);
|
||
332 | 239e1b6f | Baptiste Coudurier | return buf_size;
|
333 | 52b6bad2 | Baptiste Coudurier | } |
334 | |||
335 | 98a6fff9 | Zuxy Meng | static av_cold int dnxhd_decode_close(AVCodecContext *avctx) |
336 | 52b6bad2 | Baptiste Coudurier | { |
337 | DNXHDContext *ctx = avctx->priv_data; |
||
338 | |||
339 | dd661ebd | Baptiste Coudurier | if (ctx->picture.data[0]) |
340 | 52b6bad2 | Baptiste Coudurier | 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",
|
||
349 | 72415b2a | Stefano Sabatini | AVMEDIA_TYPE_VIDEO, |
350 | 52b6bad2 | Baptiste Coudurier | CODEC_ID_DNXHD, |
351 | sizeof(DNXHDContext),
|
||
352 | dnxhd_decode_init, |
||
353 | NULL,
|
||
354 | dnxhd_decode_close, |
||
355 | dnxhd_decode_frame, |
||
356 | CODEC_CAP_DR1, |
||
357 | fe4bf374 | Stefano Sabatini | .long_name = NULL_IF_CONFIG_SMALL("VC3/DNxHD"),
|
358 | 52b6bad2 | Baptiste Coudurier | }; |