[FFmpeg-devel] [PATCH 26/27] vaapi_encode_h265: Ensure that HDR metadata is included with seek points
Mark Thompson
sw at jkqxz.net
Fri Jan 1 23:35:36 EET 2021
Save the most recent HDR side data structures and use them when
generating an IDR or CRA frame.
---
libavcodec/vaapi_encode_h265.c | 93 ++++++++++++----------------------
1 file changed, 32 insertions(+), 61 deletions(-)
diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c
index 09d5a8b5cb..75ebb63e74 100644
--- a/libavcodec/vaapi_encode_h265.c
+++ b/libavcodec/vaapi_encode_h265.c
@@ -30,6 +30,7 @@
#include "avcodec.h"
#include "cbs.h"
#include "cbs_h265.h"
+#include "cbs_metadata.h"
#include "h265_profile_level.h"
#include "hevc.h"
#include "hevc_sei.h"
@@ -70,13 +71,15 @@ typedef struct VAAPIEncodeH265Context {
H265RawPPS raw_pps;
H265RawSlice raw_slice;
- SEIRawMasteringDisplayColourVolume sei_mastering_display;
- SEIRawContentLightLevelInfo sei_content_light_level;
-
CodedBitstreamContext *cbc;
CodedBitstreamFragment current_access_unit;
int aud_needed;
int sei_needed;
+
+ int have_mastering_display;
+ AVMasteringDisplayMetadata mastering_display;
+ int have_content_light_level;
+ AVContentLightMetadata content_light_level;
} VAAPIEncodeH265Context;
@@ -200,17 +203,17 @@ static int vaapi_encode_h265_write_extra_header(AVCodecContext *avctx,
}
if (priv->sei_needed & SEI_MASTERING_DISPLAY) {
- err = ff_cbs_sei_add_message(priv->cbc, au, 1,
- HEVC_SEI_TYPE_MASTERING_DISPLAY_INFO,
- &priv->sei_mastering_display, NULL);
+ err = ff_cbs_insert_metadata(priv->cbc, au,
+ CBS_METADATA_MASTERING_DISPLAY,
+ &priv->mastering_display);
if (err < 0)
goto fail;
}
if (priv->sei_needed & SEI_CONTENT_LIGHT_LEVEL) {
- err = ff_cbs_sei_add_message(priv->cbc, au, 1,
- HEVC_SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO,
- &priv->sei_content_light_level, NULL);
+ err = ff_cbs_insert_metadata(priv->cbc, au,
+ CBS_METADATA_CONTENT_LIGHT_LEVEL,
+ &priv->content_light_level);
if (err < 0)
goto fail;
}
@@ -746,72 +749,40 @@ static int vaapi_encode_h265_init_picture_params(AVCodecContext *avctx,
priv->sei_needed = 0;
- // Only look for the metadata on I/IDR frame on the output. We
- // may force an IDR frame on the output where the medadata gets
- // changed on the input frame.
- if ((priv->sei & SEI_MASTERING_DISPLAY) &&
- (pic->type == PICTURE_TYPE_I || pic->type == PICTURE_TYPE_IDR)) {
+ // We check for new metadata on every frame, but only include the
+ // SEI with IRAP frames.
+ if (priv->sei & SEI_MASTERING_DISPLAY) {
AVFrameSideData *sd =
av_frame_get_side_data(pic->input_image,
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) {
- SEIRawMasteringDisplayColourVolume *mdcv =
- &priv->sei_mastering_display;
- const int mapping[3] = {1, 2, 0};
- const int chroma_den = 50000;
- const int luma_den = 10000;
-
- for (i = 0; i < 3; i++) {
- const int j = mapping[i];
- mdcv->display_primaries_x[i] =
- FFMIN(lrint(chroma_den *
- av_q2d(mdm->display_primaries[j][0])),
- chroma_den);
- mdcv->display_primaries_y[i] =
- FFMIN(lrint(chroma_den *
- av_q2d(mdm->display_primaries[j][1])),
- chroma_den);
- }
-
- mdcv->white_point_x =
- FFMIN(lrint(chroma_den * av_q2d(mdm->white_point[0])),
- chroma_den);
- mdcv->white_point_y =
- FFMIN(lrint(chroma_den * av_q2d(mdm->white_point[1])),
- chroma_den);
-
- mdcv->max_display_mastering_luminance =
- lrint(luma_den * av_q2d(mdm->max_luminance));
- mdcv->min_display_mastering_luminance =
- FFMIN(lrint(luma_den * av_q2d(mdm->min_luminance)),
- mdcv->max_display_mastering_luminance);
-
- priv->sei_needed |= SEI_MASTERING_DISPLAY;
- }
+ av_assert0(sd->size >= sizeof(priv->mastering_display));
+ priv->have_mastering_display = 1;
+ memcpy(&priv->mastering_display, sd->data,
+ sizeof(priv->mastering_display));
+ }
+
+ if (priv->have_mastering_display &&
+ (pic->type == PICTURE_TYPE_IDR || pic->type == PICTURE_TYPE_I)) {
+ priv->sei_needed |= SEI_MASTERING_DISPLAY;
}
}
- if ((priv->sei & SEI_CONTENT_LIGHT_LEVEL) &&
- (pic->type == PICTURE_TYPE_I || pic->type == PICTURE_TYPE_IDR)) {
+ if (priv->sei & SEI_CONTENT_LIGHT_LEVEL) {
AVFrameSideData *sd =
av_frame_get_side_data(pic->input_image,
AV_FRAME_DATA_CONTENT_LIGHT_LEVEL);
if (sd) {
- AVContentLightMetadata *clm =
- (AVContentLightMetadata *)sd->data;
- SEIRawContentLightLevelInfo *clli =
- &priv->sei_content_light_level;
-
- clli->max_content_light_level = FFMIN(clm->MaxCLL, 65535);
- clli->max_pic_average_light_level = FFMIN(clm->MaxFALL, 65535);
+ av_assert0(sd->size >= sizeof(priv->content_light_level));
+ priv->have_mastering_display = 1;
+ memcpy(&priv->content_light_level, sd->data,
+ sizeof(priv->content_light_level));
+ }
+ if (priv->have_content_light_level &&
+ (pic->type == PICTURE_TYPE_IDR || pic->type == PICTURE_TYPE_I)) {
priv->sei_needed |= SEI_CONTENT_LIGHT_LEVEL;
}
}
--
2.29.2
More information about the ffmpeg-devel
mailing list