From: Christophe Gisquet <c.gisq...@ateme.com> Where they are allowed. No validation of profile + colorformat is performed, however. --- libavcodec/dnxhddec.c | 55 +++++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 15 deletions(-)
diff --git a/libavcodec/dnxhddec.c b/libavcodec/dnxhddec.c index c78d55aee5..359588f963 100644 --- a/libavcodec/dnxhddec.c +++ b/libavcodec/dnxhddec.c @@ -49,6 +49,13 @@ typedef struct RowContext { int format; } RowContext; +typedef enum { + DNX_CHROMAFORMAT_422 = 0, + DNX_CHROMAFORMAT_420 = 1, + DNX_CHROMAFORMAT_444 = 2, + DNX_CHROMAFORMAT_UNKNOWN = 3, +} DNXChromaFormat; + typedef struct DNXHDContext { AVCodecContext *avctx; RowContext *rows; @@ -67,7 +74,7 @@ typedef struct DNXHDContext { ScanTable scantable; const CIDEntry *cid_table; int bit_depth; // 8, 10, 12 or 0 if not initialized at all. - int is_444; + int chromafmt; int alpha; int lla; int mbaff; @@ -168,6 +175,7 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame, const uint8_t *buf, int buf_size, int first_field) { + static const char* cfname[4] = { "4:2:2", "4:2:0", "4:4:4", "Unknown" }; int i, cid, ret; int old_bit_depth = ctx->bit_depth, bitdepth; uint64_t header_prefix; @@ -234,8 +242,8 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame, 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) { + ctx->chromafmt = (buf[0x2C] >> 5) & 3; + if (ctx->chromafmt == DNX_CHROMAFORMAT_444) { if (bitdepth == 8) { avpriv_request_sample(ctx->avctx, "4:4:4 8 bits"); return AVERROR_INVALIDDATA; @@ -250,16 +258,16 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame, } } else if (bitdepth == 12) { ctx->decode_dct_block = dnxhd_decode_dct_block_12; - ctx->pix_fmt = AV_PIX_FMT_YUV422P12; + ctx->pix_fmt = ctx->chromafmt == DNX_CHROMAFORMAT_420 ? AV_PIX_FMT_YUV420P12 : AV_PIX_FMT_YUV422P12; } else if (bitdepth == 10) { 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; - ctx->pix_fmt = AV_PIX_FMT_YUV422P10; + ctx->pix_fmt = ctx->chromafmt == DNX_CHROMAFORMAT_420 ? AV_PIX_FMT_YUV420P10 : AV_PIX_FMT_YUV422P10; } else { ctx->decode_dct_block = dnxhd_decode_dct_block_8; - ctx->pix_fmt = AV_PIX_FMT_YUV422P; + ctx->pix_fmt = ctx->chromafmt == DNX_CHROMAFORMAT_420 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV422P; } ctx->avctx->bits_per_raw_sample = ctx->bit_depth = bitdepth; @@ -292,8 +300,8 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame, if ((ctx->height + 15) >> 4 == ctx->mb_height && frame->interlaced_frame) ctx->height <<= 1; - 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", + av_log(ctx->avctx, AV_LOG_VERBOSE, "%dx%d, %s %d bits, MBAFF=%d ACT=%d\n", + ctx->width, ctx->height, cfname[ctx->chromafmt], ctx->bit_depth, ctx->mbaff, ctx->act); // Newer format supports variable mb_scan_index sizes @@ -360,7 +368,7 @@ static av_always_inline int dnxhd_decode_dct_block(const DNXHDContext *ctx, ctx->bdsp.clear_block(block); - if (!ctx->is_444) { + if (ctx->chromafmt != DNX_CHROMAFORMAT_444) { if (n & 2) { component = 1 + (n & 1); scale = row->chroma_scale; @@ -478,6 +486,9 @@ static int dnxhd_decode_dct_block_12_444(const DNXHDContext *ctx, static int dnxhd_decode_macroblock(const DNXHDContext *ctx, RowContext *row, AVFrame *frame, int x, int y) { + static const char yoff[4] = { 1, 0, 1, 0 }; + static const char xoff[4] = { 0, 0, 1, 0 }; + static const uint8_t num_blocks[4] = { 8, 6, 12, 0 }; int shift1 = ctx->bit_depth >= 10; int dct_linesize_luma = frame->linesize[0]; int dct_linesize_chroma = frame->linesize[1]; @@ -516,7 +527,7 @@ static int dnxhd_decode_macroblock(const DNXHDContext *ctx, RowContext *row, row->last_qscale = qscale; } - for (i = 0; i < 8 + 4 * ctx->is_444; i++) { + for (i = 0; i < num_blocks[ctx->chromafmt]; i++) { if (ctx->decode_dct_block(ctx, row, i) < 0) return AVERROR_INVALIDDATA; } @@ -526,9 +537,9 @@ static int dnxhd_decode_macroblock(const DNXHDContext *ctx, RowContext *row, dct_linesize_chroma <<= 1; } - dest_y = frame->data[0] + ((y * dct_linesize_luma) << 4) + (x << (4 + shift1)); - 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)); + dest_y = frame->data[0] + ((y * dct_linesize_luma) << 4) + (x << (4 + shift1)); + dest_u = frame->data[1] + ((y * dct_linesize_chroma) << (3 + yoff[ctx->chromafmt])) + (x << (3 + shift1 + xoff[ctx->chromafmt])); + dest_v = frame->data[2] + ((y * dct_linesize_chroma) << (3 + yoff[ctx->chromafmt])) + (x << (3 + shift1 + xoff[ctx->chromafmt])); if (frame->interlaced_frame && ctx->cur_field) { dest_y += frame->linesize[0]; @@ -542,7 +553,8 @@ static int dnxhd_decode_macroblock(const DNXHDContext *ctx, RowContext *row, dct_y_offset = interlaced_mb ? frame->linesize[0] : (dct_linesize_luma << 3); dct_x_offset = 8 << shift1; - if (!ctx->is_444) { + switch (ctx->chromafmt) { + case DNX_CHROMAFORMAT_422: 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]); @@ -555,7 +567,8 @@ static int dnxhd_decode_macroblock(const DNXHDContext *ctx, RowContext *row, 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]); } - } else { + break; + case DNX_CHROMAFORMAT_444: 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]); @@ -572,6 +585,18 @@ static int dnxhd_decode_macroblock(const DNXHDContext *ctx, RowContext *row, 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]); } + break; + case DNX_CHROMAFORMAT_420: + 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]); + + if (!(ctx->avctx->flags & AV_CODEC_FLAG_GRAY)) { + ctx->idsp.idct_put(dest_u, dct_linesize_chroma, row->blocks[2]); + ctx->idsp.idct_put(dest_v, dct_linesize_chroma, row->blocks[3]); + } + break; } return 0; -- 2.29.2 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".