avfilter/vf_vpp_amf: Extend AMF Color Converter HDR capabilities

This commit is contained in:
Dmitrii Gershenkop
2026-03-11 10:23:35 +01:00
parent e3ee346749
commit 910000fe59
15 changed files with 467 additions and 217 deletions

View File

@@ -33,6 +33,7 @@ version 8.1:
- ProRes Vulkan encoder
- LCEVC parser
- LCEVC enhancement layer exporting in MPEG-TS
- Extend AMF Color Converter (vf_vpp_amf) HDR capabilities
version 8.0:

View File

@@ -25648,6 +25648,35 @@ Work the same as the identical @ref{scale} filter options.
@item reset_sar
Works the same as the identical @ref{scale} filter option.
@item in_color_range
Override input color range.
@item out_color_range
Specify output color range.
The accepted values for in_trc and out_trc are:
@table @samp
@item studio
Studio (or restricted, or MPEG) color range.
@item full
Full (or JPEG) color range.
@end table
@item master_display
Set SMPTE2084 mastering display color volume info using libx265-style parameter
string, format is @code{G(%hu,%hu)B(%hu,%hu)R(%hu,%hu)WP(%hu,%hu)L(%u,%u)}.
Just like in libx265, %hu are unsigned 16bit integers and %u are unsigned
32bit integers. The SEI includes X,Y display primaries for RGB channels and
white point (WP) in units of 0.00002 and max,min luminance (L) values
in units of 0.0001 candela per meter square.
@item max_cll
Set SMPTE2084 Max CLL and Max FALL values using libx265-style parameter string:
@code{%hu,%hu}, where %hu are unsigned 16bit integers. The first value is the
max content light level, the second value is the maximum picture average light level.
@anchor{color_profile}
@item color_profile
Specify all color properties at once.
@@ -25665,10 +25694,13 @@ BT.2020
@end table
@item trc
@item in_trc
Override input transfer characteristics.
@item out_trc
Specify output transfer characteristics.
The accepted values are:
The accepted values for in_trc and out_trc are:
@table @samp
@item bt709
BT.709
@@ -25720,10 +25752,13 @@ ARIB_STD_B67
@end table
@item primaries
@item in_primaries
Override input color primaries.
@item out_primaries
Specify output color primaries.
The accepted values are:
The accepted values for in_primaries and out_primaries are:
@table @samp
@item bt709
BT.709
@@ -25775,6 +25810,21 @@ Upscale to 4K and change color profile to bt2020.
@example
vpp_amf=4096:2160:color_profile=bt2020
@end example
@item
Override display mastering, max CLL and max FALL metadata for filter input to represent those parameters:
Primary G: x=0.2650 y=0.6900
Primary B: x=0.1500 y=0.0600
Primary R: x=0.6800 y=0.3200
White point: x=0.3127 y=0.3290
Max. luminance: 1100.0000 cd/m²
Min. luminance: 0.0040 cd/m²
MaxCLL: 1100 cd/m²
MaxFALL: 400 cd/m²
@example
vpp_amf=color_profile=bt2020:in_trc=smpte2084:in_primaries=bt2020:master_display='G(13250,23460)B(7500,3000)R(34000,16000)WP(15635,16450)L(11000000,40)':max_cll='1100,400'
@end example
@end itemize
@anchor{vstack}

View File

@@ -21,8 +21,6 @@
#include "amfdec.h"
#include "codec_internal.h"
#include "hwconfig.h"
#include "libavutil/imgutils.h"
#include "libavutil/mem.h"
#include "libavutil/time.h"
#include "decode.h"
#include "decode_bsf.h"
@@ -125,31 +123,7 @@ static int amf_init_decoder(AVCodecContext *avctx)
} else if (avctx->color_range != AVCOL_RANGE_UNSPECIFIED) {
AMF_ASSIGN_PROPERTY_BOOL(res, ctx->decoder, AMF_VIDEO_DECODER_FULL_RANGE_COLOR, 0);
}
color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN;
switch (avctx->colorspace) {
case AVCOL_SPC_SMPTE170M:
if (avctx->color_range == AVCOL_RANGE_JPEG) {
color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_601;
} else {
color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_601;
}
break;
case AVCOL_SPC_BT709:
if (avctx->color_range == AVCOL_RANGE_JPEG) {
color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_709;
} else {
color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_709;
}
break;
case AVCOL_SPC_BT2020_NCL:
case AVCOL_SPC_BT2020_CL:
if (avctx->color_range == AVCOL_RANGE_JPEG) {
color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_2020;
} else {
color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_2020;
}
break;
}
color_profile = av_amf_get_color_profile(avctx->color_range, avctx->colorspace);
if (color_profile != AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN)
AMF_ASSIGN_PROPERTY_INT64(res, ctx->decoder, AMF_VIDEO_DECODER_COLOR_PROFILE, color_profile);
if (avctx->color_trc != AVCOL_TRC_UNSPECIFIED)
@@ -435,41 +409,10 @@ static int amf_amfsurface_to_avframe(AVCodecContext *avctx, AMFSurface* surface,
AMFHDRMetadata * hdrmeta = (AMFHDRMetadata*)hdrmeta_buffer->pVtbl->GetNative(hdrmeta_buffer);
if (ret != AMF_OK)
return ret;
if (hdrmeta != NULL) {
AVMasteringDisplayMetadata *mastering = av_mastering_display_metadata_create_side_data(frame);
const int chroma_den = 50000;
const int luma_den = 10000;
if (!mastering)
return AVERROR(ENOMEM);
mastering->display_primaries[0][0] = av_make_q(hdrmeta->redPrimary[0], chroma_den);
mastering->display_primaries[0][1] = av_make_q(hdrmeta->redPrimary[1], chroma_den);
mastering->display_primaries[1][0] = av_make_q(hdrmeta->greenPrimary[0], chroma_den);
mastering->display_primaries[1][1] = av_make_q(hdrmeta->greenPrimary[1], chroma_den);
mastering->display_primaries[2][0] = av_make_q(hdrmeta->bluePrimary[0], chroma_den);
mastering->display_primaries[2][1] = av_make_q(hdrmeta->bluePrimary[1], chroma_den);
mastering->white_point[0] = av_make_q(hdrmeta->whitePoint[0], chroma_den);
mastering->white_point[1] = av_make_q(hdrmeta->whitePoint[1], chroma_den);
mastering->max_luminance = av_make_q(hdrmeta->maxMasteringLuminance, luma_den);
mastering->min_luminance = av_make_q(hdrmeta->maxMasteringLuminance, luma_den);
mastering->has_luminance = 1;
mastering->has_primaries = 1;
if (hdrmeta->maxContentLightLevel) {
AVContentLightMetadata *light = av_content_light_metadata_create_side_data(frame);
if (!light)
return AVERROR(ENOMEM);
light->MaxCLL = hdrmeta->maxContentLightLevel;
light->MaxFALL = hdrmeta->maxFrameAverageLightLevel;
}
}
ret = av_amf_attach_hdr_metadata(frame, hdrmeta);
if (ret < 0)
return ret;
}
}
return 0;

View File

@@ -17,13 +17,11 @@
*/
#include "config.h"
#include "config_components.h"
#include "libavutil/avassert.h"
#include "libavutil/imgutils.h"
#include "libavutil/hwcontext.h"
#include "libavutil/hwcontext_amf.h"
#include "libavutil/hwcontext_amf_internal.h"
#if CONFIG_D3D11VA
#include "libavutil/hwcontext_d3d11va.h"
#endif
@@ -37,62 +35,10 @@
#include "amfenc.h"
#include "encode.h"
#include "internal.h"
#include "libavutil/mastering_display_metadata.h"
#define AMF_AV_FRAME_REF L"av_frame_ref"
#define PTS_PROP L"PtsProp"
static int amf_save_hdr_metadata(AVCodecContext *avctx, const AVFrame *frame, AMFHDRMetadata *hdrmeta)
{
AVFrameSideData *sd_display;
AVFrameSideData *sd_light;
AVMasteringDisplayMetadata *display_meta;
AVContentLightMetadata *light_meta;
sd_display = av_frame_get_side_data(frame, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA);
if (sd_display) {
display_meta = (AVMasteringDisplayMetadata *)sd_display->data;
if (display_meta->has_luminance) {
const unsigned int luma_den = 10000;
hdrmeta->maxMasteringLuminance =
(amf_uint32)(luma_den * av_q2d(display_meta->max_luminance));
hdrmeta->minMasteringLuminance =
FFMIN((amf_uint32)(luma_den * av_q2d(display_meta->min_luminance)), hdrmeta->maxMasteringLuminance);
}
if (display_meta->has_primaries) {
const unsigned int chroma_den = 50000;
hdrmeta->redPrimary[0] =
FFMIN((amf_uint16)(chroma_den * av_q2d(display_meta->display_primaries[0][0])), chroma_den);
hdrmeta->redPrimary[1] =
FFMIN((amf_uint16)(chroma_den * av_q2d(display_meta->display_primaries[0][1])), chroma_den);
hdrmeta->greenPrimary[0] =
FFMIN((amf_uint16)(chroma_den * av_q2d(display_meta->display_primaries[1][0])), chroma_den);
hdrmeta->greenPrimary[1] =
FFMIN((amf_uint16)(chroma_den * av_q2d(display_meta->display_primaries[1][1])), chroma_den);
hdrmeta->bluePrimary[0] =
FFMIN((amf_uint16)(chroma_den * av_q2d(display_meta->display_primaries[2][0])), chroma_den);
hdrmeta->bluePrimary[1] =
FFMIN((amf_uint16)(chroma_den * av_q2d(display_meta->display_primaries[2][1])), chroma_den);
hdrmeta->whitePoint[0] =
FFMIN((amf_uint16)(chroma_den * av_q2d(display_meta->white_point[0])), chroma_den);
hdrmeta->whitePoint[1] =
FFMIN((amf_uint16)(chroma_den * av_q2d(display_meta->white_point[1])), chroma_den);
}
sd_light = av_frame_get_side_data(frame, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL);
if (sd_light) {
light_meta = (AVContentLightMetadata *)sd_light->data;
if (light_meta) {
hdrmeta->maxContentLightLevel = (amf_uint16)light_meta->MaxCLL;
hdrmeta->maxFrameAverageLightLevel = (amf_uint16)light_meta->MaxFALL;
}
}
return 0;
}
return 1;
}
#if CONFIG_D3D11VA
#include <d3d11.h>
#endif
@@ -479,7 +425,7 @@ static int amf_submit_frame(AVCodecContext *avctx, AVFrame *frame, AMFSurface
res = amf_device_ctx->context->pVtbl->AllocBuffer(amf_device_ctx->context, AMF_MEMORY_HOST, sizeof(AMFHDRMetadata), &hdrmeta_buffer);
if (res == AMF_OK) {
AMFHDRMetadata * hdrmeta = (AMFHDRMetadata*)hdrmeta_buffer->pVtbl->GetNative(hdrmeta_buffer);
if (amf_save_hdr_metadata(avctx, frame, hdrmeta) == 0) {
if (av_amf_extract_hdr_metadata(frame, hdrmeta) == 0) {
switch (avctx->codec->id) {
case AV_CODEC_ID_H264:
AMF_ASSIGN_PROPERTY_INTERFACE(res, ctx->encoder, AMF_VIDEO_ENCODER_INPUT_HDR_METADATA, hdrmeta_buffer); break;
@@ -733,41 +679,6 @@ 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),

View File

@@ -163,8 +163,6 @@ 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
*/

View File

@@ -15,7 +15,7 @@
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/hwcontext_amf.h"
#include "libavutil/internal.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/mem.h"
@@ -258,7 +258,7 @@ static av_cold int amf_encode_init_av1(AVCodecContext* avctx)
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_COLOR_BIT_DEPTH, bit_depth);
// Color profile
color_profile = ff_amf_get_color_profile(avctx);
color_profile = av_amf_get_color_profile(avctx->color_range, avctx->colorspace);
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_OUTPUT_COLOR_PROFILE, color_profile);
// Color Range

View File

@@ -17,6 +17,7 @@
*/
#include "libavutil/hwcontext_amf.h"
#include "libavutil/internal.h"
#include "libavutil/mem.h"
#include "libavutil/opt.h"
@@ -270,7 +271,7 @@ static av_cold int amf_encode_init_h264(AVCodecContext *avctx)
AMF_ASSIGN_PROPERTY_RATIO(res, ctx->encoder, AMF_VIDEO_ENCODER_ASPECT_RATIO, ratio);
}
color_profile = ff_amf_get_color_profile(avctx);
color_profile = av_amf_get_color_profile(avctx->color_range, avctx->colorspace);
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_OUTPUT_COLOR_PROFILE, color_profile);
/// Color Range (Support for older Drivers)

View File

@@ -16,6 +16,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/hwcontext_amf.h"
#include "libavutil/internal.h"
#include "libavutil/mem.h"
#include "libavutil/opt.h"
@@ -252,7 +253,7 @@ static av_cold int amf_encode_init_hevc(AVCodecContext *avctx)
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_COLOR_BIT_DEPTH, bit_depth);
// Color profile
color_profile = ff_amf_get_color_profile(avctx);
color_profile = av_amf_get_color_profile(avctx->color_range, avctx->colorspace);
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_OUTPUT_COLOR_PROFILE, color_profile);
// Color Range (Support for older Drivers)

View File

@@ -32,7 +32,7 @@
#include "version_major.h"
#define LIBAVFILTER_VERSION_MINOR 15
#define LIBAVFILTER_VERSION_MICRO 100
#define LIBAVFILTER_VERSION_MICRO 101
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \

View File

@@ -25,9 +25,9 @@
#include "libavutil/mem.h"
#include "libavutil/imgutils.h"
#include "AMF/components/VideoDecoderUVD.h"
#include "libavutil/hwcontext_amf.h"
#include "libavutil/hwcontext_amf_internal.h"
#include "AMF/components/ColorSpace.h"
#include "scale_eval.h"
#if CONFIG_DXVA2
@@ -65,6 +65,12 @@ void amf_filter_uninit(AVFilterContext *avctx)
ctx->component = NULL;
}
if (ctx->master_display)
av_freep(&ctx->master_display);
if (ctx->light_meta)
av_freep(&ctx->light_meta);
av_buffer_unref(&ctx->amf_device_ref);
av_buffer_unref(&ctx->hwdevice_ref);
av_buffer_unref(&ctx->hwframes_in_ref);
@@ -137,19 +143,19 @@ int amf_filter_filter_frame(AVFilterLink *inlink, AVFrame *in)
}
out_color_range = AVCOL_RANGE_UNSPECIFIED;
if (ctx->color_range == AMF_COLOR_RANGE_FULL)
if (ctx->out_color_range == AMF_COLOR_RANGE_FULL)
out_color_range = AVCOL_RANGE_JPEG;
else if (ctx->color_range == AMF_COLOR_RANGE_STUDIO)
else if (ctx->out_color_range == AMF_COLOR_RANGE_STUDIO)
out_color_range = AVCOL_RANGE_MPEG;
if (ctx->color_range != AMF_COLOR_RANGE_UNDEFINED)
if (ctx->out_color_range != AMF_COLOR_RANGE_UNDEFINED)
out->color_range = out_color_range;
if (ctx->primaries != AMF_COLOR_PRIMARIES_UNDEFINED)
out->color_primaries = ctx->primaries;
if (ctx->out_primaries != AMF_COLOR_PRIMARIES_UNDEFINED)
out->color_primaries = ctx->out_primaries;
if (ctx->trc != AMF_COLOR_TRANSFER_CHARACTERISTIC_UNDEFINED)
out->color_trc = ctx->trc;
if (ctx->out_trc != AMF_COLOR_TRANSFER_CHARACTERISTIC_UNDEFINED)
out->color_trc = ctx->out_trc;
if (ret < 0)
@@ -444,6 +450,7 @@ AVFrame *amf_amfsurface_to_avframe(AVFilterContext *avctx, AMFSurface* pSurface)
int amf_avframe_to_amfsurface(AVFilterContext *avctx, const AVFrame *frame, AMFSurface** ppSurface)
{
AMFVariantStruct var = { 0 };
AMFFilterContext *ctx = avctx->priv;
AMFSurface *surface;
AMF_RESULT res;
@@ -493,6 +500,71 @@ int amf_avframe_to_amfsurface(AVFilterContext *avctx, const AVFrame *frame, AMFS
break;
}
// If AMFSurface comes from other AMF components, it may have various
// properties already set. These properties can be used by other AMF
// components to perform their tasks. In the context of the AMF video
// filter, that other component could be an AMFVideoConverter. By default,
// AMFVideoConverter will use HDR related properties assigned to a surface
// by an AMFDecoder. If frames (surfaces) originated from any other source,
// i.e. from hevcdec, assign those properties from avframe; do not
// overwrite these properties if they already have a value.
res = surface->pVtbl->GetProperty(surface, AMF_VIDEO_DECODER_COLOR_TRANSFER_CHARACTERISTIC, &var);
if (res == AMF_NOT_FOUND && frame->color_trc != AVCOL_TRC_UNSPECIFIED)
// Note: as of now(Feb 2026), most AV and AMF enums are interchangeable.
// TBD: can enums change their values in the future?
// For better future-proofing it's better to have dedicated
// enum mapping functions.
AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_DECODER_COLOR_TRANSFER_CHARACTERISTIC, frame->color_trc);
res = surface->pVtbl->GetProperty(surface, AMF_VIDEO_DECODER_COLOR_PRIMARIES, &var);
if (res == AMF_NOT_FOUND && frame->color_primaries != AVCOL_PRI_UNSPECIFIED)
AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_DECODER_COLOR_PRIMARIES, frame->color_primaries);
res = surface->pVtbl->GetProperty(surface, AMF_VIDEO_DECODER_COLOR_RANGE, &var);
if (res == AMF_NOT_FOUND && frame->color_range != AVCOL_RANGE_UNSPECIFIED)
AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_DECODER_COLOR_RANGE, frame->color_range);
// Color range for older drivers
if (frame->color_range == AVCOL_RANGE_JPEG) {
AMF_ASSIGN_PROPERTY_BOOL(res, surface, AMF_VIDEO_DECODER_FULL_RANGE_COLOR, 1);
} else if (frame->color_range != AVCOL_RANGE_UNSPECIFIED)
AMF_ASSIGN_PROPERTY_BOOL(res, surface, AMF_VIDEO_DECODER_FULL_RANGE_COLOR, 0);
// Color profile for newer drivers
res = surface->pVtbl->GetProperty(surface, AMF_VIDEO_DECODER_COLOR_PROFILE, &var);
if (res == AMF_NOT_FOUND && frame->color_range != AVCOL_RANGE_UNSPECIFIED && frame->colorspace != AVCOL_SPC_UNSPECIFIED) {
amf_int64 color_profile = color_profile = av_amf_get_color_profile(frame->color_range, frame->colorspace);
if (color_profile != AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN)
AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_DECODER_COLOR_PROFILE, color_profile);
}
if (ctx->in_trc == AMF_COLOR_TRANSFER_CHARACTERISTIC_SMPTE2084 && (ctx->master_display || ctx->light_meta)) {
AMFBuffer *hdrmeta_buffer = NULL;
res = ctx->amf_device_ctx->context->pVtbl->AllocBuffer(ctx->amf_device_ctx->context, AMF_MEMORY_HOST, sizeof(AMFHDRMetadata), &hdrmeta_buffer);
if (res == AMF_OK) {
AMFHDRMetadata *hdrmeta = (AMFHDRMetadata*)hdrmeta_buffer->pVtbl->GetNative(hdrmeta_buffer);
av_amf_display_mastering_meta_to_hdrmeta(ctx->master_display, hdrmeta);
av_amf_light_metadata_to_hdrmeta(ctx->light_meta, hdrmeta);
AMF_ASSIGN_PROPERTY_INTERFACE(res, surface, AMF_VIDEO_DECODER_HDR_METADATA, hdrmeta_buffer);
}
} else if (frame->color_trc == AVCOL_TRC_SMPTE2084) {
res = surface->pVtbl->GetProperty(surface, AMF_VIDEO_DECODER_HDR_METADATA, &var);
if (res == AMF_NOT_FOUND) {
AMFBuffer *hdrmeta_buffer = NULL;
res = ctx->amf_device_ctx->context->pVtbl->AllocBuffer(ctx->amf_device_ctx->context, AMF_MEMORY_HOST, sizeof(AMFHDRMetadata), &hdrmeta_buffer);
if (res == AMF_OK) {
AMFHDRMetadata *hdrmeta = (AMFHDRMetadata*)hdrmeta_buffer->pVtbl->GetNative(hdrmeta_buffer);
if (av_amf_extract_hdr_metadata(frame, hdrmeta) == 0)
AMF_ASSIGN_PROPERTY_INTERFACE(res, surface, AMF_VIDEO_DECODER_HDR_METADATA, hdrmeta_buffer);
hdrmeta_buffer->pVtbl->Release(hdrmeta_buffer);
}
}
}
if (frame->crop_left || frame->crop_right || frame->crop_top || frame->crop_bottom) {
size_t crop_x = frame->crop_left;
size_t crop_y = frame->crop_top;

View File

@@ -24,6 +24,7 @@
#include "AMF/core/Surface.h"
#include "AMF/components/Component.h"
#include "libavutil/hwcontext_amf.h"
#include "libavutil/mastering_display_metadata.h"
typedef struct AMFFilterContext {
const AVClass *class;
@@ -31,14 +32,22 @@ typedef struct AMFFilterContext {
int width, height;
enum AVPixelFormat format;
int scale_type;
int in_color_range;
int in_primaries;
int in_trc;
int color_profile;
int color_range;
int primaries;
int trc;
int out_color_range;
int out_primaries;
int out_trc;
int fill;
int fill_color;
int keep_ratio;
char *disp_master;
char *max_cll;
AVMasteringDisplayMetadata *master_display;
AVContentLightMetadata *light_meta;
// HQScaler properties
int algorithm;
float sharpness;

View File

@@ -117,10 +117,13 @@ static int amf_filter_config_output(AVFilterLink *outlink)
AMF_ASSIGN_PROPERTY_BOOL(res, ctx->component, AMF_HQ_SCALER_FILL, ctx->fill);
AMF_ASSIGN_PROPERTY_BOOL(res, ctx->component, AMF_HQ_SCALER_KEEP_ASPECT_RATIO, ctx->keep_ratio);
// Setup default options to skip color conversion
ctx->in_color_range = AMF_COLOR_RANGE_UNDEFINED;
ctx->in_primaries = AMF_COLOR_PRIMARIES_UNDEFINED;
ctx->in_trc = AMF_COLOR_TRANSFER_CHARACTERISTIC_UNDEFINED;
ctx->color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN;
ctx->color_range = AMF_COLOR_RANGE_UNDEFINED;
ctx->primaries = AMF_COLOR_PRIMARIES_UNDEFINED;
ctx->trc = AMF_COLOR_TRANSFER_CHARACTERISTIC_UNDEFINED;
ctx->out_color_range = AMF_COLOR_RANGE_UNDEFINED;
ctx->out_primaries = AMF_COLOR_PRIMARIES_UNDEFINED;
ctx->out_trc = AMF_COLOR_TRANSFER_CHARACTERISTIC_UNDEFINED;
res = ctx->component->pVtbl->Init(ctx->component, av_av_to_amf_format(in_format), inlink->w, inlink->h);
AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, "AMFHQScaler-Init() failed with error %d\n", res);

View File

@@ -21,14 +21,9 @@
* VPP video filter with AMF hardware acceleration
*/
#include <stdio.h>
#include <string.h>
#include "libavutil/avassert.h"
#include "libavutil/imgutils.h"
#include "libavutil/mem.h"
#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"
#include "libavutil/time.h"
#include "libavutil/internal.h"
#include "libavutil/hwcontext.h"
#include "libavutil/hwcontext_amf.h"
@@ -38,8 +33,6 @@
#include "vf_amf_common.h"
#include "avfilter.h"
#include "formats.h"
#include "video.h"
#include "scale_eval.h"
#include "avfilter_internal.h"
@@ -87,17 +80,24 @@ static int amf_filter_config_output(AVFilterLink *outlink)
{
AVFilterContext *avctx = outlink->src;
AVFilterLink *inlink = avctx->inputs[0];
AMFFilterContext *ctx = avctx->priv;
AVHWFramesContext *hwframes_out = NULL;
AMFFilterContext *ctx = avctx->priv;
AMFBuffer *hdrmeta_buffer = NULL;
AMFHDRMetadata *hdrmeta = NULL;
AMFSize out_size;
int err;
size_t size = 0;
int ret;
AMF_RESULT res;
enum AMF_VIDEO_CONVERTER_COLOR_PROFILE_ENUM amf_color_profile;
enum AVPixelFormat in_format;
const int chroma_den = 50000;
const int luma_den = 10000;
const int total_max_cll_args = 2;
const int total_disp_meta_args = 10;
err = amf_init_filter_config(outlink, &in_format);
if (err < 0)
return err;
ret = amf_init_filter_config(outlink, &in_format);
if (ret < 0)
return ret;
// FIXME: add checks whether we have HW context
hwframes_out = (AVHWFramesContext*)ctx->hwframes_out_ref->data;
res = ctx->amf_device_ctx->factory->pVtbl->CreateComponent(ctx->amf_device_ctx->factory, ctx->amf_device_ctx->context, AMFVideoConverter, &ctx->component);
@@ -118,21 +118,21 @@ static int amf_filter_config_output(AVFilterLink *outlink)
switch(ctx->color_profile) {
case AMF_VIDEO_CONVERTER_COLOR_PROFILE_601:
if (ctx->color_range == AMF_COLOR_RANGE_FULL) {
if (ctx->out_color_range == AMF_COLOR_RANGE_FULL) {
amf_color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_601;
} else {
amf_color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_601;
}
break;
case AMF_VIDEO_CONVERTER_COLOR_PROFILE_709:
if (ctx->color_range == AMF_COLOR_RANGE_FULL) {
if (ctx->out_color_range == AMF_COLOR_RANGE_FULL) {
amf_color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_709;
} else {
amf_color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_709;
}
break;
case AMF_VIDEO_CONVERTER_COLOR_PROFILE_2020:
if (ctx->color_range == AMF_COLOR_RANGE_FULL) {
if (ctx->out_color_range == AMF_COLOR_RANGE_FULL) {
amf_color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_2020;
} else {
amf_color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_2020;
@@ -143,20 +143,110 @@ static int amf_filter_config_output(AVFilterLink *outlink)
break;
}
if (ctx->in_color_range != AMF_COLOR_RANGE_UNDEFINED) {
AMF_ASSIGN_PROPERTY_INT64(res, ctx->component, AMF_VIDEO_CONVERTER_INPUT_COLOR_RANGE, ctx->in_color_range);
}
if (ctx->in_primaries != AMF_COLOR_PRIMARIES_UNDEFINED) {
AMF_ASSIGN_PROPERTY_INT64(res, ctx->component, AMF_VIDEO_CONVERTER_INPUT_COLOR_PRIMARIES, ctx->in_primaries);
}
if (ctx->in_trc != AMF_COLOR_TRANSFER_CHARACTERISTIC_UNDEFINED) {
AMF_ASSIGN_PROPERTY_INT64(res, ctx->component, AMF_VIDEO_CONVERTER_INPUT_TRANSFER_CHARACTERISTIC, ctx->in_trc);
}
if (ctx->disp_master) {
ctx->master_display = av_mastering_display_metadata_alloc();
if (!ctx->master_display)
return AVERROR(ENOMEM);
ret = sscanf_s(ctx->disp_master,
"G(%hu,%hu)B(%hu,%hu)R(%hu,%hu)WP(%hu,%hu)L(%u,%u)",
(uint16_t*)&ctx->master_display->display_primaries[1][0].num,
(uint16_t*)&ctx->master_display->display_primaries[1][1].num,
(uint16_t*)&ctx->master_display->display_primaries[2][0].num,
(uint16_t*)&ctx->master_display->display_primaries[2][1].num,
(uint16_t*)&ctx->master_display->display_primaries[0][0].num,
(uint16_t*)&ctx->master_display->display_primaries[0][1].num,
(uint16_t*)&ctx->master_display->white_point[0].num,
(uint16_t*)&ctx->master_display->white_point[1].num,
(unsigned*)&ctx->master_display->max_luminance.num,
(unsigned*)&ctx->master_display->min_luminance.num
);
if (ret != total_disp_meta_args) {
av_freep(&ctx->master_display);
av_log(avctx, AV_LOG_ERROR, "failed to parse mastering_display option\n");
return AVERROR(EINVAL);
}
ctx->master_display->display_primaries[1][0].den = chroma_den;
ctx->master_display->display_primaries[1][1].den = chroma_den;
ctx->master_display->display_primaries[2][0].den = chroma_den;
ctx->master_display->display_primaries[2][1].den = chroma_den;
ctx->master_display->display_primaries[0][0].den = chroma_den;
ctx->master_display->display_primaries[0][1].den = chroma_den;
ctx->master_display->white_point[0].den = chroma_den;
ctx->master_display->white_point[1].den = chroma_den;
ctx->master_display->max_luminance.den = luma_den;
ctx->master_display->min_luminance.den = luma_den;
ctx->master_display->has_primaries = 1;
ctx->master_display->has_luminance = 1;
}
if (ctx->max_cll) {
ctx->light_meta = av_content_light_metadata_alloc(&size);
if (!ctx->light_meta)
return AVERROR(ENOMEM);
ret = sscanf_s(ctx->max_cll,
"%hu,%hu",
(uint16_t*)&ctx->light_meta->MaxCLL,
(uint16_t*)&ctx->light_meta->MaxFALL
);
if (ret != total_max_cll_args) {
av_freep(ctx->light_meta);
ctx->light_meta = NULL;
av_log(avctx, AV_LOG_ERROR, "failed to parse max_cll option\n");
return AVERROR(EINVAL);
}
}
if (ctx->light_meta || ctx->master_display) {
if (ctx->in_trc == AVCOL_TRC_SMPTEST2084) {
res = ctx->amf_device_ctx->context->pVtbl->AllocBuffer(ctx->amf_device_ctx->context, AMF_MEMORY_HOST, sizeof(AMFHDRMetadata), &hdrmeta_buffer);
if (res == AMF_OK) {
hdrmeta = (AMFHDRMetadata*)hdrmeta_buffer->pVtbl->GetNative(hdrmeta_buffer);
av_amf_display_mastering_meta_to_hdrmeta(ctx->master_display, hdrmeta);
av_amf_light_metadata_to_hdrmeta(ctx->light_meta, hdrmeta);
AMF_ASSIGN_PROPERTY_INTERFACE(res, ctx->component, AMF_VIDEO_CONVERTER_INPUT_HDR_METADATA, hdrmeta_buffer);
hdrmeta_buffer->pVtbl->Release(hdrmeta_buffer);
}
} else {
av_log(avctx, AV_LOG_WARNING, "master_display/max_cll options are applicable only if in_trc is set to SMPTE2084\n");
}
}
if (amf_color_profile != AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN) {
AMF_ASSIGN_PROPERTY_INT64(res, ctx->component, AMF_VIDEO_CONVERTER_COLOR_PROFILE, amf_color_profile);
}
if (ctx->color_range != AMF_COLOR_RANGE_UNDEFINED) {
AMF_ASSIGN_PROPERTY_INT64(res, ctx->component, AMF_VIDEO_CONVERTER_OUTPUT_COLOR_RANGE, ctx->color_range);
if (ctx->out_color_range != AMF_COLOR_RANGE_UNDEFINED) {
AMF_ASSIGN_PROPERTY_INT64(res, ctx->component, AMF_VIDEO_CONVERTER_OUTPUT_COLOR_RANGE, ctx->out_color_range);
}
if (ctx->primaries != AMF_COLOR_PRIMARIES_UNDEFINED) {
AMF_ASSIGN_PROPERTY_INT64(res, ctx->component, AMF_VIDEO_CONVERTER_OUTPUT_COLOR_PRIMARIES, ctx->primaries);
if (ctx->out_primaries != AMF_COLOR_PRIMARIES_UNDEFINED) {
AMF_ASSIGN_PROPERTY_INT64(res, ctx->component, AMF_VIDEO_CONVERTER_OUTPUT_COLOR_PRIMARIES, ctx->out_primaries);
}
if (ctx->trc != AMF_COLOR_TRANSFER_CHARACTERISTIC_UNDEFINED) {
AMF_ASSIGN_PROPERTY_INT64(res, ctx->component, AMF_VIDEO_CONVERTER_OUTPUT_TRANSFER_CHARACTERISTIC, ctx->trc);
if (ctx->out_trc != AMF_COLOR_TRANSFER_CHARACTERISTIC_UNDEFINED) {
AMF_ASSIGN_PROPERTY_INT64(res, ctx->component, AMF_VIDEO_CONVERTER_OUTPUT_TRANSFER_CHARACTERISTIC, ctx->out_trc);
}
res = ctx->component->pVtbl->Init(ctx->component, av_av_to_amf_format(in_format), inlink->w, inlink->h);
@@ -181,11 +271,13 @@ static const AVOption vpp_amf_options[] = {
{ "bt709", "BT.709", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_CONVERTER_COLOR_PROFILE_709 }, 0, 0, FLAGS, "color_profile" },
{ "bt2020", "BT.2020", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_CONVERTER_COLOR_PROFILE_2020 }, 0, 0, FLAGS, "color_profile" },
{ "color_range", "Color range", OFFSET(color_range), AV_OPT_TYPE_INT, { .i64 = AMF_COLOR_RANGE_UNDEFINED }, AMF_COLOR_RANGE_UNDEFINED, AMF_COLOR_RANGE_FULL, FLAGS, "color_range" },
{ "in_color_range", "Input color range", OFFSET(in_color_range), AV_OPT_TYPE_INT, { .i64 = AMF_COLOR_RANGE_UNDEFINED }, AMF_COLOR_RANGE_UNDEFINED, AMF_COLOR_RANGE_FULL, FLAGS, "color_range" },
{ "out_color_range", "Output color range", OFFSET(out_color_range), AV_OPT_TYPE_INT, { .i64 = AMF_COLOR_RANGE_UNDEFINED }, AMF_COLOR_RANGE_UNDEFINED, AMF_COLOR_RANGE_FULL, FLAGS, "color_range" },
{ "studio", "Studio", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_COLOR_RANGE_STUDIO }, 0, 0, FLAGS, "color_range" },
{ "full", "Full", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_COLOR_RANGE_FULL }, 0, 0, FLAGS, "color_range" },
{ "primaries", "Output color primaries", OFFSET(primaries), AV_OPT_TYPE_INT, { .i64 = AMF_COLOR_PRIMARIES_UNDEFINED }, AMF_COLOR_PRIMARIES_UNDEFINED, AMF_COLOR_PRIMARIES_JEDEC_P22, FLAGS, "primaries" },
{ "in_primaries", "Input color primaries", OFFSET(in_primaries), AV_OPT_TYPE_INT, { .i64 = AMF_COLOR_PRIMARIES_UNDEFINED }, AMF_COLOR_PRIMARIES_UNDEFINED, AMF_COLOR_PRIMARIES_JEDEC_P22, FLAGS, "primaries" },
{ "out_primaries", "Output color primaries", OFFSET(out_primaries), AV_OPT_TYPE_INT, { .i64 = AMF_COLOR_PRIMARIES_UNDEFINED }, AMF_COLOR_PRIMARIES_UNDEFINED, AMF_COLOR_PRIMARIES_JEDEC_P22, FLAGS, "primaries" },
{ "bt709", "BT.709", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_COLOR_PRIMARIES_BT709 }, 0, 0, FLAGS, "primaries" },
{ "bt470m", "BT.470M", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_COLOR_PRIMARIES_BT470M }, 0, 0, FLAGS, "primaries" },
{ "bt470bg", "BT.470BG", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_COLOR_PRIMARIES_BT470BG }, 0, 0, FLAGS, "primaries" },
@@ -198,7 +290,8 @@ static const AVOption vpp_amf_options[] = {
{ "smpte432", "SMPTE432", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_COLOR_PRIMARIES_SMPTE432 }, 0, 0, FLAGS, "primaries" },
{ "jedec-p22", "JEDEC_P22", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_COLOR_PRIMARIES_JEDEC_P22 }, 0, 0, FLAGS, "primaries" },
{ "trc", "Output transfer characteristics", OFFSET(trc), AV_OPT_TYPE_INT, { .i64 = AMF_COLOR_TRANSFER_CHARACTERISTIC_UNDEFINED }, AMF_COLOR_TRANSFER_CHARACTERISTIC_UNDEFINED, AMF_COLOR_TRANSFER_CHARACTERISTIC_ARIB_STD_B67, FLAGS, "trc" },
{ "in_trc", "Input transfer characteristics", OFFSET(in_trc), AV_OPT_TYPE_INT, { .i64 = AMF_COLOR_TRANSFER_CHARACTERISTIC_UNDEFINED }, AMF_COLOR_TRANSFER_CHARACTERISTIC_UNDEFINED, AMF_COLOR_TRANSFER_CHARACTERISTIC_ARIB_STD_B67, FLAGS, "trc" },
{ "out_trc", "Output transfer characteristics", OFFSET(out_trc), AV_OPT_TYPE_INT, { .i64 = AMF_COLOR_TRANSFER_CHARACTERISTIC_UNDEFINED }, AMF_COLOR_TRANSFER_CHARACTERISTIC_UNDEFINED, AMF_COLOR_TRANSFER_CHARACTERISTIC_ARIB_STD_B67, FLAGS, "trc" },
{ "bt709", "BT.709", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_COLOR_TRANSFER_CHARACTERISTIC_BT709 }, 0, 0, FLAGS, "trc" },
{ "gamma22", "GAMMA22", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_COLOR_TRANSFER_CHARACTERISTIC_GAMMA22 }, 0, 0, FLAGS, "trc" },
{ "gamma28", "GAMMA28", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_COLOR_TRANSFER_CHARACTERISTIC_GAMMA28 }, 0, 0, FLAGS, "trc" },
@@ -223,6 +316,13 @@ static const AVOption vpp_amf_options[] = {
{ "force_divisible_by", "enforce that the output resolution is divisible by a defined integer when force_original_aspect_ratio is used", OFFSET(force_divisible_by), AV_OPT_TYPE_INT, { .i64 = 1}, 1, 256, FLAGS },
{ "reset_sar", "reset SAR to 1 and scale to square pixels if scaling proportionally", OFFSET(reset_sar), AV_OPT_TYPE_BOOL, { .i64 = 0}, 0, 1, FLAGS },
{ "master_display",
"set SMPTE2084 mastering display color volume info using libx265-style parameter string (G(%hu,%hu)B(%hu,%hu)R(%hu,%hu)WP(%hu,%hu)L(%u,%u)).",
OFFSET(disp_master), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS
},
{ "max_cll", "set SMPTE2084 Max CLL and Max FALL values using libx265-style parameter string (%hu,%hu)", OFFSET(max_cll), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS },
{ NULL },
};

View File

@@ -16,12 +16,22 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "mem.h"
#include "buffer.h"
#include "common.h"
#include "pixfmt.h"
#include "pixdesc.h"
#include "imgutils.h"
#include "hwcontext.h"
#include "hwcontext_amf.h"
#include "hwcontext_internal.h"
#include "hwcontext_amf_internal.h"
#include "libavutil/thread.h"
#include "libavutil/avassert.h"
#include <AMF/core/Surface.h>
#include <AMF/core/Trace.h>
#if CONFIG_VULKAN
#include "hwcontext_vulkan.h"
#endif
@@ -35,14 +45,6 @@
#define COBJMACROS
#include "libavutil/hwcontext_dxva2.h"
#endif
#include "mem.h"
#include "pixdesc.h"
#include "pixfmt.h"
#include "imgutils.h"
#include "thread.h"
#include "libavutil/avassert.h"
#include <AMF/core/Surface.h>
#include <AMF/core/Trace.h>
#ifdef _WIN32
#include "compat/w32dlfcn.h"
#else
@@ -150,6 +152,157 @@ enum AVPixelFormat av_amf_to_av_format(enum AMF_SURFACE_FORMAT fmt)
return AV_PIX_FMT_NONE;
}
enum AMF_VIDEO_CONVERTER_COLOR_PROFILE_ENUM av_amf_get_color_profile(enum AVColorRange color_range, enum AVColorSpace color_space)
{
switch (color_space) {
case AVCOL_SPC_SMPTE170M:
if (color_range == AVCOL_RANGE_JPEG) {
return AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_601;
} else {
return AMF_VIDEO_CONVERTER_COLOR_PROFILE_601;
}
break;
case AVCOL_SPC_BT709:
if (color_range == AVCOL_RANGE_JPEG) {
return AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_709;
} else {
return AMF_VIDEO_CONVERTER_COLOR_PROFILE_709;
}
break;
case AVCOL_SPC_BT2020_NCL:
case AVCOL_SPC_BT2020_CL:
if (color_range == AVCOL_RANGE_JPEG) {
return AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_2020;
} else {
return AMF_VIDEO_CONVERTER_COLOR_PROFILE_2020;
}
break;
default:
return AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN;
}
}
int av_amf_display_mastering_meta_to_hdrmeta(const AVMasteringDisplayMetadata *display_meta, AMFHDRMetadata *hdrmeta)
{
if (!display_meta || !hdrmeta)
return AVERROR(EINVAL);
if (display_meta->has_luminance) {
const unsigned int luma_den = 10000;
hdrmeta->maxMasteringLuminance =
(amf_uint32)(luma_den * av_q2d(display_meta->max_luminance));
hdrmeta->minMasteringLuminance =
FFMIN((amf_uint32)(luma_den * av_q2d(display_meta->min_luminance)), hdrmeta->maxMasteringLuminance);
}
if (display_meta->has_primaries) {
const unsigned int chroma_den = 50000;
hdrmeta->redPrimary[0] =
FFMIN((amf_uint16)(chroma_den * av_q2d(display_meta->display_primaries[0][0])), chroma_den);
hdrmeta->redPrimary[1] =
FFMIN((amf_uint16)(chroma_den * av_q2d(display_meta->display_primaries[0][1])), chroma_den);
hdrmeta->greenPrimary[0] =
FFMIN((amf_uint16)(chroma_den * av_q2d(display_meta->display_primaries[1][0])), chroma_den);
hdrmeta->greenPrimary[1] =
FFMIN((amf_uint16)(chroma_den * av_q2d(display_meta->display_primaries[1][1])), chroma_den);
hdrmeta->bluePrimary[0] =
FFMIN((amf_uint16)(chroma_den * av_q2d(display_meta->display_primaries[2][0])), chroma_den);
hdrmeta->bluePrimary[1] =
FFMIN((amf_uint16)(chroma_den * av_q2d(display_meta->display_primaries[2][1])), chroma_den);
hdrmeta->whitePoint[0] =
FFMIN((amf_uint16)(chroma_den * av_q2d(display_meta->white_point[0])), chroma_den);
hdrmeta->whitePoint[1] =
FFMIN((amf_uint16)(chroma_den * av_q2d(display_meta->white_point[1])), chroma_den);
}
return 0;
}
int av_amf_light_metadata_to_hdrmeta(const AVContentLightMetadata *light_meta, AMFHDRMetadata *hdrmeta)
{
if (!light_meta || !hdrmeta)
return AVERROR(EINVAL);
hdrmeta->maxContentLightLevel = (amf_uint16)light_meta->MaxCLL;
hdrmeta->maxFrameAverageLightLevel = (amf_uint16)light_meta->MaxFALL;
return 0;
}
int av_amf_extract_hdr_metadata(const AVFrame *frame, AMFHDRMetadata *hdrmeta)
{
AVFrameSideData *sidedata;
if (!frame || !hdrmeta)
return AVERROR(EINVAL);
sidedata = av_frame_get_side_data(frame, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA);
if (!sidedata)
return AVERROR(ENODATA);
if (av_amf_display_mastering_meta_to_hdrmeta((AVMasteringDisplayMetadata *)sidedata->data, hdrmeta) != 0)
return AVERROR(ENODATA);
sidedata = av_frame_get_side_data(frame, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL);
if (sidedata)
av_amf_light_metadata_to_hdrmeta((AVContentLightMetadata *)sidedata->data, hdrmeta);
return 0;
}
int av_amf_attach_hdr_metadata(AVFrame *frame, const AMFHDRMetadata *hdrmeta) {
if (!hdrmeta || !frame)
return AVERROR(EINVAL);
AVMasteringDisplayMetadata *mastering =
av_mastering_display_metadata_create_side_data(frame);
const int chroma_den = 50000;
const int luma_den = 10000;
if (!mastering)
return AVERROR(ENOMEM);
mastering->display_primaries[0][0] =
av_make_q(hdrmeta->redPrimary[0], chroma_den);
mastering->display_primaries[0][1] =
av_make_q(hdrmeta->redPrimary[1], chroma_den);
mastering->display_primaries[1][0] =
av_make_q(hdrmeta->greenPrimary[0], chroma_den);
mastering->display_primaries[1][1] =
av_make_q(hdrmeta->greenPrimary[1], chroma_den);
mastering->display_primaries[2][0] =
av_make_q(hdrmeta->bluePrimary[0], chroma_den);
mastering->display_primaries[2][1] =
av_make_q(hdrmeta->bluePrimary[1], chroma_den);
mastering->white_point[0] = av_make_q(hdrmeta->whitePoint[0], chroma_den);
mastering->white_point[1] = av_make_q(hdrmeta->whitePoint[1], chroma_den);
mastering->max_luminance =
av_make_q(hdrmeta->maxMasteringLuminance, luma_den);
mastering->min_luminance =
av_make_q(hdrmeta->maxMasteringLuminance, luma_den);
mastering->has_luminance = 1;
mastering->has_primaries = 1;
if (hdrmeta->maxContentLightLevel) {
AVContentLightMetadata *light =
av_content_light_metadata_create_side_data(frame);
if (!light)
return AVERROR(ENOMEM);
light->MaxCLL = hdrmeta->maxContentLightLevel;
light->MaxFALL = hdrmeta->maxFrameAverageLightLevel;
}
return 0;
}
static const enum AVPixelFormat supported_formats[] = {
AV_PIX_FMT_NV12,
AV_PIX_FMT_YUV420P,
@@ -462,7 +615,7 @@ static int amf_load_library(AVAMFDeviceContext* amf_ctx, void* avcl)
version_fun = (AMFQueryVersion_Fn)dlsym(amf_ctx->library, AMF_QUERY_VERSION_FUNCTION_NAME);
AMF_RETURN_IF_FALSE(avcl, version_fun != NULL, AVERROR_UNKNOWN, "DLL %s failed to find function %s\n", AMF_DLL_NAMEA, AMF_QUERY_VERSION_FUNCTION_NAME);
res = version_fun(&amf_ctx->version);
res = version_fun((unsigned long long*)&amf_ctx->version);
AMF_RETURN_IF_FALSE(avcl, res == AMF_OK, AVERROR_UNKNOWN, "%s failed with error %d\n", AMF_QUERY_VERSION_FUNCTION_NAME, res);
res = init_fun(AMF_FULL_VERSION, &amf_ctx->factory);
AMF_RETURN_IF_FALSE(avcl, res == AMF_OK, AVERROR_UNKNOWN, "%s failed with error %d\n", AMF_INIT_FUNCTION_NAME, res);

View File

@@ -26,6 +26,8 @@
#include <AMF/core/Context.h>
#include <AMF/core/Trace.h>
#include <AMF/core/Debug.h>
#include <AMF/components/ColorSpace.h>
#include "libavutil/mastering_display_metadata.h"
/**
* This struct is allocated as AVHWDeviceContext.hwctx
@@ -47,4 +49,10 @@ typedef struct AVAMFDeviceContext {
enum AMF_SURFACE_FORMAT av_av_to_amf_format(enum AVPixelFormat fmt);
enum AVPixelFormat av_amf_to_av_format(enum AMF_SURFACE_FORMAT fmt);
enum AMF_VIDEO_CONVERTER_COLOR_PROFILE_ENUM av_amf_get_color_profile(enum AVColorRange color_range, enum AVColorSpace color_space);
int av_amf_display_mastering_meta_to_hdrmeta(const AVMasteringDisplayMetadata *display_meta, AMFHDRMetadata *hdrmeta);
int av_amf_light_metadata_to_hdrmeta(const AVContentLightMetadata *light_meta, AMFHDRMetadata *hdrmeta);
int av_amf_extract_hdr_metadata(const AVFrame *frame, AMFHDRMetadata *hdrmeta);
int av_amf_attach_hdr_metadata(AVFrame *frame, const AMFHDRMetadata *hdrmeta);
#endif /* AVUTIL_HWCONTEXT_AMF_H */