amfcodec: Initial support of Smart Access Video

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3904>
This commit is contained in:
Evgeny Pavlov 2023-01-12 17:49:14 +01:00 committed by GStreamer Marge Bot
parent 38c3de565b
commit 351b72a59a
3 changed files with 135 additions and 0 deletions

View file

@ -73,6 +73,7 @@ typedef struct
amf_int64 max_gop_size;
amf_int64 default_gop_size;
guint valign;
gboolean smart_access_supported;
} GstAmfAv1EncDeviceCaps;
/**
@ -264,6 +265,7 @@ enum
PROP_QP_I,
PROP_QP_P,
PROP_REF_FRAMES,
PROP_SMART_ACCESS
};
#define DEFAULT_USAGE AMF_VIDEO_ENCODER_AV1_USAGE_TRANSCODING
@ -273,6 +275,7 @@ enum
#define DEFAULT_MAX_BITRATE 0
#define DEFAULT_MIN_MAX_QP -1
#define DEFAULT_REF_FRAMES 1
#define DEFAULT_SMART_ACCESS FALSE
#define DOC_SINK_CAPS_COMM \
"format = (string) {NV12, P010_10LE}, " \
@ -305,6 +308,7 @@ typedef struct _GstAmfAv1Enc
guint qp_i;
guint qp_p;
guint ref_frames;
gboolean smart_access;
} GstAmfAv1Enc;
typedef struct _GstAmfAv1EncClass
@ -410,6 +414,16 @@ gst_amf_av1_enc_class_init (GstAmfAv1EncClass * klass, gpointer data)
g_param_spec_uint ("ref-frames", "Reference Frames",
"Number of reference frames", 0, 8, DEFAULT_REF_FRAMES, param_flags));
if (cdata->dev_caps.smart_access_supported) {
g_object_class_install_property (object_class, PROP_SMART_ACCESS,
g_param_spec_boolean ("smart-access-video", "Smart Access Video",
"Enable AMF SmartAccess Video feature for optimal distribution"
" between multiple AMD hardware instances", DEFAULT_SMART_ACCESS,
(GParamFlags) (G_PARAM_READWRITE |
GST_PARAM_CONDITIONALLY_AVAILABLE |
GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS)));
}
gst_element_class_set_metadata (element_class,
"AMD AMF AV1 Video Encoder",
"Codec/Encoder/Video/Hardware",
@ -480,6 +494,7 @@ gst_amf_av1_enc_init (GstAmfAv1Enc * self)
self->qp_i = (guint) dev_caps->default_qp_i;
self->qp_p = (guint) dev_caps->default_qp_p;
self->ref_frames = DEFAULT_REF_FRAMES;
self->smart_access = DEFAULT_SMART_ACCESS;
}
static void
@ -528,6 +543,18 @@ update_enum (GstAmfAv1Enc * self, gint * old_val, const GValue * new_val)
self->property_updated = TRUE;
}
static void
update_bool (GstAmfAv1Enc * self, gboolean * old_val, const GValue * new_val)
{
gboolean val = g_value_get_boolean (new_val);
if (*old_val == val)
return;
*old_val = val;
self->property_updated = TRUE;
}
static void
gst_amf_av1_enc_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
@ -575,6 +602,9 @@ gst_amf_av1_enc_set_property (GObject * object, guint prop_id,
case PROP_REF_FRAMES:
update_uint (self, &self->ref_frames, value);
break;
case PROP_SMART_ACCESS:
update_bool (self, &self->smart_access, value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -632,6 +662,9 @@ gst_amf_av1_enc_get_property (GObject * object, guint prop_id,
case PROP_REF_FRAMES:
g_value_set_uint (value, self->ref_frames);
break;
case PROP_SMART_ACCESS:
g_value_set_boolean (value, self->smart_access);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -643,6 +676,8 @@ gst_amf_av1_enc_set_format (GstAmfEncoder * encoder,
GstVideoCodecState * state, gpointer component)
{
GstAmfAv1Enc *self = GST_AMF_AV1_ENC (encoder);
GstAmfAv1EncClass *klass = GST_AMF_AV1_ENC_GET_CLASS (self);
GstAmfAv1EncDeviceCaps *dev_caps = &klass->dev_caps;
AMFComponent *comp = (AMFComponent *) component;
GstVideoInfo *info = &state->info;
AMF_RESULT result;
@ -726,6 +761,14 @@ gst_amf_av1_enc_set_format (GstAmfEncoder * encoder,
goto error;
}
if (dev_caps->smart_access_supported) {
result = comp->SetProperty (AMF_VIDEO_ENCODER_AV1_ENABLE_SMART_ACCESS_VIDEO,
(amf_bool) self->smart_access);
if (result != AMF_OK) {
GST_WARNING_OBJECT (self, "Failed to set smart access video, result %"
GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
}
}
color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN;
switch (cinfo->matrix) {
case GST_VIDEO_COLOR_MATRIX_BT601:
@ -1050,6 +1093,7 @@ gst_amf_av1_enc_create_class_data (GstD3D11Device * device, AMFComponent * comp)
amf_int32 in_min_height = 0, in_max_height = 0;
amf_int32 out_min_width = 0, out_max_width = 0;
amf_int32 out_min_height = 0, out_max_height = 0;
amf_bool smart_access_supported;
amf_int32 num_val;
std::set < std::string > formats;
std::string format_str;
@ -1203,6 +1247,11 @@ gst_amf_av1_enc_create_class_data (GstD3D11Device * device, AMFComponent * comp)
QUERY_DEFAULT_PROP (AMF_VIDEO_ENCODER_AV1_Q_INDEX_INTER, default_qp_p, 26);
#undef QUERY_DEFAULT_PROP
result = comp->GetProperty (AMF_VIDEO_ENCODER_AV1_ENABLE_SMART_ACCESS_VIDEO,
&smart_access_supported);
if (result == AMF_OK)
dev_caps.smart_access_supported = TRUE;
{
const AMFPropertyInfo *pinfo = nullptr;
result = comp->GetPropertyInfo (AMF_VIDEO_ENCODER_AV1_GOP_SIZE, &pinfo);

View file

@ -77,6 +77,7 @@ typedef struct
amf_int64 default_qp_b;
gboolean interlace_supported;
guint valign;
gboolean smart_access_supported;
} GstAmfH264EncDeviceCaps;
/**
@ -273,6 +274,7 @@ enum
PROP_REF_FRAMES,
PROP_AUD,
PROP_CABAC,
PROP_SMART_ACCESS
};
#define DEFAULT_USAGE AMF_VIDEO_ENCODER_USAGE_TRANSCODING
@ -284,6 +286,7 @@ enum
#define DEFAULT_MIN_MAX_QP -1
#define DEFAULT_AUD TRUE
#define DEFAULT_CABAC TRUE
#define DEFAULT_SMART_ACCESS FALSE
#define DOC_SINK_CAPS_COMM \
"format = (string) NV12, " \
@ -322,6 +325,7 @@ typedef struct _GstAmfH264Enc
gboolean aud;
gboolean cabac;
gboolean smart_access;
} GstAmfH264Enc;
typedef struct _GstAmfH264EncClass
@ -429,6 +433,16 @@ gst_amf_h264_enc_class_init (GstAmfH264EncClass * klass, gpointer data)
g_param_spec_boolean ("cabac", "CABAC",
"Enable CABAC entropy coding", TRUE, param_flags));
if (cdata->dev_caps.smart_access_supported) {
g_object_class_install_property (object_class, PROP_SMART_ACCESS,
g_param_spec_boolean ("smart-access-video", "Smart Access Video",
"Enable AMF SmartAccess Video feature for optimal distribution"
" between multiple AMD hardware instances", DEFAULT_SMART_ACCESS,
(GParamFlags) (G_PARAM_READWRITE |
GST_PARAM_CONDITIONALLY_AVAILABLE |
GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS)));
}
gst_element_class_set_metadata (element_class,
"AMD AMF H.264 Video Encoder",
"Codec/Encoder/Video/Hardware",
@ -502,6 +516,7 @@ gst_amf_h264_enc_init (GstAmfH264Enc * self)
self->ref_frames = (guint) dev_caps->min_ref_frames;
self->aud = DEFAULT_AUD;
self->cabac = DEFAULT_CABAC;
self->smart_access = DEFAULT_SMART_ACCESS;
}
static void
@ -611,6 +626,9 @@ gst_amf_h264_enc_set_property (GObject * object, guint prop_id,
case PROP_CABAC:
update_bool (self, &self->cabac, value);
break;
case PROP_SMART_ACCESS:
update_bool (self, &self->smart_access, value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -668,6 +686,9 @@ gst_amf_h264_enc_get_property (GObject * object, guint prop_id,
case PROP_CABAC:
g_value_set_boolean (value, self->cabac);
break;
case PROP_SMART_ACCESS:
g_value_set_boolean (value, self->smart_access);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -927,6 +948,15 @@ gst_amf_h264_enc_set_format (GstAmfEncoder * encoder,
}
}
if (dev_caps->smart_access_supported) {
result = comp->SetProperty (AMF_VIDEO_ENCODER_ENABLE_SMART_ACCESS_VIDEO,
(amf_bool) self->smart_access);
if (result != AMF_OK) {
GST_WARNING_OBJECT (self, "Failed to set smart access video, result %"
GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
}
}
result = comp->Init (AMF_SURFACE_NV12, info->width, info->height);
if (result != AMF_OK) {
GST_ERROR_OBJECT (self, "Failed to init component, result %"
@ -1330,6 +1360,7 @@ gst_amf_h264_enc_create_class_data (GstD3D11Device * device,
amf_int32 out_min_width = 0, out_max_width = 0;
amf_int32 out_min_height = 0, out_max_height = 0;
amf_bool interlace_supported;
amf_bool smart_access_supported;
amf_int32 num_val;
gboolean have_nv12 = FALSE;
gboolean d3d11_supported = FALSE;
@ -1461,6 +1492,11 @@ gst_amf_h264_enc_create_class_data (GstD3D11Device * device,
QUERY_DEFAULT_PROP (AMF_VIDEO_ENCODER_QP_I, default_qp_b, 22);
#undef QUERY_DEFAULT_PROP
result = comp->GetProperty (AMF_VIDEO_ENCODER_ENABLE_SMART_ACCESS_VIDEO,
&smart_access_supported);
if (result == AMF_OK)
dev_caps.smart_access_supported = TRUE;
min_width = MAX (in_min_width, 1);
max_width = in_max_width;
if (max_width == 0) {

View file

@ -75,6 +75,7 @@ typedef struct
amf_int64 max_gop_size;
amf_int64 default_gop_size;
guint valign;
gboolean smart_access_supported;
} GstAmfH265EncDeviceCaps;
/**
@ -273,6 +274,7 @@ enum
PROP_QP_P,
PROP_REF_FRAMES,
PROP_AUD,
PROP_SMART_ACCESS
};
#define DEFAULT_USAGE AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCODING
@ -282,6 +284,7 @@ enum
#define DEFAULT_MAX_BITRATE 0
#define DEFAULT_MIN_MAX_QP -1
#define DEFAULT_AUD TRUE
#define DEFAULT_SMART_ACCESS FALSE
#define DOC_SINK_CAPS_COMM \
"format = (string) {NV12, P010_10LE}, " \
@ -318,6 +321,7 @@ typedef struct _GstAmfH265Enc
guint ref_frames;
gboolean aud;
gboolean smart_access;
} GstAmfH265Enc;
typedef struct _GstAmfH265EncClass
@ -431,6 +435,16 @@ gst_amf_h265_enc_class_init (GstAmfH265EncClass * klass, gpointer data)
g_param_spec_boolean ("aud", "AUD",
"Use AU (Access Unit) delimiter", DEFAULT_AUD, param_flags));
if (cdata->dev_caps.smart_access_supported) {
g_object_class_install_property (object_class, PROP_SMART_ACCESS,
g_param_spec_boolean ("smart-access-video", "Smart Access Video",
"Enable AMF SmartAccess Video feature for optimal distribution"
" between multiple AMD hardware instances", DEFAULT_SMART_ACCESS,
(GParamFlags) (G_PARAM_READWRITE |
GST_PARAM_CONDITIONALLY_AVAILABLE |
GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS)));
}
gst_element_class_set_metadata (element_class,
"AMD AMF H.265 Video Encoder",
"Codec/Encoder/Video/Hardware",
@ -503,6 +517,7 @@ gst_amf_h265_enc_init (GstAmfH265Enc * self)
self->qp_p = (guint) dev_caps->default_qp_p;
self->ref_frames = (guint) dev_caps->min_ref_frames;
self->aud = DEFAULT_AUD;
self->smart_access = DEFAULT_SMART_ACCESS;
}
static void
@ -551,6 +566,18 @@ update_enum (GstAmfH265Enc * self, gint * old_val, const GValue * new_val)
self->property_updated = TRUE;
}
static void
update_bool (GstAmfH265Enc * self, gboolean * old_val, const GValue * new_val)
{
gboolean val = g_value_get_boolean (new_val);
if (*old_val == val)
return;
*old_val = val;
self->property_updated = TRUE;
}
static void
gst_amf_h265_enc_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
@ -602,6 +629,9 @@ gst_amf_h265_enc_set_property (GObject * object, guint prop_id,
/* This is per frame property, don't need to reset encoder */
self->aud = g_value_get_boolean (value);
break;
case PROP_SMART_ACCESS:
update_bool (self, &self->smart_access, value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -662,6 +692,9 @@ gst_amf_h265_enc_get_property (GObject * object, guint prop_id,
case PROP_AUD:
g_value_set_boolean (value, self->aud);
break;
case PROP_SMART_ACCESS:
g_value_set_boolean (value, self->smart_access);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -773,6 +806,8 @@ gst_amf_h265_enc_set_format (GstAmfEncoder * encoder,
GstVideoCodecState * state, gpointer component)
{
GstAmfH265Enc *self = GST_AMF_H265_ENC (encoder);
GstAmfH265EncClass *klass = GST_AMF_H265_ENC_GET_CLASS (self);
GstAmfH265EncDeviceCaps *dev_caps = &klass->dev_caps;
AMFComponent *comp = (AMFComponent *) component;
GstVideoInfo *info = &state->info;
const GstVideoColorimetry *cinfo = &info->colorimetry;
@ -893,6 +928,15 @@ gst_amf_h265_enc_set_format (GstAmfEncoder * encoder,
goto error;
}
if (dev_caps->smart_access_supported) {
result =
comp->SetProperty (AMF_VIDEO_ENCODER_HEVC_ENABLE_SMART_ACCESS_VIDEO,
(amf_bool) self->smart_access);
if (result != AMF_OK) {
GST_WARNING_OBJECT (self, "Failed to set smart access video, result %"
GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
}
}
color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN;
switch (cinfo->matrix) {
case GST_VIDEO_COLOR_MATRIX_BT601:
@ -1233,6 +1277,7 @@ gst_amf_h265_enc_create_class_data (GstD3D11Device * device,
amf_int32 in_min_height = 0, in_max_height = 0;
amf_int32 out_min_width = 0, out_max_width = 0;
amf_int32 out_min_height = 0, out_max_height = 0;
amf_bool smart_access_supported;
amf_int32 num_val;
std::set < std::string > formats;
std::string format_str;
@ -1370,6 +1415,11 @@ gst_amf_h265_enc_create_class_data (GstD3D11Device * device,
QUERY_DEFAULT_PROP (AMF_VIDEO_ENCODER_HEVC_QP_P, default_qp_p, 26);
#undef QUERY_DEFAULT_PROP
result = comp->GetProperty (AMF_VIDEO_ENCODER_HEVC_ENABLE_SMART_ACCESS_VIDEO,
&smart_access_supported);
if (result == AMF_OK)
dev_caps.smart_access_supported = TRUE;
{
const AMFPropertyInfo *pinfo = nullptr;
result = comp->GetPropertyInfo (AMF_VIDEO_ENCODER_HEVC_GOP_SIZE, &pinfo);