diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c
index 7c352e982b..ab1a09f674 100644
--- a/libavcodec/vaapi_encode_h264.c
+++ b/libavcodec/vaapi_encode_h264.c
@@ -24,11 +24,13 @@
 #include "libavutil/avassert.h"
 #include "libavutil/common.h"
 #include "libavutil/internal.h"
+#include "libavutil/mastering_display_metadata.h"
 #include "libavutil/opt.h"
 
 #include "avcodec.h"
 #include "cbs.h"
 #include "cbs_h264.h"
+#include "cbs_metadata.h"
 #include "h264.h"
 #include "h264_levels.h"
 #include "h264_sei.h"
@@ -95,6 +97,11 @@ typedef struct VAAPIEncodeH264Context {
     int aud_needed;
     int sei_needed;
     int sei_cbr_workaround_needed;
+
+    int                   have_mastering_display;
+    AVMasteringDisplayMetadata mastering_display;
+    int                   have_content_light_level;
+    AVContentLightMetadata     content_light_level;
 } VAAPIEncodeH264Context;
 
 
@@ -241,6 +248,20 @@ static int vaapi_encode_h264_write_extra_header(AVCodecContext *avctx,
             if (err < 0)
                 goto fail;
         }
+        if (priv->sei_needed & SEI_MASTERING_DISPLAY) {
+            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_insert_metadata(priv->cbc, au,
+                                         CBS_METADATA_CONTENT_LIGHT_LEVEL,
+                                         &priv->content_light_level);
+            if (err < 0)
+                goto fail;
+        }
 
         priv->sei_needed = 0;
 
@@ -674,6 +695,42 @@ static int vaapi_encode_h264_init_picture_params(AVCodecContext *avctx,
         priv->sei_needed |= SEI_RECOVERY_POINT;
     }
 
+    if (priv->sei & SEI_MASTERING_DISPLAY) {
+        AVFrameSideData *sd =
+            av_frame_get_side_data(pic->input_image,
+                                   AV_FRAME_DATA_MASTERING_DISPLAY_METADATA);
+
+        if (sd) {
+            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) {
+        AVFrameSideData *sd =
+            av_frame_get_side_data(pic->input_image,
+                                   AV_FRAME_DATA_CONTENT_LIGHT_LEVEL);
+
+        if (sd) {
+            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;
+        }
+    }
+
     vpic->CurrPic = (VAPictureH264) {
         .picture_id          = pic->recon_surface,
         .frame_idx           = hpic->frame_num,
@@ -1245,7 +1302,8 @@ static const AVOption vaapi_encode_h264_options[] = {
 
     { "sei", "Set SEI to include",
       OFFSET(sei), AV_OPT_TYPE_FLAGS,
-      { .i64 = SEI_IDENTIFIER | SEI_TIMING | SEI_RECOVERY_POINT },
+      { .i64 = SEI_IDENTIFIER | SEI_TIMING | SEI_RECOVERY_POINT |
+               SEI_MASTERING_DISPLAY | SEI_CONTENT_LIGHT_LEVEL },
       0, INT_MAX, FLAGS, "sei" },
     { "identifier", "Include encoder version identifier",
       0, AV_OPT_TYPE_CONST, { .i64 = SEI_IDENTIFIER },
@@ -1256,6 +1314,12 @@ static const AVOption vaapi_encode_h264_options[] = {
     { "recovery_point", "Include recovery points where appropriate",
       0, AV_OPT_TYPE_CONST, { .i64 = SEI_RECOVERY_POINT },
       INT_MIN, INT_MAX, FLAGS, "sei" },
+    { "hdr",
+      "Include HDR metadata (mastering display colour volume "
+      "and content light level information)",
+      0, AV_OPT_TYPE_CONST,
+      { .i64 = SEI_MASTERING_DISPLAY | SEI_CONTENT_LIGHT_LEVEL },
+      INT_MIN, INT_MAX, FLAGS, "sei" },
 
     { "profile", "Set profile (profile_idc and constraint_set*_flag)",
       OFFSET(profile), AV_OPT_TYPE_INT,
