[FFmpeg-devel] [PATCH 1/4] lav/dnxhd: better support 4:2:0 in DNXHR profiles
Christophe Gisquet
christophe.gisquet at gmail.com
Sat Jan 30 11:19:03 EET 2021
From: Christophe Gisquet <c.gisquet at 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
More information about the ffmpeg-devel
mailing list