On 10/21/2024 4:57 PM, Martin Schitter wrote:
---
  libavcodec/Makefile    |   1 +
  libavcodec/allcodecs.c |   1 +
  libavcodec/dnxucdec.c  | 338 +++++++++++++++++++++++++++++++++++++++++
  3 files changed, 340 insertions(+)
  create mode 100644 libavcodec/dnxucdec.c

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index dd5d0de..e13b127 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -328,6 +328,7 @@ OBJS-$(CONFIG_DFPWM_DECODER)           += dfpwmdec.o
  OBJS-$(CONFIG_DFPWM_ENCODER)           += dfpwmenc.o
  OBJS-$(CONFIG_DNXHD_DECODER)           += dnxhddec.o dnxhddata.o
  OBJS-$(CONFIG_DNXHD_ENCODER)           += dnxhdenc.o dnxhddata.o
+OBJS-$(CONFIG_DNXUC_DECODER)           += dnxucdec.o
  OBJS-$(CONFIG_DOLBY_E_DECODER)         += dolby_e.o dolby_e_parse.o kbdwin.o
  OBJS-$(CONFIG_DPX_DECODER)             += dpx.o
  OBJS-$(CONFIG_DPX_ENCODER)             += dpxenc.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index c7e5f99..ccca2ad 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -93,6 +93,7 @@ extern const FFCodec ff_dfa_decoder;
  extern const FFCodec ff_dirac_decoder;
  extern const FFCodec ff_dnxhd_encoder;
  extern const FFCodec ff_dnxhd_decoder;
+extern const FFCodec ff_dnxuc_decoder;
  extern const FFCodec ff_dpx_encoder;
  extern const FFCodec ff_dpx_decoder;
  extern const FFCodec ff_dsicinvideo_decoder;
diff --git a/libavcodec/dnxucdec.c b/libavcodec/dnxucdec.c
new file mode 100644
index 0000000..9d5847d
--- /dev/null
+++ b/libavcodec/dnxucdec.c
@@ -0,0 +1,338 @@
+/*
+ * Avid DNxUncomressed / SMPTE RDD 50 decoder
+ * Copyright (c) 2024 Martin Schitter
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ This decoder for DNxUncompressed video data is mostly based on
+ reverse engineering of output generated by DaVinci Resolve 19
+ but was later also checked against the SMPTE RDD 50 specification.
+
+ Not all DNxUncompressed pixel format variants are supported,
+ but at least an elementary base set is already usable:
+
+  - YUV 4:2:2 8/10/12/16bit/half/float   (16bit untested)
+    YUV 4:4:4 8/16bit/half/float         (all untested!)
+  - RGB 8/10/12/16bit/half/float         (16bit untested)
+    Alpha/Y 8/16bit                      (all untested!)

That's not good...

[...]

+static int dnxuc_decode_frame(AVCodecContext *avctx, AVFrame *frame,
+                             int *got_frame, AVPacket *avpkt)
+{
+    char fourcc_buf[AV_FOURCC_MAX_STRING_SIZE];
+    int ret;
+
+    av_fourcc_make_string(fourcc_buf, avctx->codec_tag);
+    if ((avctx->width % 2) && ((fourcc_buf[0] == 'y' && fourcc_buf[1] == '2')
+                             ||(fourcc_buf[1] == 'y' && fourcc_buf[2] == 
'2'))){
+        av_log(avctx, AV_LOG_ERROR,
+        "Image width must be a multiple of 2 for YUV 4:2:2 
DNxUncompressed!\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    switch (avctx->codec_tag) {
+        case MKTAG('y','2','0','8'):
+            ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_UYVY422, 16, 
pass_through);


+            break;
+        case MKTAG('y','4','0','8'):
+            ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_YUV444, 24, 
pass_through);

Y408 is mapped to AV_PIX_FMT_AYUV.

+            break;
+        case MKTAG('y','2','1','0'):
+            ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_YUV422P10LE, 20, 
unpack_y210);

Y210 has no pixel format, and it's packed, not planar, so definitely not AV_PIX_FMT_YUV422P10LE.

+            break;
+        case MKTAG('y','4','1','0'):
+            ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_YUV444P10LE, 20, 
unpack_y410);

Y410 is mapped to AV_PIX_FMT_XV30LE.

+            break;
+        case MKTAG('y','2','1','2'):
+            ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_YUV422P12LE, 24, 
unpack_y212);

AV_PIX_FMT_Y212?

+            break;
+        case MKTAG('y','4','1','2'):
+            ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_YUV444P12LE, 24, 
unpack_y412);

This one is probably AV_PIX_FMT_XV36, and definitely not planar.

+            break;
+        case MKTAG('y','2','1','6'):
+            ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_UYVY422_16LE, 32, 
pass_through);

The order of y216 appears to be YUYV, not UYVY. https://learn.microsoft.com/en-us/windows/win32/medfound/10-bit-and-16-bit-yuv-video-formats

+            break;
+        case MKTAG('y','4','1','6'):
+            ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_YUV444_16LE, 48, 
pass_through);

This one is probably AV_PIX_FMT_AYUV64.

+            break;
+        case MKTAG(' ','y','2','h'):
+            ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_UYVY422F16LE, 32, 
pass_through);
+            break;
+        case MKTAG(' ','y','4','h'):
+            ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_YUV444F16LE, 48, 
pass_through);
+            break;
+        case MKTAG(' ','y','2','f'):
+            ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_UYVY422F32LE, 64, 
pass_through);
+            break;
+        case MKTAG(' ','y','4','f'):
+            ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_YUV444F32LE, 96, 
pass_through);
+            break;
+
+        case MKTAG('r','g','0','8'):
+            ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_RGB24, 24, 
pass_through);
+            break;
+        case MKTAG('r','g','1','0'):
+            ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_GBRP10LE, 30, 
unpack_rg10);
+            break;
+        case MKTAG('r','g','1','2'):
+            ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_GBRP12LE, 36, 
unpack_rg12);
+            break;
+        case MKTAG('r','g','1','6'):
+            ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_RGB48LE, 48, 
pass_through);
+            break;
+        case MKTAG(' ','r','g','h'):
+            ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_RGBF16LE, 48, 
pass_through);
+            break;
+        case MKTAG(' ','r','g','f'):
+            ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_RGBF32LE, 96, 
pass_through);
+            break;
+
+        case MKTAG(' ','a','0','8'):
+        case MKTAG(' ','y','0','8'):
+            ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_GRAY8, 8, 
pass_through);
+            break;
+        case MKTAG(' ','a','1','6'):
+        case MKTAG(' ','y','1','6'):
+            ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_GRAY16LE, 16, 
pass_through);
+            break;
+
+        // case MKTAG('r','l','0','8'): TODO: RLE encoded 8bit alpha
+        // case MKTAG('r','l','1','6'): TODO: RLE encoded 16bit alpha
+
+        default:
+            av_log(avctx, AV_LOG_ERROR,
+            "Unsupported DNxUncompressed pixel format variant: '%s'\n",
+            fourcc_buf);
+            return AVERROR_PATCHWELCOME;
+    }
+
+    if (ret < 0) {
+        av_buffer_unref(&frame->buf[0]);
+        return ret;
+    }
+
+    *got_frame = 1;
+
+    return avpkt->size;
+}
+
+const FFCodec ff_dnxuc_decoder = {
+    .p.name         = "dnxuc",
+    CODEC_LONG_NAME("DNxUncompressed (SMPTE RDD 50)"),
+    .p.type         = AVMEDIA_TYPE_VIDEO,
+    .p.id             = AV_CODEC_ID_DNXUC,
+    FF_CODEC_DECODE_CB(dnxuc_decode_frame),
+    .p.capabilities = AV_CODEC_CAP_FRAME_THREADS,
+};

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to