summaryrefslogtreecommitdiff
path: root/libavcodec/dnxhddec.c
diff options
context:
space:
mode:
authorChristophe Gisquet <christophe.gisquet@gmail.com>2015-09-26 17:38:22 +0200
committerVittorio Giovara <vittorio.giovara@gmail.com>2015-09-29 14:33:01 +0200
commitc49cbecbae5a42f4ca004197b0118cc50aaaca2e (patch)
tree944a2e2b32c3d4534f45be01b4c574859bdeb064 /libavcodec/dnxhddec.c
parentc5e5e6306223623de8352a3ecd224956aa5beb37 (diff)
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 (this flag is dependent on a higher-level flag located in the header). 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). Signed-off-by: Vittorio Giovara <vittorio.giovara@gmail.com>
Diffstat (limited to 'libavcodec/dnxhddec.c')
-rw-r--r--libavcodec/dnxhddec.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/libavcodec/dnxhddec.c b/libavcodec/dnxhddec.c
index 72f63e06e7..c1bf3afac8 100644
--- a/libavcodec/dnxhddec.c
+++ b/libavcodec/dnxhddec.c
@@ -48,6 +48,7 @@ typedef struct DNXHDContext {
const CIDEntry *cid_table;
int bit_depth; // 8, 10 or 0 if not initialized at all.
int is_444;
+ int mbaff;
void (*decode_dct_block)(struct DNXHDContext *ctx, int16_t *block,
int n, int qscale);
} DNXHDContext;
@@ -131,6 +132,7 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame,
av_log(ctx->avctx, AV_LOG_DEBUG,
"interlaced %d, cur field %d\n", buf[5] & 3, ctx->cur_field);
}
+ ctx->mbaff = buf[0x6] & 32;
ctx->height = AV_RB16(buf + 0x18);
ctx->width = AV_RB16(buf + 0x1a);
@@ -168,6 +170,9 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame,
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");
// make sure profile size constraints are respected
// DNx100 allows 1920->1440 and 1280->960 subsampling
@@ -321,8 +326,14 @@ 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;
- qscale = get_bits(&ctx->gb, 11);
+ if (ctx->mbaff) {
+ interlaced_mb = get_bits1(&ctx->gb);
+ qscale = get_bits(&ctx->gb, 10);
+ } else {
+ qscale = get_bits(&ctx->gb, 11);
+ }
skip_bits1(&ctx->gb);
for (i = 0; i < 8; i++) {
@@ -350,8 +361,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]);
@@ -360,7 +375,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]);
@@ -373,7 +388,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]);