[FFmpeg-devel] [PATCH 1/3] dnxhddec: better support for 4:4:4
Christophe Gisquet
christophe.gisquet at gmail.com
Mon Oct 5 20:44:44 CEST 2015
Profiles 1256 & 1270 (currently) signal at the frame header and MB
levels the colorspace used, either RGB or YUV. While a MB-level
varying colorspace is not supported, whether it is constant can be
tracked so as to determine the exact colorspace.
It is not tested against a true RGB sequence, though.
---
libavcodec/dnxhddec.c | 82 ++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 62 insertions(+), 20 deletions(-)
diff --git a/libavcodec/dnxhddec.c b/libavcodec/dnxhddec.c
index fec9aac..52fd334 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 {
@@ -202,6 +204,18 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame,
}
ctx->avctx->bits_per_raw_sample = ctx->bit_depth;
+ cid = AV_RB32(buf + 0x28);
+ if ((ret = dnxhd_init_vlc(ctx, cid)) < 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");
+
ctx->is_444 = (buf[0x2C] >> 6) & 1;
if (ctx->is_444) {
if (ctx->bit_depth == 8) {
@@ -209,10 +223,12 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame,
return AVERROR_INVALIDDATA;
} else if (ctx->bit_depth == 10) {
ctx->decode_dct_block = dnxhd_decode_dct_block_10_444;
- ctx->pix_fmt = AV_PIX_FMT_YUV444P10;
+ 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 = AV_PIX_FMT_YUV444P12;
+ ctx->pix_fmt = ctx->act ? AV_PIX_FMT_YUV444P12
+ : AV_PIX_FMT_GBRP12;
}
} else if (ctx->bit_depth == 12) {
ctx->decode_dct_block = dnxhd_decode_dct_block_12;
@@ -231,19 +247,6 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame,
ff_zigzag_direct);
}
- cid = AV_RB32(buf + 0x28);
-
- if ((ret = dnxhd_init_vlc(ctx, cid)) < 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");
-
// make sure profile size constraints are respected
// DNx100 allows 1920->1440 and 1280->960 subsampling
if (ctx->width != ctx->cid_table->width &&
@@ -462,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 = 0;
+ 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
}
}
@@ -577,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;
@@ -622,6 +634,36 @@ decode_coding_unit:
ctx->rows[i].errors = 0;
}
+ if (ctx->act) {
+ static int act_warned = 0;
+ 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;
--
2.5.2
More information about the ffmpeg-devel
mailing list