This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

The following commit(s) were added to refs/heads/master by this push:
     new bccaf86a89 avcodec/amfdec: propagate color and HDR metadata from AMF 
surfaces
bccaf86a89 is described below

commit bccaf86a89699ffb54b01503c935eb489a39a8b0
Author:     Azat Nurgaliev <[email protected]>
AuthorDate: Mon Jun 8 10:11:37 2026 +0200
Commit:     ArazIusubov <[email protected]>
CommitDate: Fri Jun 19 09:48:56 2026 +0000

    avcodec/amfdec: propagate color and HDR metadata from AMF surfaces
    
    The AMF hardware decoder exposes color information and HDR side data on
    output surfaces, but the decoder previously copied only static avctx
    values onto output frames. Read primaries, transfer, range, and profile
    from each surface, keep avctx updated, and fall back to cached values
    when a field is not signalled on a given frame.
    
    On resolution change, re-create the hw frames context instead of
    trying to re-init an already initialized pool.
    
    Attach HDR10 mastering/display metadata when PQ transfer is detected.
    Release the AMF HDR metadata buffer after attaching side data.
---
 libavcodec/amfdec.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 170 insertions(+), 21 deletions(-)

diff --git a/libavcodec/amfdec.c b/libavcodec/amfdec.c
index 38fae3f4e7..00a17360f5 100644
--- a/libavcodec/amfdec.c
+++ b/libavcodec/amfdec.c
@@ -18,13 +18,13 @@
 
 #include "libavutil/hwcontext_amf.h"
 #include "libavutil/hwcontext_amf_internal.h"
+#include "libavutil/pixdesc.h"
 #include "amfdec.h"
 #include "codec_internal.h"
 #include "hwconfig.h"
 #include "libavutil/time.h"
 #include "decode.h"
 #include "decode_bsf.h"
-#include "libavutil/mastering_display_metadata.h"
 
 #if CONFIG_D3D11VA
 #include "libavutil/hwcontext_d3d11va.h"
@@ -233,13 +233,27 @@ static int amf_init_frames_context(AVCodecContext *avctx, 
int sw_format, int new
 
     ret = av_hwframe_ctx_init(avctx->hw_frames_ctx);
     if (ret < 0) {
-        av_log(NULL, AV_LOG_ERROR, "Error initializing a AMF frame pool\n");
+        av_log(avctx, AV_LOG_ERROR, "Error initializing a AMF frame pool\n");
         av_buffer_unref(&avctx->hw_frames_ctx);
         return ret;
     }
     return 0;
 }
 
+static int amf_reinit_frames_context(AVCodecContext *avctx, int sw_format,
+                                     int new_width, int new_height)
+{
+    if (!avctx->hw_device_ctx)
+        return 0;
+
+    av_buffer_unref(&avctx->hw_frames_ctx);
+    avctx->hw_frames_ctx = av_hwframe_ctx_alloc(avctx->hw_device_ctx);
+    if (!avctx->hw_frames_ctx)
+        return AVERROR(ENOMEM);
+
+    return amf_init_frames_context(avctx, sw_format, new_width, new_height);
+}
+
 static int amf_decode_init(AVCodecContext *avctx)
 {
     AMFDecoderContext *ctx = avctx->priv_data;
@@ -321,6 +335,122 @@ fail:
     return ret;
 }
 
+static int amf_color_primaries_valid(enum AVColorPrimaries pri)
+{
+    return pri != AVCOL_PRI_UNSPECIFIED && pri != AVCOL_PRI_RESERVED0 &&
+           pri != AVCOL_PRI_RESERVED && av_color_primaries_name(pri);
+}
+
+static int amf_color_trc_valid(enum AVColorTransferCharacteristic trc)
+{
+    return trc != AVCOL_TRC_UNSPECIFIED && trc != AVCOL_TRC_RESERVED0 &&
+           trc != AVCOL_TRC_RESERVED && av_color_transfer_name(trc);
+}
+
+static enum AVColorPrimaries amf_to_av_primaries(enum AMF_COLOR_PRIMARIES_ENUM 
pri)
+{
+    enum AVColorPrimaries avpri = (enum AVColorPrimaries)pri;
+
+    switch (pri) {
+    case AMF_COLOR_PRIMARIES_UNDEFINED:
+    case AMF_COLOR_PRIMARIES_UNSPECIFIED:
+    case AMF_COLOR_PRIMARIES_RESERVED:
+        return AVCOL_PRI_UNSPECIFIED;
+    default:
+        if (amf_color_primaries_valid(avpri))
+            return avpri;
+        return AVCOL_PRI_UNSPECIFIED;
+    }
+}
+
+static enum AVColorTransferCharacteristic amf_to_av_trc(enum 
AMF_COLOR_TRANSFER_CHARACTERISTIC_ENUM trc)
+{
+    enum AVColorTransferCharacteristic avtrc = (enum 
AVColorTransferCharacteristic)trc;
+
+    switch (trc) {
+    case AMF_COLOR_TRANSFER_CHARACTERISTIC_UNDEFINED:
+    case AMF_COLOR_TRANSFER_CHARACTERISTIC_UNSPECIFIED:
+    case AMF_COLOR_TRANSFER_CHARACTERISTIC_RESERVED:
+        return AVCOL_TRC_UNSPECIFIED;
+    default:
+        if (amf_color_trc_valid(avtrc))
+            return avtrc;
+        return AVCOL_TRC_UNSPECIFIED;
+    }
+}
+
+static enum AVColorRange amf_to_av_range(enum AMF_COLOR_RANGE_ENUM range)
+{
+    switch (range) {
+    case AMF_COLOR_RANGE_FULL:
+        return AVCOL_RANGE_JPEG;
+    case AMF_COLOR_RANGE_STUDIO:
+        return AVCOL_RANGE_MPEG;
+    default:
+        return AVCOL_RANGE_UNSPECIFIED;
+    }
+}
+
+static enum AVColorSpace amf_to_av_colorspace(enum 
AMF_VIDEO_CONVERTER_COLOR_PROFILE_ENUM profile)
+{
+    switch (profile) {
+    case AMF_VIDEO_CONVERTER_COLOR_PROFILE_601:
+    case AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_601:
+        return AVCOL_SPC_SMPTE170M;
+    case AMF_VIDEO_CONVERTER_COLOR_PROFILE_709:
+    case AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_709:
+        return AVCOL_SPC_BT709;
+    case AMF_VIDEO_CONVERTER_COLOR_PROFILE_2020:
+    case AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_2020:
+        return AVCOL_SPC_BT2020_NCL;
+    default:
+        return AVCOL_SPC_UNSPECIFIED;
+    }
+}
+
+static void amf_read_surface_color(AVCodecContext *avctx, AMFSurface *surface,
+                                   AVFrame *frame)
+{
+    AMFVariantStruct var = {0};
+    AMF_RESULT res;
+    enum AVColorPrimaries primaries = avctx->color_primaries;
+    enum AVColorTransferCharacteristic trc = avctx->color_trc;
+    enum AVColorSpace colorspace = avctx->colorspace;
+    enum AVColorRange range = avctx->color_range;
+
+    res = surface->pVtbl->GetProperty(surface, 
AMF_VIDEO_DECODER_COLOR_PRIMARIES, &var);
+    if (res == AMF_OK)
+        primaries = amf_to_av_primaries((enum 
AMF_COLOR_PRIMARIES_ENUM)var.int64Value);
+    AMFVariantClear(&var);
+
+    res = surface->pVtbl->GetProperty(surface, 
AMF_VIDEO_DECODER_COLOR_TRANSFER_CHARACTERISTIC, &var);
+    if (res == AMF_OK)
+        trc = amf_to_av_trc((enum 
AMF_COLOR_TRANSFER_CHARACTERISTIC_ENUM)var.int64Value);
+    AMFVariantClear(&var);
+
+    res = surface->pVtbl->GetProperty(surface, 
AMF_VIDEO_DECODER_COLOR_PROFILE, &var);
+    if (res == AMF_OK)
+        colorspace = amf_to_av_colorspace((enum 
AMF_VIDEO_CONVERTER_COLOR_PROFILE_ENUM)var.int64Value);
+    AMFVariantClear(&var);
+
+    if (primaries != AVCOL_PRI_UNSPECIFIED || trc != AVCOL_TRC_UNSPECIFIED ||
+         colorspace != AVCOL_SPC_UNSPECIFIED) {
+        res = surface->pVtbl->GetProperty(surface, 
AMF_VIDEO_DECODER_COLOR_RANGE, &var);
+        if (res == AMF_OK)
+            range = amf_to_av_range((enum AMF_COLOR_RANGE_ENUM)var.int64Value);
+        AMFVariantClear(&var);
+    }
+    avctx->color_primaries = primaries;
+    avctx->color_trc       = trc;
+    avctx->colorspace      = colorspace;
+    avctx->color_range     = range;
+
+    frame->color_primaries = primaries;
+    frame->color_trc       = trc;
+    frame->colorspace      = colorspace;
+    frame->color_range     = range;
+}
+
 static AMF_RESULT amf_get_property_buffer(AMFData *object, const wchar_t 
*name, AMFBuffer **val)
 {
     AMF_RESULT res;
@@ -342,6 +472,37 @@ static AMF_RESULT amf_get_property_buffer(AMFData *object, 
const wchar_t *name,
     return res;
 }
 
+static int amf_attach_hdr_metadata(AVCodecContext *avctx, AMFSurface *surface, 
AVFrame *frame)
+{
+    AMFBuffer *hdrmeta_buffer = NULL;
+    AMFHDRMetadata *hdrmeta;
+    AMF_RESULT res;
+    int ret;
+
+    if (frame->color_trc != AVCOL_TRC_SMPTE2084)
+        return 0;
+
+    res = amf_get_property_buffer((AMFData *)surface, 
AMF_VIDEO_DECODER_HDR_METADATA,
+                                  &hdrmeta_buffer);
+    if (!hdrmeta_buffer)
+        return 0;
+
+    if (res != AMF_OK) {
+        hdrmeta_buffer->pVtbl->Release(hdrmeta_buffer);
+        return AVERROR(EINVAL);
+    }
+
+    hdrmeta = (AMFHDRMetadata 
*)hdrmeta_buffer->pVtbl->GetNative(hdrmeta_buffer);
+    if (!hdrmeta) {
+        hdrmeta_buffer->pVtbl->Release(hdrmeta_buffer);
+        return AVERROR(EINVAL);
+    }
+
+    ret = av_amf_attach_hdr_metadata(frame, hdrmeta);
+    hdrmeta_buffer->pVtbl->Release(hdrmeta_buffer);
+    return ret;
+}
+
 static int amf_amfsurface_to_avframe(AVCodecContext *avctx, AMFSurface* 
surface, AVFrame *frame)
 {
     AMFVariantStruct    var = {0};
@@ -407,24 +568,12 @@ static int amf_amfsurface_to_avframe(AVCodecContext 
*avctx, AMFSurface* surface,
     if (frame->duration < 0)
         frame->duration = 0;
 
-    frame->color_range = avctx->color_range;
-    frame->colorspace = avctx->colorspace;
-    frame->color_trc = avctx->color_trc;
-    frame->color_primaries = avctx->color_primaries;
-
-    if (frame->color_trc == AVCOL_TRC_SMPTE2084) {
-        AMFBuffer * hdrmeta_buffer = NULL;
-        ret = amf_get_property_buffer((AMFData *)surface, 
AMF_VIDEO_DECODER_HDR_METADATA, &hdrmeta_buffer);
-        if (hdrmeta_buffer != NULL) {
-            AMFHDRMetadata * hdrmeta = 
(AMFHDRMetadata*)hdrmeta_buffer->pVtbl->GetNative(hdrmeta_buffer);
-            if (ret != AMF_OK)
-                return ret;
+    amf_read_surface_color(avctx, surface, frame);
+
+    ret = amf_attach_hdr_metadata(avctx, surface, frame);
+    if (ret < 0)
+        return ret;
 
-            ret = av_amf_attach_hdr_metadata(frame, hdrmeta);
-            if (ret < 0)
-                return ret;
-        }
-    }
     return 0;
 }
 
@@ -617,10 +766,10 @@ static int amf_decode_frame(AVCodecContext *avctx, struct 
AVFrame *frame)
             if (res != AMF_OK) {
                 return AVERROR(EINVAL);
             }
-            int ret = amf_init_frames_context(avctx, 
av_amf_to_av_format(format_var.int64Value), avctx->coded_width, 
avctx->coded_height);
+            int ret = amf_reinit_frames_context(avctx, 
av_amf_to_av_format(format_var.int64Value), avctx->coded_width, 
avctx->coded_height);
             if (ret < 0)
                 return ret;
-        }else
+        } else
             return AVERROR_EOF;
     } else {
         av_log(avctx, AV_LOG_ERROR, "Unknown result from QueryOutput %d\n", 
res);

_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to