[FFmpeg-cvslog] lavc/qsvenc_hevc: accept HDR metadata if have

Haihao Xiang git at videolan.org
Tue Oct 25 04:20:33 EEST 2022


ffmpeg | branch: master | Haihao Xiang <haihao.xiang at intel.com> | Tue Oct 18 12:59:25 2022 +0800| [1af499cde0958264d4cc03f0ff6371c5ae8edbf4] | committer: Haihao Xiang

lavc/qsvenc_hevc: accept HDR metadata if have

The SDK may accept HDR metadata via mfxEncodeCtrl::ExtParam

Signed-off-by: Haihao Xiang <haihao.xiang at intel.com>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=1af499cde0958264d4cc03f0ff6371c5ae8edbf4
---

 libavcodec/qsvenc_hevc.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 80 insertions(+)

diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c
index 2a3f34b915..28d2cfcae1 100644
--- a/libavcodec/qsvenc_hevc.c
+++ b/libavcodec/qsvenc_hevc.c
@@ -26,6 +26,7 @@
 
 #include "libavutil/common.h"
 #include "libavutil/opt.h"
+#include "libavutil/mastering_display_metadata.h"
 
 #include "avcodec.h"
 #include "bytestream.h"
@@ -160,6 +161,83 @@ static int generate_fake_vps(QSVEncContext *q, AVCodecContext *avctx)
     return 0;
 }
 
+static int qsv_hevc_set_encode_ctrl(AVCodecContext *avctx,
+                                    const AVFrame *frame, mfxEncodeCtrl *enc_ctrl)
+{
+    QSVHEVCEncContext *q = avctx->priv_data;
+    AVFrameSideData *sd;
+
+    if (!frame || !QSV_RUNTIME_VERSION_ATLEAST(q->qsv.ver, 1, 25))
+        return 0;
+
+    sd = av_frame_get_side_data(frame, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA);
+    if (sd) {
+        AVMasteringDisplayMetadata *mdm = (AVMasteringDisplayMetadata *)sd->data;
+
+        // SEI is needed when both the primaries and luminance are set
+        if (mdm->has_primaries && mdm->has_luminance) {
+            const int mapping[3] = {1, 2, 0};
+            const int chroma_den = 50000;
+            const int luma_den   = 10000;
+            int i;
+            mfxExtMasteringDisplayColourVolume *mdcv = av_mallocz(sizeof(mfxExtMasteringDisplayColourVolume));
+
+            if (!mdcv)
+                return AVERROR(ENOMEM);
+
+            mdcv->Header.BufferId = MFX_EXTBUFF_MASTERING_DISPLAY_COLOUR_VOLUME;
+            mdcv->Header.BufferSz = sizeof(*mdcv);
+
+            for (i = 0; i < 3; i++) {
+                const int j = mapping[i];
+
+                mdcv->DisplayPrimariesX[i] =
+                    FFMIN(lrint(chroma_den *
+                                av_q2d(mdm->display_primaries[j][0])),
+                          chroma_den);
+                mdcv->DisplayPrimariesY[i] =
+                    FFMIN(lrint(chroma_den *
+                                av_q2d(mdm->display_primaries[j][1])),
+                          chroma_den);
+            }
+
+            mdcv->WhitePointX =
+                FFMIN(lrint(chroma_den * av_q2d(mdm->white_point[0])),
+                      chroma_den);
+            mdcv->WhitePointY =
+                FFMIN(lrint(chroma_den * av_q2d(mdm->white_point[1])),
+                      chroma_den);
+
+            mdcv->MaxDisplayMasteringLuminance =
+                lrint(luma_den * av_q2d(mdm->max_luminance));
+            mdcv->MinDisplayMasteringLuminance =
+                FFMIN(lrint(luma_den * av_q2d(mdm->min_luminance)),
+                      mdcv->MaxDisplayMasteringLuminance);
+
+            enc_ctrl->ExtParam[enc_ctrl->NumExtParam++] = (mfxExtBuffer *)mdcv;
+        }
+    }
+
+    sd = av_frame_get_side_data(frame, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL);
+    if (sd) {
+        AVContentLightMetadata *clm = (AVContentLightMetadata *)sd->data;
+        mfxExtContentLightLevelInfo * clli = av_mallocz(sizeof(mfxExtContentLightLevelInfo));
+
+        if (!clli)
+            return AVERROR(ENOMEM);
+
+        clli->Header.BufferId = MFX_EXTBUFF_CONTENT_LIGHT_LEVEL_INFO;
+        clli->Header.BufferSz = sizeof(*clli);
+
+        clli->MaxContentLightLevel          = FFMIN(clm->MaxCLL,  65535);
+        clli->MaxPicAverageLightLevel       = FFMIN(clm->MaxFALL, 65535);
+
+        enc_ctrl->ExtParam[enc_ctrl->NumExtParam++] = (mfxExtBuffer *)clli;
+    }
+
+    return 0;
+}
+
 static av_cold int qsv_enc_init(AVCodecContext *avctx)
 {
     QSVHEVCEncContext *q = avctx->priv_data;
@@ -189,6 +267,8 @@ static av_cold int qsv_enc_init(AVCodecContext *avctx)
     // HEVC and H264 meaning of the value is shifted by 1, make it consistent
     q->qsv.idr_interval++;
 
+    q->qsv.set_encode_ctrl_cb = qsv_hevc_set_encode_ctrl;
+
     ret = ff_qsv_enc_init(avctx, &q->qsv);
     if (ret < 0)
         return ret;



More information about the ffmpeg-cvslog mailing list