From f5f9c166a1b48212262974d74a5524e180d8f86f Mon Sep 17 00:00:00 2001 From: Christophe Gisquet Date: Fri, 25 Sep 2015 18:57:17 +0200 Subject: [PATCH] dnxhddec: decode and use interlace mb flag This bit is 1 in some samples, and seems to coincide with interlaced mbs and CID1260. 2008 specs do not know about it, and maintain qscale is 11 bits. This looks oversized, but may help larger bitdepths. Currently, it leads to an obviously incorrect qscale value, meaning its syntax is shifted by 1. However, reading 11 bits also leads to obviously incorrect decoding: qscale seems to be 10 bits. However, as most profiles still have 11bits qscale, the feature is restricted to the CID1260 profile. The encoder writes 12 bits of syntax, last and first bits always 0, which is now somewhat inconsistent with the decoder, but ends up with the same effect (progressive + reserved bit). Partially fixes ticket #4876. Signed-off-by: Michael Niedermayer (cherry picked from commit 2801a1352dc8682b028e53880f9847fcb2116947) Signed-off-by: Michael Niedermayer --- libavcodec/dnxhddec.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/libavcodec/dnxhddec.c b/libavcodec/dnxhddec.c index 1034d8970b..4a42360388 100644 --- a/libavcodec/dnxhddec.c +++ b/libavcodec/dnxhddec.c @@ -349,7 +349,12 @@ static int dnxhd_decode_macroblock(DNXHDContext *ctx, AVFrame *frame, uint8_t *dest_y, *dest_u, *dest_v; int dct_y_offset, dct_x_offset; int qscale, i; + int interlaced_mb = 0; + if (ctx->cid_table->cid == 1260) { + interlaced_mb = get_bits1(&ctx->gb); + qscale = get_bits(&ctx->gb, 10); + } else qscale = get_bits(&ctx->gb, 11); skip_bits1(&ctx->gb); @@ -386,8 +391,12 @@ static int dnxhd_decode_macroblock(DNXHDContext *ctx, AVFrame *frame, dest_u += frame->linesize[1]; dest_v += frame->linesize[2]; } + if (interlaced_mb) { + dct_linesize_luma <<= 1; + dct_linesize_chroma <<= 1; + } - dct_y_offset = dct_linesize_luma << 3; + dct_y_offset = interlaced_mb ? frame->linesize[0] : (dct_linesize_luma << 3); dct_x_offset = 8 << shift1; if (!ctx->is_444) { ctx->idsp.idct_put(dest_y, dct_linesize_luma, ctx->blocks[0]); @@ -396,7 +405,7 @@ static int dnxhd_decode_macroblock(DNXHDContext *ctx, AVFrame *frame, ctx->idsp.idct_put(dest_y + dct_y_offset + dct_x_offset, dct_linesize_luma, ctx->blocks[5]); if (!(ctx->avctx->flags & AV_CODEC_FLAG_GRAY)) { - dct_y_offset = dct_linesize_chroma << 3; + dct_y_offset = interlaced_mb ? frame->linesize[1] : (dct_linesize_chroma << 3); ctx->idsp.idct_put(dest_u, dct_linesize_chroma, ctx->blocks[2]); ctx->idsp.idct_put(dest_v, dct_linesize_chroma, ctx->blocks[3]); ctx->idsp.idct_put(dest_u + dct_y_offset, dct_linesize_chroma, ctx->blocks[6]); @@ -409,7 +418,7 @@ static int dnxhd_decode_macroblock(DNXHDContext *ctx, AVFrame *frame, ctx->idsp.idct_put(dest_y + dct_y_offset + dct_x_offset, dct_linesize_luma, ctx->blocks[7]); if (!(ctx->avctx->flags & AV_CODEC_FLAG_GRAY)) { - dct_y_offset = dct_linesize_chroma << 3; + dct_y_offset = interlaced_mb ? frame->linesize[1] : (dct_linesize_chroma << 3); ctx->idsp.idct_put(dest_u, dct_linesize_chroma, ctx->blocks[2]); ctx->idsp.idct_put(dest_u + dct_x_offset, dct_linesize_chroma, ctx->blocks[3]); ctx->idsp.idct_put(dest_u + dct_y_offset, dct_linesize_chroma, ctx->blocks[8]);