The sdk av1 encoder can accept HDR metadata via mfxEncodeCtrl::ExtParam.
Showing the changes to libavcodec (1 of 1 file). Show all
Unified · Split
| @@ -25,6 +25,8 @@ · 24 unmodified lines | ||
| 25 | 25 | #include <mfxvideo.h> |
| 26 | 26 | |
| 27 | 27 | #include "libavutil/common.h" |
| 28 | +#include "libavutil/mastering_display_metadata.h" | |
| 29 | +#include "libavutil/mem.h" | |
| 28 | 30 | #include "libavutil/opt.h" |
| 29 | 31 | |
| 30 | 32 | #include "avcodec.h" |
| @@ -39,6 +41,75 @@ typedef struct QSVAV1EncContext { · 8 unmodified lines | ||
| 39 | 41 | QSVEncContext qsv; |
| 40 | 42 | } QSVAV1EncContext; |
| 41 | 43 | |
| 44 | +static int qsv_av1_set_encode_ctrl(AVCodecContext *avctx, | |
| 45 | + const AVFrame *frame, mfxEncodeCtrl *enc_ctrl) | |
| 46 | +{ | |
| 47 | + QSVAV1EncContext *q = avctx->priv_data; | |
| 48 | + AVFrameSideData *sd; | |
| 49 | + | |
| 50 | + if (!frame || !QSV_RUNTIME_VERSION_ATLEAST(q->qsv.ver, 2, 11)) | |
| 51 | + return 0; | |
| 52 | + | |
| 53 | + sd = av_frame_get_side_data(frame, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA); | |
| 54 | + if (sd) { | |
| 55 | + AVMasteringDisplayMetadata *mdm = (AVMasteringDisplayMetadata *)sd->data; | |
| 56 | + if (mdm->has_primaries && mdm->has_luminance) { | |
| 57 | + const int chroma_den = 1 << 16; | |
| 58 | + const int max_luma_den = 1 << 8; | |
| 59 | + const int min_luma_den = 1 << 14; | |
| 60 | + mfxExtMasteringDisplayColourVolume *mdcv = av_mallocz(sizeof(*mdcv)); | |
| 61 | + if (!mdcv) | |
| 62 | + return AVERROR(ENOMEM); | |
| 63 | + | |
| 64 | + mdcv->Header.BufferId = MFX_EXTBUFF_MASTERING_DISPLAY_COLOUR_VOLUME; | |
| 65 | + mdcv->Header.BufferSz = sizeof(*mdcv); | |
| 66 | + | |
| 67 | + for (int i = 0; i < 3; i++) { | |
| 68 | + mdcv->DisplayPrimariesX[i] = | |
| 69 | + av_rescale(mdm->display_primaries[i][0].num, chroma_den, | |
| 70 | + mdm->display_primaries[i][0].den); | |
| 71 | + mdcv->DisplayPrimariesY[i] = | |
| 72 | + av_rescale(mdm->display_primaries[i][1].num, chroma_den, | |
| 73 | + mdm->display_primaries[i][1].den); | |
| 74 | + } | |
| 75 | + | |
| 76 | + mdcv->WhitePointX = | |
| 77 | + av_rescale(mdm->white_point[0].num, chroma_den, | |
| 78 | + mdm->white_point[0].den); | |
| 79 | + mdcv->WhitePointY = | |
| 80 | + av_rescale(mdm->white_point[1].num, chroma_den, | |
| 81 | + mdm->white_point[1].den); | |
| 82 | + | |
| 83 | + mdcv->MaxDisplayMasteringLuminance = | |
| 84 | + av_rescale(mdm->max_luminance.num, max_luma_den, | |
| 85 | + mdm->max_luminance.den); | |
| 86 | + mdcv->MinDisplayMasteringLuminance = | |
| 87 | + av_rescale(mdm->min_luminance.num, min_luma_den, | |
| 88 | + mdm->min_luminance.den); | |
| 89 | + | |
| 90 | + enc_ctrl->ExtParam[enc_ctrl->NumExtParam++] = (mfxExtBuffer *)mdcv; | |
| 91 | + } | |
| 92 | + } | |
| 93 | + | |
| 94 | + sd = av_frame_get_side_data(frame, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL); | |
| 95 | + if (sd) { | |
| 96 | + AVContentLightMetadata *clm = (AVContentLightMetadata *)sd->data; | |
| 97 | + mfxExtContentLightLevelInfo *clli = av_mallocz(sizeof(*clli)); | |
| 98 | + if (!clli) | |
| 99 | + return AVERROR(ENOMEM); | |
| 100 | + | |
| 101 | + clli->Header.BufferId = MFX_EXTBUFF_CONTENT_LIGHT_LEVEL_INFO; | |
| 102 | + clli->Header.BufferSz = sizeof(*clli); | |
| 103 | + | |
| 104 | + clli->MaxContentLightLevel = clm->MaxCLL; | |
| 105 | + clli->MaxPicAverageLightLevel = clm->MaxFALL; | |
| 106 | + | |
| 107 | + enc_ctrl->ExtParam[enc_ctrl->NumExtParam++] = (mfxExtBuffer *)clli; | |
| 108 | + } | |
| 109 | + | |
| 110 | + return 0; | |
| 111 | +} | |
| 112 | + | |
| 42 | 113 | static av_cold int qsv_enc_init(AVCodecContext *avctx) |
| 43 | 114 | { |
| 44 | 115 | QSVAV1EncContext *q = avctx->priv_data; |
| @@ -61,6 +132,8 @@ static av_cold int qsv_enc_init(AVCodecContext *avctx) · 16 unmodified lines | ||
| 61 | 132 | return ret; |
| 62 | 133 | } |
| 63 | 134 | |
| 135 | + q->qsv.set_encode_ctrl_cb = qsv_av1_set_encode_ctrl; | |
| 136 | + | |
| 64 | 137 | return ff_qsv_enc_init(avctx, &q->qsv); |
| 65 | 138 | } |
| 66 | 139 | |