X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fdnxhddec.c;h=2eb07ec5d848fcb7bd7a82a30145e8cc2e94a29c;hb=b9fb1db9b42cfad6b4073daf70ca7b89840a1c15;hp=296f7f74d6b95d97e739deaa40f5690b230d98e5;hpb=cda503a1b92c776cd197ec5a8879b793d9deaad8;p=ffmpeg diff --git a/libavcodec/dnxhddec.c b/libavcodec/dnxhddec.c index 296f7f74d6b..2eb07ec5d84 100644 --- a/libavcodec/dnxhddec.c +++ b/libavcodec/dnxhddec.c @@ -43,6 +43,8 @@ typedef struct RowContext { int last_dc[3]; int last_qscale; int errors; + /** -1:not set yet 0:off=RGB 1:on=YUV 2:variable */ + int format; } RowContext; typedef struct DNXHDContext { @@ -55,13 +57,14 @@ typedef struct DNXHDContext { unsigned int width, height; enum AVPixelFormat pix_fmt; unsigned int mb_width, mb_height; - uint32_t mb_scan_index[68]; /* max for 1080p */ + uint32_t *mb_scan_index; + int data_offset; // End of mb_scan_index, where macroblocks start int cur_field; ///< current interlaced field VLC ac_vlc, dc_vlc, run_vlc; IDCTDSPContext idsp; ScanTable scantable; const CIDEntry *cid_table; - int bit_depth; // 8, 10 or 0 if not initialized at all. + int bit_depth; // 8, 10, 12 or 0 if not initialized at all. int is_444; int mbaff; int act; @@ -78,6 +81,10 @@ static int dnxhd_decode_dct_block_10(const DNXHDContext *ctx, RowContext *row, int n); static int dnxhd_decode_dct_block_10_444(const DNXHDContext *ctx, RowContext *row, int n); +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); static av_cold int dnxhd_decode_init(AVCodecContext *avctx) { @@ -97,7 +104,7 @@ static av_cold int dnxhd_decode_init(AVCodecContext *avctx) return 0; } -static int dnxhd_init_vlc(DNXHDContext *ctx, uint32_t cid) +static int dnxhd_init_vlc(DNXHDContext *ctx, uint32_t cid, int bitdepth) { if (cid != ctx->cid) { int index; @@ -106,8 +113,9 @@ static int dnxhd_init_vlc(DNXHDContext *ctx, uint32_t cid) av_log(ctx->avctx, AV_LOG_ERROR, "unsupported cid %d\n", cid); return AVERROR(ENOSYS); } - if (ff_dnxhd_cid_table[index].bit_depth != ctx->bit_depth) { - av_log(ctx->avctx, AV_LOG_ERROR, "bit depth mismatches %d %d\n", ff_dnxhd_cid_table[index].bit_depth, ctx->bit_depth); + if (ff_dnxhd_cid_table[index].bit_depth != bitdepth && + ff_dnxhd_cid_table[index].bit_depth != DNXHD_VARIABLE) { + av_log(ctx->avctx, AV_LOG_ERROR, "bit depth mismatches %d %d\n", ff_dnxhd_cid_table[index].bit_depth, bitdepth); return AVERROR_INVALIDDATA; } ctx->cid_table = &ff_dnxhd_cid_table[index]; @@ -120,7 +128,7 @@ static int dnxhd_init_vlc(DNXHDContext *ctx, uint32_t cid) init_vlc(&ctx->ac_vlc, DNXHD_VLC_BITS, 257, ctx->cid_table->ac_bits, 1, 1, ctx->cid_table->ac_codes, 2, 2, 0); - init_vlc(&ctx->dc_vlc, DNXHD_DC_VLC_BITS, ctx->bit_depth + 4, + init_vlc(&ctx->dc_vlc, DNXHD_DC_VLC_BITS, bitdepth + 4, ctx->cid_table->dc_bits, 1, 1, ctx->cid_table->dc_codes, 1, 1, 0); init_vlc(&ctx->run_vlc, DNXHD_VLC_BITS, 62, @@ -152,8 +160,11 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame, { static const uint8_t header_prefix[] = { 0x00, 0x00, 0x02, 0x80, 0x01 }; static const uint8_t header_prefix444[] = { 0x00, 0x00, 0x02, 0x80, 0x02 }; + static const uint8_t header_prefixhr1[] = { 0x00, 0x00, 0x02, 0x80, 0x03 }; + static const uint8_t header_prefixhr2[] = { 0x00, 0x00, 0x03, 0x8C, 0x03 }; int i, cid, ret; - int old_bit_depth = ctx->bit_depth; + int old_bit_depth = ctx->bit_depth, bitdepth; + int old_mb_height = ctx->mb_height; if (buf_size < 0x280) { av_log(ctx->avctx, AV_LOG_ERROR, @@ -161,7 +172,8 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame, return AVERROR_INVALIDDATA; } - if (memcmp(buf, header_prefix, 5) && memcmp(buf, header_prefix444, 5)) { + if (memcmp(buf, header_prefix, 5) && memcmp(buf, header_prefix444, 5) && + memcmp(buf, header_prefixhr1, 5) && memcmp(buf, header_prefixhr2, 5)) { 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]); @@ -176,60 +188,70 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame, } else { ctx->cur_field = 0; } - ctx->mbaff = buf[0x6] & 32; + ctx->mbaff = (buf[0x6] >> 5) & 1; ctx->height = AV_RB16(buf + 0x18); ctx->width = AV_RB16(buf + 0x1a); - ff_dlog(ctx->avctx, "width %d, height %d\n", ctx->width, ctx->height); - - if (buf[0x21] == 0x58) { /* 10 bit */ - ctx->bit_depth = ctx->avctx->bits_per_raw_sample = 10; - - if (buf[0x4] == 0x2) { - ctx->decode_dct_block = dnxhd_decode_dct_block_10_444; - ctx->pix_fmt = AV_PIX_FMT_YUV444P10; - ctx->is_444 = 1; - } else { - ctx->decode_dct_block = dnxhd_decode_dct_block_10; - ctx->pix_fmt = AV_PIX_FMT_YUV422P10; - ctx->is_444 = 0; - } - } else if (buf[0x21] == 0x38) { /* 8 bit */ - ctx->bit_depth = ctx->avctx->bits_per_raw_sample = 8; - - ctx->pix_fmt = AV_PIX_FMT_YUV422P; - ctx->is_444 = 0; - ctx->decode_dct_block = dnxhd_decode_dct_block_8; - } else { + switch(buf[0x21] >> 5) { + case 1: bitdepth = 8; break; + case 2: bitdepth = 10; break; + case 3: bitdepth = 12; break; + default: av_log(ctx->avctx, AV_LOG_ERROR, - "invalid bit depth value (%d).\n", buf[0x21]); + "Unknown bitdepth indicator (%d)\n", buf[0x21] >> 5); return AVERROR_INVALIDDATA; } - if (ctx->bit_depth != old_bit_depth) { - ff_blockdsp_init(&ctx->bdsp, ctx->avctx); - ff_idctdsp_init(&ctx->idsp, ctx->avctx); - ff_init_scantable(ctx->idsp.idct_permutation, &ctx->scantable, - ff_zigzag_direct); - } cid = AV_RB32(buf + 0x28); - ff_dlog(ctx->avctx, "compression id %d\n", cid); - - if ((ret = dnxhd_init_vlc(ctx, cid)) < 0) + 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) + 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"); + ctx->is_444 = (buf[0x2C] >> 6) & 1; + if (ctx->is_444) { + if (bitdepth == 8) { + avpriv_request_sample(ctx->avctx, "4:4:4 8 bits\n"); + return AVERROR_INVALIDDATA; + } else if (bitdepth == 10) { + ctx->decode_dct_block = dnxhd_decode_dct_block_10_444; + ctx->pix_fmt = ctx->act ? AV_PIX_FMT_YUV444P10 + : AV_PIX_FMT_GBRP10; + } else { + ctx->decode_dct_block = dnxhd_decode_dct_block_12_444; + ctx->pix_fmt = ctx->act ? AV_PIX_FMT_YUV444P12 + : AV_PIX_FMT_GBRP12; + } + } else if (bitdepth == 12) { + ctx->decode_dct_block = dnxhd_decode_dct_block_12; + ctx->pix_fmt = AV_PIX_FMT_YUV422P12; + } else if (bitdepth == 10) { + ctx->decode_dct_block = dnxhd_decode_dct_block_10; + ctx->pix_fmt = AV_PIX_FMT_YUV422P10; + } else { + ctx->decode_dct_block = dnxhd_decode_dct_block_8; + ctx->pix_fmt = AV_PIX_FMT_YUV422P; + } + + ctx->avctx->bits_per_raw_sample = ctx->bit_depth = bitdepth; + if (ctx->bit_depth != old_bit_depth) { + ff_blockdsp_init(&ctx->bdsp, ctx->avctx); + ff_idctdsp_init(&ctx->idsp, ctx->avctx); + ff_init_scantable(ctx->idsp.idct_permutation, &ctx->scantable, + ff_zigzag_direct); + } + // make sure profile size constraints are respected // DNx100 allows 1920->1440 and 1280->960 subsampling - if (ctx->width != ctx->cid_table->width) { + if (ctx->width != ctx->cid_table->width && + ctx->cid_table->width != DNXHD_VARIABLE) { av_reduce(&ctx->avctx->sample_aspect_ratio.num, &ctx->avctx->sample_aspect_ratio.den, ctx->width, ctx->cid_table->width, 255); @@ -242,29 +264,50 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame, return AVERROR_INVALIDDATA; } - ctx->mb_width = ctx->width >> 4; + ctx->mb_width = (ctx->width + 15)>> 4; ctx->mb_height = buf[0x16d]; - ff_dlog(ctx->avctx, - "mb width %d, mb height %d\n", ctx->mb_width, ctx->mb_height); - if ((ctx->height + 15) >> 4 == ctx->mb_height && frame->interlaced_frame) ctx->height <<= 1; - if (ctx->mb_height > 68 || - (ctx->mb_height << frame->interlaced_frame) > (ctx->height + 15) >> 4) { + 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); + + // Newer format supports variable mb_scan_index sizes + if (!memcmp(buf, header_prefixhr2, 5)) { + 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) { av_log(ctx->avctx, AV_LOG_ERROR, - "mb height too big: %d\n", ctx->mb_height); + "buffer too small (%d < %d).\n", buf_size, ctx->data_offset); return AVERROR_INVALIDDATA; } + if (ctx->mb_height != old_mb_height) { + av_freep(&ctx->mb_scan_index); + + ctx->mb_scan_index = av_mallocz_array(ctx->mb_height, sizeof(uint32_t)); + if (!ctx->mb_scan_index) + return AVERROR(ENOMEM); + } + for (i = 0; i < ctx->mb_height; i++) { ctx->mb_scan_index[i] = AV_RB32(buf + 0x170 + (i << 2)); - ff_dlog(ctx->avctx, "mb scan index %d\n", ctx->mb_scan_index[i]); - if (buf_size < ctx->mb_scan_index[i] + 0x280LL) { + 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]) { av_log(ctx->avctx, AV_LOG_ERROR, - "invalid mb scan index (%d < %d).\n", - buf_size, ctx->mb_scan_index[i] + 0x280); + "invalid mb scan index (%u vs %u).\n", + ctx->mb_scan_index[i], buf_size - ctx->data_offset); return AVERROR_INVALIDDATA; } } @@ -277,14 +320,14 @@ static av_always_inline int dnxhd_decode_dct_block(const DNXHDContext *ctx, int n, int index_bits, int level_bias, - int level_shift) + int level_shift, + int dc_shift) { int i, j, index1, index2, len, flags; int level, component, sign; const int *scale; const uint8_t *weight_matrix; - const uint8_t *ac_level = ctx->cid_table->ac_level; - const uint8_t *ac_flags = ctx->cid_table->ac_flags; + const uint8_t *ac_info = ctx->cid_table->ac_info; int16_t *block = row->blocks[n]; const int eob_index = ctx->cid_table->eob_index; int ret = 0; @@ -320,7 +363,7 @@ static av_always_inline int dnxhd_decode_dct_block(const DNXHDContext *ctx, LAST_SKIP_BITS(bs, &row->gb, len); sign = ~level >> 31; level = (NEG_USR32(sign ^ level, len) ^ sign) - sign; - row->last_dc[component] += level; + row->last_dc[component] += level << dc_shift; } block[0] = row->last_dc[component]; @@ -331,8 +374,8 @@ static av_always_inline int dnxhd_decode_dct_block(const DNXHDContext *ctx, DNXHD_VLC_BITS, 2); while (index1 != eob_index) { - level = ac_level[index1]; - flags = ac_flags[index1]; + level = ac_info[2*index1+0]; + flags = ac_info[2*index1+1]; sign = SHOW_SBITS(bs, &row->gb, 1); SKIP_BITS(bs, &row->gb, 1); @@ -376,25 +419,37 @@ static av_always_inline int dnxhd_decode_dct_block(const DNXHDContext *ctx, static int dnxhd_decode_dct_block_8(const DNXHDContext *ctx, RowContext *row, int n) { - return dnxhd_decode_dct_block(ctx, row, n, 4, 32, 6); + return dnxhd_decode_dct_block(ctx, row, n, 4, 32, 6, 0); } static int dnxhd_decode_dct_block_10(const DNXHDContext *ctx, RowContext *row, int n) { - return dnxhd_decode_dct_block(ctx, row, n, 6, 8, 4); + return dnxhd_decode_dct_block(ctx, row, n, 6, 8, 4, 0); } static int dnxhd_decode_dct_block_10_444(const DNXHDContext *ctx, RowContext *row, int n) { - return dnxhd_decode_dct_block(ctx, row, n, 6, 32, 6); + 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); } static int dnxhd_decode_macroblock(const DNXHDContext *ctx, RowContext *row, AVFrame *frame, int x, int y) { - int shift1 = ctx->bit_depth == 10; + int shift1 = ctx->bit_depth >= 10; int dct_linesize_luma = frame->linesize[0]; int dct_linesize_chroma = frame->linesize[1]; uint8_t *dest_y, *dest_u, *dest_v; @@ -410,11 +465,17 @@ static int dnxhd_decode_macroblock(const DNXHDContext *ctx, RowContext *row, } act = get_bits1(&row->gb); if (act) { - static int warned = 0; - if (!warned) { - warned = 1; - av_log(ctx->avctx, AV_LOG_ERROR, - "Unsupported adaptive color transform, patch welcome.\n"); + 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 } } @@ -525,6 +586,9 @@ static int dnxhd_decode_frame(AVCodecContext *avctx, void *data, ff_dlog(avctx, "frame size %d\n", buf_size); + for (i = 0; i < avctx->thread_count; i++) + ctx->rows[i].format = -1; + decode_coding_unit: if ((ret = dnxhd_decode_header(ctx, picture, buf, buf_size, first_field)) < 0) return ret; @@ -553,8 +617,8 @@ decode_coding_unit: picture->key_frame = 1; } - ctx->buf_size = buf_size - 0x280; - ctx->buf = buf + 0x280; + ctx->buf_size = buf_size - ctx->data_offset; + ctx->buf = buf + ctx->data_offset; avctx->execute2(avctx, dnxhd_decode_row, picture, NULL, ctx->mb_height); if (first_field && picture->interlaced_frame) { @@ -570,6 +634,36 @@ decode_coding_unit: ctx->rows[i].errors = 0; } + 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; if (ret) { av_log(ctx->avctx, AV_LOG_ERROR, "%d lines with errors\n", ret); return AVERROR_INVALIDDATA; @@ -587,6 +681,7 @@ static av_cold int dnxhd_decode_close(AVCodecContext *avctx) ff_free_vlc(&ctx->dc_vlc); ff_free_vlc(&ctx->run_vlc); + av_freep(&ctx->mb_scan_index); av_freep(&ctx->rows); return 0;