dnxhddec.c 25 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[512];
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) {
114
            av_log(ctx->avctx, AV_LOG_ERROR, "unsupported cid %"PRIu32"\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 %"PRIu32".\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
static av_cold int dnxhd_decode_init_thread_copy(AVCodecContext *avctx)
{
    DNXHDContext *ctx = avctx->priv_data;

148
    ctx->avctx = avctx;
149 150 151 152 153 154 155 156 157 158
    // 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;
}

159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
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;
}

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

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

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

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

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

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

224 225 226 227 228 229 230 231 232 233
    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");
234

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

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

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

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

287
    ctx->mb_width  = (ctx->width + 15)>> 4;
288
    ctx->mb_height = AV_RB16(buf + 0x16c);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
289

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

293 294 295 296
    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);

297
    // Newer format supports variable mb_scan_index sizes
298
    if (ctx->mb_height > 68 && ff_dnxhd_check_header_prefix_hr(header_prefix)) {
299 300 301 302 303 304 305 306 307 308 309 310
        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) {
311
        av_log(ctx->avctx, AV_LOG_ERROR,
312
               "buffer too small (%d < %d).\n", buf_size, ctx->data_offset);
313
        return AVERROR_INVALIDDATA;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
314 315
    }

316 317
    if (ctx->mb_height > FF_ARRAY_ELEMS(ctx->mb_scan_index)) {
        av_log(ctx->avctx, AV_LOG_ERROR,
318
               "mb_height too big (%d > %"SIZE_SPECIFIER").\n", ctx->mb_height, FF_ARRAY_ELEMS(ctx->mb_scan_index));
319 320
        return AVERROR_INVALIDDATA;
    }
321

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

    return 0;
}

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

355 356
    ctx->bdsp.clear_block(block);

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

378 379
    UPDATE_CACHE(bs, &row->gb);
    GET_VLC(len, bs, &row->gb, ctx->dc_vlc.table, DNXHD_DC_VLC_BITS, 1);
380
    if (len) {
381 382
        level = GET_CACHE(bs, &row->gb);
        LAST_SKIP_BITS(bs, &row->gb, len);
383 384
        sign  = ~level >> 31;
        level = (NEG_USR32(sign ^ level, len) ^ sign) - sign;
385
        row->last_dc[component] += level * (1 << dc_shift);
386
    }
387
    block[0] = row->last_dc[component];
388

389
    i = 0;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
390

391 392
    UPDATE_CACHE(bs, &row->gb);
    GET_VLC(index1, bs, &row->gb, ctx->ac_vlc.table,
393 394
            DNXHD_VLC_BITS, 2);

395
    while (index1 != eob_index) {
396 397
        level = ac_info[2*index1+0];
        flags = ac_info[2*index1+1];
Baptiste Coudurier's avatar
Baptiste Coudurier committed
398

399 400
        sign = SHOW_SBITS(bs, &row->gb, 1);
        SKIP_BITS(bs, &row->gb, 1);
401

402
        if (flags & 1) {
403 404
            level += SHOW_UBITS(bs, &row->gb, index_bits) << 7;
            SKIP_BITS(bs, &row->gb, index_bits);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
405 406
        }

407
        if (flags & 2) {
408 409
            UPDATE_CACHE(bs, &row->gb);
            GET_VLC(index2, bs, &row->gb, ctx->run_vlc.table,
410
                    DNXHD_VLC_BITS, 2);
411
            i += ctx->cid_table->run[index2];
Baptiste Coudurier's avatar
Baptiste Coudurier committed
412 413
        }

414
        if (++i > 63) {
415
            av_log(ctx->avctx, AV_LOG_ERROR, "ac tex damaged %d, %d\n", n, i);
416
            ret = -1;
417
            break;
418 419
        }

420
        j     = ctx->scantable.permutated[i];
421
        level *= scale[i];
422
        level += scale[i] >> 1;
423
        if (level_bias < 32 || weight_matrix[i] != level_bias)
424
            level += level_bias; // 1<<(level_shift-1)
425 426
        level >>= level_shift;

427
        block[j] = (level ^ sign) - sign;
428

429 430
        UPDATE_CACHE(bs, &row->gb);
        GET_VLC(index1, bs, &row->gb, ctx->ac_vlc.table,
431
                DNXHD_VLC_BITS, 2);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
432
    }
433

434
    CLOSE_READER(bs, &row->gb);
435
    return ret;
436 437
}

438
static int dnxhd_decode_dct_block_8(const DNXHDContext *ctx,
439
                                    RowContext *row, int n)
440
{
441
    return dnxhd_decode_dct_block(ctx, row, n, 4, 32, 6, 0);
442 443
}

444
static int dnxhd_decode_dct_block_10(const DNXHDContext *ctx,
445
                                     RowContext *row, int n)
446
{
447
    return dnxhd_decode_dct_block(ctx, row, n, 6, 8, 4, 0);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
448 449
}

450
static int dnxhd_decode_dct_block_10_444(const DNXHDContext *ctx,
451
                                         RowContext *row, int n)
Kostya Shishkov's avatar
Kostya Shishkov committed
452
{
453 454 455 456 457 458 459 460 461 462 463 464 465
    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
466 467
}

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

479
    if (ctx->mbaff) {
480 481
        interlaced_mb = get_bits1(&row->gb);
        qscale = get_bits(&row->gb, 10);
482
    } else {
483
        qscale = get_bits(&row->gb, 11);
484
    }
485
    act = get_bits1(&row->gb);
486
    if (act) {
487 488 489 490 491 492 493 494 495 496 497
        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
498 499
        }
    }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
500

501
    if (qscale != row->last_qscale) {
502
        for (i = 0; i < 64; i++) {
503 504
            row->luma_scale[i]   = qscale * ctx->cid_table->luma_weight[i];
            row->chroma_scale[i] = qscale * ctx->cid_table->chroma_weight[i];
505
        }
506
        row->last_qscale = qscale;
507 508
    }

509
    for (i = 0; i < 8 + 4 * ctx->is_444; i++) {
510 511
        if (ctx->decode_dct_block(ctx, row, i) < 0)
            return AVERROR_INVALIDDATA;
Kostya Shishkov's avatar
Kostya Shishkov committed
512
    }
513

514
    if (frame->interlaced_frame) {
515 516 517 518
        dct_linesize_luma   <<= 1;
        dct_linesize_chroma <<= 1;
    }

519
    dest_y = frame->data[0] + ((y * dct_linesize_luma)   << 4) + (x << (4 + shift1));
Kostya Shishkov's avatar
Kostya Shishkov committed
520 521
    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
522

523
    if (frame->interlaced_frame && ctx->cur_field) {
524 525 526
        dest_y += frame->linesize[0];
        dest_u += frame->linesize[1];
        dest_v += frame->linesize[2];
527
    }
528 529 530 531
    if (interlaced_mb) {
        dct_linesize_luma   <<= 1;
        dct_linesize_chroma <<= 1;
    }
532

533
    dct_y_offset = interlaced_mb ? frame->linesize[0] : (dct_linesize_luma << 3);
534
    dct_x_offset = 8 << shift1;
Kostya Shishkov's avatar
Kostya Shishkov committed
535
    if (!ctx->is_444) {
536 537 538 539
        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
540

541
        if (!(ctx->avctx->flags & AV_CODEC_FLAG_GRAY)) {
542
            dct_y_offset = interlaced_mb ? frame->linesize[1] : (dct_linesize_chroma << 3);
543 544 545 546
            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
547 548
        }
    } else {
549 550 551 552
        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
553

554
        if (!(ctx->avctx->flags & AV_CODEC_FLAG_GRAY)) {
555
            dct_y_offset = interlaced_mb ? frame->linesize[1] : (dct_linesize_chroma << 3);
556 557 558 559 560 561 562 563
            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
564
        }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
565 566 567 568 569
    }

    return 0;
}

570 571
static int dnxhd_decode_row(AVCodecContext *avctx, void *data,
                            int rownb, int threadnb)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
572
{
573 574 575 576 577 578 579 580 581 582 583
    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;
584 585 586 587 588
        int ret = dnxhd_decode_macroblock(ctx, row, data, x, rownb);
        if (ret < 0) {
            row->errors++;
            return ret;
        }
589
        //STOP_TIMER("decode macroblock");
Baptiste Coudurier's avatar
Baptiste Coudurier committed
590
    }
591

Baptiste Coudurier's avatar
Baptiste Coudurier committed
592 593 594
    return 0;
}

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

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

608 609 610
    for (i = 0; i < avctx->thread_count; i++)
        ctx->rows[i].format = -1;

611
decode_coding_unit:
612 613
    if ((ret = dnxhd_decode_header(ctx, picture, buf, buf_size, first_field)) < 0)
        return ret;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
614

615 616
    if ((avctx->width || avctx->height) &&
        (ctx->width != avctx->width || ctx->height != avctx->height)) {
617
        av_log(avctx, AV_LOG_WARNING, "frame size changed: %dx%d -> %ux%u\n",
618 619 620
               avctx->width, avctx->height, ctx->width, ctx->height);
        first_field = 1;
    }
621 622 623 624 625
    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;
    }
626

627
    avctx->pix_fmt = ctx->pix_fmt;
628 629 630
    ret = ff_set_dimensions(avctx, ctx->width, ctx->height);
    if (ret < 0)
        return ret;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
631

632
    if (first_field) {
633
        if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
634
            return ret;
635 636
        picture->pict_type = AV_PICTURE_TYPE_I;
        picture->key_frame = 1;
637
    }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
638

639 640
    ctx->buf_size = buf_size - ctx->data_offset;
    ctx->buf = buf + ctx->data_offset;
641
    avctx->execute2(avctx, dnxhd_decode_row, picture, NULL, ctx->mb_height);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
642

643
    if (first_field && picture->interlaced_frame) {
644 645 646 647 648 649
        buf      += ctx->cid_table->coding_unit_size;
        buf_size -= ctx->cid_table->coding_unit_size;
        first_field = 0;
        goto decode_coding_unit;
    }

650 651 652 653 654 655
    ret = 0;
    for (i = 0; i < avctx->thread_count; i++) {
        ret += ctx->rows[i].errors;
        ctx->rows[i].errors = 0;
    }

656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685
    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;
686 687 688 689 690
    if (ret) {
        av_log(ctx->avctx, AV_LOG_ERROR, "%d lines with errors\n", ret);
        return AVERROR_INVALIDDATA;
    }

691
    *got_frame = 1;
692
    return avpkt->size;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
693 694
}

695
static av_cold int dnxhd_decode_close(AVCodecContext *avctx)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
696 697 698
{
    DNXHDContext *ctx = avctx->priv_data;

699 700 701
    ff_free_vlc(&ctx->ac_vlc);
    ff_free_vlc(&ctx->dc_vlc);
    ff_free_vlc(&ctx->run_vlc);
702 703 704

    av_freep(&ctx->rows);

Baptiste Coudurier's avatar
Baptiste Coudurier committed
705 706 707
    return 0;
}

708
AVCodec ff_dnxhd_decoder = {
709
    .name           = "dnxhd",
710
    .long_name      = NULL_IF_CONFIG_SMALL("VC3/DNxHD"),
711
    .type           = AVMEDIA_TYPE_VIDEO,
712
    .id             = AV_CODEC_ID_DNXHD,
713 714 715 716
    .priv_data_size = sizeof(DNXHDContext),
    .init           = dnxhd_decode_init,
    .close          = dnxhd_decode_close,
    .decode         = dnxhd_decode_frame,
717 718 719
    .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),
720
    .profiles       = NULL_IF_CONFIG_SMALL(ff_dnxhd_profiles),
Baptiste Coudurier's avatar
Baptiste Coudurier committed
721
};