[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