dnxhddec.c 24.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
 * Copyright (c) 2011 MirriAd Ltd
5
 * Copyright (c) 2015 Christophe Gisquet
6 7
 *
 * 10 bit support added by MirriAd Ltd, Joseph Artsimovich <joseph@mirriad.com>
8
 * Slice multithreading and MB interlaced support added by Christophe Gisquet
Baptiste Coudurier's avatar
Baptiste Coudurier committed
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * 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.
 *
 * FFmpeg is distributed in the hope that it will be useful,
 * 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
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

27
#include "libavutil/imgutils.h"
28
#include "libavutil/timer.h"
Baptiste Coudurier's avatar
Baptiste Coudurier committed
29
#include "avcodec.h"
30
#include "blockdsp.h"
31
#define  UNCHECKED_BITSTREAM_READER 1
32
#include "get_bits.h"
Baptiste Coudurier's avatar
Baptiste Coudurier committed
33
#include "dnxhddata.h"
34
#include "idctdsp.h"
35
#include "internal.h"
36
#include "profiles.h"
37
#include "thread.h"
Baptiste Coudurier's avatar
Baptiste Coudurier committed
38

39 40 41 42 43 44 45
typedef struct RowContext {
    DECLARE_ALIGNED(16, int16_t, blocks)[12][64];
    int luma_scale[64];
    int chroma_scale[64];
    GetBitContext gb;
    int last_dc[3];
    int last_qscale;
46
    int errors;
47 48
    /** -1:not set yet  0:off=RGB  1:on=YUV  2:variable */
    int format;
49 50
} RowContext;

51
typedef struct DNXHDContext {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
52
    AVCodecContext *avctx;
53
    RowContext *rows;
54
    BlockDSPContext bdsp;
55 56
    const uint8_t* buf;
    int buf_size;
57
    int64_t cid;                        ///< compression id
Baptiste Coudurier's avatar
Baptiste Coudurier committed
58
    unsigned int width, height;
59
    enum AVPixelFormat pix_fmt;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
60
    unsigned int mb_width, mb_height;
61
    uint32_t mb_scan_index[256];
62
    int data_offset;                    // End of mb_scan_index, where macroblocks start
Baptiste Coudurier's avatar
Baptiste Coudurier committed
63 64
    int cur_field;                      ///< current interlaced field
    VLC ac_vlc, dc_vlc, run_vlc;
65
    IDCTDSPContext idsp;
66
    ScanTable scantable;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
67
    const CIDEntry *cid_table;
68
    int bit_depth; // 8, 10, 12 or 0 if not initialized at all.
Kostya Shishkov's avatar
Kostya Shishkov committed
69
    int is_444;
70
    int mbaff;
71
    int act;
72
    int (*decode_dct_block)(const struct DNXHDContext *ctx,
73
                            RowContext *row, int n);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
74 75 76
} DNXHDContext;

#define DNXHD_VLC_BITS 9
77
#define DNXHD_DC_VLC_BITS 7
Baptiste Coudurier's avatar
Baptiste Coudurier committed
78

79
static int dnxhd_decode_dct_block_8(const DNXHDContext *ctx,
80
                                    RowContext *row, int n);
81
static int dnxhd_decode_dct_block_10(const DNXHDContext *ctx,
82
                                     RowContext *row, int n);
83
static int dnxhd_decode_dct_block_10_444(const DNXHDContext *ctx,
84
                                         RowContext *row, int n);
85 86 87 88
static int dnxhd_decode_dct_block_12(const DNXHDContext *ctx,
                                     RowContext *row, int n);
static int dnxhd_decode_dct_block_12_444(const DNXHDContext *ctx,
                                         RowContext *row, int n);
89

90
static av_cold int dnxhd_decode_init(AVCodecContext *avctx)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
91 92 93 94
{
    DNXHDContext *ctx = avctx->priv_data;

    ctx->avctx = avctx;
95
    ctx->cid = -1;
96
    avctx->colorspace = AVCOL_SPC_BT709;
97

98 99 100
    avctx->coded_width  = FFALIGN(avctx->width,  16);
    avctx->coded_height = FFALIGN(avctx->height, 16);

101 102 103 104
    ctx->rows = av_mallocz_array(avctx->thread_count, sizeof(RowContext));
    if (!ctx->rows)
        return AVERROR(ENOMEM);

Baptiste Coudurier's avatar
Baptiste Coudurier committed
105 106 107
    return 0;
}

108
static int dnxhd_init_vlc(DNXHDContext *ctx, uint32_t cid, int bitdepth)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
109
{
110
    if (cid != ctx->cid) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
111 112
        int index;

113
        if ((index = ff_dnxhd_get_cid_table(cid)) < 0) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
114
            av_log(ctx->avctx, AV_LOG_ERROR, "unsupported cid %d\n", cid);
115
            return AVERROR(ENOSYS);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
116
        }
117
        if (ff_dnxhd_cid_table[index].bit_depth != bitdepth &&
118
            ff_dnxhd_cid_table[index].bit_depth != DNXHD_VARIABLE) {
119
            av_log(ctx->avctx, AV_LOG_ERROR, "bit depth mismatches %d %d\n", ff_dnxhd_cid_table[index].bit_depth, bitdepth);
120 121
            return AVERROR_INVALIDDATA;
        }
122
        ctx->cid_table = &ff_dnxhd_cid_table[index];
123
        av_log(ctx->avctx, AV_LOG_VERBOSE, "Profile cid %d.\n", cid);
124

125 126 127
        ff_free_vlc(&ctx->ac_vlc);
        ff_free_vlc(&ctx->dc_vlc);
        ff_free_vlc(&ctx->run_vlc);
128

Baptiste Coudurier's avatar
Baptiste Coudurier committed
129
        init_vlc(&ctx->ac_vlc, DNXHD_VLC_BITS, 257,
130 131
                 ctx->cid_table->ac_bits, 1, 1,
                 ctx->cid_table->ac_codes, 2, 2, 0);
132
        init_vlc(&ctx->dc_vlc, DNXHD_DC_VLC_BITS, bitdepth > 8 ? 14 : 12,
133 134
                 ctx->cid_table->dc_bits, 1, 1,
                 ctx->cid_table->dc_codes, 1, 1, 0);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
135
        init_vlc(&ctx->run_vlc, DNXHD_VLC_BITS, 62,
136 137
                 ctx->cid_table->run_bits, 1, 1,
                 ctx->cid_table->run_codes, 2, 2, 0);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
138

139
        ctx->cid = cid;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
140 141 142 143
    }
    return 0;
}

144 145 146 147 148 149 150 151 152 153 154 155 156 157
static av_cold int dnxhd_decode_init_thread_copy(AVCodecContext *avctx)
{
    DNXHDContext *ctx = avctx->priv_data;

    // make sure VLC tables will be loaded when cid is parsed
    ctx->cid = -1;

    ctx->rows = av_mallocz_array(avctx->thread_count, sizeof(RowContext));
    if (!ctx->rows)
        return AVERROR(ENOMEM);

    return 0;
}

158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
static int dnxhd_get_profile(int cid)
{
    switch(cid) {
    case 1270:
        return FF_PROFILE_DNXHR_444;
    case 1271:
        return FF_PROFILE_DNXHR_HQX;
    case 1272:
        return FF_PROFILE_DNXHR_HQ;
    case 1273:
        return FF_PROFILE_DNXHR_SQ;
    case 1274:
        return FF_PROFILE_DNXHR_LB;
    }
    return FF_PROFILE_DNXHD;
}

175
static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame,
176 177
                               const uint8_t *buf, int buf_size,
                               int first_field)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
178
{
179
    int i, cid, ret;
180
    int old_bit_depth = ctx->bit_depth, bitdepth;
181
    uint64_t header_prefix;
182
    if (buf_size < 0x280) {
183 184
        av_log(ctx->avctx, AV_LOG_ERROR,
               "buffer too small (%d < 640).\n", buf_size);
185
        return AVERROR_INVALIDDATA;
186
    }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
187

188
    header_prefix = ff_dnxhd_parse_header_prefix(buf);
189
    if (header_prefix == 0) {
190 191 192
        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]);
193
        return AVERROR_INVALIDDATA;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
194
    }
195 196
    if (buf[5] & 2) { /* interlaced */
        ctx->cur_field = buf[5] & 1;
197 198
        frame->interlaced_frame = 1;
        frame->top_field_first  = first_field ^ ctx->cur_field;
199 200
        av_log(ctx->avctx, AV_LOG_DEBUG,
               "interlaced %d, cur field %d\n", buf[5] & 3, ctx->cur_field);
201 202
    } else {
        ctx->cur_field = 0;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
203
    }
204
    ctx->mbaff = (buf[0x6] >> 5) & 1;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
205 206 207 208

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

209
    switch(buf[0x21] >> 5) {
210 211 212
    case 1: bitdepth = 8; break;
    case 2: bitdepth = 10; break;
    case 3: bitdepth = 12; break;
213 214 215 216 217
    default:
        av_log(ctx->avctx, AV_LOG_ERROR,
               "Unknown bitdepth indicator (%d)\n", buf[0x21] >> 5);
        return AVERROR_INVALIDDATA;
    }
218 219

    cid = AV_RB32(buf + 0x28);
220 221 222

    ctx->avctx->profile = dnxhd_get_profile(cid);

223 224 225 226 227 228 229 230 231 232
    if ((ret = dnxhd_init_vlc(ctx, cid, bitdepth)) < 0)
        return ret;
    if (ctx->mbaff && ctx->cid_table->cid != 1260)
        av_log(ctx->avctx, AV_LOG_WARNING,
               "Adaptive MB interlace flag in an unsupported profile.\n");

    ctx->act = buf[0x2C] & 7;
    if (ctx->act && ctx->cid_table->cid != 1256 && ctx->cid_table->cid != 1270)
        av_log(ctx->avctx, AV_LOG_WARNING,
               "Adaptive color transform in an unsupported profile.\n");
233

234 235
    ctx->is_444 = (buf[0x2C] >> 6) & 1;
    if (ctx->is_444) {
236
        if (bitdepth == 8) {
237
            avpriv_request_sample(ctx->avctx, "4:4:4 8 bits");
238
            return AVERROR_INVALIDDATA;
239
        } else if (bitdepth == 10) {
240
            ctx->decode_dct_block = dnxhd_decode_dct_block_10_444;
241 242
            ctx->pix_fmt = ctx->act ? AV_PIX_FMT_YUV444P10
                                    : AV_PIX_FMT_GBRP10;
243 244
        } else {
            ctx->decode_dct_block = dnxhd_decode_dct_block_12_444;
245 246
            ctx->pix_fmt = ctx->act ? AV_PIX_FMT_YUV444P12
                                    : AV_PIX_FMT_GBRP12;
247
        }
248
    } else if (bitdepth == 12) {
249 250
        ctx->decode_dct_block = dnxhd_decode_dct_block_12;
        ctx->pix_fmt = AV_PIX_FMT_YUV422P12;
251
    } else if (bitdepth == 10) {
252 253 254 255
        if (ctx->avctx->profile == FF_PROFILE_DNXHR_HQX)
            ctx->decode_dct_block = dnxhd_decode_dct_block_10_444;
        else
            ctx->decode_dct_block = dnxhd_decode_dct_block_10;
256
        ctx->pix_fmt = AV_PIX_FMT_YUV422P10;
257
    } else {
258 259
        ctx->decode_dct_block = dnxhd_decode_dct_block_8;
        ctx->pix_fmt = AV_PIX_FMT_YUV422P;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
260
    }
261 262

    ctx->avctx->bits_per_raw_sample = ctx->bit_depth = bitdepth;
263 264 265
    if (ctx->bit_depth != old_bit_depth) {
        ff_blockdsp_init(&ctx->bdsp, ctx->avctx);
        ff_idctdsp_init(&ctx->idsp, ctx->avctx);
266 267
        ff_init_scantable(ctx->idsp.idct_permutation, &ctx->scantable,
                          ff_zigzag_direct);
268
    }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
269

270 271
    // make sure profile size constraints are respected
    // DNx100 allows 1920->1440 and 1280->960 subsampling
272 273
    if (ctx->width != ctx->cid_table->width &&
        ctx->cid_table->width != DNXHD_VARIABLE) {
274 275 276 277 278 279
        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;
    }

280
    if (buf_size < ctx->cid_table->coding_unit_size) {
281 282
        av_log(ctx->avctx, AV_LOG_ERROR, "incorrect frame size (%d < %d).\n",
               buf_size, ctx->cid_table->coding_unit_size);
283
        return AVERROR_INVALIDDATA;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
284 285
    }

286
    ctx->mb_width  = (ctx->width + 15)>> 4;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
287 288
    ctx->mb_height = buf[0x16d];

289
    if ((ctx->height + 15) >> 4 == ctx->mb_height && frame->interlaced_frame)
290 291
        ctx->height <<= 1;

292 293 294 295
    av_log(ctx->avctx, AV_LOG_VERBOSE, "%dx%d, 4:%s %d bits, MBAFF=%d ACT=%d\n",
           ctx->width, ctx->height, ctx->is_444 ? "4:4" : "2:2",
           ctx->bit_depth, ctx->mbaff, ctx->act);

296
    // Newer format supports variable mb_scan_index sizes
297
    if (ctx->mb_height > 68 && ff_dnxhd_check_header_prefix_hr(header_prefix)) {
298 299 300 301 302 303 304 305 306 307 308 309
        ctx->data_offset = 0x170 + (ctx->mb_height << 2);
    } else {
        if (ctx->mb_height > 68 ||
            (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);
            return AVERROR_INVALIDDATA;
        }
        ctx->data_offset = 0x280;
    }

    if (buf_size < ctx->data_offset) {
310
        av_log(ctx->avctx, AV_LOG_ERROR,
311
               "buffer too small (%d < %d).\n", buf_size, ctx->data_offset);
312
        return AVERROR_INVALIDDATA;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
313 314
    }

315
    av_assert0((unsigned)ctx->mb_height <= FF_ARRAY_ELEMS(ctx->mb_scan_index));
316

Baptiste Coudurier's avatar
Baptiste Coudurier committed
317
    for (i = 0; i < ctx->mb_height; i++) {
318
        ctx->mb_scan_index[i] = AV_RB32(buf + 0x170 + (i << 2));
319 320
        ff_dlog(ctx->avctx, "mb scan index %d, pos %d: %u\n", i, 0x170 + (i << 2), ctx->mb_scan_index[i]);
        if (buf_size - ctx->data_offset < ctx->mb_scan_index[i]) {
321
            av_log(ctx->avctx, AV_LOG_ERROR,
322 323
                   "invalid mb scan index (%u vs %u).\n",
                   ctx->mb_scan_index[i], buf_size - ctx->data_offset);
324
            return AVERROR_INVALIDDATA;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
325 326 327 328 329 330
        }
    }

    return 0;
}

331
static av_always_inline int dnxhd_decode_dct_block(const DNXHDContext *ctx,
332 333 334 335
                                                   RowContext *row,
                                                   int n,
                                                   int index_bits,
                                                   int level_bias,
336 337
                                                   int level_shift,
                                                   int dc_shift)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
338
{
339
    int i, j, index1, index2, len, flags;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
340
    int level, component, sign;
341
    const int *scale;
342
    const uint8_t *weight_matrix;
343
    const uint8_t *ac_info = ctx->cid_table->ac_info;
344
    int16_t *block = row->blocks[n];
345
    const int eob_index     = ctx->cid_table->eob_index;
346
    int ret = 0;
347
    OPEN_READER(bs, &row->gb);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
348

349 350
    ctx->bdsp.clear_block(block);

Kostya Shishkov's avatar
Kostya Shishkov committed
351
    if (!ctx->is_444) {
352 353
        if (n & 2) {
            component     = 1 + (n & 1);
354
            scale = row->chroma_scale;
Kostya Shishkov's avatar
Kostya Shishkov committed
355 356
            weight_matrix = ctx->cid_table->chroma_weight;
        } else {
357
            component     = 0;
358
            scale = row->luma_scale;
Kostya Shishkov's avatar
Kostya Shishkov committed
359 360
            weight_matrix = ctx->cid_table->luma_weight;
        }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
361
    } else {
Kostya Shishkov's avatar
Kostya Shishkov committed
362 363
        component = (n >> 1) % 3;
        if (component) {
364
            scale = row->chroma_scale;
Kostya Shishkov's avatar
Kostya Shishkov committed
365 366
            weight_matrix = ctx->cid_table->chroma_weight;
        } else {
367
            scale = row->luma_scale;
Kostya Shishkov's avatar
Kostya Shishkov committed
368 369
            weight_matrix = ctx->cid_table->luma_weight;
        }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
370 371
    }

372 373
    UPDATE_CACHE(bs, &row->gb);
    GET_VLC(len, bs, &row->gb, ctx->dc_vlc.table, DNXHD_DC_VLC_BITS, 1);
374
    if (len) {
375 376
        level = GET_CACHE(bs, &row->gb);
        LAST_SKIP_BITS(bs, &row->gb, len);
377 378
        sign  = ~level >> 31;
        level = (NEG_USR32(sign ^ level, len) ^ sign) - sign;
379
        row->last_dc[component] += level * (1 << dc_shift);
380
    }
381
    block[0] = row->last_dc[component];
382

383
    i = 0;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
384

385 386
    UPDATE_CACHE(bs, &row->gb);
    GET_VLC(index1, bs, &row->gb, ctx->ac_vlc.table,
387 388
            DNXHD_VLC_BITS, 2);

389
    while (index1 != eob_index) {
390 391
        level = ac_info[2*index1+0];
        flags = ac_info[2*index1+1];
Baptiste Coudurier's avatar
Baptiste Coudurier committed
392

393 394
        sign = SHOW_SBITS(bs, &row->gb, 1);
        SKIP_BITS(bs, &row->gb, 1);
395

396
        if (flags & 1) {
397 398
            level += SHOW_UBITS(bs, &row->gb, index_bits) << 7;
            SKIP_BITS(bs, &row->gb, index_bits);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
399 400
        }

401
        if (flags & 2) {
402 403
            UPDATE_CACHE(bs, &row->gb);
            GET_VLC(index2, bs, &row->gb, ctx->run_vlc.table,
404
                    DNXHD_VLC_BITS, 2);
405
            i += ctx->cid_table->run[index2];
Baptiste Coudurier's avatar
Baptiste Coudurier committed
406 407
        }

408
        if (++i > 63) {
409
            av_log(ctx->avctx, AV_LOG_ERROR, "ac tex damaged %d, %d\n", n, i);
410
            ret = -1;
411
            break;
412 413
        }

414
        j     = ctx->scantable.permutated[i];
415
        level *= scale[i];
416
        level += scale[i] >> 1;
417
        if (level_bias < 32 || weight_matrix[i] != level_bias)
418
            level += level_bias; // 1<<(level_shift-1)
419 420
        level >>= level_shift;

421
        block[j] = (level ^ sign) - sign;
422

423 424
        UPDATE_CACHE(bs, &row->gb);
        GET_VLC(index1, bs, &row->gb, ctx->ac_vlc.table,
425
                DNXHD_VLC_BITS, 2);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
426
    }
427

428
    CLOSE_READER(bs, &row->gb);
429
    return ret;
430 431
}

432
static int dnxhd_decode_dct_block_8(const DNXHDContext *ctx,
433
                                    RowContext *row, int n)
434
{
435
    return dnxhd_decode_dct_block(ctx, row, n, 4, 32, 6, 0);
436 437
}

438
static int dnxhd_decode_dct_block_10(const DNXHDContext *ctx,
439
                                     RowContext *row, int n)
440
{
441
    return dnxhd_decode_dct_block(ctx, row, n, 6, 8, 4, 0);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
442 443
}

444
static int dnxhd_decode_dct_block_10_444(const DNXHDContext *ctx,
445
                                         RowContext *row, int n)
Kostya Shishkov's avatar
Kostya Shishkov committed
446
{
447 448 449 450 451 452 453 454 455 456 457 458 459
    return dnxhd_decode_dct_block(ctx, row, n, 6, 32, 6, 0);
}

static int dnxhd_decode_dct_block_12(const DNXHDContext *ctx,
                                     RowContext *row, int n)
{
    return dnxhd_decode_dct_block(ctx, row, n, 6, 8, 4, 2);
}

static int dnxhd_decode_dct_block_12_444(const DNXHDContext *ctx,
                                         RowContext *row, int n)
{
    return dnxhd_decode_dct_block(ctx, row, n, 6, 32, 4, 2);
Kostya Shishkov's avatar
Kostya Shishkov committed
460 461
}

462 463
static int dnxhd_decode_macroblock(const DNXHDContext *ctx, RowContext *row,
                                   AVFrame *frame, int x, int y)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
464
{
465
    int shift1 = ctx->bit_depth >= 10;
466 467
    int dct_linesize_luma   = frame->linesize[0];
    int dct_linesize_chroma = frame->linesize[1];
Baptiste Coudurier's avatar
Baptiste Coudurier committed
468
    uint8_t *dest_y, *dest_u, *dest_v;
469
    int dct_y_offset, dct_x_offset;
470
    int qscale, i, act;
471
    int interlaced_mb = 0;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
472

473
    if (ctx->mbaff) {
474 475
        interlaced_mb = get_bits1(&row->gb);
        qscale = get_bits(&row->gb, 10);
476
    } else {
477
        qscale = get_bits(&row->gb, 11);
478
    }
479
    act = get_bits1(&row->gb);
480
    if (act) {
481 482 483 484 485 486 487 488 489 490 491
        if (!ctx->act) {
            static int act_warned;
            if (!act_warned) {
                act_warned = 1;
                av_log(ctx->avctx, AV_LOG_ERROR,
                       "ACT flag set, in violation of frame header.\n");
            }
        } else if (row->format == -1) {
            row->format = act;
        } else if (row->format != act) {
            row->format = 2; // Variable
492 493
        }
    }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
494

495
    if (qscale != row->last_qscale) {
496
        for (i = 0; i < 64; i++) {
497 498
            row->luma_scale[i]   = qscale * ctx->cid_table->luma_weight[i];
            row->chroma_scale[i] = qscale * ctx->cid_table->chroma_weight[i];
499
        }
500
        row->last_qscale = qscale;
501 502
    }

503
    for (i = 0; i < 8 + 4 * ctx->is_444; i++) {
504 505
        if (ctx->decode_dct_block(ctx, row, i) < 0)
            return AVERROR_INVALIDDATA;
Kostya Shishkov's avatar
Kostya Shishkov committed
506
    }
507

508
    if (frame->interlaced_frame) {
509 510 511 512
        dct_linesize_luma   <<= 1;
        dct_linesize_chroma <<= 1;
    }

513
    dest_y = frame->data[0] + ((y * dct_linesize_luma)   << 4) + (x << (4 + shift1));
Kostya Shishkov's avatar
Kostya Shishkov committed
514 515
    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
516

517
    if (frame->interlaced_frame && ctx->cur_field) {
518 519 520
        dest_y += frame->linesize[0];
        dest_u += frame->linesize[1];
        dest_v += frame->linesize[2];
521
    }
522 523 524 525
    if (interlaced_mb) {
        dct_linesize_luma   <<= 1;
        dct_linesize_chroma <<= 1;
    }
526

527
    dct_y_offset = interlaced_mb ? frame->linesize[0] : (dct_linesize_luma << 3);
528
    dct_x_offset = 8 << shift1;
Kostya Shishkov's avatar
Kostya Shishkov committed
529
    if (!ctx->is_444) {
530 531 532 533
        ctx->idsp.idct_put(dest_y,                               dct_linesize_luma, row->blocks[0]);
        ctx->idsp.idct_put(dest_y + dct_x_offset,                dct_linesize_luma, row->blocks[1]);
        ctx->idsp.idct_put(dest_y + dct_y_offset,                dct_linesize_luma, row->blocks[4]);
        ctx->idsp.idct_put(dest_y + dct_y_offset + dct_x_offset, dct_linesize_luma, row->blocks[5]);
Kostya Shishkov's avatar
Kostya Shishkov committed
534

535
        if (!(ctx->avctx->flags & AV_CODEC_FLAG_GRAY)) {
536
            dct_y_offset = interlaced_mb ? frame->linesize[1] : (dct_linesize_chroma << 3);
537 538 539 540
            ctx->idsp.idct_put(dest_u,                dct_linesize_chroma, row->blocks[2]);
            ctx->idsp.idct_put(dest_v,                dct_linesize_chroma, row->blocks[3]);
            ctx->idsp.idct_put(dest_u + dct_y_offset, dct_linesize_chroma, row->blocks[6]);
            ctx->idsp.idct_put(dest_v + dct_y_offset, dct_linesize_chroma, row->blocks[7]);
Kostya Shishkov's avatar
Kostya Shishkov committed
541 542
        }
    } else {
543 544 545 546
        ctx->idsp.idct_put(dest_y,                               dct_linesize_luma, row->blocks[0]);
        ctx->idsp.idct_put(dest_y + dct_x_offset,                dct_linesize_luma, row->blocks[1]);
        ctx->idsp.idct_put(dest_y + dct_y_offset,                dct_linesize_luma, row->blocks[6]);
        ctx->idsp.idct_put(dest_y + dct_y_offset + dct_x_offset, dct_linesize_luma, row->blocks[7]);
Kostya Shishkov's avatar
Kostya Shishkov committed
547

548
        if (!(ctx->avctx->flags & AV_CODEC_FLAG_GRAY)) {
549
            dct_y_offset = interlaced_mb ? frame->linesize[1] : (dct_linesize_chroma << 3);
550 551 552 553 554 555 556 557
            ctx->idsp.idct_put(dest_u,                               dct_linesize_chroma, row->blocks[2]);
            ctx->idsp.idct_put(dest_u + dct_x_offset,                dct_linesize_chroma, row->blocks[3]);
            ctx->idsp.idct_put(dest_u + dct_y_offset,                dct_linesize_chroma, row->blocks[8]);
            ctx->idsp.idct_put(dest_u + dct_y_offset + dct_x_offset, dct_linesize_chroma, row->blocks[9]);
            ctx->idsp.idct_put(dest_v,                               dct_linesize_chroma, row->blocks[4]);
            ctx->idsp.idct_put(dest_v + dct_x_offset,                dct_linesize_chroma, row->blocks[5]);
            ctx->idsp.idct_put(dest_v + dct_y_offset,                dct_linesize_chroma, row->blocks[10]);
            ctx->idsp.idct_put(dest_v + dct_y_offset + dct_x_offset, dct_linesize_chroma, row->blocks[11]);
Kostya Shishkov's avatar
Kostya Shishkov committed
558
        }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
559 560 561 562 563
    }

    return 0;
}

564 565
static int dnxhd_decode_row(AVCodecContext *avctx, void *data,
                            int rownb, int threadnb)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
566
{
567 568 569 570 571 572 573 574 575 576 577
    const DNXHDContext *ctx = avctx->priv_data;
    uint32_t offset = ctx->mb_scan_index[rownb];
    RowContext *row = ctx->rows + threadnb;
    int x;

    row->last_dc[0] =
    row->last_dc[1] =
    row->last_dc[2] = 1 << (ctx->bit_depth + 2); // for levels +2^(bitdepth-1)
    init_get_bits(&row->gb, ctx->buf + offset, (ctx->buf_size - offset) << 3);
    for (x = 0; x < ctx->mb_width; x++) {
        //START_TIMER;
578 579 580 581 582
        int ret = dnxhd_decode_macroblock(ctx, row, data, x, rownb);
        if (ret < 0) {
            row->errors++;
            return ret;
        }
583
        //STOP_TIMER("decode macroblock");
Baptiste Coudurier's avatar
Baptiste Coudurier committed
584
    }
585

Baptiste Coudurier's avatar
Baptiste Coudurier committed
586 587 588
    return 0;
}

589 590
static int dnxhd_decode_frame(AVCodecContext *avctx, void *data,
                              int *got_frame, AVPacket *avpkt)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
591
{
592 593
    const uint8_t *buf = avpkt->data;
    int buf_size = avpkt->size;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
594
    DNXHDContext *ctx = avctx->priv_data;
595
    ThreadFrame frame = { .f = data };
Baptiste Coudurier's avatar
Baptiste Coudurier committed
596
    AVFrame *picture = data;
597
    int first_field = 1;
598
    int ret, i;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
599

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

602 603 604
    for (i = 0; i < avctx->thread_count; i++)
        ctx->rows[i].format = -1;

605
decode_coding_unit:
606 607
    if ((ret = dnxhd_decode_header(ctx, picture, buf, buf_size, first_field)) < 0)
        return ret;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
608

609 610 611 612 613 614
    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;
    }
615 616 617 618 619
    if (avctx->pix_fmt != AV_PIX_FMT_NONE && avctx->pix_fmt != ctx->pix_fmt) {
        av_log(avctx, AV_LOG_WARNING, "pix_fmt changed: %s -> %s\n",
               av_get_pix_fmt_name(avctx->pix_fmt), av_get_pix_fmt_name(ctx->pix_fmt));
        first_field = 1;
    }
620

621
    avctx->pix_fmt = ctx->pix_fmt;
622 623 624
    ret = ff_set_dimensions(avctx, ctx->width, ctx->height);
    if (ret < 0)
        return ret;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
625

626
    if (first_field) {
627
        if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
628
            return ret;
629 630
        picture->pict_type = AV_PICTURE_TYPE_I;
        picture->key_frame = 1;
631
    }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
632

633 634
    ctx->buf_size = buf_size - ctx->data_offset;
    ctx->buf = buf + ctx->data_offset;
635
    avctx->execute2(avctx, dnxhd_decode_row, picture, NULL, ctx->mb_height);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
636

637
    if (first_field && picture->interlaced_frame) {
638 639 640 641 642 643
        buf      += ctx->cid_table->coding_unit_size;
        buf_size -= ctx->cid_table->coding_unit_size;
        first_field = 0;
        goto decode_coding_unit;
    }

644 645 646 647 648 649
    ret = 0;
    for (i = 0; i < avctx->thread_count; i++) {
        ret += ctx->rows[i].errors;
        ctx->rows[i].errors = 0;
    }

650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679
    if (ctx->act) {
        static int act_warned;
        int format = ctx->rows[0].format;
        for (i = 1; i < avctx->thread_count; i++) {
            if (ctx->rows[i].format != format &&
                ctx->rows[i].format != -1 /* not run */) {
                format = 2;
                break;
            }
        }
        switch (format) {
        case -1:
        case 2:
            if (!act_warned) {
                act_warned = 1;
                av_log(ctx->avctx, AV_LOG_ERROR,
                       "Unsupported: variable ACT flag.\n");
            }
            break;
        case 0:
            ctx->pix_fmt = ctx->bit_depth==10
                         ? AV_PIX_FMT_GBRP10 : AV_PIX_FMT_GBRP12;
            break;
        case 1:
            ctx->pix_fmt = ctx->bit_depth==10
                         ? AV_PIX_FMT_YUV444P10 : AV_PIX_FMT_YUV444P12;
            break;
        }
    }
    avctx->pix_fmt = ctx->pix_fmt;
680 681 682 683 684
    if (ret) {
        av_log(ctx->avctx, AV_LOG_ERROR, "%d lines with errors\n", ret);
        return AVERROR_INVALIDDATA;
    }

685
    *got_frame = 1;
686
    return avpkt->size;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
687 688
}

689
static av_cold int dnxhd_decode_close(AVCodecContext *avctx)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
690 691 692
{
    DNXHDContext *ctx = avctx->priv_data;

693 694 695
    ff_free_vlc(&ctx->ac_vlc);
    ff_free_vlc(&ctx->dc_vlc);
    ff_free_vlc(&ctx->run_vlc);
696 697 698

    av_freep(&ctx->rows);

Baptiste Coudurier's avatar
Baptiste Coudurier committed
699 700 701
    return 0;
}

702
AVCodec ff_dnxhd_decoder = {
703
    .name           = "dnxhd",
704
    .long_name      = NULL_IF_CONFIG_SMALL("VC3/DNxHD"),
705
    .type           = AVMEDIA_TYPE_VIDEO,
706
    .id             = AV_CODEC_ID_DNXHD,
707 708 709 710
    .priv_data_size = sizeof(DNXHDContext),
    .init           = dnxhd_decode_init,
    .close          = dnxhd_decode_close,
    .decode         = dnxhd_decode_frame,
711 712 713
    .capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
                      AV_CODEC_CAP_SLICE_THREADS,
    .init_thread_copy = ONLY_IF_THREADS_ENABLED(dnxhd_decode_init_thread_copy),
714
    .profiles       = NULL_IF_CONFIG_SMALL(ff_dnxhd_profiles),
Baptiste Coudurier's avatar
Baptiste Coudurier committed
715
};