[RESOLVED] DNxHD 444 patch tentative

Archive of historical development discussions
Discussions / Development has moved to GitHub
Forum rules
*******************************
Please be aware we are now using GitHub for issue tracking and feature requests.
- This section of the forum is now closed to new topics.

*******************************
Post Reply
Deleted User 13735

[RESOLVED] DNxHD 444 patch tentative

Post by Deleted User 13735 »

A developer at libav sent me a tentative patch for "[Bug 99] Support new DNxHD 10-bit 444 Mbps templates" that I submitted some time back. If someone has the time to try this and get back to lu_zero@gentu.org and include me in the loop I would be so grateful.
The sample DNx file I provided them is at https://drive.google.com/file/d/0B-mik7 ... sp=sharing
The Windows codecs themselves are at http://avid.force.com/pkb/servlet/fileF ... 2__Body__s

I am a willing beta tester. I just don't have the coding/compiling skills to implement it myself.

https://bugzilla.libav.org/show_bug.cgi?id=99
https://bugzilla.libav.org/attachment.cgi?id=454
https://bugzilla.libav.org/show_bug.cgi?id=99
--- Comment #8 from lu_zero@gentoo.org <lu_zero@gentoo.org> 2014-01-11 21:14:36 CET ---
Created attachment 454
--> https://bugzilla.libav.org/attachment.cgi?id=454
Try patch
Could you please try this tentative patch and report if it works properly?
--
Configure bugmail: https://bugzilla.libav.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You reported the bug.

Code: Select all

From efe5028c7de16bc01e93232cdc5aa0d24e24a446 Mon Sep 17 00:00:00 2001
From: Kostya Shishkov <kostya.shishkov@gmail.com>
Date: Sat, 11 Jan 2014 21:07:03 +0100
Subject: [PATCH] dnxhd: try to add 444 decoding support

---
 libavcodec/dnxhddata.c |   18 ++++++++++
 libavcodec/dnxhddec.c  |   90 ++++++++++++++++++++++++++++++++++++------------
 2 files changed, 86 insertions(+), 22 deletions(-)

diff --git a/libavcodec/dnxhddata.c b/libavcodec/dnxhddata.c
index 96895da..a8d713b 100644
--- a/libavcodec/dnxhddata.c
+++ b/libavcodec/dnxhddata.c
@@ -220,6 +220,17 @@ static const uint8_t dnxhd_1252_chroma_weight[] = {
     114, 128, 125, 129, 134, 125, 116, 116,
 };
 
+static const uint8_t dnxhd_1256_chroma_weight[] = {
+     0, 32, 32, 32, 32, 32, 32, 33,
+    32, 32, 32, 32, 32, 32, 32, 34,
+    32, 32, 32, 32, 32, 32, 33, 37,
+    32, 32, 32, 32, 32, 32, 36, 39,
+    32, 32, 32, 32, 32, 34, 39, 44,
+    32, 37, 32, 32, 35, 40, 43, 49,
+    32, 33, 36, 36, 40, 43, 50, 60,
+    34, 37, 39, 44, 51, 56, 61, 70,
+};
+
 static const uint8_t dnxhd_1237_dc_codes[12] = {
     0, 12, 13, 1, 2, 3, 4, 5, 14, 30, 62, 63,
 };
@@ -1133,6 +1144,13 @@ const CIDEntry ff_dnxhd_cid_table[] = {
       dnxhd_1237_ac_run_flag, dnxhd_1237_ac_index_flag,
       dnxhd_1237_run_codes, dnxhd_1237_run_bits, dnxhd_1237_run,
       { 36, 45, 75, 90 } },
+    { 1256, 1920, 1080, 0, 1835008, 1835008, 6, 10,
+      dnxhd_1235_luma_weight, dnxhd_1256_chroma_weight,
+      dnxhd_1235_1241_dc_codes, dnxhd_1235_1241_dc_bits,
+      dnxhd_1235_1241_ac_codes, dnxhd_1235_1241_ac_bits, dnxhd_1235_1241_ac_level,
+      dnxhd_1235_1241_ac_run_flag, dnxhd_1235_1241_ac_index_flag,
+      dnxhd_1235_1238_1241_run_codes, dnxhd_1235_1238_1241_run_bits, dnxhd_1235_1241_run,
+      { 350, 390, 440, 730, 880 } },
 };
 
 int ff_dnxhd_get_cid_table(int cid)
diff --git a/libavcodec/dnxhddec.c b/libavcodec/dnxhddec.c
index 5c29b3e..213411b 100644
--- a/libavcodec/dnxhddec.c
+++ b/libavcodec/dnxhddec.c
@@ -40,10 +40,11 @@ typedef struct DNXHDContext {
     VLC ac_vlc, dc_vlc, run_vlc;
     int last_dc[3];
     DSPContext dsp;
-    DECLARE_ALIGNED(16, int16_t, blocks)[8][64];
+    DECLARE_ALIGNED(16, int16_t, blocks)[12][64];
     ScanTable scantable;
     const CIDEntry *cid_table;
     int bit_depth; // 8, 10 or 0 if not initialized at all.
+    int is_444;
     void (*decode_dct_block)(struct DNXHDContext *ctx, int16_t *block,
                              int n, int qscale);
 } DNXHDContext;
@@ -96,13 +97,14 @@ static int dnxhd_init_vlc(DNXHDContext *ctx, int cid)
 static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame,
                                const uint8_t *buf, int buf_size, int first_field)
 {
-    static const uint8_t header_prefix[] = { 0x00, 0x00, 0x02, 0x80, 0x01 };
+    static const uint8_t header_prefix[]    = { 0x00, 0x00, 0x02, 0x80, 0x01 };
+    static const uint8_t header_prefix444[] = { 0x00, 0x00, 0x02, 0x80, 0x02 };
     int i, cid;
 
     if (buf_size < 0x280)
         return -1;
 
-    if (memcmp(buf, header_prefix, 5)) {
+    if (memcmp(buf, header_prefix, 5) && memcmp(buf, header_prefix444, 5)) {
         av_log(ctx->avctx, AV_LOG_ERROR, "error in header\n");
         return -1;
     }
@@ -118,7 +120,17 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame,
 
     av_dlog(ctx->avctx, "width %d, height %d\n", ctx->width, ctx->height);
 
-    if (buf[0x21] & 0x40) {
+    ctx->is_444 = 0;
+    if (buf[0x4] == 0x2) {
+        ctx->avctx->pix_fmt = AV_PIX_FMT_YUV444P10;
+        ctx->avctx->bits_per_raw_sample = 10;
+        if (ctx->bit_depth != 10) {
+            ff_dsputil_init(&ctx->dsp, ctx->avctx);
+            ctx->bit_depth = 10;
+            ctx->decode_dct_block = dnxhd_decode_dct_block_10;
+        }
+        ctx->is_444 = 1;
+    } else if (buf[0x21] & 0x40) {
         ctx->avctx->pix_fmt = AV_PIX_FMT_YUV422P10;
         ctx->avctx->bits_per_raw_sample = 10;
         if (ctx->bit_depth != 10) {
@@ -185,12 +197,21 @@ static av_always_inline void dnxhd_decode_dct_block(DNXHDContext *ctx,
     const uint8_t *weight_matrix;
     OPEN_READER(bs, &ctx->gb);
 
-    if (n&2) {
-        component = 1 + (n&1);
-        weight_matrix = ctx->cid_table->chroma_weight;
+    if (!ctx->is_444) {
+        if (n&2) {
+            component = 1 + (n&1);
+            weight_matrix = ctx->cid_table->chroma_weight;
+        } else {
+            component = 0;
+            weight_matrix = ctx->cid_table->luma_weight;
+        }
     } else {
-        component = 0;
-        weight_matrix = ctx->cid_table->luma_weight;
+        component = (n >> 1) % 3;
+        if (component) {
+            weight_matrix = ctx->cid_table->chroma_weight;
+        } else {
+            weight_matrix = ctx->cid_table->luma_weight;
+        }
     }
 
     UPDATE_CACHE(bs, &ctx->gb);
@@ -272,6 +293,12 @@ static int dnxhd_decode_macroblock(DNXHDContext *ctx, AVFrame *frame, int x, int
         ctx->dsp.clear_block(ctx->blocks[i]);
         ctx->decode_dct_block(ctx, ctx->blocks[i], i, qscale);
     }
+    if (ctx->is_444) {
+        for (; i < 12; i++) {
+            ctx->dsp.clear_block(ctx->blocks[i]);
+            ctx->decode_dct_block(ctx, ctx->blocks[i], i, qscale);
+        }
+    }
 
     if (frame->interlaced_frame) {
         dct_linesize_luma   <<= 1;
@@ -279,8 +306,8 @@ static int dnxhd_decode_macroblock(DNXHDContext *ctx, AVFrame *frame, int x, int
     }
 
     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));
-    dest_v = frame->data[2] + ((y * dct_linesize_chroma) << 4) + (x << (3 + 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));
 
     if (ctx->cur_field) {
         dest_y += frame->linesize[0];
@@ -290,17 +317,36 @@ static int dnxhd_decode_macroblock(DNXHDContext *ctx, AVFrame *frame, int x, int
 
     dct_y_offset = dct_linesize_luma << 3;
     dct_x_offset = 8 << shift1;
-    ctx->dsp.idct_put(dest_y,                               dct_linesize_luma, ctx->blocks[0]);
-    ctx->dsp.idct_put(dest_y + dct_x_offset,                dct_linesize_luma, ctx->blocks[1]);
-    ctx->dsp.idct_put(dest_y + dct_y_offset,                dct_linesize_luma, ctx->blocks[4]);
-    ctx->dsp.idct_put(dest_y + dct_y_offset + dct_x_offset, dct_linesize_luma, ctx->blocks[5]);
-
-    if (!(ctx->avctx->flags & CODEC_FLAG_GRAY)) {
-        dct_y_offset = dct_linesize_chroma << 3;
-        ctx->dsp.idct_put(dest_u,                dct_linesize_chroma, ctx->blocks[2]);
-        ctx->dsp.idct_put(dest_v,                dct_linesize_chroma, ctx->blocks[3]);
-        ctx->dsp.idct_put(dest_u + dct_y_offset, dct_linesize_chroma, ctx->blocks[6]);
-        ctx->dsp.idct_put(dest_v + dct_y_offset, dct_linesize_chroma, ctx->blocks[7]);
+    if (!ctx->is_444) {
+        ctx->dsp.idct_put(dest_y,                               dct_linesize_luma, ctx->blocks[0]);
+        ctx->dsp.idct_put(dest_y + dct_x_offset,                dct_linesize_luma, ctx->blocks[1]);
+        ctx->dsp.idct_put(dest_y + dct_y_offset,                dct_linesize_luma, ctx->blocks[4]);
+        ctx->dsp.idct_put(dest_y + dct_y_offset + dct_x_offset, dct_linesize_luma, ctx->blocks[5]);
+
+        if (!(ctx->avctx->flags & CODEC_FLAG_GRAY)) {
+            dct_y_offset = dct_linesize_chroma << 3;
+            ctx->dsp.idct_put(dest_u,                dct_linesize_chroma, ctx->blocks[2]);
+            ctx->dsp.idct_put(dest_v,                dct_linesize_chroma, ctx->blocks[3]);
+            ctx->dsp.idct_put(dest_u + dct_y_offset, dct_linesize_chroma, ctx->blocks[6]);
+            ctx->dsp.idct_put(dest_v + dct_y_offset, dct_linesize_chroma, ctx->blocks[7]);
+        }
+    } else {
+        ctx->dsp.idct_put(dest_y,                               dct_linesize_luma, ctx->blocks[0]);
+        ctx->dsp.idct_put(dest_y + dct_x_offset,                dct_linesize_luma, ctx->blocks[1]);
+        ctx->dsp.idct_put(dest_y + dct_y_offset,                dct_linesize_luma, ctx->blocks[6]);
+        ctx->dsp.idct_put(dest_y + dct_y_offset + dct_x_offset, dct_linesize_luma, ctx->blocks[7]);
+
+        if (!(ctx->avctx->flags & CODEC_FLAG_GRAY)) {
+            dct_y_offset = dct_linesize_chroma << 3;
+            ctx->dsp.idct_put(dest_u,                               dct_linesize_chroma, ctx->blocks[2]);
+            ctx->dsp.idct_put(dest_u + dct_x_offset,                dct_linesize_chroma, ctx->blocks[3]);
+            ctx->dsp.idct_put(dest_u + dct_y_offset,                dct_linesize_chroma, ctx->blocks[8]);
+            ctx->dsp.idct_put(dest_u + dct_y_offset + dct_x_offset, dct_linesize_chroma, ctx->blocks[9]);
+            ctx->dsp.idct_put(dest_v,                               dct_linesize_chroma, ctx->blocks[4]);
+            ctx->dsp.idct_put(dest_v + dct_x_offset,                dct_linesize_chroma, ctx->blocks[5]);
+            ctx->dsp.idct_put(dest_v + dct_y_offset,                dct_linesize_chroma, ctx->blocks[10]);
+            ctx->dsp.idct_put(dest_v + dct_y_offset + dct_x_offset, dct_linesize_chroma, ctx->blocks[11]);
+        }
     }
 
     return 0;
-- 
1.7.9.5

Last edited by Deleted User 13735 on Thu Feb 20, 2014 3:04 pm, edited 1 time in total.
Deleted User 11865

Re: DNxHD 444 patch tentative

Post by Deleted User 11865 »

You're running HB on Windows, right? Do you have any experience as a Linux user?
Deleted User 13735

Re: DNxHD 444 patch tentative

Post by Deleted User 13735 »

Unfortunately, I don't.
Deleted User 13735

{RESOLVED} DNxHD 444 patch tentative

Post by Deleted User 13735 »

After working more with the developer, I got this response from them this morning. Persistence and politeness does pay off, and my friends will be excited about trying libav10 when it is released.
;?)
----------------------------------------------------------------------------
Status|REOPENED |RESOLVED
Resolution| |FIXED

--- Comment #9 from lu_zero@gentoo.org <lu_zero@gentoo.org> 2014-02-19 11:48:20 CET ---
Support for 444 is in tree and will be part of libav10.
Last edited by Deleted User 13735 on Thu Feb 20, 2014 3:07 pm, edited 1 time in total.
User avatar
JohnAStebbins
HandBrake Team
Posts: 5723
Joined: Sat Feb 09, 2008 7:21 pm

Re: DNxHD 444 patch tentative

Post by JohnAStebbins »

Yup, and it should be in the nightly builds as of https://trac.handbrake.fr/changeset/6039
Deleted User 13735

Re: [RESOLVED] DNxHD 444 patch tentative

Post by Deleted User 13735 »

Well, now I know what I'm going to be doing this weekend . . .
;?)
Deleted User 13735

Re: [RESOLVED] DNxHD 444 patch tentative

Post by Deleted User 13735 »

It works! It just works. If you're editing 10 bit source or doing 32 bit float grading, CG, or animation and encoding your work for the unwashed masses, you have to try this as an intermediate to Handbrake.
Post Reply