[FFmpeg-devel] [PATCH] avcodec/cuviddec: Add handling HDR10+ sidedata on cuviddec.

yoonjoo yoonjoo.kim at samsung.com
Thu Sep 19 07:43:32 EEST 2024


Implemented decoding of NAL units and handling HDR10+ sidedata
by referring to hevcdec.

Signed-off-by: yoonjoo <yoonjoo.kim at samsung.com>
---
 libavcodec/cuviddec.c | 69 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/libavcodec/cuviddec.c b/libavcodec/cuviddec.c
index 3fae9c1..1b80b81 100644
--- a/libavcodec/cuviddec.c
+++ b/libavcodec/cuviddec.c
@@ -33,6 +33,7 @@
 #include "libavutil/mem.h"
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
+#include "libavutil/hdr_dynamic_metadata.h"
 
 #include "avcodec.h"
 #include "bsf.h"
@@ -41,6 +42,11 @@
 #include "hwconfig.h"
 #include "nvdec.h"
 #include "internal.h"
+#include "h2645_parse.h"
+#include "bytestream.h"
+#include "hevc/hevc.h"
+#include "hevc/sei.h"
+#include "hevc/ps.h"
 
 #if !NVDECAPI_CHECK_VERSION(9, 0)
 #define cudaVideoSurfaceFormat_YUV444 2
@@ -488,6 +494,64 @@ error:
         return 0;
 }
 
+static void decode_nal_units(AVCodecContext* avctx, const uint8_t *buf,
int length, AVFrame* frame)
+{
+    H2645Packet hpkt = { 0 };
+    int is_nalff = 1;
+    int nal_length_size = 4;
+    HEVCSEI sei = { 0 };
+    HEVCParamSets ps = { 0 };
+
+    av_log(avctx, AV_LOG_TRACE, "decode_nal_units\n");
+    ff_h2645_packet_split(&hpkt, buf, length, avctx, is_nalff,
nal_length_size, avctx->codec_id, 1, 0);
+
+    for (int i = 0; i < hpkt.nb_nals; i++) {
+        H2645NAL* nal = &hpkt.nals[i];
+        GetBitContext gb = nal->gb;
+
+        av_log(avctx, AV_LOG_TRACE, "[%d/%d] NAL type = %d\n", i + 1, hpkt.
nb_nals, nal->type);
+
+        switch (nal->type) {
+        case HEVC_NAL_SEI_PREFIX:
+        {
+            int ret = ff_hevc_decode_nal_sei(&gb, avctx, &sei, &ps, nal-
>type);
+            if (ret < 0) {
+                av_log(avctx, AV_LOG_WARNING, "Skipping invalid
undecodable NALU: %d\n", nal->type);
+                return;
+            }
+
+            if (sei.common.dynamic_hdr_plus.info)
+                av_frame_new_side_data_from_buf(frame,
AV_FRAME_DATA_DYNAMIC_HDR_PLUS, sei.common.dynamic_hdr_plus.info);
+            break;
+        }
+        case HEVC_NAL_VPS:
+        case HEVC_NAL_SPS:
+        case HEVC_NAL_PPS:
+        case HEVC_NAL_TRAIL_R:
+        case HEVC_NAL_TRAIL_N:
+        case HEVC_NAL_TSA_N:
+        case HEVC_NAL_TSA_R:
+        case HEVC_NAL_STSA_N:
+        case HEVC_NAL_STSA_R:
+        case HEVC_NAL_BLA_W_LP:
+        case HEVC_NAL_BLA_W_RADL:
+        case HEVC_NAL_BLA_N_LP:
+        case HEVC_NAL_IDR_W_RADL:
+        case HEVC_NAL_IDR_N_LP:
+        case HEVC_NAL_CRA_NUT:
+        case HEVC_NAL_RADL_N:
+        case HEVC_NAL_RADL_R:
+        case HEVC_NAL_RASL_N:
+        case HEVC_NAL_RASL_R:
+            // these Nal types will be handled in 'cuvid_decode_packet()'
+            break;
+        default:
+            av_log(avctx, AV_LOG_INFO, "Skipping NAL unit %d\n", nal-
>type);
+            break;
+        }
+    }
+}
+
 static int cuvid_output_frame(AVCodecContext *avctx, AVFrame *frame)
 {
     CuvidContext *ctx = avctx->priv_data;
@@ -497,6 +561,8 @@ static int cuvid_output_frame(AVCodecContext *avctx,
AVFrame *frame)
     CuvidParsedFrame parsed_frame;
     CUdeviceptr mapped_frame = 0;
     int ret = 0, eret = 0;
+    uint8_t *pkt_data = avctx->internal->buffer_pkt->data;
+    int pkt_size = avctx->internal->buffer_pkt->size;
 
     av_log(avctx, AV_LOG_TRACE, "cuvid_output_frame\n");
 
@@ -512,6 +578,9 @@ static int cuvid_output_frame(AVCodecContext *avctx,
AVFrame *frame)
         if (ret < 0 && ret != AVERROR_EOF)
             return ret;
         ret = cuvid_decode_packet(avctx, pkt);
+
+        decode_nal_units(avctx, pkt_data, pkt_size, frame);
+
         av_packet_unref(pkt);
         // cuvid_is_buffer_full() should avoid this.
         if (ret == AVERROR(EAGAIN))
-- 
2.45.1.windows.1




More information about the ffmpeg-devel mailing list