diff mbox series

[FFmpeg-devel,3/4] dnxhd: add partial alpha support for parsing

Message ID 20210130091906.312-4-christophe.gisquet@gmail.com
State New
Headers show
Series Better colorspace support in dnxhddec
Related show

Checks

Context Check Description
andriy/x86_make success Make finished
andriy/x86_make_fate success Make fate finished
andriy/PPC64_make success Make finished
andriy/PPC64_make_fate success Make fate finished

Commit Message

Christophe Gisquet Jan. 30, 2021, 9:19 a.m. UTC
From: Christophe Gisquet <c.gisquet@ateme.com>

This multiplies the framesize by 1.5 when there is alpha, for the CIDs
allowing alpha. In addition, a new header is checked, because the alpha
marking seems to be different.
---
 libavcodec/dnxhd_parser.c |  7 ++++---
 libavcodec/dnxhddata.c    | 17 ++++++++++++-----
 libavcodec/dnxhddata.h    |  6 ++++--
 libavcodec/dnxhdenc.c     |  2 +-
 libavformat/mxfenc.c      |  7 ++++---
 5 files changed, 25 insertions(+), 14 deletions(-)

Comments

Paul B Mahol Jan. 30, 2021, 9:53 a.m. UTC | #1
Are you telling us that you do not have specification for this?

Last time I checked AVID files had uncompressed alpha that did not matched
with specification at all.
Christophe Gisquet Jan. 31, 2021, noon UTC | #2
Le sam. 30 janv. 2021 à 10:54, Paul B Mahol <onemda@gmail.com> a écrit :
> Are you telling us that you do not have specification for this?

Yes, cf. cover letter. In fact, this patch could be dropped (not sure).

> Last time I checked AVID files had uncompressed alpha that did not matched
> with specification at all.

I don't know, though I wouldn't mind peaking a look. This precise
patch does no parsing.
diff mbox series

Patch

diff --git a/libavcodec/dnxhd_parser.c b/libavcodec/dnxhd_parser.c
index 63b4ff89e1..726fb2f5de 100644
--- a/libavcodec/dnxhd_parser.c
+++ b/libavcodec/dnxhd_parser.c
@@ -31,7 +31,7 @@  typedef struct {
     ParseContext pc;
     int cur_byte;
     int remaining;
-    int w, h;
+    int w, h, alpha;
 } DNXHDParserContext;
 
 static int dnxhd_find_frame_end(DNXHDParserContext *dctx,
@@ -58,6 +58,7 @@  static int dnxhd_find_frame_end(DNXHDParserContext *dctx,
     if (pic_found && !dctx->remaining) {
         if (!buf_size) /* EOF considered as end of frame */
             return 0;
+        dctx->alpha = (state >> 8) & 5;
         for (; i < buf_size; i++) {
             dctx->cur_byte++;
             state = (state << 8) | buf[i];
@@ -73,9 +74,9 @@  static int dnxhd_find_frame_end(DNXHDParserContext *dctx,
                 if (cid <= 0)
                     continue;
 
-                remaining = avpriv_dnxhd_get_frame_size(cid);
+                remaining = avpriv_dnxhd_get_frame_size(cid, dctx->alpha);
                 if (remaining <= 0) {
-                    remaining = avpriv_dnxhd_get_hr_frame_size(cid, dctx->w, dctx->h);
+                    remaining = avpriv_dnxhd_get_hr_frame_size(cid, dctx->w, dctx->h, dctx->alpha);
                     if (remaining <= 0)
                         continue;
                 }
diff --git a/libavcodec/dnxhddata.c b/libavcodec/dnxhddata.c
index 3a69a0f501..54663aa432 100644
--- a/libavcodec/dnxhddata.c
+++ b/libavcodec/dnxhddata.c
@@ -1083,15 +1083,19 @@  const CIDEntry *ff_dnxhd_get_cid_table(int cid)
     return NULL;
 }
 
-int avpriv_dnxhd_get_frame_size(int cid)
+int avpriv_dnxhd_get_frame_size(int cid, int alpha)
 {
     const CIDEntry *entry = ff_dnxhd_get_cid_table(cid);
+    int result;
     if (!entry)
         return -1;
-    return entry->frame_size;
+    result = entry->frame_size;
+    if (alpha && (entry->flags & DNXHD_444))
+        result = (result * 3) >> 1;
+    return result;
 }
 
-int avpriv_dnxhd_get_hr_frame_size(int cid, int w, int h)
+int avpriv_dnxhd_get_hr_frame_size(int cid, int w, int h, int alpha)
 {
     const CIDEntry *entry = ff_dnxhd_get_cid_table(cid);
     int result;
@@ -1099,8 +1103,11 @@  int avpriv_dnxhd_get_hr_frame_size(int cid, int w, int h)
     if (!entry)
         return -1;
 
-    result = ((h + 15) / 16) * ((w + 15) / 16) * (int64_t)entry->packet_scale.num / entry->packet_scale.den;
-    result = (result + 2048) / 4096 * 4096;
+    result = AV_CEIL_RSHIFT(h, 4) * AV_CEIL_RSHIFT(w, 4)
+           * (int64_t)entry->packet_scale.num / entry->packet_scale.den;
+    if (alpha && (entry->flags & DNXHD_444))
+        result = (result * 3) >> 1;
+    result = (result + 2048) & -4096;
 
     return FFMAX(result, 8192);
 }
diff --git a/libavcodec/dnxhddata.h b/libavcodec/dnxhddata.h
index 898079cffc..21738af453 100644
--- a/libavcodec/dnxhddata.h
+++ b/libavcodec/dnxhddata.h
@@ -35,6 +35,7 @@ 
 /** Frame headers, extra 0x00 added to end for parser */
 #define DNXHD_HEADER_INITIAL 0x000002800100
 #define DNXHD_HEADER_444     0x000002800200
+#define DNXHD_HEADER_RGBA    0x000002800400
 
 /** Indicate that a CIDEntry value must be read in the bitstream */
 #define DNXHD_VARIABLE 0
@@ -76,6 +77,7 @@  static av_always_inline uint64_t ff_dnxhd_check_header_prefix(uint64_t prefix)
 {
     if (prefix == DNXHD_HEADER_INITIAL ||
         prefix == DNXHD_HEADER_444     ||
+        prefix == DNXHD_HEADER_RGBA    ||
         ff_dnxhd_check_header_prefix_hr(prefix))
         return prefix;
     return 0;
@@ -88,8 +90,8 @@  static av_always_inline uint64_t ff_dnxhd_parse_header_prefix(const uint8_t *buf
     return ff_dnxhd_check_header_prefix(prefix);
 }
 
-int avpriv_dnxhd_get_frame_size(int cid);
-int avpriv_dnxhd_get_hr_frame_size(int cid, int w, int h);
+int avpriv_dnxhd_get_frame_size(int cid, int alpha);
+int avpriv_dnxhd_get_hr_frame_size(int cid, int w, int h, int alpha);
 int avpriv_dnxhd_get_interlaced(int cid);
 
 #endif /* AVCODEC_DNXHDDATA_H */
diff --git a/libavcodec/dnxhdenc.c b/libavcodec/dnxhdenc.c
index 2461c51727..fb059060aa 100644
--- a/libavcodec/dnxhdenc.c
+++ b/libavcodec/dnxhdenc.c
@@ -467,7 +467,7 @@  static av_cold int dnxhd_encode_init(AVCodecContext *avctx)
 
     if (ctx->cid_table->frame_size == DNXHD_VARIABLE) {
         ctx->frame_size = avpriv_dnxhd_get_hr_frame_size(ctx->cid,
-                                                     avctx->width, avctx->height);
+                                                     avctx->width, avctx->height, 0);
         av_assert0(ctx->frame_size >= 0);
         ctx->coding_unit_size = ctx->frame_size;
     } else {
diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c
index 0c464d4cfd..653060ae75 100644
--- a/libavformat/mxfenc.c
+++ b/libavformat/mxfenc.c
@@ -2025,7 +2025,7 @@  static int mxf_parse_dnxhd_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt
 {
     MXFContext *mxf = s->priv_data;
     MXFStreamContext *sc = st->priv_data;
-    int i, cid, frame_size = 0;
+    int i, alpha, cid, frame_size = 0;
 
     if (mxf->header_written)
         return 1;
@@ -2034,6 +2034,7 @@  static int mxf_parse_dnxhd_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt
         return 0;
 
     sc->codec_ul = NULL;
+    alpha = pkt->data[0x7] & 1;
     cid = AV_RB32(pkt->data + 0x28);
     for (i = 0; i < FF_ARRAY_ELEMS(mxf_dnxhd_codec_uls); i++) {
         if (cid == mxf_dnxhd_codec_uls[i].cid) {
@@ -2053,8 +2054,8 @@  static int mxf_parse_dnxhd_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt
     if (!sc->component_depth)
         return 0;
 
-    if ((frame_size = avpriv_dnxhd_get_frame_size(cid)) == DNXHD_VARIABLE) {
-        frame_size = avpriv_dnxhd_get_hr_frame_size(cid, st->codecpar->width, st->codecpar->height);
+    if ((frame_size = avpriv_dnxhd_get_frame_size(cid, alpha)) == DNXHD_VARIABLE) {
+        frame_size = avpriv_dnxhd_get_hr_frame_size(cid, st->codecpar->width, st->codecpar->height, alpha);
     }
     if (frame_size < 0)
         return 0;