dnxhddec.c 17.7 KB
Newer Older
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1 2
/*
 * VC3/DNxHD decoder.
3
 * Copyright (c) 2007 SmartJog S.A., Baptiste Coudurier <baptiste dot coudurier at smartjog dot com>
4 5 6
 * Copyright (c) 2011 MirriAd Ltd
 *
 * 10 bit support added by MirriAd Ltd, Joseph Artsimovich <joseph@mirriad.com>
Baptiste Coudurier's avatar
Baptiste Coudurier committed
7
 *
8
 * This file is part of Libav.
Baptiste Coudurier's avatar
Baptiste Coudurier committed
9
 *
10
 * Libav is free software; you can redistribute it and/or
Baptiste Coudurier's avatar
Baptiste Coudurier committed
11 12 13 14
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
15
 * Libav is distributed in the hope that it will be useful,
Baptiste Coudurier's avatar
Baptiste Coudurier committed
16 17 18 19 20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
21
 * License along with Libav; if not, write to the Free Software
Baptiste Coudurier's avatar
Baptiste Coudurier committed
22 23 24
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

25
#include "libavutil/imgutils.h"
26
#include "libavutil/timer.h"
Baptiste Coudurier's avatar
Baptiste Coudurier committed
27
#include "avcodec.h"
28
#include "blockdsp.h"
29
#include "get_bits.h"
Baptiste Coudurier's avatar
Baptiste Coudurier committed
30
#include "dnxhddata.h"
31
#include "idctdsp.h"
32
#include "internal.h"
33
#include "thread.h"
Baptiste Coudurier's avatar
Baptiste Coudurier committed
34

35
typedef struct DNXHDContext {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
36 37
    AVCodecContext *avctx;
    GetBitContext gb;
38
    BlockDSPContext bdsp;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
39 40 41 42 43 44 45
    int cid;                            ///< compression id
    unsigned int width, height;
    unsigned int mb_width, mb_height;
    uint32_t mb_scan_index[68];         /* max for 1080p */
    int cur_field;                      ///< current interlaced field
    VLC ac_vlc, dc_vlc, run_vlc;
    int last_dc[3];
46
    IDCTDSPContext idsp;
Kostya Shishkov's avatar
Kostya Shishkov committed
47
    DECLARE_ALIGNED(16, int16_t, blocks)[12][64];
48
    ScanTable scantable;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
49
    const CIDEntry *cid_table;
50
    int bit_depth; // 8, 10 or 0 if not initialized at all.
Kostya Shishkov's avatar
Kostya Shishkov committed
51
    int is_444;
52
    int mbaff;
Diego Biurrun's avatar
Diego Biurrun committed
53
    void (*decode_dct_block)(struct DNXHDContext *ctx, int16_t *block,
54
                             int n, int qscale);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
55 56 57
} DNXHDContext;

#define DNXHD_VLC_BITS 9
58
#define DNXHD_DC_VLC_BITS 7
Baptiste Coudurier's avatar
Baptiste Coudurier committed
59

60 61 62 63 64 65
static void dnxhd_decode_dct_block_8(DNXHDContext *ctx, int16_t *block,
                                     int n, int qscale);
static void dnxhd_decode_dct_block_10(DNXHDContext *ctx, int16_t *block,
                                      int n, int qscale);
static void dnxhd_decode_dct_block_10_444(DNXHDContext *ctx, int16_t *block,
                                          int n, int qscale);
66

67
static av_cold int dnxhd_decode_init(AVCodecContext *avctx)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
68 69 70 71 72 73 74 75 76
{
    DNXHDContext *ctx = avctx->priv_data;

    ctx->avctx = avctx;
    return 0;
}

static int dnxhd_init_vlc(DNXHDContext *ctx, int cid)
{
77
    if (cid != ctx->cid) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
78 79
        int index;

80
        if ((index = ff_dnxhd_get_cid_table(cid)) < 0) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
81
            av_log(ctx->avctx, AV_LOG_ERROR, "unsupported cid %d\n", cid);
82
            return AVERROR(ENOSYS);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
83
        }
84
        ctx->cid_table = &ff_dnxhd_cid_table[index];
85
        av_log(ctx->avctx, AV_LOG_VERBOSE, "Profile cid %d.\n", cid);
86

87 88 89
        ff_free_vlc(&ctx->ac_vlc);
        ff_free_vlc(&ctx->dc_vlc);
        ff_free_vlc(&ctx->run_vlc);
90

Baptiste Coudurier's avatar
Baptiste Coudurier committed
91
        init_vlc(&ctx->ac_vlc, DNXHD_VLC_BITS, 257,
92 93
                 ctx->cid_table->ac_bits, 1, 1,
                 ctx->cid_table->ac_codes, 2, 2, 0);
94
        init_vlc(&ctx->dc_vlc, DNXHD_DC_VLC_BITS, ctx->bit_depth + 4,
95 96
                 ctx->cid_table->dc_bits, 1, 1,
                 ctx->cid_table->dc_codes, 1, 1, 0);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
97
        init_vlc(&ctx->run_vlc, DNXHD_VLC_BITS, 62,
98 99
                 ctx->cid_table->run_bits, 1, 1,
                 ctx->cid_table->run_codes, 2, 2, 0);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
100

101
        ff_init_scantable(ctx->idsp.idct_permutation, &ctx->scantable,
102
                          ff_zigzag_direct);
103
        ctx->cid = cid;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
104 105 106 107
    }
    return 0;
}

108
static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame,
109 110
                               const uint8_t *buf, int buf_size,
                               int first_field)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
111
{
Kostya Shishkov's avatar
Kostya Shishkov committed
112 113
    static const uint8_t header_prefix[]    = { 0x00, 0x00, 0x02, 0x80, 0x01 };
    static const uint8_t header_prefix444[] = { 0x00, 0x00, 0x02, 0x80, 0x02 };
114
    int i, cid, ret;
115
    int old_bit_depth = ctx->bit_depth;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
116

117 118 119
    if (buf_size < 0x280) {
        av_log(ctx->avctx, AV_LOG_ERROR, "buffer too small (%d < 640).\n",
               buf_size);
120
        return AVERROR_INVALIDDATA;
121
    }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
122

Kostya Shishkov's avatar
Kostya Shishkov committed
123
    if (memcmp(buf, header_prefix, 5) && memcmp(buf, header_prefix444, 5)) {
124 125 126
        av_log(ctx->avctx, AV_LOG_ERROR,
               "unknown header 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n",
               buf[0], buf[1], buf[2], buf[3], buf[4]);
127
        return AVERROR_INVALIDDATA;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
128
    }
129 130
    if (buf[5] & 2) { /* interlaced */
        ctx->cur_field = buf[5] & 1;
131 132
        frame->interlaced_frame = 1;
        frame->top_field_first  = first_field ^ ctx->cur_field;
133 134
        av_log(ctx->avctx, AV_LOG_DEBUG,
               "interlaced %d, cur field %d\n", buf[5] & 3, ctx->cur_field);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
135
    }
136
    ctx->mbaff = buf[0x6] & 32;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
137 138 139 140

    ctx->height = AV_RB16(buf + 0x18);
    ctx->width  = AV_RB16(buf + 0x1a);

141
    ff_dlog(ctx->avctx, "width %d, height %d\n", ctx->width, ctx->height);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
142

143 144 145 146
    if (buf[0x21] == 0x58) { /* 10 bit */
        ctx->bit_depth = ctx->avctx->bits_per_raw_sample = 10;

        if (buf[0x4] == 0x2) {
Kostya Shishkov's avatar
Kostya Shishkov committed
147
            ctx->decode_dct_block = dnxhd_decode_dct_block_10_444;
148 149 150
            ctx->avctx->pix_fmt = AV_PIX_FMT_YUV444P10;
            ctx->is_444 = 1;
        } else {
151
            ctx->decode_dct_block = dnxhd_decode_dct_block_10;
152
            ctx->avctx->pix_fmt = AV_PIX_FMT_YUV422P10;
153
        }
154 155 156
    } else if (buf[0x21] == 0x38) { /* 8 bit */
        ctx->bit_depth = ctx->avctx->bits_per_raw_sample = 8;

157
        ctx->avctx->pix_fmt = AV_PIX_FMT_YUV422P;
158 159 160 161 162
        ctx->decode_dct_block = dnxhd_decode_dct_block_8;
    } else {
        av_log(ctx->avctx, AV_LOG_ERROR, "invalid bit depth value (%d).\n",
               buf[0x21]);
        return AVERROR_INVALIDDATA;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
163
    }
164 165 166 167
    if (ctx->bit_depth != old_bit_depth) {
        ff_blockdsp_init(&ctx->bdsp, ctx->avctx);
        ff_idctdsp_init(&ctx->idsp, ctx->avctx);
    }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
168

169
    cid = AV_RB32(buf + 0x28);
170
    ff_dlog(ctx->avctx, "compression id %d\n", cid);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
171

172 173
    if ((ret = dnxhd_init_vlc(ctx, cid)) < 0)
        return ret;
174 175 176
    if (ctx->mbaff && ctx->cid_table->cid != 1260)
        av_log(ctx->avctx, AV_LOG_WARNING,
               "Adaptive MB interlace flag in an unsupported profile.\n");
Baptiste Coudurier's avatar
Baptiste Coudurier committed
177

178 179 180 181 182 183 184 185 186
    // make sure profile size constraints are respected
    // DNx100 allows 1920->1440 and 1280->960 subsampling
    if (ctx->width != ctx->cid_table->width) {
        av_reduce(&ctx->avctx->sample_aspect_ratio.num,
                  &ctx->avctx->sample_aspect_ratio.den,
                  ctx->width, ctx->cid_table->width, 255);
        ctx->width = ctx->cid_table->width;
    }

187
    if (buf_size < ctx->cid_table->coding_unit_size) {
188 189
        av_log(ctx->avctx, AV_LOG_ERROR, "incorrect frame size (%d < %d).\n",
               buf_size, ctx->cid_table->coding_unit_size);
190
        return AVERROR_INVALIDDATA;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
191 192
    }

193
    ctx->mb_width  = ctx->width >> 4;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
194 195
    ctx->mb_height = buf[0x16d];

196
    ff_dlog(ctx->avctx,
197
            "mb width %d, mb height %d\n", ctx->mb_width, ctx->mb_height);
198

199
    if ((ctx->height + 15) >> 4 == ctx->mb_height && frame->interlaced_frame)
200 201 202
        ctx->height <<= 1;

    if (ctx->mb_height > 68 ||
203 204 205
        (ctx->mb_height << frame->interlaced_frame) > (ctx->height + 15) >> 4) {
        av_log(ctx->avctx, AV_LOG_ERROR,
               "mb height too big: %d\n", ctx->mb_height);
206
        return AVERROR_INVALIDDATA;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
207 208 209
    }

    for (i = 0; i < ctx->mb_height; i++) {
210
        ctx->mb_scan_index[i] = AV_RB32(buf + 0x170 + (i << 2));
211
        ff_dlog(ctx->avctx, "mb scan index %d\n", ctx->mb_scan_index[i]);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
212
        if (buf_size < ctx->mb_scan_index[i] + 0x280) {
213 214 215
            av_log(ctx->avctx, AV_LOG_ERROR,
                   "invalid mb scan index (%d < %d).\n",
                   buf_size, ctx->mb_scan_index[i] + 0x280);
216
            return AVERROR_INVALIDDATA;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
217 218 219 220 221 222
        }
    }

    return 0;
}

223
static av_always_inline void dnxhd_decode_dct_block(DNXHDContext *ctx,
Diego Biurrun's avatar
Diego Biurrun committed
224
                                                    int16_t *block, int n,
225 226 227 228
                                                    int qscale,
                                                    int index_bits,
                                                    int level_bias,
                                                    int level_shift)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
229
{
230
    int i, j, index1, index2, len;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
231
    int level, component, sign;
232 233
    const uint8_t *weight_matrix;
    OPEN_READER(bs, &ctx->gb);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
234

Kostya Shishkov's avatar
Kostya Shishkov committed
235
    if (!ctx->is_444) {
236 237
        if (n & 2) {
            component     = 1 + (n & 1);
Kostya Shishkov's avatar
Kostya Shishkov committed
238 239
            weight_matrix = ctx->cid_table->chroma_weight;
        } else {
240
            component     = 0;
Kostya Shishkov's avatar
Kostya Shishkov committed
241 242
            weight_matrix = ctx->cid_table->luma_weight;
        }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
243
    } else {
Kostya Shishkov's avatar
Kostya Shishkov committed
244 245 246 247 248 249
        component = (n >> 1) % 3;
        if (component) {
            weight_matrix = ctx->cid_table->chroma_weight;
        } else {
            weight_matrix = ctx->cid_table->luma_weight;
        }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
250 251
    }

252 253 254 255 256 257 258 259 260
    UPDATE_CACHE(bs, &ctx->gb);
    GET_VLC(len, bs, &ctx->gb, ctx->dc_vlc.table, DNXHD_DC_VLC_BITS, 1);
    if (len) {
        level = GET_CACHE(bs, &ctx->gb);
        LAST_SKIP_BITS(bs, &ctx->gb, len);
        sign  = ~level >> 31;
        level = (NEG_USR32(sign ^ level, len) ^ sign) - sign;
        ctx->last_dc[component] += level;
    }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
261
    block[0] = ctx->last_dc[component];
262

Baptiste Coudurier's avatar
Baptiste Coudurier committed
263
    for (i = 1; ; i++) {
264 265 266 267
        UPDATE_CACHE(bs, &ctx->gb);
        GET_VLC(index1, bs, &ctx->gb, ctx->ac_vlc.table,
                DNXHD_VLC_BITS, 2);
        level = ctx->cid_table->ac_level[index1];
268
        if (!level) /* EOB */
269
            break;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
270

271 272 273 274 275 276
        sign = SHOW_SBITS(bs, &ctx->gb, 1);
        SKIP_BITS(bs, &ctx->gb, 1);

        if (ctx->cid_table->ac_index_flag[index1]) {
            level += SHOW_UBITS(bs, &ctx->gb, index_bits) << 6;
            SKIP_BITS(bs, &ctx->gb, index_bits);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
277 278
        }

279 280 281 282
        if (ctx->cid_table->ac_run_flag[index1]) {
            UPDATE_CACHE(bs, &ctx->gb);
            GET_VLC(index2, bs, &ctx->gb, ctx->run_vlc.table,
                    DNXHD_VLC_BITS, 2);
283
            i += ctx->cid_table->run[index2];
Baptiste Coudurier's avatar
Baptiste Coudurier committed
284 285
        }

286 287
        if (i > 63) {
            av_log(ctx->avctx, AV_LOG_ERROR, "ac tex damaged %d, %d\n", n, i);
288
            break;
289 290
        }

291 292
        j     = ctx->scantable.permutated[i];
        level = (2 * level + 1) * qscale * weight_matrix[i];
293
        if (level_bias < 32 || weight_matrix[i] != level_bias)
294 295 296
            level += level_bias;
        level >>= level_shift;

297
        block[j] = (level ^ sign) - sign;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
298
    }
299 300 301 302

    CLOSE_READER(bs, &ctx->gb);
}

Diego Biurrun's avatar
Diego Biurrun committed
303
static void dnxhd_decode_dct_block_8(DNXHDContext *ctx, int16_t *block,
304 305 306 307 308
                                     int n, int qscale)
{
    dnxhd_decode_dct_block(ctx, block, n, qscale, 4, 32, 6);
}

Diego Biurrun's avatar
Diego Biurrun committed
309
static void dnxhd_decode_dct_block_10(DNXHDContext *ctx, int16_t *block,
310 311 312
                                      int n, int qscale)
{
    dnxhd_decode_dct_block(ctx, block, n, qscale, 6, 8, 4);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
313 314
}

Kostya Shishkov's avatar
Kostya Shishkov committed
315 316 317 318 319 320
static void dnxhd_decode_dct_block_10_444(DNXHDContext *ctx, int16_t *block,
                                          int n, int qscale)
{
    dnxhd_decode_dct_block(ctx, block, n, qscale, 6, 32, 6);
}

321 322
static int dnxhd_decode_macroblock(DNXHDContext *ctx, AVFrame *frame,
                                   int x, int y)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
323
{
324
    int shift1 = ctx->bit_depth == 10;
325 326
    int dct_linesize_luma   = frame->linesize[0];
    int dct_linesize_chroma = frame->linesize[1];
Baptiste Coudurier's avatar
Baptiste Coudurier committed
327
    uint8_t *dest_y, *dest_u, *dest_v;
328
    int dct_y_offset, dct_x_offset;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
329
    int qscale, i;
330
    int interlaced_mb = 0;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
331

332 333 334 335 336 337
    if (ctx->mbaff) {
        interlaced_mb = get_bits1(&ctx->gb);
        qscale = get_bits(&ctx->gb, 10);
    } else {
        qscale = get_bits(&ctx->gb, 11);
    }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
338 339 340
    skip_bits1(&ctx->gb);

    for (i = 0; i < 8; i++) {
341
        ctx->bdsp.clear_block(ctx->blocks[i]);
342
        ctx->decode_dct_block(ctx, ctx->blocks[i], i, qscale);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
343
    }
Kostya Shishkov's avatar
Kostya Shishkov committed
344 345
    if (ctx->is_444) {
        for (; i < 12; i++) {
346
            ctx->bdsp.clear_block(ctx->blocks[i]);
Kostya Shishkov's avatar
Kostya Shishkov committed
347 348 349
            ctx->decode_dct_block(ctx, ctx->blocks[i], i, qscale);
        }
    }
350

351
    if (frame->interlaced_frame) {
352 353 354 355
        dct_linesize_luma   <<= 1;
        dct_linesize_chroma <<= 1;
    }

356
    dest_y = frame->data[0] + ((y * dct_linesize_luma)   << 4) + (x << (4 + shift1));
Kostya Shishkov's avatar
Kostya Shishkov committed
357 358
    dest_u = frame->data[1] + ((y * dct_linesize_chroma) << 4) + (x << (3 + shift1 + ctx->is_444));
    dest_v = frame->data[2] + ((y * dct_linesize_chroma) << 4) + (x << (3 + shift1 + ctx->is_444));
Baptiste Coudurier's avatar
Baptiste Coudurier committed
359

360
    if (ctx->cur_field) {
361 362 363
        dest_y += frame->linesize[0];
        dest_u += frame->linesize[1];
        dest_v += frame->linesize[2];
364
    }
365 366 367 368
    if (interlaced_mb) {
        dct_linesize_luma   <<= 1;
        dct_linesize_chroma <<= 1;
    }
369

370
    dct_y_offset = interlaced_mb ? frame->linesize[0] : (dct_linesize_luma << 3);
371
    dct_x_offset = 8 << shift1;
Kostya Shishkov's avatar
Kostya Shishkov committed
372
    if (!ctx->is_444) {
373 374 375 376
        ctx->idsp.idct_put(dest_y,                               dct_linesize_luma, ctx->blocks[0]);
        ctx->idsp.idct_put(dest_y + dct_x_offset,                dct_linesize_luma, ctx->blocks[1]);
        ctx->idsp.idct_put(dest_y + dct_y_offset,                dct_linesize_luma, ctx->blocks[4]);
        ctx->idsp.idct_put(dest_y + dct_y_offset + dct_x_offset, dct_linesize_luma, ctx->blocks[5]);
Kostya Shishkov's avatar
Kostya Shishkov committed
377

378
        if (!(ctx->avctx->flags & AV_CODEC_FLAG_GRAY)) {
379
            dct_y_offset = interlaced_mb ? frame->linesize[1] : (dct_linesize_chroma << 3);
380 381 382 383
            ctx->idsp.idct_put(dest_u,                dct_linesize_chroma, ctx->blocks[2]);
            ctx->idsp.idct_put(dest_v,                dct_linesize_chroma, ctx->blocks[3]);
            ctx->idsp.idct_put(dest_u + dct_y_offset, dct_linesize_chroma, ctx->blocks[6]);
            ctx->idsp.idct_put(dest_v + dct_y_offset, dct_linesize_chroma, ctx->blocks[7]);
Kostya Shishkov's avatar
Kostya Shishkov committed
384 385
        }
    } else {
386 387 388 389
        ctx->idsp.idct_put(dest_y,                               dct_linesize_luma, ctx->blocks[0]);
        ctx->idsp.idct_put(dest_y + dct_x_offset,                dct_linesize_luma, ctx->blocks[1]);
        ctx->idsp.idct_put(dest_y + dct_y_offset,                dct_linesize_luma, ctx->blocks[6]);
        ctx->idsp.idct_put(dest_y + dct_y_offset + dct_x_offset, dct_linesize_luma, ctx->blocks[7]);
Kostya Shishkov's avatar
Kostya Shishkov committed
390

391
        if (!(ctx->avctx->flags & AV_CODEC_FLAG_GRAY)) {
392
            dct_y_offset = interlaced_mb ? frame->linesize[1] : (dct_linesize_chroma << 3);
393 394 395 396 397 398 399 400
            ctx->idsp.idct_put(dest_u,                               dct_linesize_chroma, ctx->blocks[2]);
            ctx->idsp.idct_put(dest_u + dct_x_offset,                dct_linesize_chroma, ctx->blocks[3]);
            ctx->idsp.idct_put(dest_u + dct_y_offset,                dct_linesize_chroma, ctx->blocks[8]);
            ctx->idsp.idct_put(dest_u + dct_y_offset + dct_x_offset, dct_linesize_chroma, ctx->blocks[9]);
            ctx->idsp.idct_put(dest_v,                               dct_linesize_chroma, ctx->blocks[4]);
            ctx->idsp.idct_put(dest_v + dct_x_offset,                dct_linesize_chroma, ctx->blocks[5]);
            ctx->idsp.idct_put(dest_v + dct_y_offset,                dct_linesize_chroma, ctx->blocks[10]);
            ctx->idsp.idct_put(dest_v + dct_y_offset + dct_x_offset, dct_linesize_chroma, ctx->blocks[11]);
Kostya Shishkov's avatar
Kostya Shishkov committed
401
        }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
402 403 404 405 406
    }

    return 0;
}

407 408
static int dnxhd_decode_macroblocks(DNXHDContext *ctx, AVFrame *frame,
                                    const uint8_t *buf, int buf_size)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
409 410 411
{
    int x, y;
    for (y = 0; y < ctx->mb_height; y++) {
412 413
        ctx->last_dc[0] =
        ctx->last_dc[1] =
414
        ctx->last_dc[2] = 1 << (ctx->bit_depth + 2); // for levels +2^(bitdepth-1)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
415 416 417
        init_get_bits(&ctx->gb, buf + ctx->mb_scan_index[y], (buf_size - ctx->mb_scan_index[y]) << 3);
        for (x = 0; x < ctx->mb_width; x++) {
            //START_TIMER;
418
            dnxhd_decode_macroblock(ctx, frame, x, y);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
419 420 421 422 423 424
            //STOP_TIMER("decode macroblock");
        }
    }
    return 0;
}

425 426
static int dnxhd_decode_frame(AVCodecContext *avctx, void *data,
                              int *got_frame, AVPacket *avpkt)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
427
{
428 429
    const uint8_t *buf = avpkt->data;
    int buf_size = avpkt->size;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
430
    DNXHDContext *ctx = avctx->priv_data;
431
    ThreadFrame tf;
432
    int first_field = 1;
433
    int ret;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
434

435 436
    tf.f = data;

437
    ff_dlog(avctx, "frame size %d\n", buf_size);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
438

439
decode_coding_unit:
440
    if ((ret = dnxhd_decode_header(ctx, tf.f, buf, buf_size, first_field)) < 0)
441
        return ret;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
442

443 444 445 446 447 448 449
    if ((avctx->width || avctx->height) &&
        (ctx->width != avctx->width || ctx->height != avctx->height)) {
        av_log(avctx, AV_LOG_WARNING, "frame size changed: %dx%d -> %dx%d\n",
               avctx->width, avctx->height, ctx->width, ctx->height);
        first_field = 1;
    }

450 451 452
    ret = ff_set_dimensions(avctx, ctx->width, ctx->height);
    if (ret < 0)
        return ret;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
453

454
    if (first_field) {
455
        if ((ret = ff_thread_get_buffer(avctx, &tf, 0)) < 0) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
456
            av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
457
            return ret;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
458
        }
459 460
        tf.f->pict_type = AV_PICTURE_TYPE_I;
        tf.f->key_frame = 1;
461
    }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
462

463
    dnxhd_decode_macroblocks(ctx, tf.f, buf + 0x280, buf_size - 0x280);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
464

465
    if (first_field && tf.f->interlaced_frame) {
466 467 468 469 470 471
        buf      += ctx->cid_table->coding_unit_size;
        buf_size -= ctx->cid_table->coding_unit_size;
        first_field = 0;
        goto decode_coding_unit;
    }

472
    *got_frame = 1;
473
    return buf_size;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
474 475
}

476
static av_cold int dnxhd_decode_close(AVCodecContext *avctx)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
477 478 479
{
    DNXHDContext *ctx = avctx->priv_data;

480 481 482
    ff_free_vlc(&ctx->ac_vlc);
    ff_free_vlc(&ctx->dc_vlc);
    ff_free_vlc(&ctx->run_vlc);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
483 484 485
    return 0;
}

486
AVCodec ff_dnxhd_decoder = {
487
    .name           = "dnxhd",
488
    .long_name      = NULL_IF_CONFIG_SMALL("VC3/DNxHD"),
489
    .type           = AVMEDIA_TYPE_VIDEO,
490
    .id             = AV_CODEC_ID_DNXHD,
491 492 493 494
    .priv_data_size = sizeof(DNXHDContext),
    .init           = dnxhd_decode_init,
    .close          = dnxhd_decode_close,
    .decode         = dnxhd_decode_frame,
495
    .capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
Baptiste Coudurier's avatar
Baptiste Coudurier committed
496
};