mirror of
https://mirror.skon.top/https://github.com/FFmpeg/FFmpeg
synced 2026-04-20 21:00:41 +08:00
avfilter/vf_vpp_amf: Extend AMF Color Converter HDR capabilities
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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, \
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 },
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user