amfcodec: Initial support of preanalysis and preencoding for AMF encoders

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3847>
This commit is contained in:
Evgeny Pavlov 2023-02-09 11:16:19 +01:00 committed by GStreamer Marge Bot
parent e8060c40f5
commit 00988e70ac
5 changed files with 1510 additions and 8 deletions

View file

@ -73,7 +73,9 @@ typedef struct
amf_int64 max_gop_size;
amf_int64 default_gop_size;
guint valign;
gboolean pre_encode_supported;
gboolean smart_access_supported;
GstAmfEncoderPASupportedOptions pa_supported;
} GstAmfAv1EncDeviceCaps;
/**
@ -265,7 +267,23 @@ enum
PROP_QP_I,
PROP_QP_P,
PROP_REF_FRAMES,
PROP_SMART_ACCESS
PROP_SMART_ACCESS,
PROP_PRE_ENCODE,
PROP_PRE_ANALYSIS,
PROP_PA_ACTIVITY_TYPE,
PROP_PA_SCENE_CHANGE_DETECTION,
PROP_PA_SCENE_CHANGE_DETECTION_SENSITIVITY,
PROP_PA_STATIC_SCENE_DETECTION,
PROP_PA_STATIC_SCENE_DETECTION_SENSITIVITY,
PROP_PA_INITIAL_QP,
PROP_PA_MAX_QP,
PROP_PA_CAQ_STRENGTH,
PROP_PA_FRAME_SAD,
PROP_PA_LTR,
PROP_PA_LOOKAHEAD_BUFFER_DEPTH,
PROP_PA_PAQ_MODE,
PROP_PA_TAQ_MODE,
PROP_PA_HQMB_MODE,
};
#define DEFAULT_USAGE AMF_VIDEO_ENCODER_AV1_USAGE_TRANSCODING
@ -276,6 +294,7 @@ enum
#define DEFAULT_MIN_MAX_QP -1
#define DEFAULT_REF_FRAMES 1
#define DEFAULT_SMART_ACCESS FALSE
#define DEFAULT_PRE_ENCODE FALSE
#define DOC_SINK_CAPS_COMM \
"format = (string) {NV12, P010_10LE}, " \
@ -309,6 +328,8 @@ typedef struct _GstAmfAv1Enc
guint qp_p;
guint ref_frames;
gboolean smart_access;
gboolean pre_encode;
GstAmfEncoderPreAnalysis pa;
} GstAmfAv1Enc;
typedef struct _GstAmfAv1EncClass
@ -346,8 +367,11 @@ gst_amf_av1_enc_class_init (GstAmfAv1EncClass * klass, gpointer data)
GstAmfEncoderClass *amf_class = GST_AMF_ENCODER_CLASS (klass);
GstAmfAv1EncClassData *cdata = (GstAmfAv1EncClassData *) data;
GstAmfAv1EncDeviceCaps *dev_caps = &cdata->dev_caps;
GstAmfEncoderPASupportedOptions *pa_supported = &dev_caps->pa_supported;
GParamFlags param_flags = (GParamFlags) (G_PARAM_READWRITE |
GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
GParamFlags pa_param_flags = (GParamFlags) (G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS | GST_PARAM_CONDITIONALLY_AVAILABLE);
GstPadTemplate *pad_templ;
GstCaps *doc_caps;
@ -413,7 +437,12 @@ gst_amf_av1_enc_class_init (GstAmfAv1EncClass * klass, gpointer data)
g_object_class_install_property (object_class, PROP_REF_FRAMES,
g_param_spec_uint ("ref-frames", "Reference Frames",
"Number of reference frames", 0, 8, DEFAULT_REF_FRAMES, param_flags));
if (cdata->dev_caps.pre_encode_supported) {
g_object_class_install_property (object_class, PROP_PRE_ENCODE,
g_param_spec_boolean ("pre-encode", "Pre-encode",
"Enable pre-encode", DEFAULT_PRE_ENCODE,
(GParamFlags) (param_flags | GST_PARAM_CONDITIONALLY_AVAILABLE)));
}
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",
@ -424,6 +453,113 @@ gst_amf_av1_enc_class_init (GstAmfAv1EncClass * klass, gpointer data)
GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS)));
}
if (dev_caps->pre_analysis) {
g_object_class_install_property (object_class, PROP_PRE_ANALYSIS,
g_param_spec_boolean ("pre-analysis", "Pre-analysis",
"Enable pre-analysis", DEFAULT_PRE_ANALYSIS, param_flags));
if (pa_supported->activity_type) {
g_object_class_install_property (object_class, PROP_PA_ACTIVITY_TYPE,
g_param_spec_enum ("pa-activity-type", "Pre-analysis activity type",
"Set the type of activity analysis for pre-analysis",
GST_TYPE_AMF_ENC_PA_ACTIVITY_TYPE, DEFAULT_PA_ACTIVITY_TYPE,
pa_param_flags));
}
if (pa_supported->scene_change_detection) {
g_object_class_install_property (object_class,
PROP_PA_SCENE_CHANGE_DETECTION,
g_param_spec_boolean ("pa-scene-change-detection",
"Pre-analysis scene change detection",
"Enable scene change detection for pre-analysis",
DEFAULT_PA_SCENE_CHANGE_DETECTION, pa_param_flags));
}
if (pa_supported->scene_change_detection_sensitivity) {
g_object_class_install_property (object_class,
PROP_PA_SCENE_CHANGE_DETECTION_SENSITIVITY,
g_param_spec_enum ("pa-scene-change-detection-sensitivity",
"Pre-analysis scene change detection sensitivity",
"Set the sensitivity of scene change detection for pre-analysis",
GST_TYPE_AMF_ENC_PA_SCENE_CHANGE_DETECTION_SENSITIVITY,
DEFAULT_PA_SCENE_CHANGE_DETECTION_SENSITIVITY, pa_param_flags));
}
if (pa_supported->static_scene_detection) {
g_object_class_install_property (object_class,
PROP_PA_STATIC_SCENE_DETECTION,
g_param_spec_boolean ("pa-static-scene-detection",
"Pre-analysis static scene detection",
"Enable static scene detection for pre-analysis",
DEFAULT_PA_STATIC_SCENE_DETECTION, pa_param_flags));
}
if (pa_supported->static_scene_detection_sensitivity) {
g_object_class_install_property (object_class,
PROP_PA_STATIC_SCENE_DETECTION_SENSITIVITY,
g_param_spec_enum ("pa-static-scene-detection-sensitivity",
"Pre-analysis static scene detection sensitivity",
"Set the sensitivity of static scene detection for pre-analysis",
GST_TYPE_AMF_ENC_PA_STATIC_SCENE_DETECTION_SENSITIVITY,
DEFAULT_PA_STATIC_SCENE_DETECTION_SENSITIVITY, pa_param_flags));
}
if (pa_supported->initial_qp) {
g_object_class_install_property (object_class, PROP_PA_INITIAL_QP,
g_param_spec_uint ("pa-initial-qp", "Pre-analysis initial QP",
"The QP value that is used immediately after a scene change", 0,
51, DEFAULT_PA_INITIAL_QP, pa_param_flags));
}
if (pa_supported->max_qp) {
g_object_class_install_property (object_class, PROP_PA_MAX_QP,
g_param_spec_uint ("pa-max-qp", "Pre-analysis max QP",
"The QP threshold to allow a skip frame", 0, 51,
DEFAULT_PA_MAX_QP, pa_param_flags));
}
if (pa_supported->caq_strength) {
g_object_class_install_property (object_class, PROP_PA_CAQ_STRENGTH,
g_param_spec_enum ("pa-caq-strength", "Pre-analysis CAQ strength",
"Content Adaptive Quantization strength for pre-analysis",
GST_TYPE_AMF_ENC_PA_CAQ_STRENGTH, DEFAULT_PA_CAQ_STRENGTH,
pa_param_flags));
}
if (pa_supported->frame_sad) {
g_object_class_install_property (object_class, PROP_PA_FRAME_SAD,
g_param_spec_boolean ("pa-frame-sad", "Pre-analysis SAD algorithm",
"Enable Frame SAD algorithm", DEFAULT_PA_FRAME_SAD,
pa_param_flags));
}
if (pa_supported->ltr) {
g_object_class_install_property (object_class, PROP_PA_LTR,
g_param_spec_boolean ("pa-ltr", "Pre-analysis LTR",
"Enable long term reference frame management", DEFAULT_PA_LTR,
pa_param_flags));
}
if (pa_supported->lookahead_buffer_depth) {
g_object_class_install_property (object_class,
PROP_PA_LOOKAHEAD_BUFFER_DEPTH,
g_param_spec_uint ("pa-lookahead-buffer-depth",
"Pre-analysis lookahead buffer depth",
"Set the PA lookahead buffer size", 0, 41,
DEFAULT_PA_LOOKAHEAD_BUFFER_DEPTH, pa_param_flags));
}
if (pa_supported->paq_mode) {
g_object_class_install_property (object_class, PROP_PA_PAQ_MODE,
g_param_spec_enum ("pa-paq-mode", "Pre-analysis PAQ mode",
"Set the perceptual adaptive quantization mode",
GST_TYPE_AMF_ENC_PA_PAQ_MODE, DEFAULT_PA_PAQ_MODE,
pa_param_flags));
}
if (pa_supported->taq_mode) {
g_object_class_install_property (object_class, PROP_PA_TAQ_MODE,
g_param_spec_enum ("pa-taq-mode", "Pre-analysis TAQ mode",
"Set the temporal adaptive quantization mode",
GST_TYPE_AMF_ENC_PA_TAQ_MODE, DEFAULT_PA_TAQ_MODE,
pa_param_flags));
}
if (pa_supported->hmqb_mode) {
g_object_class_install_property (object_class, PROP_PA_HQMB_MODE,
g_param_spec_enum ("pa-hqmb-mode", "Pre-analysis HQMB mode",
"Set the PA high motion quality boost mode",
GST_TYPE_AMF_ENC_PA_HQMB_MODE, DEFAULT_PA_HQMB_MODE,
pa_param_flags));
}
}
gst_element_class_set_metadata (element_class,
"AMD AMF AV1 Video Encoder",
"Codec/Encoder/Video/Hardware",
@ -495,6 +631,25 @@ gst_amf_av1_enc_init (GstAmfAv1Enc * self)
self->qp_p = (guint) dev_caps->default_qp_p;
self->ref_frames = DEFAULT_REF_FRAMES;
self->smart_access = DEFAULT_SMART_ACCESS;
self->pre_encode = DEFAULT_PRE_ENCODE;
// Init pre-analysis options
self->pa.pre_analysis = DEFAULT_PRE_ANALYSIS;
self->pa.activity_type = DEFAULT_PA_ACTIVITY_TYPE;
self->pa.scene_change_detection = DEFAULT_PA_SCENE_CHANGE_DETECTION;
self->pa.scene_change_detection_sensitivity =
DEFAULT_PA_SCENE_CHANGE_DETECTION_SENSITIVITY;
self->pa.static_scene_detection = DEFAULT_PA_STATIC_SCENE_DETECTION;
self->pa.static_scene_detection_sensitivity =
DEFAULT_PA_STATIC_SCENE_DETECTION_SENSITIVITY;
self->pa.initial_qp = DEFAULT_PA_INITIAL_QP;
self->pa.max_qp = DEFAULT_PA_MAX_QP;
self->pa.caq_strength = DEFAULT_PA_CAQ_STRENGTH;
self->pa.frame_sad = DEFAULT_PA_FRAME_SAD;
self->pa.ltr = DEFAULT_PA_LTR;
self->pa.lookahead_buffer_depth = DEFAULT_PA_LOOKAHEAD_BUFFER_DEPTH;
self->pa.paq_mode = DEFAULT_PA_PAQ_MODE;
self->pa.taq_mode = DEFAULT_PA_TAQ_MODE;
self->pa.hmqb_mode = DEFAULT_PA_HQMB_MODE;
}
static void
@ -605,6 +760,53 @@ gst_amf_av1_enc_set_property (GObject * object, guint prop_id,
case PROP_SMART_ACCESS:
update_bool (self, &self->smart_access, value);
break;
case PROP_PRE_ENCODE:
update_bool (self, &self->pre_encode, value);
break;
case PROP_PRE_ANALYSIS:
update_bool (self, &self->pa.pre_analysis, value);
break;
case PROP_PA_ACTIVITY_TYPE:
update_enum (self, &self->pa.activity_type, value);
break;
case PROP_PA_SCENE_CHANGE_DETECTION:
update_bool (self, &self->pa.scene_change_detection, value);
break;
case PROP_PA_SCENE_CHANGE_DETECTION_SENSITIVITY:
update_enum (self, &self->pa.scene_change_detection_sensitivity, value);
break;
case PROP_PA_STATIC_SCENE_DETECTION:
update_bool (self, &self->pa.static_scene_detection, value);
break;
case PROP_PA_STATIC_SCENE_DETECTION_SENSITIVITY:
update_enum (self, &self->pa.static_scene_detection_sensitivity, value);
break;
case PROP_PA_INITIAL_QP:
update_uint (self, &self->pa.initial_qp, value);
break;
case PROP_PA_MAX_QP:
update_uint (self, &self->pa.max_qp, value);
break;
case PROP_PA_CAQ_STRENGTH:
update_enum (self, &self->pa.caq_strength, value);
break;
case PROP_PA_FRAME_SAD:
update_bool (self, &self->pa.frame_sad, value);
case PROP_PA_LTR:
update_bool (self, &self->pa.ltr, value);
break;
case PROP_PA_LOOKAHEAD_BUFFER_DEPTH:
update_uint (self, &self->pa.lookahead_buffer_depth, value);
break;
case PROP_PA_PAQ_MODE:
update_enum (self, &self->pa.paq_mode, value);
break;
case PROP_PA_TAQ_MODE:
update_enum (self, &self->pa.taq_mode, value);
break;
case PROP_PA_HQMB_MODE:
update_enum (self, &self->pa.hmqb_mode, value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -665,6 +867,54 @@ gst_amf_av1_enc_get_property (GObject * object, guint prop_id,
case PROP_SMART_ACCESS:
g_value_set_boolean (value, self->smart_access);
break;
case PROP_PRE_ENCODE:
g_value_set_boolean (value, self->pre_encode);
break;
case PROP_PRE_ANALYSIS:
g_value_set_boolean (value, self->pa.pre_analysis);
break;
case PROP_PA_ACTIVITY_TYPE:
g_value_set_enum (value, self->pa.activity_type);
break;
case PROP_PA_SCENE_CHANGE_DETECTION:
g_value_set_boolean (value, self->pa.scene_change_detection);
break;
case PROP_PA_SCENE_CHANGE_DETECTION_SENSITIVITY:
g_value_set_enum (value, self->pa.scene_change_detection_sensitivity);
break;
case PROP_PA_STATIC_SCENE_DETECTION:
g_value_set_boolean (value, self->pa.static_scene_detection);
break;
case PROP_PA_STATIC_SCENE_DETECTION_SENSITIVITY:
g_value_set_enum (value, self->pa.static_scene_detection_sensitivity);
break;
case PROP_PA_INITIAL_QP:
g_value_set_uint (value, self->pa.initial_qp);
break;
case PROP_PA_MAX_QP:
g_value_set_uint (value, self->pa.max_qp);
break;
case PROP_PA_CAQ_STRENGTH:
g_value_set_enum (value, self->pa.caq_strength);
break;
case PROP_PA_FRAME_SAD:
g_value_set_boolean (value, self->pa.frame_sad);
break;
case PROP_PA_LTR:
g_value_set_boolean (value, self->pa.ltr);
break;
case PROP_PA_LOOKAHEAD_BUFFER_DEPTH:
g_value_set_uint (value, self->pa.lookahead_buffer_depth);
break;
case PROP_PA_PAQ_MODE:
g_value_set_enum (value, self->pa.paq_mode);
break;
case PROP_PA_TAQ_MODE:
g_value_set_enum (value, self->pa.taq_mode);
break;
case PROP_PA_HQMB_MODE:
g_value_set_enum (value, self->pa.hmqb_mode);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -871,6 +1121,33 @@ gst_amf_av1_enc_set_format (GstAmfEncoder * encoder,
}
}
if (dev_caps->pre_encode_supported) {
result = comp->SetProperty (AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_PREENCODE,
(amf_bool) self->pre_encode);
if (result != AMF_OK) {
GST_ERROR_OBJECT (self, "Failed to set pre-encode, result %"
GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
goto error;
}
}
if (dev_caps->pre_analysis) {
result = comp->SetProperty (AMF_VIDEO_ENCODER_AV1_PRE_ANALYSIS_ENABLE,
(amf_bool) self->pa.pre_analysis);
if (result != AMF_OK) {
GST_ERROR_OBJECT (self, "Failed to set pre-analysis, result %"
GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
goto error;
}
if (self->pa.pre_analysis) {
result =
gst_amf_encoder_set_pre_analysis_options (encoder, comp, &self->pa,
&dev_caps->pa_supported);
if (result != AMF_OK)
goto error;
}
}
result = comp->Init (surface_format, info->width, info->height);
if (result != AMF_OK) {
GST_ERROR_OBJECT (self, "Failed to init component, result %"
@ -1093,6 +1370,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 pre_encode_supported;
amf_bool smart_access_supported;
amf_int32 num_val;
std::set < std::string > formats;
@ -1247,11 +1525,41 @@ 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_RATE_CONTROL_PREENCODE,
&pre_encode_supported);
if (result == AMF_OK)
dev_caps.pre_encode_supported = TRUE;
result = comp->GetProperty (AMF_VIDEO_ENCODER_AV1_ENABLE_SMART_ACCESS_VIDEO,
&smart_access_supported);
if (result == AMF_OK)
dev_caps.smart_access_supported = TRUE;
if (dev_caps.pre_analysis) {
amf_bool pre_analysis = FALSE;
// Store initial pre-analysis value
result =
comp->GetProperty (AMF_VIDEO_ENCODER_AV1_PRE_ANALYSIS_ENABLE,
&pre_analysis);
if (result != AMF_OK) {
GST_WARNING_OBJECT (device, "Failed to get pre-analysis option");
}
// We need to enable pre-analysis for checking options availability
result =
comp->SetProperty (AMF_VIDEO_ENCODER_AV1_PRE_ANALYSIS_ENABLE,
(amf_bool) TRUE);
if (result != AMF_OK) {
GST_WARNING_OBJECT (device, "Failed to set pre-analysis option");
}
gst_amf_encoder_check_pa_supported_options (&dev_caps.pa_supported, comp);
result =
comp->SetProperty (AMF_VIDEO_ENCODER_AV1_PRE_ANALYSIS_ENABLE,
pre_analysis);
if (result != AMF_OK) {
GST_WARNING_OBJECT (device, "Failed to set pre-analysis option");
}
}
{
const AMFPropertyInfo *pinfo = nullptr;
result = comp->GetPropertyInfo (AMF_VIDEO_ENCODER_AV1_GOP_SIZE, &pinfo);

View file

@ -35,6 +35,300 @@ using namespace Microsoft::WRL;
using namespace amf;
/* *INDENT-ON* */
/**
* GstAmfEncPAActivityType:
*
* Determines whether activity analysis is performed on the Luma component
* only (Y) or on both Luma and Chroma (YUV).
*
* Since: 1.24
*/
GType
gst_amf_enc_pa_activity_get_type (void)
{
static GType pa_activity_type = 0;
static const GEnumValue activity_types[] = {
/**
* GstAmfEncPAActivityType::y:
*
* Activity analysis is performed on the Luma component only (Y)
*/
{AMF_PA_ACTIVITY_Y, "Luma (Y) component only",
"y"},
/**
* GstAmfEncPAActivityType::yuv:
*
* Activity analysis is performed on both Luma and Chroma components (YUV)
*/
{AMF_PA_ACTIVITY_YUV, "Luma and Chroma components (YUV)", "yuv"},
{0, nullptr, nullptr}
};
if (g_once_init_enter (&pa_activity_type)) {
GType type =
g_enum_register_static ("GstAmfEncPAActivityType", activity_types);
g_once_init_leave (&pa_activity_type, type);
}
return pa_activity_type;
}
/**
* GstAmfEncPASceneChangeDetectionSensitivity:
*
* Sensitivity of scene change detection. The higher the sensitivity, the more
* restrictive it is to detect a scene change. This parameter takes effect
* only when AMF_PA_LOOKAHEAH_BUFFER_DEPTH is set to 0.
*
* Since: 1.24
*/
GType
gst_amf_enc_pa_scene_change_detection_sensitivity_get_type (void)
{
static GType pa_scene_change_detection_sensitivity = 0;
static const GEnumValue sensitivity_types[] = {
/**
* GstAmfEncPASceneChangeDetectionSensitivity::low:
*
* Low sensitivity
*/
{AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY_LOW, "Low", "low"},
/**
* GstAmfEncPASceneChangeDetectionSensitivity::medium:
*
* Medium sensitivity
*/
{AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY_MEDIUM, "Medium", "medium"},
/**
* GstAmfEncPASceneChangeDetectionSensitivity::high:
*
* High sensitivity
*/
{AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY_HIGH, "High", "high"},
{0, nullptr, nullptr}
};
if (g_once_init_enter (&pa_scene_change_detection_sensitivity)) {
GType type =
g_enum_register_static
("GstAmfEncPASceneChangeDetectionSensitivity", sensitivity_types);
g_once_init_leave (&pa_scene_change_detection_sensitivity, type);
}
return pa_scene_change_detection_sensitivity;
}
/**
* GstAmfEncPAStaticSceneDetectionSensitivity:
*
* Sensitivity of static scene detection. The higher the sensitivity, the more
* restrictive it is to detect a static scene.
*
* Since: 1.24
*/
GType
gst_amf_enc_pa_static_scene_detection_sensitivity_get_type (void)
{
static GType pa_static_scene_detection_sensitivity = 0;
static const GEnumValue sensitivity_types[] = {
/**
* GstAmfEncPAStaticSceneDetectionSensitivity::low:
*
* Low sensitivity
*/
{AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY_LOW, "Low", "low"},
/**
* GstAmfEncPAStaticSceneDetectionSensitivity::medium:
*
* Medium sensitivity
*/
{AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY_MEDIUM, "Medium", "medium"},
/**
* GstAmfEncPAStaticSceneDetectionSensitivity::high:
*
* High sensitivity
*/
{AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY_HIGH, "High", "high"},
{0, nullptr, nullptr}
};
if (g_once_init_enter (&pa_static_scene_detection_sensitivity)) {
GType type =
g_enum_register_static
("GstAmfEncPAStaticSceneDetectionSensitivity", sensitivity_types);
g_once_init_leave (&pa_static_scene_detection_sensitivity, type);
}
return pa_static_scene_detection_sensitivity;
}
/**
* GstAmfEncPACAQStrength:
*
* Content Adaptive Quantization strength. Stronger CAQ strength means larger
* variation in block level QP assignment.
*
* Since: 1.24
*/
GType
gst_amf_enc_pa_caq_strength_get_type (void)
{
static GType pa_caq_strength = 0;
static const GEnumValue strength_types[] = {
/**
* GstAmfEncPACAQStrength::low:
*
* Low strength
*/
{AMF_PA_CAQ_STRENGTH_LOW, "Low", "low"},
/**
* GstAmfEncPACAQStrength::medium:
*
* Medium strength
*/
{AMF_PA_CAQ_STRENGTH_MEDIUM, "Medium", "medium"},
/**
* GstAmfEncPACAQStrength::high:
*
* High strength
*/
{AMF_PA_CAQ_STRENGTH_HIGH, "High", "high"},
{0, nullptr, nullptr}
};
if (g_once_init_enter (&pa_caq_strength)) {
GType type =
g_enum_register_static ("GstAmfEncPACAQStrength", strength_types);
g_once_init_leave (&pa_caq_strength, type);
}
return pa_caq_strength;
}
/**
* GstAmfEncPAPAQMode:
*
* Sets the perceptual adaptive quantization mode.
*
* Since: 1.24
*/
GType
gst_amf_enc_pa_paq_mode_get_type (void)
{
static GType pa_paq_mode = 0;
static const GEnumValue paq_modes[] = {
/**
* GstAmfEncPAPAQMode::none:
*
* No perceptual adaptive quantization
*/
{AMF_PA_PAQ_MODE_NONE, "None", "none"},
/**
* GstAmfEncPAPAQMode::caq:
*
* Content Adaptive Quantization (CAQ) mode
*/
{AMF_PA_PAQ_MODE_CAQ, "Content Adaptive Quantization (CAQ) mode", "caq"},
{0, nullptr, nullptr}
};
if (g_once_init_enter (&pa_paq_mode)) {
GType type = g_enum_register_static ("GstAmfEncPAPAQMode", paq_modes);
g_once_init_leave (&pa_paq_mode, type);
}
return pa_paq_mode;
}
/**
* GstAmfEncPATAQMode:
*
* Sets the temporal adaptive quantization mode. MODE_1 is suitable for non-gaming
* applications whereas MODE_2 is suitable for gaming applications.
*
* Since: 1.24
*/
GType
gst_amf_enc_pa_taq_mode_get_type (void)
{
static GType pa_taq_mode = 0;
static const GEnumValue taq_modes[] = {
/**
* GstAmfEncPATAQMode::none:
*
* No temporal adaptive quantization
*/
{AMF_PA_TAQ_MODE_NONE, "None", "none"},
/**
* GstAmfEncPATAQMode::mode1:
*
* MODE_1 is suitable for non-gaming applications
*/
{AMF_PA_TAQ_MODE_1, "Mode_1 is suitable for non-gaming applications",
"mode1"},
/**
* GstAmfEncPATAQMode::mode2:
*
* MODE_2 is suitable for for gaming applications
*/
{AMF_PA_TAQ_MODE_2, "Mode_2 is suitable for gaming applications", "mode2"},
{0, nullptr, nullptr}
};
if (g_once_init_enter (&pa_taq_mode)) {
GType type = g_enum_register_static ("GstAmfEncPATAQMode", taq_modes);
g_once_init_leave (&pa_taq_mode, type);
}
return pa_taq_mode;
}
/**
* GstAmfEncPAHQMBMode:
*
* Sets the PA high motion quality boost (HQMB) mode to help the encoder in motion search.
*
* Since: 1.24
*/
GType
gst_amf_enc_pa_hmbq_mode_get_type (void)
{
static GType pa_hmbq_mode = 0;
static const GEnumValue hmbq_modes[] = {
/**
* GstAmfEncPAHQMBMode::none:
*
* No high motion quality boost
*/
{AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE_NONE, "None", "none"},
/**
* GstAmfEncPAHQMBMode::auto:
*
* Automatic mode
*/
{AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE_AUTO, "Auto", "auto"},
{0, nullptr, nullptr}
};
if (g_once_init_enter (&pa_hmbq_mode)) {
GType type = g_enum_register_static ("GstAmfEncPAHQMBMode", hmbq_modes);
g_once_init_leave (&pa_hmbq_mode, type);
}
return pa_hmbq_mode;
}
GST_DEBUG_CATEGORY_STATIC (gst_amf_encoder_debug);
#define GST_CAT_DEFAULT gst_amf_encoder_debug
@ -122,6 +416,22 @@ gst_amf_encoder_class_init (GstAmfEncoderClass * klass)
"amfencoder", 0, "amfencoder");
gst_type_mark_as_plugin_api (GST_TYPE_AMF_ENCODER, (GstPluginAPIFlags) 0);
gst_type_mark_as_plugin_api (GST_TYPE_AMF_ENC_PA_ACTIVITY_TYPE,
(GstPluginAPIFlags) 0);
gst_type_mark_as_plugin_api
(GST_TYPE_AMF_ENC_PA_SCENE_CHANGE_DETECTION_SENSITIVITY,
(GstPluginAPIFlags) 0);
gst_type_mark_as_plugin_api
(GST_TYPE_AMF_ENC_PA_STATIC_SCENE_DETECTION_SENSITIVITY,
(GstPluginAPIFlags) 0);
gst_type_mark_as_plugin_api (GST_TYPE_AMF_ENC_PA_CAQ_STRENGTH,
(GstPluginAPIFlags) 0);
gst_type_mark_as_plugin_api (GST_TYPE_AMF_ENC_PA_PAQ_MODE,
(GstPluginAPIFlags) 0);
gst_type_mark_as_plugin_api (GST_TYPE_AMF_ENC_PA_TAQ_MODE,
(GstPluginAPIFlags) 0);
gst_type_mark_as_plugin_api (GST_TYPE_AMF_ENC_PA_HQMB_MODE,
(GstPluginAPIFlags) 0);
}
static void
@ -466,7 +776,7 @@ gst_amf_encoder_prepare_internal_pool (GstAmfEncoder * self)
GST_VIDEO_INFO_SIZE (info), 0, 0);
params = gst_d3d11_allocation_params_new (priv->device, info,
GST_D3D11_ALLOCATION_FLAG_DEFAULT, 0, 0);
GST_D3D11_ALLOCATION_FLAG_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0);
params->desc[0].MiscFlags = D3D11_RESOURCE_MISC_SHARED;
gst_buffer_pool_config_set_d3d11_allocation_params (config, params);
@ -775,7 +1085,8 @@ gst_amf_encoder_upload_buffer (GstAmfEncoder * self, GstBuffer * buffer)
}
gst_d3d11_memory_get_texture_desc (dmem, &desc);
if (desc.Usage != D3D11_USAGE_DEFAULT) {
if (desc.Usage != D3D11_USAGE_DEFAULT
|| (desc.BindFlags & D3D11_BIND_SHADER_RESOURCE) == 0) {
GST_TRACE_OBJECT (self, "Not a default usage texture, d3d11 copy");
gst_d3d11_device_lock (priv->device);
ret = gst_amf_encoder_copy_d3d11 (self, buffer, FALSE);
@ -1012,6 +1323,7 @@ gst_amf_encoder_propose_allocation (GstVideoEncoder * encoder, GstQuery * query)
GstCapsFeatures *features;
gboolean is_d3d11 = FALSE;
guint min_buffers = 0;
GstD3D11AllocationParams *params;
gst_query_parse_allocation (query, &caps, nullptr);
if (!caps) {
@ -1048,6 +1360,11 @@ gst_amf_encoder_propose_allocation (GstVideoEncoder * encoder, GstQuery * query)
size = GST_VIDEO_INFO_SIZE (&info);
gst_buffer_pool_config_set_params (config, caps, size, min_buffers, 0);
params = gst_d3d11_allocation_params_new (device, &info,
GST_D3D11_ALLOCATION_FLAG_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0);
gst_buffer_pool_config_set_d3d11_allocation_params (config, params);
gst_d3d11_allocation_params_free (params);
if (!gst_buffer_pool_set_config (pool, config)) {
GST_WARNING_OBJECT (self, "Failed to set pool config");
gst_object_unref (pool);
@ -1082,3 +1399,181 @@ gst_amf_encoder_set_subclass_data (GstAmfEncoder * encoder, gint64 adapter_luid,
priv->codec_id = codec_id;
}
/* *INDENT-ON* */
AMF_RESULT
gst_amf_encoder_set_pre_analysis_options (GstAmfEncoder * self,
AMFComponent * comp, const GstAmfEncoderPreAnalysis * pa,
GstAmfEncoderPASupportedOptions * pa_supported)
{
AMF_RESULT result;
if (pa_supported->activity_type) {
result = comp->SetProperty (AMF_PA_ACTIVITY_TYPE,
(AMF_PA_ACTIVITY_TYPE_ENUM) pa->activity_type);
if (result != AMF_OK) {
GST_ERROR_OBJECT (self,
"Failed to set pre-analysis activity type, result %"
GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
return result;
}
}
if (pa_supported->scene_change_detection) {
result = comp->SetProperty (AMF_PA_SCENE_CHANGE_DETECTION_ENABLE,
(amf_bool) pa->scene_change_detection);
if (result != AMF_OK) {
GST_ERROR_OBJECT (self,
"Failed to set pre-analysis scene change detection, result %"
GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
return result;
}
}
if (pa_supported->scene_change_detection_sensitivity) {
result = comp->SetProperty (AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY,
(AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY_ENUM)
pa->scene_change_detection_sensitivity);
if (result != AMF_OK) {
GST_ERROR_OBJECT (self,
"Failed to set pre-analysis scene change detection sensitivity, result %"
GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
return result;
}
}
if (pa_supported->static_scene_detection) {
result = comp->SetProperty (AMF_PA_STATIC_SCENE_DETECTION_ENABLE,
(amf_bool) pa->static_scene_detection);
if (result != AMF_OK) {
GST_ERROR_OBJECT (self,
"Failed to set pre-analysis static scene detection, result %"
GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
return result;
}
}
if (pa_supported->static_scene_detection_sensitivity) {
result = comp->SetProperty (AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY,
(AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY_ENUM)
pa->static_scene_detection_sensitivity);
if (result != AMF_OK) {
GST_ERROR_OBJECT (self,
"Failed to set pre-analysis static scene detection sensitivity, result %"
GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
return result;
}
}
if (pa_supported->initial_qp) {
result = comp->SetProperty (AMF_PA_INITIAL_QP_AFTER_SCENE_CHANGE,
(amf_int64) pa->initial_qp);
if (result != AMF_OK) {
GST_ERROR_OBJECT (self, "Failed to set pre-analysis initial QP, result %"
GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
return result;
}
}
if (pa_supported->max_qp) {
result = comp->SetProperty (AMF_PA_MAX_QP_BEFORE_FORCE_SKIP,
(amf_int64) pa->max_qp);
if (result != AMF_OK) {
GST_ERROR_OBJECT (self, "Failed to set pre-analysis max QP, result %"
GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
return result;
}
}
if (pa_supported->caq_strength) {
result = comp->SetProperty (AMF_PA_CAQ_STRENGTH,
(amf_int64) pa->caq_strength);
if (result != AMF_OK) {
GST_ERROR_OBJECT (self,
"Failed to set pre-analysis CAQ strength, result %"
GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
return result;
}
}
if (pa_supported->frame_sad) {
result = comp->SetProperty (AMF_PA_FRAME_SAD_ENABLE,
(amf_bool) pa->frame_sad);
if (result != AMF_OK) {
GST_ERROR_OBJECT (self,
"Failed to set pre-analysis frame SAD algorithm, result %"
GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
return result;
}
}
if (pa_supported->ltr) {
result = comp->SetProperty (AMF_PA_LTR_ENABLE, (amf_bool) pa->ltr);
if (result != AMF_OK) {
GST_ERROR_OBJECT (self,
"Failed to set pre-analysis automatic Long Term Reference frame management, result %"
GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
return result;
}
}
if (pa_supported->lookahead_buffer_depth) {
result = comp->SetProperty (AMF_PA_LOOKAHEAD_BUFFER_DEPTH,
(amf_int64) pa->lookahead_buffer_depth);
if (result != AMF_OK) {
GST_ERROR_OBJECT (self,
"Failed to set pre-analysis lookahead buffer depth, result %"
GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
return result;
}
}
if (pa_supported->paq_mode) {
result = comp->SetProperty (AMF_PA_PAQ_MODE, (amf_int64) pa->paq_mode);
if (result != AMF_OK) {
GST_ERROR_OBJECT (self, "Failed to set pre-analysis PAQ mode, result %"
GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
return result;
}
}
if (pa_supported->taq_mode) {
result = comp->SetProperty (AMF_PA_TAQ_MODE, (amf_int64) pa->taq_mode);
if (result != AMF_OK) {
GST_ERROR_OBJECT (self, "Failed to set pre-analysis TAQ mode, result %"
GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
return result;
}
}
if (pa_supported->hmqb_mode) {
result = comp->SetProperty (AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE,
(amf_int64) pa->hmqb_mode);
if (result != AMF_OK) {
GST_ERROR_OBJECT (self,
"Failed to set pre-analysis high motion quality boost mode, result %"
GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
return result;
}
}
return AMF_OK;
}
void
gst_amf_encoder_check_pa_supported_options (GstAmfEncoderPASupportedOptions *
pa_supported, AMFComponent * comp)
{
if (comp->HasProperty (AMF_PA_ACTIVITY_TYPE))
pa_supported->activity_type = TRUE;
if (comp->HasProperty (AMF_PA_SCENE_CHANGE_DETECTION_ENABLE))
pa_supported->scene_change_detection = TRUE;
if (comp->HasProperty (AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY))
pa_supported->scene_change_detection_sensitivity = TRUE;
if (comp->HasProperty (AMF_PA_STATIC_SCENE_DETECTION_ENABLE))
pa_supported->static_scene_detection = TRUE;
if (comp->HasProperty (AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY))
pa_supported->static_scene_detection_sensitivity = TRUE;
if (comp->HasProperty (AMF_PA_INITIAL_QP_AFTER_SCENE_CHANGE))
pa_supported->initial_qp = TRUE;
if (comp->HasProperty (AMF_PA_MAX_QP_BEFORE_FORCE_SKIP))
pa_supported->max_qp = TRUE;
if (comp->HasProperty (AMF_PA_CAQ_STRENGTH))
pa_supported->caq_strength = TRUE;
if (comp->HasProperty (AMF_PA_FRAME_SAD_ENABLE))
pa_supported->frame_sad = TRUE;
if (comp->HasProperty (AMF_PA_LTR_ENABLE))
pa_supported->ltr = TRUE;
if (comp->HasProperty (AMF_PA_LOOKAHEAD_BUFFER_DEPTH))
pa_supported->lookahead_buffer_depth = TRUE;
if (comp->HasProperty (AMF_PA_PAQ_MODE))
pa_supported->paq_mode = TRUE;
if (comp->HasProperty (AMF_PA_TAQ_MODE))
pa_supported->taq_mode = TRUE;
if (comp->HasProperty (AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE))
pa_supported->hmqb_mode = TRUE;
}

View file

@ -19,6 +19,8 @@
#pragma once
#include <components/Component.h>
#include <components/PreAnalysis.h>
#include <gst/gst.h>
#include <gst/video/video.h>
#include "gstamfutils.h"
@ -37,6 +39,42 @@ typedef struct _GstAmfEncoder GstAmfEncoder;
typedef struct _GstAmfEncoderClass GstAmfEncoderClass;
typedef struct _GstAmfEncoderPrivate GstAmfEncoderPrivate;
typedef struct _GstAmfEncoderPASupportedOptions {
gboolean activity_type;
gboolean scene_change_detection;
gboolean scene_change_detection_sensitivity;
gboolean static_scene_detection;
gboolean static_scene_detection_sensitivity;
gboolean initial_qp;
gboolean max_qp;
gboolean caq_strength;
gboolean frame_sad;
gboolean ltr;
gboolean lookahead_buffer_depth;
gboolean paq_mode;
gboolean taq_mode;
gboolean hmqb_mode;
} GstAmfEncoderPASupportedOptions;
typedef struct _GstAmfEncoderPreAnalysis
{
gboolean pre_analysis;
gint activity_type;
gboolean scene_change_detection;
gint scene_change_detection_sensitivity;
gboolean static_scene_detection;
gint static_scene_detection_sensitivity;
guint initial_qp;
guint max_qp;
gint caq_strength;
gboolean frame_sad;
gboolean ltr;
guint lookahead_buffer_depth;
gint paq_mode;
gint taq_mode;
gint hmqb_mode;
} GstAmfEncoderPreAnalysis;
struct _GstAmfEncoder
{
GstVideoEncoder parent;
@ -47,7 +85,7 @@ struct _GstAmfEncoder
struct _GstAmfEncoderClass
{
GstVideoEncoderClass parent_class;
GstAmfEncoderPASupportedOptions pa_supported;
gboolean (*set_format) (GstAmfEncoder * encoder,
GstVideoCodecState * state,
gpointer component);
@ -73,6 +111,53 @@ void gst_amf_encoder_set_subclass_data (GstAmfEncoder * encoder,
gint64 adapter_luid,
const wchar_t * codec_id);
AMF_RESULT gst_amf_encoder_set_pre_analysis_options (GstAmfEncoder * self,
amf::AMFComponent * comp,
const GstAmfEncoderPreAnalysis * pa,
GstAmfEncoderPASupportedOptions * pa_supported);
void gst_amf_encoder_check_pa_supported_options (GstAmfEncoderPASupportedOptions * pa_supported,
amf::AMFComponent * comp);
// Pre-analysis settings
#define DEFAULT_PRE_ANALYSIS FALSE
#define DEFAULT_PA_ACTIVITY_TYPE AMF_PA_ACTIVITY_Y
#define DEFAULT_PA_SCENE_CHANGE_DETECTION TRUE
#define DEFAULT_PA_SCENE_CHANGE_DETECTION_SENSITIVITY AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY_MEDIUM
#define DEFAULT_PA_STATIC_SCENE_DETECTION FALSE
#define DEFAULT_PA_STATIC_SCENE_DETECTION_SENSITIVITY AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY_HIGH
#define DEFAULT_PA_INITIAL_QP 0
#define DEFAULT_PA_MAX_QP 35
#define DEFAULT_PA_CAQ_STRENGTH AMF_PA_CAQ_STRENGTH_MEDIUM
#define DEFAULT_PA_FRAME_SAD TRUE
#define DEFAULT_PA_LTR FALSE
#define DEFAULT_PA_LOOKAHEAD_BUFFER_DEPTH 0
#define DEFAULT_PA_PAQ_MODE AMF_PA_PAQ_MODE_NONE
#define DEFAULT_PA_TAQ_MODE AMF_PA_TAQ_MODE_NONE
#define DEFAULT_PA_HQMB_MODE AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE_NONE
#define GST_TYPE_AMF_ENC_PA_ACTIVITY_TYPE (gst_amf_enc_pa_activity_get_type ())
GType gst_amf_enc_pa_activity_get_type (void);
#define GST_TYPE_AMF_ENC_PA_SCENE_CHANGE_DETECTION_SENSITIVITY (gst_amf_enc_pa_scene_change_detection_sensitivity_get_type ())
GType gst_amf_enc_pa_scene_change_detection_sensitivity_get_type (void);
#define GST_TYPE_AMF_ENC_PA_STATIC_SCENE_DETECTION_SENSITIVITY (gst_amf_enc_pa_static_scene_detection_sensitivity_get_type ())
GType gst_amf_enc_pa_static_scene_detection_sensitivity_get_type (void);
#define GST_TYPE_AMF_ENC_PA_CAQ_STRENGTH (gst_amf_enc_pa_caq_strength_get_type ())
GType gst_amf_enc_pa_caq_strength_get_type (void);
#define GST_TYPE_AMF_ENC_PA_PAQ_MODE (gst_amf_enc_pa_paq_mode_get_type ())
GType gst_amf_enc_pa_paq_mode_get_type (void);
#define GST_TYPE_AMF_ENC_PA_TAQ_MODE (gst_amf_enc_pa_taq_mode_get_type ())
GType gst_amf_enc_pa_taq_mode_get_type (void);
#define GST_TYPE_AMF_ENC_PA_HQMB_MODE (gst_amf_enc_pa_hmbq_mode_get_type ())
GType gst_amf_enc_pa_hmbq_mode_get_type (void);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstAmfEncoder, gst_object_unref)
G_END_DECLS

View file

@ -77,7 +77,9 @@ typedef struct
amf_int64 default_qp_b;
gboolean interlace_supported;
guint valign;
gboolean pre_encode_supported;
gboolean smart_access_supported;
GstAmfEncoderPASupportedOptions pa_supported;
} GstAmfH264EncDeviceCaps;
/**
@ -274,7 +276,23 @@ enum
PROP_REF_FRAMES,
PROP_AUD,
PROP_CABAC,
PROP_SMART_ACCESS
PROP_SMART_ACCESS,
PROP_PRE_ENCODE,
PROP_PRE_ANALYSIS,
PROP_PA_ACTIVITY_TYPE,
PROP_PA_SCENE_CHANGE_DETECTION,
PROP_PA_SCENE_CHANGE_DETECTION_SENSITIVITY,
PROP_PA_STATIC_SCENE_DETECTION,
PROP_PA_STATIC_SCENE_DETECTION_SENSITIVITY,
PROP_PA_INITIAL_QP,
PROP_PA_MAX_QP,
PROP_PA_CAQ_STRENGTH,
PROP_PA_FRAME_SAD,
PROP_PA_LTR,
PROP_PA_LOOKAHEAD_BUFFER_DEPTH,
PROP_PA_PAQ_MODE,
PROP_PA_TAQ_MODE,
PROP_PA_HQMB_MODE,
};
#define DEFAULT_USAGE AMF_VIDEO_ENCODER_USAGE_TRANSCODING
@ -287,6 +305,7 @@ enum
#define DEFAULT_AUD TRUE
#define DEFAULT_CABAC TRUE
#define DEFAULT_SMART_ACCESS FALSE
#define DEFAULT_PRE_ENCODE FALSE
#define DOC_SINK_CAPS_COMM \
"format = (string) NV12, " \
@ -301,6 +320,7 @@ enum
"profile = (string) { main, high, constrained-baseline, baseline }, " \
"stream-format = (string) { avc, byte-stream }, alignment = (string) au"
typedef struct _GstAmfH264Enc
{
GstAmfEncoder parent;
@ -326,6 +346,8 @@ typedef struct _GstAmfH264Enc
gboolean aud;
gboolean cabac;
gboolean smart_access;
gboolean pre_encode;
GstAmfEncoderPreAnalysis pa;
} GstAmfH264Enc;
typedef struct _GstAmfH264EncClass
@ -366,8 +388,11 @@ gst_amf_h264_enc_class_init (GstAmfH264EncClass * klass, gpointer data)
GstAmfEncoderClass *amf_class = GST_AMF_ENCODER_CLASS (klass);
GstAmfH264EncClassData *cdata = (GstAmfH264EncClassData *) data;
GstAmfH264EncDeviceCaps *dev_caps = &cdata->dev_caps;
GstAmfEncoderPASupportedOptions *pa_supported = &dev_caps->pa_supported;
GParamFlags param_flags = (GParamFlags) (G_PARAM_READWRITE |
GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
GParamFlags pa_param_flags = (GParamFlags) (G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS | GST_PARAM_CONDITIONALLY_AVAILABLE);
GstPadTemplate *pad_templ;
GstCaps *doc_caps;
@ -432,7 +457,12 @@ gst_amf_h264_enc_class_init (GstAmfH264EncClass * klass, gpointer data)
g_object_class_install_property (object_class, PROP_CABAC,
g_param_spec_boolean ("cabac", "CABAC",
"Enable CABAC entropy coding", TRUE, param_flags));
if (cdata->dev_caps.pre_encode_supported) {
g_object_class_install_property (object_class, PROP_PRE_ENCODE,
g_param_spec_boolean ("pre-encode", "Pre-encode",
"Enable pre-encode", DEFAULT_PRE_ENCODE,
(GParamFlags) (param_flags | GST_PARAM_CONDITIONALLY_AVAILABLE)));
}
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",
@ -443,6 +473,112 @@ gst_amf_h264_enc_class_init (GstAmfH264EncClass * klass, gpointer data)
GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS)));
}
if (dev_caps->pre_analysis) {
g_object_class_install_property (object_class, PROP_PRE_ANALYSIS,
g_param_spec_boolean ("pre-analysis", "Pre Analysis",
"Enable pre-analysis", DEFAULT_PRE_ANALYSIS, param_flags));
if (pa_supported->activity_type) {
g_object_class_install_property (object_class, PROP_PA_ACTIVITY_TYPE,
g_param_spec_enum ("pa-activity-type", "Pre-analysis activity type",
"Set the type of activity analysis for pre-analysis",
GST_TYPE_AMF_ENC_PA_ACTIVITY_TYPE, DEFAULT_PA_ACTIVITY_TYPE,
pa_param_flags));
}
if (pa_supported->scene_change_detection) {
g_object_class_install_property (object_class,
PROP_PA_SCENE_CHANGE_DETECTION,
g_param_spec_boolean ("pa-scene-change-detection",
"Pre-analysis scene change detection",
"Enable scene change detection for pre-analysis",
DEFAULT_PA_SCENE_CHANGE_DETECTION, pa_param_flags));
}
if (pa_supported->scene_change_detection_sensitivity) {
g_object_class_install_property (object_class,
PROP_PA_SCENE_CHANGE_DETECTION_SENSITIVITY,
g_param_spec_enum ("pa-scene-change-detection-sensitivity",
"Pre-analysis scene change detection sensitivity",
"Set the sensitivity of scene change detection for pre-analysis",
GST_TYPE_AMF_ENC_PA_SCENE_CHANGE_DETECTION_SENSITIVITY,
DEFAULT_PA_SCENE_CHANGE_DETECTION_SENSITIVITY, pa_param_flags));
}
if (pa_supported->static_scene_detection) {
g_object_class_install_property (object_class,
PROP_PA_STATIC_SCENE_DETECTION,
g_param_spec_boolean ("pa-static-scene-detection",
"Pre-analysis static scene detection",
"Enable static scene detection for pre-analysis",
DEFAULT_PA_STATIC_SCENE_DETECTION, pa_param_flags));
}
if (pa_supported->static_scene_detection_sensitivity) {
g_object_class_install_property (object_class,
PROP_PA_STATIC_SCENE_DETECTION_SENSITIVITY,
g_param_spec_enum ("pa-static-scene-detection-sensitivity",
"Pre-analysis static scene detection sensitivity",
"Set the sensitivity of static scene detection for pre-analysis",
GST_TYPE_AMF_ENC_PA_STATIC_SCENE_DETECTION_SENSITIVITY,
DEFAULT_PA_STATIC_SCENE_DETECTION_SENSITIVITY, pa_param_flags));
}
if (pa_supported->initial_qp) {
g_object_class_install_property (object_class, PROP_PA_INITIAL_QP,
g_param_spec_uint ("pa-initial-qp", "Pre-analysis initial QP",
"The QP value that is used immediately after a scene change", 0,
51, DEFAULT_PA_INITIAL_QP, pa_param_flags));
}
if (pa_supported->max_qp) {
g_object_class_install_property (object_class, PROP_PA_MAX_QP,
g_param_spec_uint ("pa-max-qp", "Pre-analysis max QP",
"The QP threshold to allow a skip frame", 0, 51,
DEFAULT_PA_MAX_QP, pa_param_flags));
}
if (pa_supported->caq_strength) {
g_object_class_install_property (object_class, PROP_PA_CAQ_STRENGTH,
g_param_spec_enum ("pa-caq-strength", "Pre-analysis CAQ strength",
"Content Adaptive Quantization strength for pre-analysis",
GST_TYPE_AMF_ENC_PA_CAQ_STRENGTH, DEFAULT_PA_CAQ_STRENGTH,
pa_param_flags));
}
if (pa_supported->frame_sad) {
g_object_class_install_property (object_class, PROP_PA_FRAME_SAD,
g_param_spec_boolean ("pa-frame-sad", "Pre-analysis SAD algorithm",
"Enable Frame SAD algorithm", DEFAULT_PA_FRAME_SAD,
pa_param_flags));
}
if (pa_supported->ltr) {
g_object_class_install_property (object_class, PROP_PA_LTR,
g_param_spec_boolean ("pa-ltr", "Pre-analysis LTR",
"Enable long term reference frame management", DEFAULT_PA_LTR,
pa_param_flags));
}
if (pa_supported->lookahead_buffer_depth) {
g_object_class_install_property (object_class,
PROP_PA_LOOKAHEAD_BUFFER_DEPTH,
g_param_spec_uint ("pa-lookahead-buffer-depth",
"Pre-analysis lookahead buffer depth",
"Set the PA lookahead buffer size", 0, 41,
DEFAULT_PA_LOOKAHEAD_BUFFER_DEPTH, pa_param_flags));
}
if (pa_supported->paq_mode) {
g_object_class_install_property (object_class, PROP_PA_PAQ_MODE,
g_param_spec_enum ("pa-paq-mode", "Pre-analysis PAQ mode",
"Set the perceptual adaptive quantization mode",
GST_TYPE_AMF_ENC_PA_PAQ_MODE, DEFAULT_PA_PAQ_MODE,
pa_param_flags));
}
if (pa_supported->taq_mode) {
g_object_class_install_property (object_class, PROP_PA_TAQ_MODE,
g_param_spec_enum ("pa-taq-mode", "Pre-analysis TAQ mode",
"Set the temporal adaptive quantization mode",
GST_TYPE_AMF_ENC_PA_TAQ_MODE, DEFAULT_PA_TAQ_MODE,
pa_param_flags));
}
if (pa_supported->hmqb_mode) {
g_object_class_install_property (object_class, PROP_PA_HQMB_MODE,
g_param_spec_enum ("pa-hqmb-mode", "Pre-analysis HQMB mode",
"Set the PA high motion quality boost mode",
GST_TYPE_AMF_ENC_PA_HQMB_MODE, DEFAULT_PA_HQMB_MODE,
pa_param_flags));
}
}
gst_element_class_set_metadata (element_class,
"AMD AMF H.264 Video Encoder",
"Codec/Encoder/Video/Hardware",
@ -517,6 +653,25 @@ gst_amf_h264_enc_init (GstAmfH264Enc * self)
self->aud = DEFAULT_AUD;
self->cabac = DEFAULT_CABAC;
self->smart_access = DEFAULT_SMART_ACCESS;
self->pre_encode = DEFAULT_PRE_ENCODE;
// Init pre-analysis options
self->pa.pre_analysis = DEFAULT_PRE_ANALYSIS;
self->pa.activity_type = DEFAULT_PA_ACTIVITY_TYPE;
self->pa.scene_change_detection = DEFAULT_PA_SCENE_CHANGE_DETECTION;
self->pa.scene_change_detection_sensitivity =
DEFAULT_PA_SCENE_CHANGE_DETECTION_SENSITIVITY;
self->pa.static_scene_detection = DEFAULT_PA_STATIC_SCENE_DETECTION;
self->pa.static_scene_detection_sensitivity =
DEFAULT_PA_STATIC_SCENE_DETECTION_SENSITIVITY;
self->pa.initial_qp = DEFAULT_PA_INITIAL_QP;
self->pa.max_qp = DEFAULT_PA_MAX_QP;
self->pa.caq_strength = DEFAULT_PA_CAQ_STRENGTH;
self->pa.frame_sad = DEFAULT_PA_FRAME_SAD;
self->pa.ltr = DEFAULT_PA_LTR;
self->pa.lookahead_buffer_depth = DEFAULT_PA_LOOKAHEAD_BUFFER_DEPTH;
self->pa.paq_mode = DEFAULT_PA_PAQ_MODE;
self->pa.taq_mode = DEFAULT_PA_TAQ_MODE;
self->pa.hmqb_mode = DEFAULT_PA_HQMB_MODE;
}
static void
@ -629,6 +784,53 @@ gst_amf_h264_enc_set_property (GObject * object, guint prop_id,
case PROP_SMART_ACCESS:
update_bool (self, &self->smart_access, value);
break;
case PROP_PRE_ENCODE:
update_bool (self, &self->pre_encode, value);
break;
case PROP_PRE_ANALYSIS:
update_bool (self, &self->pa.pre_analysis, value);
break;
case PROP_PA_ACTIVITY_TYPE:
update_enum (self, &self->pa.activity_type, value);
break;
case PROP_PA_SCENE_CHANGE_DETECTION:
update_bool (self, &self->pa.scene_change_detection, value);
break;
case PROP_PA_SCENE_CHANGE_DETECTION_SENSITIVITY:
update_enum (self, &self->pa.scene_change_detection_sensitivity, value);
break;
case PROP_PA_STATIC_SCENE_DETECTION:
update_bool (self, &self->pa.static_scene_detection, value);
break;
case PROP_PA_STATIC_SCENE_DETECTION_SENSITIVITY:
update_enum (self, &self->pa.static_scene_detection_sensitivity, value);
break;
case PROP_PA_INITIAL_QP:
update_uint (self, &self->pa.initial_qp, value);
break;
case PROP_PA_MAX_QP:
update_uint (self, &self->pa.max_qp, value);
break;
case PROP_PA_CAQ_STRENGTH:
update_enum (self, &self->pa.caq_strength, value);
break;
case PROP_PA_FRAME_SAD:
update_bool (self, &self->pa.frame_sad, value);
case PROP_PA_LTR:
update_bool (self, &self->pa.ltr, value);
break;
case PROP_PA_LOOKAHEAD_BUFFER_DEPTH:
update_uint (self, &self->pa.lookahead_buffer_depth, value);
break;
case PROP_PA_PAQ_MODE:
update_enum (self, &self->pa.paq_mode, value);
break;
case PROP_PA_TAQ_MODE:
update_enum (self, &self->pa.taq_mode, value);
break;
case PROP_PA_HQMB_MODE:
update_enum (self, &self->pa.hmqb_mode, value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -689,6 +891,54 @@ gst_amf_h264_enc_get_property (GObject * object, guint prop_id,
case PROP_SMART_ACCESS:
g_value_set_boolean (value, self->smart_access);
break;
case PROP_PRE_ENCODE:
g_value_set_boolean (value, self->pre_encode);
break;
case PROP_PRE_ANALYSIS:
g_value_set_boolean (value, self->pa.pre_analysis);
break;
case PROP_PA_ACTIVITY_TYPE:
g_value_set_enum (value, self->pa.activity_type);
break;
case PROP_PA_SCENE_CHANGE_DETECTION:
g_value_set_boolean (value, self->pa.scene_change_detection);
break;
case PROP_PA_SCENE_CHANGE_DETECTION_SENSITIVITY:
g_value_set_enum (value, self->pa.scene_change_detection_sensitivity);
break;
case PROP_PA_STATIC_SCENE_DETECTION:
g_value_set_boolean (value, self->pa.static_scene_detection);
break;
case PROP_PA_STATIC_SCENE_DETECTION_SENSITIVITY:
g_value_set_enum (value, self->pa.static_scene_detection_sensitivity);
break;
case PROP_PA_INITIAL_QP:
g_value_set_uint (value, self->pa.initial_qp);
break;
case PROP_PA_MAX_QP:
g_value_set_uint (value, self->pa.max_qp);
break;
case PROP_PA_CAQ_STRENGTH:
g_value_set_enum (value, self->pa.caq_strength);
break;
case PROP_PA_FRAME_SAD:
g_value_set_boolean (value, self->pa.frame_sad);
break;
case PROP_PA_LTR:
g_value_set_boolean (value, self->pa.ltr);
break;
case PROP_PA_LOOKAHEAD_BUFFER_DEPTH:
g_value_set_uint (value, self->pa.lookahead_buffer_depth);
break;
case PROP_PA_PAQ_MODE:
g_value_set_enum (value, self->pa.paq_mode);
break;
case PROP_PA_TAQ_MODE:
g_value_set_enum (value, self->pa.taq_mode);
break;
case PROP_PA_HQMB_MODE:
g_value_set_enum (value, self->pa.hmqb_mode);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -956,7 +1206,32 @@ gst_amf_h264_enc_set_format (GstAmfEncoder * encoder,
GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
}
}
if (dev_caps->pre_encode_supported) {
result = comp->SetProperty (AMF_VIDEO_ENCODER_PREENCODE_ENABLE,
(amf_bool) self->pre_encode);
if (result != AMF_OK) {
GST_ERROR_OBJECT (self, "Failed to set pre-encode, result %"
GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
goto error;
}
}
if (dev_caps->pre_analysis) {
result = comp->SetProperty (AMF_VIDEO_ENCODER_PRE_ANALYSIS_ENABLE,
(amf_bool) self->pa.pre_analysis);
if (result != AMF_OK) {
GST_ERROR_OBJECT (self, "Failed to set pre-analysis, result %"
GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
goto error;
}
if (self->pa.pre_analysis) {
result =
gst_amf_encoder_set_pre_analysis_options (encoder, comp, &self->pa,
&dev_caps->pa_supported);
if (result != AMF_OK)
goto error;
}
}
result = comp->Init (AMF_SURFACE_NV12, info->width, info->height);
if (result != AMF_OK) {
GST_ERROR_OBJECT (self, "Failed to init component, result %"
@ -1360,6 +1635,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 pre_encode_supported;
amf_bool smart_access_supported;
amf_int32 num_val;
gboolean have_nv12 = FALSE;
@ -1492,11 +1768,40 @@ 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_PREENCODE_ENABLE,
&pre_encode_supported);
if (result == AMF_OK)
dev_caps.pre_encode_supported = TRUE;
result = comp->GetProperty (AMF_VIDEO_ENCODER_ENABLE_SMART_ACCESS_VIDEO,
&smart_access_supported);
if (result == AMF_OK)
dev_caps.smart_access_supported = TRUE;
if (dev_caps.pre_analysis) {
amf_bool pre_analysis = FALSE;
// Store initial pre-analysis value
result =
comp->GetProperty (AMF_VIDEO_ENCODER_PRE_ANALYSIS_ENABLE,
&pre_analysis);
if (result != AMF_OK) {
GST_WARNING_OBJECT (device, "Failed to get pre-analysis option");
}
// We need to enable pre-analysis for checking options availability
result =
comp->SetProperty (AMF_VIDEO_ENCODER_PRE_ANALYSIS_ENABLE,
(amf_bool) TRUE);
if (result != AMF_OK) {
GST_WARNING_OBJECT (device, "Failed to set pre-analysis option");
}
gst_amf_encoder_check_pa_supported_options (&dev_caps.pa_supported, comp);
result =
comp->SetProperty (AMF_VIDEO_ENCODER_PRE_ANALYSIS_ENABLE, pre_analysis);
if (result != AMF_OK) {
GST_WARNING_OBJECT (device, "Failed to set pre-analysis options");
}
}
min_width = MAX (in_min_width, 1);
max_width = in_max_width;
if (max_width == 0) {

View file

@ -75,7 +75,9 @@ typedef struct
amf_int64 max_gop_size;
amf_int64 default_gop_size;
guint valign;
gboolean pre_encode_supported;
gboolean smart_access_supported;
GstAmfEncoderPASupportedOptions pa_supported;
} GstAmfH265EncDeviceCaps;
/**
@ -274,7 +276,23 @@ enum
PROP_QP_P,
PROP_REF_FRAMES,
PROP_AUD,
PROP_SMART_ACCESS
PROP_SMART_ACCESS,
PROP_PRE_ENCODE,
PROP_PRE_ANALYSIS,
PROP_PA_ACTIVITY_TYPE,
PROP_PA_SCENE_CHANGE_DETECTION,
PROP_PA_SCENE_CHANGE_DETECTION_SENSITIVITY,
PROP_PA_STATIC_SCENE_DETECTION,
PROP_PA_STATIC_SCENE_DETECTION_SENSITIVITY,
PROP_PA_INITIAL_QP,
PROP_PA_MAX_QP,
PROP_PA_CAQ_STRENGTH,
PROP_PA_FRAME_SAD,
PROP_PA_LTR,
PROP_PA_LOOKAHEAD_BUFFER_DEPTH,
PROP_PA_PAQ_MODE,
PROP_PA_TAQ_MODE,
PROP_PA_HQMB_MODE,
};
#define DEFAULT_USAGE AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCODING
@ -285,6 +303,7 @@ enum
#define DEFAULT_MIN_MAX_QP -1
#define DEFAULT_AUD TRUE
#define DEFAULT_SMART_ACCESS FALSE
#define DEFAULT_PRE_ENCODE FALSE
#define DOC_SINK_CAPS_COMM \
"format = (string) {NV12, P010_10LE}, " \
@ -322,6 +341,8 @@ typedef struct _GstAmfH265Enc
gboolean aud;
gboolean smart_access;
gboolean pre_encode;
GstAmfEncoderPreAnalysis pa;
} GstAmfH265Enc;
typedef struct _GstAmfH265EncClass
@ -362,8 +383,11 @@ gst_amf_h265_enc_class_init (GstAmfH265EncClass * klass, gpointer data)
GstAmfEncoderClass *amf_class = GST_AMF_ENCODER_CLASS (klass);
GstAmfH265EncClassData *cdata = (GstAmfH265EncClassData *) data;
GstAmfH265EncDeviceCaps *dev_caps = &cdata->dev_caps;
GstAmfEncoderPASupportedOptions *pa_supported = &dev_caps->pa_supported;
GParamFlags param_flags = (GParamFlags) (G_PARAM_READWRITE |
GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
GParamFlags pa_param_flags = (GParamFlags) (G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS | GST_PARAM_CONDITIONALLY_AVAILABLE);
GstPadTemplate *pad_templ;
GstCaps *doc_caps;
@ -434,6 +458,12 @@ gst_amf_h265_enc_class_init (GstAmfH265EncClass * klass, gpointer data)
g_object_class_install_property (object_class, PROP_AUD,
g_param_spec_boolean ("aud", "AUD",
"Use AU (Access Unit) delimiter", DEFAULT_AUD, param_flags));
if (cdata->dev_caps.pre_encode_supported) {
g_object_class_install_property (object_class, PROP_PRE_ENCODE,
g_param_spec_boolean ("pre-encode", "Pre-encode",
"Enable pre-encode", DEFAULT_PRE_ENCODE,
(GParamFlags) (param_flags | GST_PARAM_CONDITIONALLY_AVAILABLE)));
}
if (cdata->dev_caps.smart_access_supported) {
g_object_class_install_property (object_class, PROP_SMART_ACCESS,
@ -445,6 +475,113 @@ gst_amf_h265_enc_class_init (GstAmfH265EncClass * klass, gpointer data)
GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS)));
}
if (dev_caps->pre_analysis) {
g_object_class_install_property (object_class, PROP_PRE_ANALYSIS,
g_param_spec_boolean ("pre-analysis", "Pre-analysis",
"Enable pre-analysis", DEFAULT_PRE_ANALYSIS, param_flags));
if (pa_supported->activity_type) {
g_object_class_install_property (object_class, PROP_PA_ACTIVITY_TYPE,
g_param_spec_enum ("pa-activity-type", "Pre-analysis activity type",
"Set the type of activity analysis for pre-analysis",
GST_TYPE_AMF_ENC_PA_ACTIVITY_TYPE, DEFAULT_PA_ACTIVITY_TYPE,
pa_param_flags));
}
if (pa_supported->scene_change_detection) {
g_object_class_install_property (object_class,
PROP_PA_SCENE_CHANGE_DETECTION,
g_param_spec_boolean ("pa-scene-change-detection",
"Pre-analysis scene change detection",
"Enable scene change detection for pre-analysis",
DEFAULT_PA_SCENE_CHANGE_DETECTION, pa_param_flags));
}
if (pa_supported->scene_change_detection_sensitivity) {
g_object_class_install_property (object_class,
PROP_PA_SCENE_CHANGE_DETECTION_SENSITIVITY,
g_param_spec_enum ("pa-scene-change-detection-sensitivity",
"Pre-analysis scene change detection sensitivity",
"Set the sensitivity of scene change detection for pre-analysis",
GST_TYPE_AMF_ENC_PA_SCENE_CHANGE_DETECTION_SENSITIVITY,
DEFAULT_PA_SCENE_CHANGE_DETECTION_SENSITIVITY, pa_param_flags));
}
if (pa_supported->static_scene_detection) {
g_object_class_install_property (object_class,
PROP_PA_STATIC_SCENE_DETECTION,
g_param_spec_boolean ("pa-static-scene-detection",
"Pre-analysis static scene detection",
"Enable static scene detection for pre-analysis",
DEFAULT_PA_STATIC_SCENE_DETECTION, pa_param_flags));
}
if (pa_supported->static_scene_detection_sensitivity) {
g_object_class_install_property (object_class,
PROP_PA_STATIC_SCENE_DETECTION_SENSITIVITY,
g_param_spec_enum ("pa-static-scene-detection-sensitivity",
"Pre-analysis static scene detection sensitivity",
"Set the sensitivity of static scene detection for pre-analysis",
GST_TYPE_AMF_ENC_PA_STATIC_SCENE_DETECTION_SENSITIVITY,
DEFAULT_PA_STATIC_SCENE_DETECTION_SENSITIVITY, pa_param_flags));
}
if (pa_supported->initial_qp) {
g_object_class_install_property (object_class, PROP_PA_INITIAL_QP,
g_param_spec_uint ("pa-initial-qp", "Pre-analysis initial QP",
"The QP value that is used immediately after a scene change", 0,
51, DEFAULT_PA_INITIAL_QP, pa_param_flags));
}
if (pa_supported->max_qp) {
g_object_class_install_property (object_class, PROP_PA_MAX_QP,
g_param_spec_uint ("pa-max-qp", "Pre-analysis max QP",
"The QP threshold to allow a skip frame", 0, 51,
DEFAULT_PA_MAX_QP, pa_param_flags));
}
if (pa_supported->caq_strength) {
g_object_class_install_property (object_class, PROP_PA_CAQ_STRENGTH,
g_param_spec_enum ("pa-caq-strength", "Pre-analysis CAQ strength",
"Content Adaptive Quantization strength for pre-analysis",
GST_TYPE_AMF_ENC_PA_CAQ_STRENGTH, DEFAULT_PA_CAQ_STRENGTH,
pa_param_flags));
}
if (pa_supported->frame_sad) {
g_object_class_install_property (object_class, PROP_PA_FRAME_SAD,
g_param_spec_boolean ("pa-frame-sad", "Pre-analysis SAD algorithm",
"Enable Frame SAD algorithm", DEFAULT_PA_FRAME_SAD,
pa_param_flags));
}
if (pa_supported->ltr) {
g_object_class_install_property (object_class, PROP_PA_LTR,
g_param_spec_boolean ("pa-ltr", "Pre-analysis LTR",
"Enable long term reference frame management", DEFAULT_PA_LTR,
pa_param_flags));
}
if (pa_supported->lookahead_buffer_depth) {
g_object_class_install_property (object_class,
PROP_PA_LOOKAHEAD_BUFFER_DEPTH,
g_param_spec_uint ("pa-lookahead-buffer-depth",
"Pre-analysis lookahead buffer depth",
"Set the PA lookahead buffer size", 0, 41,
DEFAULT_PA_LOOKAHEAD_BUFFER_DEPTH, pa_param_flags));
}
if (pa_supported->paq_mode) {
g_object_class_install_property (object_class, PROP_PA_PAQ_MODE,
g_param_spec_enum ("pa-paq-mode", "Pre-analysis PAQ mode",
"Set the perceptual adaptive quantization mode",
GST_TYPE_AMF_ENC_PA_PAQ_MODE, DEFAULT_PA_PAQ_MODE,
pa_param_flags));
}
if (pa_supported->taq_mode) {
g_object_class_install_property (object_class, PROP_PA_TAQ_MODE,
g_param_spec_enum ("pa-taq-mode", "Pre-analysis TAQ mode",
"Set the temporal adaptive quantization mode",
GST_TYPE_AMF_ENC_PA_TAQ_MODE, DEFAULT_PA_TAQ_MODE,
pa_param_flags));
}
if (pa_supported->hmqb_mode) {
g_object_class_install_property (object_class, PROP_PA_HQMB_MODE,
g_param_spec_enum ("pa-hqmb-mode", "Pre-analysis HQMB mode",
"Set the PA high motion quality boost mode",
GST_TYPE_AMF_ENC_PA_HQMB_MODE, DEFAULT_PA_HQMB_MODE,
pa_param_flags));
}
}
gst_element_class_set_metadata (element_class,
"AMD AMF H.265 Video Encoder",
"Codec/Encoder/Video/Hardware",
@ -518,6 +655,25 @@ gst_amf_h265_enc_init (GstAmfH265Enc * self)
self->ref_frames = (guint) dev_caps->min_ref_frames;
self->aud = DEFAULT_AUD;
self->smart_access = DEFAULT_SMART_ACCESS;
self->pre_encode = DEFAULT_PRE_ENCODE;
// Init pre-analysis options
self->pa.pre_analysis = DEFAULT_PRE_ANALYSIS;
self->pa.activity_type = DEFAULT_PA_ACTIVITY_TYPE;
self->pa.scene_change_detection = DEFAULT_PA_SCENE_CHANGE_DETECTION;
self->pa.scene_change_detection_sensitivity =
DEFAULT_PA_SCENE_CHANGE_DETECTION_SENSITIVITY;
self->pa.static_scene_detection = DEFAULT_PA_STATIC_SCENE_DETECTION;
self->pa.static_scene_detection_sensitivity =
DEFAULT_PA_STATIC_SCENE_DETECTION_SENSITIVITY;
self->pa.initial_qp = DEFAULT_PA_INITIAL_QP;
self->pa.max_qp = DEFAULT_PA_MAX_QP;
self->pa.caq_strength = DEFAULT_PA_CAQ_STRENGTH;
self->pa.frame_sad = DEFAULT_PA_FRAME_SAD;
self->pa.ltr = DEFAULT_PA_LTR;
self->pa.lookahead_buffer_depth = DEFAULT_PA_LOOKAHEAD_BUFFER_DEPTH;
self->pa.paq_mode = DEFAULT_PA_PAQ_MODE;
self->pa.taq_mode = DEFAULT_PA_TAQ_MODE;
self->pa.hmqb_mode = DEFAULT_PA_HQMB_MODE;
}
static void
@ -632,6 +788,53 @@ gst_amf_h265_enc_set_property (GObject * object, guint prop_id,
case PROP_SMART_ACCESS:
update_bool (self, &self->smart_access, value);
break;
case PROP_PRE_ENCODE:
update_bool (self, &self->pre_encode, value);
break;
case PROP_PRE_ANALYSIS:
update_bool (self, &self->pa.pre_analysis, value);
break;
case PROP_PA_ACTIVITY_TYPE:
update_enum (self, &self->pa.activity_type, value);
break;
case PROP_PA_SCENE_CHANGE_DETECTION:
update_bool (self, &self->pa.scene_change_detection, value);
break;
case PROP_PA_SCENE_CHANGE_DETECTION_SENSITIVITY:
update_enum (self, &self->pa.scene_change_detection_sensitivity, value);
break;
case PROP_PA_STATIC_SCENE_DETECTION:
update_bool (self, &self->pa.static_scene_detection, value);
break;
case PROP_PA_STATIC_SCENE_DETECTION_SENSITIVITY:
update_enum (self, &self->pa.static_scene_detection_sensitivity, value);
break;
case PROP_PA_INITIAL_QP:
update_uint (self, &self->pa.initial_qp, value);
break;
case PROP_PA_MAX_QP:
update_uint (self, &self->pa.max_qp, value);
break;
case PROP_PA_CAQ_STRENGTH:
update_enum (self, &self->pa.caq_strength, value);
break;
case PROP_PA_FRAME_SAD:
update_bool (self, &self->pa.frame_sad, value);
case PROP_PA_LTR:
update_bool (self, &self->pa.ltr, value);
break;
case PROP_PA_LOOKAHEAD_BUFFER_DEPTH:
update_uint (self, &self->pa.lookahead_buffer_depth, value);
break;
case PROP_PA_PAQ_MODE:
update_enum (self, &self->pa.paq_mode, value);
break;
case PROP_PA_TAQ_MODE:
update_enum (self, &self->pa.taq_mode, value);
break;
case PROP_PA_HQMB_MODE:
update_enum (self, &self->pa.hmqb_mode, value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -695,6 +898,54 @@ gst_amf_h265_enc_get_property (GObject * object, guint prop_id,
case PROP_SMART_ACCESS:
g_value_set_boolean (value, self->smart_access);
break;
case PROP_PRE_ENCODE:
g_value_set_boolean (value, self->pre_encode);
break;
case PROP_PRE_ANALYSIS:
g_value_set_boolean (value, self->pa.pre_analysis);
break;
case PROP_PA_ACTIVITY_TYPE:
g_value_set_enum (value, self->pa.activity_type);
break;
case PROP_PA_SCENE_CHANGE_DETECTION:
g_value_set_boolean (value, self->pa.scene_change_detection);
break;
case PROP_PA_SCENE_CHANGE_DETECTION_SENSITIVITY:
g_value_set_enum (value, self->pa.scene_change_detection_sensitivity);
break;
case PROP_PA_STATIC_SCENE_DETECTION:
g_value_set_boolean (value, self->pa.static_scene_detection);
break;
case PROP_PA_STATIC_SCENE_DETECTION_SENSITIVITY:
g_value_set_enum (value, self->pa.static_scene_detection_sensitivity);
break;
case PROP_PA_INITIAL_QP:
g_value_set_uint (value, self->pa.initial_qp);
break;
case PROP_PA_MAX_QP:
g_value_set_uint (value, self->pa.max_qp);
break;
case PROP_PA_CAQ_STRENGTH:
g_value_set_enum (value, self->pa.caq_strength);
break;
case PROP_PA_FRAME_SAD:
g_value_set_boolean (value, self->pa.frame_sad);
break;
case PROP_PA_LTR:
g_value_set_boolean (value, self->pa.ltr);
break;
case PROP_PA_LOOKAHEAD_BUFFER_DEPTH:
g_value_set_uint (value, self->pa.lookahead_buffer_depth);
break;
case PROP_PA_PAQ_MODE:
g_value_set_enum (value, self->pa.paq_mode);
break;
case PROP_PA_TAQ_MODE:
g_value_set_enum (value, self->pa.taq_mode);
break;
case PROP_PA_HQMB_MODE:
g_value_set_enum (value, self->pa.hmqb_mode);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -1038,6 +1289,33 @@ gst_amf_h265_enc_set_format (GstAmfEncoder * encoder,
}
}
if (dev_caps->pre_encode_supported) {
result = comp->SetProperty (AMF_VIDEO_ENCODER_HEVC_PREENCODE_ENABLE,
(amf_bool) self->pre_encode);
if (result != AMF_OK) {
GST_ERROR_OBJECT (self, "Failed to set pre-encode, result %"
GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
goto error;
}
}
if (dev_caps->pre_analysis) {
result = comp->SetProperty (AMF_VIDEO_ENCODER_HEVC_PRE_ANALYSIS_ENABLE,
(amf_bool) self->pa.pre_analysis);
if (result != AMF_OK) {
GST_ERROR_OBJECT (self, "Failed to set pre-analysis, result %"
GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
goto error;
}
if (self->pa.pre_analysis) {
result =
gst_amf_encoder_set_pre_analysis_options (encoder, comp, &self->pa,
&dev_caps->pa_supported);
if (result != AMF_OK)
goto error;
}
}
result = comp->Init (surface_format, info->width, info->height);
if (result != AMF_OK) {
GST_ERROR_OBJECT (self, "Failed to init component, result %"
@ -1277,6 +1555,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 pre_encode_supported;
amf_bool smart_access_supported;
amf_int32 num_val;
std::set < std::string > formats;
@ -1415,11 +1694,41 @@ 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_PREENCODE_ENABLE,
&pre_encode_supported);
if (result == AMF_OK)
dev_caps.pre_encode_supported = TRUE;
result = comp->GetProperty (AMF_VIDEO_ENCODER_HEVC_ENABLE_SMART_ACCESS_VIDEO,
&smart_access_supported);
if (result == AMF_OK)
dev_caps.smart_access_supported = TRUE;
if (dev_caps.pre_analysis) {
amf_bool pre_analysis = FALSE;
// Store initial pre-analysis value
result =
comp->GetProperty (AMF_VIDEO_ENCODER_HEVC_PRE_ANALYSIS_ENABLE,
&pre_analysis);
if (result != AMF_OK) {
GST_WARNING_OBJECT (device, "Failed to get pre-analysis option");
}
// We need to enable pre-analysis for checking options availability
result =
comp->SetProperty (AMF_VIDEO_ENCODER_HEVC_PRE_ANALYSIS_ENABLE,
(amf_bool) TRUE);
if (result != AMF_OK) {
GST_WARNING_OBJECT (device, "Failed to set pre-analysis option");
}
gst_amf_encoder_check_pa_supported_options (&dev_caps.pa_supported, comp);
result =
comp->SetProperty (AMF_VIDEO_ENCODER_HEVC_PRE_ANALYSIS_ENABLE,
pre_analysis);
if (result != AMF_OK) {
GST_WARNING_OBJECT (device, "Failed to set pre-analysis option");
}
}
{
const AMFPropertyInfo *pinfo = nullptr;
result = comp->GetPropertyInfo (AMF_VIDEO_ENCODER_HEVC_GOP_SIZE, &pinfo);