Message ID | 20240801111338.1683-1-Primeadvice@gmail.com |
---|---|
State | New |
Headers | show |
Series | [FFmpeg-devel,1/4,v2] avcodec/amfenc: Fixes the color information in the output. | expand |
Context | Check | Description |
---|---|---|
yinshiyou/make_loongarch64 | success | Make finished |
yinshiyou/make_fate_loongarch64 | success | Make fate finished |
andriy/make_x86 | success | Make finished |
andriy/make_fate_x86 | success | Make fate finished |
Araz Iusubov: > From: Michael Fabian 'Xaymar' Dirks <michael.dirks@xaymar.com> > > added 10 bit support for amf hevc. > > before: > > command - ffmpeg.exe -hide_banner -y -hwaccel d3d11va -hwaccel_output_format d3d11 -i test_10bit_file.mkv -an -c:v h264_amf res.dx11_hw_h264.mkv > output - Format of input frames context (p010le) is not supported by AMF. > command - ffmpeg.exe -hide_banner -y -hwaccel d3d11va -hwaccel_output_format d3d11 -i test_10bit_file -an -c:v hevc_amf res.dx11_hw_hevc.mkv > output - Format of input frames context (p010le) is not supported by AMF. > > after: > > command - ffmpeg.exe -hide_banner -y -hwaccel d3d11va -hwaccel_output_format d3d11 -i test_10bit_file -an -c:v h264_amf res.dx11_hw_h264.mkv > output - 10-bit input video is not supported by AMF H264 encoder > command - ffmpeg.exe -hide_banner -y -hwaccel d3d11va -hwaccel_output_format d3d11 -i test_10bit_file -an -c:v hevc_amf res.dx11_hw_hevc.mkv > output - 10bit file > > v2 - lost line returned in ff_amf_pix_fmts > v3 - fixes after review > v4 - extract duplicated code, fix incorrect processing of 10-bit input for h264 > v5 - non-functional changes after review > > Co-authored-by: Evgeny Pavlov <lucenticus@gmail.com> > Co-authored-by: Araz Iusubov <Primeadvice@gmail.com> > --- > libavcodec/amfenc.c | 37 +++++++++++++++++++++++++++++++++++++ > libavcodec/amfenc.h | 3 +++ > libavcodec/amfenc_h264.c | 24 ++++++++++++++++++++---- > libavcodec/amfenc_hevc.c | 31 ++++++++++++++++++++++++++++++- > 4 files changed, 90 insertions(+), 5 deletions(-) > > diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c > index 061859f85c..0bd15dd812 100644 > --- a/libavcodec/amfenc.c > +++ b/libavcodec/amfenc.c > @@ -60,6 +60,7 @@ const enum AVPixelFormat ff_amf_pix_fmts[] = { > #if CONFIG_DXVA2 > AV_PIX_FMT_DXVA2_VLD, > #endif > + AV_PIX_FMT_P010, > AV_PIX_FMT_NONE > }; > > @@ -72,6 +73,7 @@ static const FormatMap format_map[] = > { > { AV_PIX_FMT_NONE, AMF_SURFACE_UNKNOWN }, > { AV_PIX_FMT_NV12, AMF_SURFACE_NV12 }, > + { AV_PIX_FMT_P010, AMF_SURFACE_P010 }, Why is this in this commit? > { AV_PIX_FMT_BGR0, AMF_SURFACE_BGRA }, > { AV_PIX_FMT_RGB0, AMF_SURFACE_RGBA }, > { AV_PIX_FMT_GRAY8, AMF_SURFACE_GRAY8 }, > @@ -785,6 +787,41 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) > return ret; > } > > +int ff_amf_get_color_profile(AVCodecContext *avctx) > +{ > + amf_int64 color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN; > + if (avctx->color_range == AVCOL_RANGE_JPEG) { > + /// Color Space for Full (JPEG) Range > + switch (avctx->colorspace) { > + case AVCOL_SPC_SMPTE170M: > + color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_601; > + break; > + case AVCOL_SPC_BT709: > + color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_709; > + break; > + case AVCOL_SPC_BT2020_NCL: > + case AVCOL_SPC_BT2020_CL: > + color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_2020; > + break; > + } > + } else { > + /// Color Space for Limited (MPEG) range > + switch (avctx->colorspace) { > + case AVCOL_SPC_SMPTE170M: > + color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_601; > + break; > + case AVCOL_SPC_BT709: > + color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_709; > + break; > + case AVCOL_SPC_BT2020_NCL: > + case AVCOL_SPC_BT2020_CL: > + color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_2020; > + break; > + } > + } > + return color_profile; > +} > + > const AVCodecHWConfigInternal *const ff_amfenc_hw_configs[] = { > #if CONFIG_D3D11VA > HW_CONFIG_ENCODER_FRAMES(D3D11, D3D11VA), > diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h > index 2dbd378ef8..62736ef579 100644 > --- a/libavcodec/amfenc.h > +++ b/libavcodec/amfenc.h > @@ -21,6 +21,7 @@ > > #include <AMF/core/Factory.h> > > +#include <AMF/components/ColorSpace.h> > #include <AMF/components/VideoEncoderVCE.h> > #include <AMF/components/VideoEncoderHEVC.h> > #include <AMF/components/VideoEncoderAV1.h> > @@ -170,6 +171,8 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt); > */ > extern const enum AVPixelFormat ff_amf_pix_fmts[]; > > +int ff_amf_get_color_profile(AVCodecContext *avctx); > + > /** > * Error handling helper > */ > diff --git a/libavcodec/amfenc_h264.c b/libavcodec/amfenc_h264.c > index 32baa8e91a..7caeca748d 100644 > --- a/libavcodec/amfenc_h264.c > +++ b/libavcodec/amfenc_h264.c > @@ -200,6 +200,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_profile; > + enum AVPixelFormat pix_fmt; > > if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { > framerate = AMFConstructRate(avctx->framerate.num, avctx->framerate.den); > @@ -270,10 +272,24 @@ FF_ENABLE_DEPRECATION_WARNINGS > AMF_ASSIGN_PROPERTY_RATIO(res, ctx->encoder, AMF_VIDEO_ENCODER_ASPECT_RATIO, ratio); > } > > - /// Color Range (Partial/TV/MPEG or Full/PC/JPEG) > - if (avctx->color_range == AVCOL_RANGE_JPEG) { > - AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_FULL_RANGE_COLOR, 1); > - } > + color_profile = ff_amf_get_color_profile(avctx); > + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_OUTPUT_COLOR_PROFILE, color_profile); > + > + /// Color Range (Support for older Drivers) > + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_FULL_RANGE_COLOR, !!(avctx->color_range == AVCOL_RANGE_JPEG)); > + > + /// Color Depth > + pix_fmt = avctx->hw_frames_ctx ? ((AVHWFramesContext*)avctx->hw_frames_ctx->data)->sw_format > + : avctx->pix_fmt; > + > + // 10 bit input video is not supported by AMF H264 encoder > + 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 2915a83677..5422835100 100644 > --- a/libavcodec/amfenc_hevc.c > +++ b/libavcodec/amfenc_hevc.c > @@ -35,8 +35,9 @@ static const AVOption options[] = { > { "high_quality", "High quality usecase", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_HIGH_QUALITY }, 0, 0, VE, .unit = "usage" }, > { "lowlatency_high_quality", "Low latency yet high quality usecase", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_LOW_LATENCY_HIGH_QUALITY }, 0, 0, VE, .unit = "usage" }, > > + { "profile", "Set the profile", OFFSET(profile), AV_OPT_TYPE_INT,{ .i64 = -1 }, -1, AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN_10, VE, .unit = "profile" }, > { "main", "", 0, AV_OPT_TYPE_CONST,{ .i64 = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN }, 0, 0, VE, .unit = "profile" }, > - { "profile", "Set the profile", OFFSET(profile), AV_OPT_TYPE_INT,{ .i64 = -1 }, -1, AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN, VE, .unit = "profile" }, > + { "main10", "", 0, AV_OPT_TYPE_CONST,{ .i64 = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN_10 }, 0, 0, VE, .unit = "profile" }, > > { "profile_tier", "Set the profile tier (default main)", OFFSET(tier), AV_OPT_TYPE_INT,{ .i64 = -1 }, -1, AMF_VIDEO_ENCODER_HEVC_TIER_HIGH, VE, .unit = "tier" }, > { "main", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_TIER_MAIN }, 0, 0, VE, .unit = "tier" }, > @@ -163,6 +164,9 @@ static av_cold int amf_encode_init_hevc(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_depth; > + amf_int64 color_profile; > + enum AVPixelFormat pix_fmt; > > if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { > framerate = AMFConstructRate(avctx->framerate.num, avctx->framerate.den); > @@ -192,6 +196,9 @@ FF_ENABLE_DEPRECATION_WARNINGS > case AV_PROFILE_HEVC_MAIN: > profile = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN; > break; > + case AV_PROFILE_HEVC_MAIN_10: > + profile = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN_10; > + break; > default: > break; > } > @@ -232,6 +239,28 @@ FF_ENABLE_DEPRECATION_WARNINGS > AMF_ASSIGN_PROPERTY_RATIO(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ASPECT_RATIO, ratio); > } > > + color_profile = ff_amf_get_color_profile(avctx); > + 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)); > + /// Color Depth > + color_depth = AMF_COLOR_BIT_DEPTH_8; > + pix_fmt = avctx->hw_frames_ctx ? ((AVHWFramesContext*)avctx->hw_frames_ctx->data)->sw_format > + : avctx->pix_fmt; > + if (pix_fmt == AV_PIX_FMT_P010) { > + 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); > AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_GOP_SIZE, avctx->gop_size);
> > + AV_PIX_FMT_P010, > > AV_PIX_FMT_NONE > > }; > > > > @@ -72,6 +73,7 @@ static const FormatMap format_map[] = > > { > > { AV_PIX_FMT_NONE, AMF_SURFACE_UNKNOWN }, > > { AV_PIX_FMT_NV12, AMF_SURFACE_NV12 }, > > + { AV_PIX_FMT_P010, AMF_SURFACE_P010 }, > Why is this in this commit? This patch mostly fixes color information. 10-bit pixel format update is too small to make a separate patch for it. I can rename that patch or split it on 2 patches.
If there are no objections, I would like to merge this patch series on the next week.
On Thu, Aug 1, 2024 at 6:51 AM Araz Iusubov <primeadvice@gmail.com> wrote: > > From: Michael Fabian 'Xaymar' Dirks <michael.dirks@xaymar.com> > > added 10 bit support for amf hevc. > > before: > > command - ffmpeg.exe -hide_banner -y -hwaccel d3d11va -hwaccel_output_format d3d11 -i test_10bit_file.mkv -an -c:v h264_amf res.dx11_hw_h264.mkv > output - Format of input frames context (p010le) is not supported by AMF. > command - ffmpeg.exe -hide_banner -y -hwaccel d3d11va -hwaccel_output_format d3d11 -i test_10bit_file -an -c:v hevc_amf res.dx11_hw_hevc.mkv > output - Format of input frames context (p010le) is not supported by AMF. > > after: > > command - ffmpeg.exe -hide_banner -y -hwaccel d3d11va -hwaccel_output_format d3d11 -i test_10bit_file -an -c:v h264_amf res.dx11_hw_h264.mkv > output - 10-bit input video is not supported by AMF H264 encoder > command - ffmpeg.exe -hide_banner -y -hwaccel d3d11va -hwaccel_output_format d3d11 -i test_10bit_file -an -c:v hevc_amf res.dx11_hw_hevc.mkv > output - 10bit file > > v2 - lost line returned in ff_amf_pix_fmts > v3 - fixes after review > v4 - extract duplicated code, fix incorrect processing of 10-bit input for h264 > v5 - non-functional changes after review > > Co-authored-by: Evgeny Pavlov <lucenticus@gmail.com> > Co-authored-by: Araz Iusubov <Primeadvice@gmail.com> > --- > libavcodec/amfenc.c | 37 +++++++++++++++++++++++++++++++++++++ > libavcodec/amfenc.h | 3 +++ > libavcodec/amfenc_h264.c | 24 ++++++++++++++++++++---- > libavcodec/amfenc_hevc.c | 31 ++++++++++++++++++++++++++++++- > 4 files changed, 90 insertions(+), 5 deletions(-) > > diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c > index 061859f85c..0bd15dd812 100644 > --- a/libavcodec/amfenc.c > +++ b/libavcodec/amfenc.c > @@ -60,6 +60,7 @@ const enum AVPixelFormat ff_amf_pix_fmts[] = { > #if CONFIG_DXVA2 > AV_PIX_FMT_DXVA2_VLD, > #endif > + AV_PIX_FMT_P010, > AV_PIX_FMT_NONE > }; > > @@ -72,6 +73,7 @@ static const FormatMap format_map[] = > { > { AV_PIX_FMT_NONE, AMF_SURFACE_UNKNOWN }, > { AV_PIX_FMT_NV12, AMF_SURFACE_NV12 }, > + { AV_PIX_FMT_P010, AMF_SURFACE_P010 }, > { AV_PIX_FMT_BGR0, AMF_SURFACE_BGRA }, > { AV_PIX_FMT_RGB0, AMF_SURFACE_RGBA }, > { AV_PIX_FMT_GRAY8, AMF_SURFACE_GRAY8 }, > @@ -785,6 +787,41 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) > return ret; > } > > +int ff_amf_get_color_profile(AVCodecContext *avctx) > +{ > + amf_int64 color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN; > + if (avctx->color_range == AVCOL_RANGE_JPEG) { > + /// Color Space for Full (JPEG) Range > + switch (avctx->colorspace) { > + case AVCOL_SPC_SMPTE170M: > + color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_601; > + break; > + case AVCOL_SPC_BT709: > + color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_709; > + break; > + case AVCOL_SPC_BT2020_NCL: > + case AVCOL_SPC_BT2020_CL: > + color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_2020; > + break; > + } > + } else { > + /// Color Space for Limited (MPEG) range > + switch (avctx->colorspace) { > + case AVCOL_SPC_SMPTE170M: > + color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_601; > + break; > + case AVCOL_SPC_BT709: > + color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_709; > + break; > + case AVCOL_SPC_BT2020_NCL: > + case AVCOL_SPC_BT2020_CL: > + color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_2020; > + break; > + } > + } > + return color_profile; > +} > + > const AVCodecHWConfigInternal *const ff_amfenc_hw_configs[] = { > #if CONFIG_D3D11VA > HW_CONFIG_ENCODER_FRAMES(D3D11, D3D11VA), > diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h > index 2dbd378ef8..62736ef579 100644 > --- a/libavcodec/amfenc.h > +++ b/libavcodec/amfenc.h > @@ -21,6 +21,7 @@ > > #include <AMF/core/Factory.h> > > +#include <AMF/components/ColorSpace.h> > #include <AMF/components/VideoEncoderVCE.h> > #include <AMF/components/VideoEncoderHEVC.h> > #include <AMF/components/VideoEncoderAV1.h> > @@ -170,6 +171,8 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt); > */ > extern const enum AVPixelFormat ff_amf_pix_fmts[]; > > +int ff_amf_get_color_profile(AVCodecContext *avctx); > + > /** > * Error handling helper > */ > diff --git a/libavcodec/amfenc_h264.c b/libavcodec/amfenc_h264.c > index 32baa8e91a..7caeca748d 100644 > --- a/libavcodec/amfenc_h264.c > +++ b/libavcodec/amfenc_h264.c > @@ -200,6 +200,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_profile; > + enum AVPixelFormat pix_fmt; > > if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { > framerate = AMFConstructRate(avctx->framerate.num, avctx->framerate.den); > @@ -270,10 +272,24 @@ FF_ENABLE_DEPRECATION_WARNINGS > AMF_ASSIGN_PROPERTY_RATIO(res, ctx->encoder, AMF_VIDEO_ENCODER_ASPECT_RATIO, ratio); > } > > - /// Color Range (Partial/TV/MPEG or Full/PC/JPEG) > - if (avctx->color_range == AVCOL_RANGE_JPEG) { > - AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_FULL_RANGE_COLOR, 1); > - } > + color_profile = ff_amf_get_color_profile(avctx); > + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_OUTPUT_COLOR_PROFILE, color_profile); > + > + /// Color Range (Support for older Drivers) > + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_FULL_RANGE_COLOR, !!(avctx->color_range == AVCOL_RANGE_JPEG)); > + > + /// Color Depth > + pix_fmt = avctx->hw_frames_ctx ? ((AVHWFramesContext*)avctx->hw_frames_ctx->data)->sw_format > + : avctx->pix_fmt; > + > + // 10 bit input video is not supported by AMF H264 encoder > + 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 2915a83677..5422835100 100644 > --- a/libavcodec/amfenc_hevc.c > +++ b/libavcodec/amfenc_hevc.c > @@ -35,8 +35,9 @@ static const AVOption options[] = { > { "high_quality", "High quality usecase", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_HIGH_QUALITY }, 0, 0, VE, .unit = "usage" }, > { "lowlatency_high_quality", "Low latency yet high quality usecase", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_LOW_LATENCY_HIGH_QUALITY }, 0, 0, VE, .unit = "usage" }, > > + { "profile", "Set the profile", OFFSET(profile), AV_OPT_TYPE_INT,{ .i64 = -1 }, -1, AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN_10, VE, .unit = "profile" }, > { "main", "", 0, AV_OPT_TYPE_CONST,{ .i64 = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN }, 0, 0, VE, .unit = "profile" }, > - { "profile", "Set the profile", OFFSET(profile), AV_OPT_TYPE_INT,{ .i64 = -1 }, -1, AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN, VE, .unit = "profile" }, > + { "main10", "", 0, AV_OPT_TYPE_CONST,{ .i64 = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN_10 }, 0, 0, VE, .unit = "profile" }, > > { "profile_tier", "Set the profile tier (default main)", OFFSET(tier), AV_OPT_TYPE_INT,{ .i64 = -1 }, -1, AMF_VIDEO_ENCODER_HEVC_TIER_HIGH, VE, .unit = "tier" }, > { "main", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_TIER_MAIN }, 0, 0, VE, .unit = "tier" }, > @@ -163,6 +164,9 @@ static av_cold int amf_encode_init_hevc(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_depth; > + amf_int64 color_profile; > + enum AVPixelFormat pix_fmt; > > if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { > framerate = AMFConstructRate(avctx->framerate.num, avctx->framerate.den); > @@ -192,6 +196,9 @@ FF_ENABLE_DEPRECATION_WARNINGS > case AV_PROFILE_HEVC_MAIN: > profile = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN; > break; > + case AV_PROFILE_HEVC_MAIN_10: > + profile = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN_10; > + break; > default: > break; > } > @@ -232,6 +239,28 @@ FF_ENABLE_DEPRECATION_WARNINGS > AMF_ASSIGN_PROPERTY_RATIO(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ASPECT_RATIO, ratio); > } > > + color_profile = ff_amf_get_color_profile(avctx); > + 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)); > + /// Color Depth > + color_depth = AMF_COLOR_BIT_DEPTH_8; > + pix_fmt = avctx->hw_frames_ctx ? ((AVHWFramesContext*)avctx->hw_frames_ctx->data)->sw_format > + : avctx->pix_fmt; > + if (pix_fmt == AV_PIX_FMT_P010) { > + 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); > + } Apologies for missing this prior to merge, but you can't safely make these assumptions about primaries and TRC just based on the input bit depth. Just because it's 8-bit content doesn't mean it will be BT.709 and likewise for 10-bit and BT.2020+SMPTE 2084 PQ. Why doesn't amfenc_hevc (and amfenc_av1) use the values from avctx like amfenc_h264 does? Cameron > + > // Picture control properties > AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_NUM_GOPS_PER_IDR, ctx->gops_per_idr); > AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_GOP_SIZE, avctx->gop_size); > -- > 2.45.2.windows.1 > > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
> Apologies for missing this prior to merge, but you can't safely make these > assumptions about primaries and TRC just based on the input bit depth. Just > because it's 8-bit content doesn't mean it will be BT.709 and likewise for > 10-bit and BT.2020+SMPTE 2084 PQ. > > Why doesn't amfenc_hevc (and amfenc_av1) use the values from avctx like > amfenc_h264 does? Current hardware color space converter does not support transfer characteristics other than this: (BT709 for 8-bit output and BT2084 for 10-bit output) so for RGB input we need them hard-coded. If conversion is done before AMF encoder, the encoder can accept any value as it is just fields in VUI header. So, we will come with a separate patch which would reflect this logic.
On Mon, Sep 9, 2024 at 9:24 AM Araz <primeadvice@gmail.com> wrote: > > > Apologies for missing this prior to merge, but you can't safely make these > > assumptions about primaries and TRC just based on the input bit depth. Just > > because it's 8-bit content doesn't mean it will be BT.709 and likewise for > > 10-bit and BT.2020+SMPTE 2084 PQ. > > > > Why doesn't amfenc_hevc (and amfenc_av1) use the values from avctx like > > amfenc_h264 does? > > Current hardware color space converter does not support transfer > characteristics other than this: > (BT709 for 8-bit output and BT2084 for 10-bit output) so for RGB input > we need them hard-coded. If conversion is done before AMF encoder, the > encoder can accept any value as it is just fields in VUI header. Thanks for the clarification. My use case is in that second category where I've already done the color conversion and just needed the proper VUI values set in the encoded bitstream. > So, we will come with a separate patch which would reflect this logic. Feel free to send it my way once it's ready. I'd be happy to test for you.
diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c index 061859f85c..0bd15dd812 100644 --- a/libavcodec/amfenc.c +++ b/libavcodec/amfenc.c @@ -60,6 +60,7 @@ const enum AVPixelFormat ff_amf_pix_fmts[] = { #if CONFIG_DXVA2 AV_PIX_FMT_DXVA2_VLD, #endif + AV_PIX_FMT_P010, AV_PIX_FMT_NONE }; @@ -72,6 +73,7 @@ static const FormatMap format_map[] = { { AV_PIX_FMT_NONE, AMF_SURFACE_UNKNOWN }, { AV_PIX_FMT_NV12, AMF_SURFACE_NV12 }, + { AV_PIX_FMT_P010, AMF_SURFACE_P010 }, { AV_PIX_FMT_BGR0, AMF_SURFACE_BGRA }, { AV_PIX_FMT_RGB0, AMF_SURFACE_RGBA }, { AV_PIX_FMT_GRAY8, AMF_SURFACE_GRAY8 }, @@ -785,6 +787,41 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) return ret; } +int ff_amf_get_color_profile(AVCodecContext *avctx) +{ + amf_int64 color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN; + if (avctx->color_range == AVCOL_RANGE_JPEG) { + /// Color Space for Full (JPEG) Range + switch (avctx->colorspace) { + case AVCOL_SPC_SMPTE170M: + color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_601; + break; + case AVCOL_SPC_BT709: + color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_709; + break; + case AVCOL_SPC_BT2020_NCL: + case AVCOL_SPC_BT2020_CL: + color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_2020; + break; + } + } else { + /// Color Space for Limited (MPEG) range + switch (avctx->colorspace) { + case AVCOL_SPC_SMPTE170M: + color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_601; + break; + case AVCOL_SPC_BT709: + color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_709; + break; + case AVCOL_SPC_BT2020_NCL: + case AVCOL_SPC_BT2020_CL: + color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_2020; + break; + } + } + return color_profile; +} + const AVCodecHWConfigInternal *const ff_amfenc_hw_configs[] = { #if CONFIG_D3D11VA HW_CONFIG_ENCODER_FRAMES(D3D11, D3D11VA), diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h index 2dbd378ef8..62736ef579 100644 --- a/libavcodec/amfenc.h +++ b/libavcodec/amfenc.h @@ -21,6 +21,7 @@ #include <AMF/core/Factory.h> +#include <AMF/components/ColorSpace.h> #include <AMF/components/VideoEncoderVCE.h> #include <AMF/components/VideoEncoderHEVC.h> #include <AMF/components/VideoEncoderAV1.h> @@ -170,6 +171,8 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt); */ extern const enum AVPixelFormat ff_amf_pix_fmts[]; +int ff_amf_get_color_profile(AVCodecContext *avctx); + /** * Error handling helper */ diff --git a/libavcodec/amfenc_h264.c b/libavcodec/amfenc_h264.c index 32baa8e91a..7caeca748d 100644 --- a/libavcodec/amfenc_h264.c +++ b/libavcodec/amfenc_h264.c @@ -200,6 +200,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_profile; + enum AVPixelFormat pix_fmt; if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { framerate = AMFConstructRate(avctx->framerate.num, avctx->framerate.den); @@ -270,10 +272,24 @@ FF_ENABLE_DEPRECATION_WARNINGS AMF_ASSIGN_PROPERTY_RATIO(res, ctx->encoder, AMF_VIDEO_ENCODER_ASPECT_RATIO, ratio); } - /// Color Range (Partial/TV/MPEG or Full/PC/JPEG) - if (avctx->color_range == AVCOL_RANGE_JPEG) { - AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_FULL_RANGE_COLOR, 1); - } + color_profile = ff_amf_get_color_profile(avctx); + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_OUTPUT_COLOR_PROFILE, color_profile); + + /// Color Range (Support for older Drivers) + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_FULL_RANGE_COLOR, !!(avctx->color_range == AVCOL_RANGE_JPEG)); + + /// Color Depth + pix_fmt = avctx->hw_frames_ctx ? ((AVHWFramesContext*)avctx->hw_frames_ctx->data)->sw_format + : avctx->pix_fmt; + + // 10 bit input video is not supported by AMF H264 encoder + 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 2915a83677..5422835100 100644 --- a/libavcodec/amfenc_hevc.c +++ b/libavcodec/amfenc_hevc.c @@ -35,8 +35,9 @@ static const AVOption options[] = { { "high_quality", "High quality usecase", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_HIGH_QUALITY }, 0, 0, VE, .unit = "usage" }, { "lowlatency_high_quality", "Low latency yet high quality usecase", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_LOW_LATENCY_HIGH_QUALITY }, 0, 0, VE, .unit = "usage" }, + { "profile", "Set the profile", OFFSET(profile), AV_OPT_TYPE_INT,{ .i64 = -1 }, -1, AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN_10, VE, .unit = "profile" }, { "main", "", 0, AV_OPT_TYPE_CONST,{ .i64 = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN }, 0, 0, VE, .unit = "profile" }, - { "profile", "Set the profile", OFFSET(profile), AV_OPT_TYPE_INT,{ .i64 = -1 }, -1, AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN, VE, .unit = "profile" }, + { "main10", "", 0, AV_OPT_TYPE_CONST,{ .i64 = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN_10 }, 0, 0, VE, .unit = "profile" }, { "profile_tier", "Set the profile tier (default main)", OFFSET(tier), AV_OPT_TYPE_INT,{ .i64 = -1 }, -1, AMF_VIDEO_ENCODER_HEVC_TIER_HIGH, VE, .unit = "tier" }, { "main", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_TIER_MAIN }, 0, 0, VE, .unit = "tier" }, @@ -163,6 +164,9 @@ static av_cold int amf_encode_init_hevc(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_depth; + amf_int64 color_profile; + enum AVPixelFormat pix_fmt; if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { framerate = AMFConstructRate(avctx->framerate.num, avctx->framerate.den); @@ -192,6 +196,9 @@ FF_ENABLE_DEPRECATION_WARNINGS case AV_PROFILE_HEVC_MAIN: profile = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN; break; + case AV_PROFILE_HEVC_MAIN_10: + profile = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN_10; + break; default: break; } @@ -232,6 +239,28 @@ FF_ENABLE_DEPRECATION_WARNINGS AMF_ASSIGN_PROPERTY_RATIO(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ASPECT_RATIO, ratio); } + color_profile = ff_amf_get_color_profile(avctx); + 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)); + /// Color Depth + color_depth = AMF_COLOR_BIT_DEPTH_8; + pix_fmt = avctx->hw_frames_ctx ? ((AVHWFramesContext*)avctx->hw_frames_ctx->data)->sw_format + : avctx->pix_fmt; + if (pix_fmt == AV_PIX_FMT_P010) { + 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); AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_GOP_SIZE, avctx->gop_size);
From: Michael Fabian 'Xaymar' Dirks <michael.dirks@xaymar.com> added 10 bit support for amf hevc. before: command - ffmpeg.exe -hide_banner -y -hwaccel d3d11va -hwaccel_output_format d3d11 -i test_10bit_file.mkv -an -c:v h264_amf res.dx11_hw_h264.mkv output - Format of input frames context (p010le) is not supported by AMF. command - ffmpeg.exe -hide_banner -y -hwaccel d3d11va -hwaccel_output_format d3d11 -i test_10bit_file -an -c:v hevc_amf res.dx11_hw_hevc.mkv output - Format of input frames context (p010le) is not supported by AMF. after: command - ffmpeg.exe -hide_banner -y -hwaccel d3d11va -hwaccel_output_format d3d11 -i test_10bit_file -an -c:v h264_amf res.dx11_hw_h264.mkv output - 10-bit input video is not supported by AMF H264 encoder command - ffmpeg.exe -hide_banner -y -hwaccel d3d11va -hwaccel_output_format d3d11 -i test_10bit_file -an -c:v hevc_amf res.dx11_hw_hevc.mkv output - 10bit file v2 - lost line returned in ff_amf_pix_fmts v3 - fixes after review v4 - extract duplicated code, fix incorrect processing of 10-bit input for h264 v5 - non-functional changes after review Co-authored-by: Evgeny Pavlov <lucenticus@gmail.com> Co-authored-by: Araz Iusubov <Primeadvice@gmail.com> --- libavcodec/amfenc.c | 37 +++++++++++++++++++++++++++++++++++++ libavcodec/amfenc.h | 3 +++ libavcodec/amfenc_h264.c | 24 ++++++++++++++++++++---- libavcodec/amfenc_hevc.c | 31 ++++++++++++++++++++++++++++++- 4 files changed, 90 insertions(+), 5 deletions(-)