[FFmpeg-devel,3/3] avcodec/nvenc: add more sei support for SDR HLG

Submitted by lance.lmwang@gmail.com on May 22, 2019, 6:59 a.m.

Details

Message ID 20190522065954.62328-3-lance.lmwang@gmail.com
State New
Headers show

Commit Message

lance.lmwang@gmail.com May 22, 2019, 6:59 a.m.
From: Limin Wang <lance.lmwang@gmail.com>

The testing command for the HLG output with nvenc:

./ffmpeg_g -y -i 4K.mp4 -c:v hevc_nvenc -g 7 -color_primaries bt2020 -colorspace bt2020_ncl -color_trc smpte2084 -sei hlg test.ts
---
 libavcodec/nvenc.c      | 24 ++++++++++++++++++++++++
 libavcodec/nvenc.h      |  1 +
 libavcodec/nvenc_hevc.c |  3 +++
 3 files changed, 28 insertions(+)

Patch hide | download patch | download mbox

diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c
index 3fd0eca4a5..239788b2d7 100644
--- a/libavcodec/nvenc.c
+++ b/libavcodec/nvenc.c
@@ -1019,6 +1019,10 @@  static av_cold int nvenc_setup_hevc_config(AVCodecContext *avctx)
     vui->colourMatrix = avctx->colorspace;
     vui->colourPrimaries = avctx->color_primaries;
     vui->transferCharacteristics = avctx->color_trc;
+    if (ctx->sei & SEI_ALTER_TRANSFER_CHAR) {
+        if (IS_10BIT(ctx->data_pix_fmt))
+            vui->transferCharacteristics = AVCOL_TRC_BT2020_10;
+    }
     vui->videoFullRangeFlag = (avctx->color_range == AVCOL_RANGE_JPEG
         || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ420P || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ422P || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ444P);
 
@@ -2239,6 +2243,26 @@  int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
             }
         }
 
+        if (ctx->sei & SEI_ALTER_TRANSFER_CHAR) {
+            if (avctx->codec->id == AV_CODEC_ID_HEVC) {
+                size_t transfer_sei_size = sizeof(H265RawSEIAlternativeTransferCharacteristics);
+                H265RawSEIAlternativeTransferCharacteristics transfer_data;
+                transfer_data.preferred_transfer_characteristics = AVCOL_TRC_ARIB_STD_B67;
+
+                sei_data[sei_count].payloadSize = transfer_sei_size;
+                sei_data[sei_count].payloadType = HEVC_SEI_TYPE_ALTERNATIVE_TRANSFER_CHARACTERISTICS;
+                sei_data[sei_count].payload = av_malloc(transfer_sei_size);
+                if (sei_data[sei_count].payload) {
+                    PutBitContext pb;
+                    init_put_bits(&pb, sei_data[sei_count].payload, sei_data[sei_count].payloadSize);
+                    put_bits(&pb, 8, transfer_data.preferred_transfer_characteristics);
+                    flush_put_bits(&pb);
+
+                    sei_count ++;
+                }
+            }
+        }
+
         nvenc_codec_specific_pic_params(avctx, &pic_params, sei_data, sei_count);
     } else {
         pic_params.encodePicFlags = NV_ENC_PIC_FLAG_EOS;
diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h
index 583c48d090..8be0d341ea 100644
--- a/libavcodec/nvenc.h
+++ b/libavcodec/nvenc.h
@@ -55,6 +55,7 @@  typedef void ID3D11Device;
 #endif
 
 enum {
+    SEI_ALTER_TRANSFER_CHAR     = 0x04,
     SEI_MASTERING_DISPLAY       = 0x08,
     SEI_CONTENT_LIGHT_LEVEL     = 0x10,
 };
diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c
index 74ebd03d8e..23ba593439 100644
--- a/libavcodec/nvenc_hevc.c
+++ b/libavcodec/nvenc_hevc.c
@@ -134,6 +134,9 @@  static const AVOption options[] = {
     { "hdr10","Include HDR metadata for mastering display colour volume and content light level information",
                                                             0, AV_OPT_TYPE_CONST,   { .i64 = SEI_MASTERING_DISPLAY | SEI_CONTENT_LIGHT_LEVEL },
                                                             0, 0, VE, "sei" },
+    { "hlg","Include HLG metadata for alternative transfer characteristics",
+                                                            0, AV_OPT_TYPE_CONST,   { .i64 = SEI_ALTER_TRANSFER_CHAR },
+                                                            0, 0, VE, "sei" },
     { "master_display",     "SMPTE ST 2086 master display color volume info SEI (HDR), the string format is: \"G(x,y)B(x,y)R(x,y)WP(x,y)L(max,min)\"",
                                                             OFFSET(master_display), AV_OPT_TYPE_STRING,   { .str = NULL }, 0, 0, VE },
     { "max_cll",             "content light level info, the string format is: \"cll, fall\"",