diff mbox series

[FFmpeg-devel] avcodec/amfenc: properly set primaries, transfer, and matrix values

Message ID 20241019135339.33059-1-damiog@gmail.com
State New
Headers show
Series [FFmpeg-devel] avcodec/amfenc: properly set primaries, transfer, and matrix values | expand

Commit Message

Damiano Galassi Oct. 19, 2024, 1:53 p.m. UTC
HEVC and AV1 encoders had hard-coded color values for 8-bit and 10-bit depths,
and they were completely disregarding the provided values.
---
 libavcodec/amfenc.c      | 109 +++++++++++++++++++++++++++++++++++++++
 libavcodec/amfenc.h      |   2 +
 libavcodec/amfenc_av1.c  |  16 +++---
 libavcodec/amfenc_h264.c |  10 ++--
 libavcodec/amfenc_hevc.c |  15 +++---
 5 files changed, 129 insertions(+), 23 deletions(-)
diff mbox series

Patch

diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c
index 225fb9df27..a83f5b2013 100644
--- a/libavcodec/amfenc.c
+++ b/libavcodec/amfenc.c
@@ -917,6 +917,115 @@  int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
     return ret;
 }
 
+int ff_amf_get_color_primaries(AVCodecContext *avctx)
+{
+    amf_int64 color_primaries = AMF_COLOR_PRIMARIES_UNDEFINED;
+    switch (avctx->color_primaries) {
+        case AVCOL_PRI_BT709:
+            color_primaries = AMF_COLOR_PRIMARIES_BT709;
+            break;
+        case AVCOL_PRI_UNSPECIFIED:
+            color_primaries = AMF_COLOR_PRIMARIES_UNSPECIFIED;
+            break;
+        case AVCOL_PRI_RESERVED:
+            color_primaries = AMF_COLOR_PRIMARIES_RESERVED;
+            break;
+        case AVCOL_PRI_BT470M:
+            color_primaries = AMF_COLOR_PRIMARIES_BT470M;
+            break;
+        case AVCOL_PRI_BT470BG:
+            color_primaries = AMF_COLOR_PRIMARIES_BT470BG;
+            break;
+        case AVCOL_PRI_SMPTE170M:
+            color_primaries = AMF_COLOR_PRIMARIES_SMPTE170M;
+            break;
+        case AVCOL_PRI_SMPTE240M:
+            color_primaries = AMF_COLOR_PRIMARIES_SMPTE240M;
+            break;
+        case AVCOL_PRI_FILM:
+            color_primaries = AMF_COLOR_PRIMARIES_FILM;
+            break;
+        case AVCOL_PRI_BT2020:
+            color_primaries = AMF_COLOR_PRIMARIES_BT2020;
+            break;
+        case AVCOL_PRI_SMPTE428:
+            color_primaries = AMF_COLOR_PRIMARIES_SMPTE428;
+            break;
+        case AVCOL_PRI_SMPTE431:
+            color_primaries = AMF_COLOR_PRIMARIES_SMPTE431;
+            break;
+        case AVCOL_PRI_SMPTE432:
+            color_primaries = AMF_COLOR_PRIMARIES_SMPTE432;
+            break;
+        case AVCOL_PRI_EBU3213:
+            color_primaries = AMF_COLOR_PRIMARIES_JEDEC_P22;
+            break;
+    }
+    return color_primaries;
+}
+
+int ff_amf_get_transfer_characteristic(AVCodecContext *avctx)
+{
+    amf_int64 transfer_characteristic = AMF_COLOR_TRANSFER_CHARACTERISTIC_UNDEFINED;
+    switch (avctx->color_trc) {
+        case AVCOL_TRC_BT709:
+            transfer_characteristic = AMF_COLOR_TRANSFER_CHARACTERISTIC_BT709;
+            break;
+        case AVCOL_TRC_UNSPECIFIED:
+            transfer_characteristic = AMF_COLOR_TRANSFER_CHARACTERISTIC_UNSPECIFIED;
+            break;
+        case AVCOL_TRC_RESERVED:
+            transfer_characteristic = AMF_COLOR_TRANSFER_CHARACTERISTIC_RESERVED;
+            break;
+        case AVCOL_TRC_GAMMA22:
+            transfer_characteristic = AMF_COLOR_TRANSFER_CHARACTERISTIC_GAMMA22;
+            break;
+        case AVCOL_TRC_GAMMA28:
+            transfer_characteristic = AMF_COLOR_TRANSFER_CHARACTERISTIC_GAMMA28;
+            break;
+        case AVCOL_TRC_SMPTE170M:
+            transfer_characteristic = AMF_COLOR_TRANSFER_CHARACTERISTIC_SMPTE170M;
+            break;
+        case AVCOL_TRC_SMPTE240M:
+            transfer_characteristic = AMF_COLOR_TRANSFER_CHARACTERISTIC_SMPTE240M;
+            break;
+        case AVCOL_TRC_LINEAR:
+            transfer_characteristic = AMF_COLOR_TRANSFER_CHARACTERISTIC_LINEAR;
+            break;
+        case AVCOL_TRC_LOG:
+            transfer_characteristic = AMF_COLOR_TRANSFER_CHARACTERISTIC_LOG;
+            break;
+        case AVCOL_TRC_LOG_SQRT:
+            transfer_characteristic = AMF_COLOR_TRANSFER_CHARACTERISTIC_LOG_SQRT;
+            break;
+        case AVCOL_TRC_IEC61966_2_4:
+            transfer_characteristic = AMF_COLOR_TRANSFER_CHARACTERISTIC_IEC61966_2_4;
+            break;
+        case AVCOL_TRC_BT1361_ECG:
+            transfer_characteristic = AMF_COLOR_TRANSFER_CHARACTERISTIC_BT1361_ECG;
+            break;
+        case AVCOL_TRC_IEC61966_2_1:
+            transfer_characteristic = AMF_COLOR_TRANSFER_CHARACTERISTIC_IEC61966_2_1;
+            break;
+        case AVCOL_TRC_BT2020_10:
+            transfer_characteristic = AMF_COLOR_TRANSFER_CHARACTERISTIC_BT2020_10;
+            break;
+        case AVCOL_TRC_BT2020_12:
+            transfer_characteristic = AMF_COLOR_TRANSFER_CHARACTERISTIC_BT2020_12;
+            break;
+        case AVCOL_TRC_SMPTE2084:
+            transfer_characteristic = AMF_COLOR_TRANSFER_CHARACTERISTIC_SMPTE2084;
+            break;
+        case AVCOL_TRC_SMPTE428:
+            transfer_characteristic = AMF_COLOR_TRANSFER_CHARACTERISTIC_SMPTE428;
+            break;
+        case AVCOL_TRC_ARIB_STD_B67:
+            transfer_characteristic = AMF_COLOR_TRANSFER_CHARACTERISTIC_ARIB_STD_B67;
+            break;
+    }
+    return transfer_characteristic;
+}
+
 int ff_amf_get_color_profile(AVCodecContext *avctx)
 {
     amf_int64 color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN;
diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h
index 0f2abcbd82..0c0624e786 100644
--- a/libavcodec/amfenc.h
+++ b/libavcodec/amfenc.h
@@ -174,6 +174,8 @@  int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt);
 */
 extern const enum AVPixelFormat ff_amf_pix_fmts[];
 
+int ff_amf_get_color_primaries(AVCodecContext *avctx);
+int ff_amf_get_transfer_characteristic(AVCodecContext *avctx);
 int ff_amf_get_color_profile(AVCodecContext *avctx);
 
 /**
diff --git a/libavcodec/amfenc_av1.c b/libavcodec/amfenc_av1.c
index b40d54f70c..a947c1d232 100644
--- a/libavcodec/amfenc_av1.c
+++ b/libavcodec/amfenc_av1.c
@@ -187,6 +187,8 @@  static av_cold int amf_encode_init_av1(AVCodecContext* avctx)
     AMFRate             framerate;
     AMFSize             framesize = AMFConstructSize(avctx->width, avctx->height);
     amf_int64           color_depth;
+    amf_int64           color_primaries;
+    amf_int64           transfer_characteristic;
     amf_int64           color_profile;
     enum                AVPixelFormat pix_fmt;
 
@@ -239,7 +241,11 @@  FF_ENABLE_DEPRECATION_WARNINGS
     }
 
     /// Color profile
+    color_primaries = ff_amf_get_color_primaries(avctx);
+    transfer_characteristic = ff_amf_get_transfer_characteristic(avctx);
     color_profile = ff_amf_get_color_profile(avctx);
+    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_OUTPUT_COLOR_PRIMARIES, color_primaries);
+    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_OUTPUT_TRANSFER_CHARACTERISTIC, transfer_characteristic);
     AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_OUTPUT_COLOR_PROFILE, color_profile);
 
     /// Color Depth
@@ -251,16 +257,6 @@  FF_ENABLE_DEPRECATION_WARNINGS
     }
 
     AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_COLOR_BIT_DEPTH, color_depth);
-    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_OUTPUT_COLOR_PROFILE, color_profile);
-    if (color_depth == AMF_COLOR_BIT_DEPTH_8) {
-        /// Color Transfer Characteristics (AMF matches ISO/IEC)
-        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_OUTPUT_TRANSFER_CHARACTERISTIC, AMF_COLOR_TRANSFER_CHARACTERISTIC_BT709);
-        /// Color Primaries (AMF matches ISO/IEC)
-        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_OUTPUT_COLOR_PRIMARIES, AMF_COLOR_PRIMARIES_BT709);
-    } else {
-        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_OUTPUT_TRANSFER_CHARACTERISTIC, AMF_COLOR_TRANSFER_CHARACTERISTIC_SMPTE2084);
-        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_OUTPUT_COLOR_PRIMARIES, AMF_COLOR_PRIMARIES_BT2020);
-    }
 
     profile_level = avctx->level;
     if (profile_level == AV_LEVEL_UNKNOWN) {
diff --git a/libavcodec/amfenc_h264.c b/libavcodec/amfenc_h264.c
index 959be9eab6..2406f7401f 100644
--- a/libavcodec/amfenc_h264.c
+++ b/libavcodec/amfenc_h264.c
@@ -202,6 +202,8 @@  static av_cold int amf_encode_init_h264(AVCodecContext *avctx)
     AMFRate                          framerate;
     AMFSize                          framesize = AMFConstructSize(avctx->width, avctx->height);
     int                              deblocking_filter = (avctx->flags & AV_CODEC_FLAG_LOOP_FILTER) ? 1 : 0;
+    amf_int64                        color_primaries;
+    amf_int64                        transfer_characteristic;
     amf_int64                        color_profile;
     enum                             AVPixelFormat pix_fmt;
 
@@ -274,7 +276,11 @@  FF_ENABLE_DEPRECATION_WARNINGS
         AMF_ASSIGN_PROPERTY_RATIO(res, ctx->encoder, AMF_VIDEO_ENCODER_ASPECT_RATIO, ratio);
     }
 
+    color_primaries = ff_amf_get_color_primaries(avctx);
+    transfer_characteristic = ff_amf_get_transfer_characteristic(avctx);
     color_profile = ff_amf_get_color_profile(avctx);
+    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_OUTPUT_COLOR_PRIMARIES, color_primaries);
+    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_OUTPUT_TRANSFER_CHARACTERISTIC, transfer_characteristic);
     AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_OUTPUT_COLOR_PROFILE, color_profile);
 
     /// Color Range (Support for older Drivers)
@@ -288,10 +294,6 @@  FF_ENABLE_DEPRECATION_WARNINGS
     AMF_RETURN_IF_FALSE(ctx, pix_fmt != AV_PIX_FMT_P010, AVERROR_INVALIDDATA, "10-bit input video is not supported by AMF H264 encoder\n");
 
     AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_COLOR_BIT_DEPTH, AMF_COLOR_BIT_DEPTH_8);
-    /// Color Transfer Characteristics (AMF matches ISO/IEC)
-    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_OUTPUT_TRANSFER_CHARACTERISTIC, (amf_int64)avctx->color_trc);
-    /// Color Primaries (AMF matches ISO/IEC)
-    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_OUTPUT_COLOR_PRIMARIES, (amf_int64)avctx->color_primaries);
 
     // autodetect rate control method
     if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_UNKNOWN) {
diff --git a/libavcodec/amfenc_hevc.c b/libavcodec/amfenc_hevc.c
index f9f6f8adb3..84587c9fb6 100644
--- a/libavcodec/amfenc_hevc.c
+++ b/libavcodec/amfenc_hevc.c
@@ -168,6 +168,8 @@  static av_cold int amf_encode_init_hevc(AVCodecContext *avctx)
     AMFSize             framesize = AMFConstructSize(avctx->width, avctx->height);
     int                 deblocking_filter = (avctx->flags & AV_CODEC_FLAG_LOOP_FILTER) ? 1 : 0;
     amf_int64           color_depth;
+    amf_int64           color_primaries;
+    amf_int64           transfer_characteristic;
     amf_int64           color_profile;
     enum                AVPixelFormat pix_fmt;
 
@@ -242,7 +244,11 @@  FF_ENABLE_DEPRECATION_WARNINGS
         AMF_ASSIGN_PROPERTY_RATIO(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ASPECT_RATIO, ratio);
     }
 
+    color_primaries = ff_amf_get_color_primaries(avctx);
+    transfer_characteristic = ff_amf_get_transfer_characteristic(avctx);
     color_profile = ff_amf_get_color_profile(avctx);
+    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_OUTPUT_COLOR_PRIMARIES, color_primaries);
+    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_OUTPUT_TRANSFER_CHARACTERISTIC, transfer_characteristic);
     AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_OUTPUT_COLOR_PROFILE, color_profile);
     /// Color Range (Support for older Drivers)
     AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_NOMINAL_RANGE, !!(avctx->color_range == AVCOL_RANGE_JPEG));
@@ -254,15 +260,6 @@  FF_ENABLE_DEPRECATION_WARNINGS
         color_depth = AMF_COLOR_BIT_DEPTH_10;
     }
     AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_COLOR_BIT_DEPTH, color_depth);
-    if (color_depth == AMF_COLOR_BIT_DEPTH_8) {
-        /// Color Transfer Characteristics (AMF matches ISO/IEC)
-        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_OUTPUT_TRANSFER_CHARACTERISTIC, AMF_COLOR_TRANSFER_CHARACTERISTIC_BT709);
-        /// Color Primaries (AMF matches ISO/IEC)
-        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_OUTPUT_COLOR_PRIMARIES, AMF_COLOR_PRIMARIES_BT709);
-    } else {
-        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_OUTPUT_TRANSFER_CHARACTERISTIC, AMF_COLOR_TRANSFER_CHARACTERISTIC_SMPTE2084);
-        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_OUTPUT_COLOR_PRIMARIES, AMF_COLOR_PRIMARIES_BT2020);
-    }
 
     // Picture control properties
     AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_NUM_GOPS_PER_IDR, ctx->gops_per_idr);