diff --git a/subprojects/gst-plugins-bad/sys/nvcodec/gstnvenc.c b/subprojects/gst-plugins-bad/sys/nvcodec/gstnvenc.c index 040414ccb8..c65c85a231 100644 --- a/subprojects/gst-plugins-bad/sys/nvcodec/gstnvenc.c +++ b/subprojects/gst-plugins-bad/sys/nvcodec/gstnvenc.c @@ -150,6 +150,18 @@ NvEncGetEncodePresetConfig (void *encoder, GUID encodeGUID, presetConfig); } +NVENCSTATUS NVENCAPI +NvEncGetEncodePresetConfigEx (void *encoder, GUID encodeGUID, + GUID presetGUID, NV_ENC_TUNING_INFO tuningInfo, + NV_ENC_PRESET_CONFIG * presetConfig) +{ + if (!nvenc_api.nvEncGetEncodePresetConfigEx) + return NV_ENC_ERR_UNIMPLEMENTED; + + return nvenc_api.nvEncGetEncodePresetConfigEx (encoder, encodeGUID, + presetGUID, tuningInfo, presetConfig); +} + NVENCSTATUS NVENCAPI NvEncGetEncodeCaps (void *encoder, GUID encodeGUID, NV_ENC_CAPS_PARAM * capsParam, int *capsVal) diff --git a/subprojects/gst-plugins-bad/sys/nvcodec/gstnvencoder.cpp b/subprojects/gst-plugins-bad/sys/nvcodec/gstnvencoder.cpp index bacbae01ad..0a17c259db 100644 --- a/subprojects/gst-plugins-bad/sys/nvcodec/gstnvencoder.cpp +++ b/subprojects/gst-plugins-bad/sys/nvcodec/gstnvencoder.cpp @@ -2063,17 +2063,32 @@ gst_nv_encoder_preset_get_type (void) { static GType preset_type = 0; static const GEnumValue presets[] = { - {GST_NV_ENCODER_PRESET_DEFAULT, "Default", "default"}, - {GST_NV_ENCODER_PRESET_HP, "High Performance", "hp"}, - {GST_NV_ENCODER_PRESET_HQ, "High Quality", "hq"}, - {GST_NV_ENCODER_PRESET_LOW_LATENCY_DEFAULT, "Low Latency", "low-latency"}, - {GST_NV_ENCODER_PRESET_LOW_LATENCY_HQ, "Low Latency, High Quality", + {GST_NV_ENCODER_PRESET_DEFAULT, "Default (deprecated, use p1~7 with tune)", + "default"}, + {GST_NV_ENCODER_PRESET_HP, + "High Performance (deprecated, use p1~7 with tune)", "hp"}, + {GST_NV_ENCODER_PRESET_HQ, "High Quality (deprecated, use p1~7 with tune)", + "hq"}, + {GST_NV_ENCODER_PRESET_LOW_LATENCY_DEFAULT, + "Low Latency (deprecated, use p1~7 with tune)", "low-latency"}, + {GST_NV_ENCODER_PRESET_LOW_LATENCY_HQ, + "Low Latency (deprecated, use p1~7 with tune), High Quality", "low-latency-hq"}, - {GST_NV_ENCODER_PRESET_LOW_LATENCY_HP, "Low Latency, High Performance", + {GST_NV_ENCODER_PRESET_LOW_LATENCY_HP, + "Low Latency (deprecated, use p1~7 with tune), High Performance", "low-latency-hp"}, - {GST_NV_ENCODER_PRESET_LOSSLESS_DEFAULT, "Lossless", "lossless"}, - {GST_NV_ENCODER_PRESET_LOSSLESS_HP, "Lossless, High Performance", + {GST_NV_ENCODER_PRESET_LOSSLESS_DEFAULT, + "Lossless (deprecated, use p1~7 with tune)", "lossless"}, + {GST_NV_ENCODER_PRESET_LOSSLESS_HP, + "Lossless (deprecated, use p1~7 with tune), High Performance", "lossless-hp"}, + {GST_NV_ENCODER_PRESET_P1, "P1, fastest", "p1"}, + {GST_NV_ENCODER_PRESET_P2, "P2, faster", "p2"}, + {GST_NV_ENCODER_PRESET_P3, "P3, fast", "p3"}, + {GST_NV_ENCODER_PRESET_P4, "P4, medium", "p4"}, + {GST_NV_ENCODER_PRESET_P5, "P5, slow", "p5"}, + {GST_NV_ENCODER_PRESET_P6, "P6, slower", "p6"}, + {GST_NV_ENCODER_PRESET_P7, "P7, slowest", "p7"}, {0, NULL, NULL}, }; @@ -2086,41 +2101,6 @@ gst_nv_encoder_preset_get_type (void) return preset_type; } -void -gst_nv_encoder_preset_to_guid (GstNvEncoderPreset preset, GUID * guid) -{ - switch (preset) { - case GST_NV_ENCODER_PRESET_DEFAULT: - *guid = NV_ENC_PRESET_DEFAULT_GUID; - break; - case GST_NV_ENCODER_PRESET_HP: - *guid = NV_ENC_PRESET_HP_GUID; - break; - case GST_NV_ENCODER_PRESET_HQ: - *guid = NV_ENC_PRESET_HQ_GUID; - break; - case GST_NV_ENCODER_PRESET_LOW_LATENCY_DEFAULT: - *guid = NV_ENC_PRESET_LOW_LATENCY_DEFAULT_GUID; - break; - case GST_NV_ENCODER_PRESET_LOW_LATENCY_HQ: - *guid = NV_ENC_PRESET_LOW_LATENCY_HQ_GUID; - break; - case GST_NV_ENCODER_PRESET_LOW_LATENCY_HP: - *guid = NV_ENC_PRESET_LOW_LATENCY_HP_GUID; - break; - case GST_NV_ENCODER_PRESET_LOSSLESS_DEFAULT: - *guid = NV_ENC_PRESET_LOSSLESS_DEFAULT_GUID; - break; - case GST_NV_ENCODER_PRESET_LOSSLESS_HP: - *guid = NV_ENC_PRESET_LOSSLESS_HP_GUID; - break; - default: - break; - } - - *guid = NV_ENC_PRESET_DEFAULT_GUID; -} - /** * GstNvEncoderRCMode: * @@ -2135,9 +2115,12 @@ gst_nv_encoder_rc_mode_get_type (void) {GST_NV_ENCODER_RC_MODE_VBR, "Variable Bit Rate", "vbr"}, {GST_NV_ENCODER_RC_MODE_CBR, "Constant Bit Rate", "cbr"}, {GST_NV_ENCODER_RC_MODE_CBR_LOWDELAY_HQ, - "Low-Delay CBR, High Quality", "cbr-ld-hq"}, - {GST_NV_ENCODER_RC_MODE_CBR_HQ, "CBR, High Quality (slower)", "cbr-hq"}, - {GST_NV_ENCODER_RC_MODE_VBR_HQ, "VBR, High Quality (slower)", "vbr-hq"}, + "Low-Delay CBR, High Quality " + "(deprecated, use cbr with tune and multipass)", "cbr-ld-hq"}, + {GST_NV_ENCODER_RC_MODE_CBR_HQ, "CBR, High Quality " + "(deprecated, use cbr with tune and multipass)", "cbr-hq"}, + {GST_NV_ENCODER_RC_MODE_VBR_HQ, "VBR, High Quality " + "(deprecated, use vbr with tune and multipass)", "vbr-hq"}, {0, NULL, NULL}, }; @@ -2150,27 +2133,148 @@ gst_nv_encoder_rc_mode_get_type (void) return rc_mode_type; } -NV_ENC_PARAMS_RC_MODE -gst_nv_encoder_rc_mode_to_native (GstNvEncoderRCMode rc_mode) +void +gst_nv_encoder_preset_to_native (GstNvEncoderPreset preset, + GstNvEncoderTune tune, GUID * preset_guid, NV_ENC_TUNING_INFO * tune_info) { - switch (rc_mode) { - case GST_NV_ENCODER_RC_MODE_CONSTQP: - return NV_ENC_PARAMS_RC_CONSTQP; - case GST_NV_ENCODER_RC_MODE_VBR: - return NV_ENC_PARAMS_RC_VBR; - case GST_NV_ENCODER_RC_MODE_CBR: - return NV_ENC_PARAMS_RC_CBR; - case GST_NV_ENCODER_RC_MODE_CBR_LOWDELAY_HQ: - return NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ; - case GST_NV_ENCODER_RC_MODE_CBR_HQ: - return NV_ENC_PARAMS_RC_CBR_HQ; - case GST_NV_ENCODER_RC_MODE_VBR_HQ: - return NV_ENC_PARAMS_RC_VBR_HQ; + gboolean is_low_latency = FALSE; + gboolean is_lossless = FALSE; + switch (preset) { + case GST_NV_ENCODER_PRESET_DEFAULT: + *preset_guid = NV_ENC_PRESET_P4_GUID; + break; + case GST_NV_ENCODER_PRESET_HP: + *preset_guid = NV_ENC_PRESET_P1_GUID; + break; + case GST_NV_ENCODER_PRESET_HQ: + *preset_guid = NV_ENC_PRESET_P7_GUID; + break; + case GST_NV_ENCODER_PRESET_LOW_LATENCY_DEFAULT: + is_low_latency = TRUE; + *preset_guid = NV_ENC_PRESET_P4_GUID; + break; + case GST_NV_ENCODER_PRESET_LOW_LATENCY_HQ: + is_low_latency = TRUE; + *preset_guid = NV_ENC_PRESET_P7_GUID; + break; + case GST_NV_ENCODER_PRESET_LOW_LATENCY_HP: + is_low_latency = TRUE; + *preset_guid = NV_ENC_PRESET_P1_GUID; + break; + case GST_NV_ENCODER_PRESET_LOSSLESS_DEFAULT: + is_lossless = TRUE; + *preset_guid = NV_ENC_PRESET_P4_GUID; + break; + case GST_NV_ENCODER_PRESET_LOSSLESS_HP: + is_lossless = TRUE; + *preset_guid = NV_ENC_PRESET_P1_GUID; + break; + case GST_NV_ENCODER_PRESET_P1: + *preset_guid = NV_ENC_PRESET_P1_GUID; + break; + case GST_NV_ENCODER_PRESET_P2: + *preset_guid = NV_ENC_PRESET_P2_GUID; + break; + case GST_NV_ENCODER_PRESET_P3: + *preset_guid = NV_ENC_PRESET_P3_GUID; + break; + case GST_NV_ENCODER_PRESET_P4: + *preset_guid = NV_ENC_PRESET_P4_GUID; + break; + case GST_NV_ENCODER_PRESET_P5: + *preset_guid = NV_ENC_PRESET_P5_GUID; + break; + case GST_NV_ENCODER_PRESET_P6: + *preset_guid = NV_ENC_PRESET_P6_GUID; + break; + case GST_NV_ENCODER_PRESET_P7: + *preset_guid = NV_ENC_PRESET_P7_GUID; + break; default: + *preset_guid = NV_ENC_PRESET_P4_GUID; break; } - return NV_ENC_PARAMS_RC_VBR; + switch (tune) { + case GST_NV_ENCODER_TUNE_DEFAULT: + if (is_low_latency) + *tune_info = NV_ENC_TUNING_INFO_LOW_LATENCY; + else if (is_lossless) + *tune_info = NV_ENC_TUNING_INFO_LOSSLESS; + else + *tune_info = NV_ENC_TUNING_INFO_HIGH_QUALITY; + break; + case GST_NV_ENCODER_TUNE_HIGH_QUALITY: + *tune_info = NV_ENC_TUNING_INFO_HIGH_QUALITY; + break; + case GST_NV_ENCODER_TUNE_LOW_LATENCY: + *tune_info = NV_ENC_TUNING_INFO_LOW_LATENCY; + break; + case GST_NV_ENCODER_TUNE_ULTRA_LOW_LATENCY: + *tune_info = NV_ENC_TUNING_INFO_ULTRA_LOW_LATENCY; + break; + case GST_NV_ENCODER_TUNE_LOSSLESS: + *tune_info = NV_ENC_TUNING_INFO_LOSSLESS; + break; + default: + *tune_info = NV_ENC_TUNING_INFO_HIGH_QUALITY; + break; + } +} + +void +gst_nv_encoder_rc_mode_to_native (GstNvEncoderRCMode rc_mode, + GstNvEncoderMultiPass multipass, NV_ENC_PARAMS_RC_MODE * rc_mode_native, + NV_ENC_MULTI_PASS * multipass_native) +{ + gboolean is_hq = FALSE; + switch (rc_mode) { + case GST_NV_ENCODER_RC_MODE_CONSTQP: + *rc_mode_native = NV_ENC_PARAMS_RC_CONSTQP; + break; + case GST_NV_ENCODER_RC_MODE_VBR: + *rc_mode_native = NV_ENC_PARAMS_RC_VBR; + break; + case GST_NV_ENCODER_RC_MODE_CBR: + *rc_mode_native = NV_ENC_PARAMS_RC_CBR; + break; + case GST_NV_ENCODER_RC_MODE_CBR_LOWDELAY_HQ: + is_hq = TRUE; + *rc_mode_native = NV_ENC_PARAMS_RC_CBR; + break; + case GST_NV_ENCODER_RC_MODE_CBR_HQ: + is_hq = TRUE; + *rc_mode_native = NV_ENC_PARAMS_RC_CBR; + break; + case GST_NV_ENCODER_RC_MODE_VBR_HQ: + is_hq = TRUE; + *rc_mode_native = NV_ENC_PARAMS_RC_VBR; + break; + default: + *rc_mode_native = NV_ENC_PARAMS_RC_VBR; + break; + } + + switch (multipass) { + case GST_NV_ENCODER_MULTI_PASS_DEFAULT: + if (is_hq) + *multipass_native = NV_ENC_TWO_PASS_QUARTER_RESOLUTION; + else + *multipass_native = NV_ENC_MULTI_PASS_DISABLED; + break; + case GST_NV_ENCODER_MULTI_PASS_DISABLED: + *multipass_native = NV_ENC_MULTI_PASS_DISABLED; + break; + case GST_NV_ENCODER_TWO_PASS_QUARTER_RESOLUTION: + *multipass_native = NV_ENC_TWO_PASS_QUARTER_RESOLUTION; + break; + case GST_NV_ENCODER_TWO_PASS_FULL_RESOLUTION: + *multipass_native = NV_ENC_TWO_PASS_FULL_RESOLUTION; + break; + default: + *multipass_native = NV_ENC_MULTI_PASS_DISABLED; + break; + } } /** @@ -2215,6 +2319,113 @@ gst_nv_encoder_sei_insert_mode_get_type (void) return type; } +/** + * GstNvEncoderMultiPass: + * + * Since: 1.24 + */ +GType +gst_nv_encoder_multi_pass_get_type (void) +{ + static GType type = 0; + static const GEnumValue modes[] = { + /** + * GstNvEncoderMultiPass::disabled: + * + * Since: 1.24 + */ + {GST_NV_ENCODER_MULTI_PASS_DEFAULT, + "Disable multi-pass when cqp, vbr or cbr is used. " + "Otherwise encoder will select it based on rc-mode", "default"}, + + /** + * GstNvEncoderMultiPass::disabled: + * + * Since: 1.24 + */ + {GST_NV_ENCODER_MULTI_PASS_DISABLED, "Disabled", "disabled"}, + + /** + * GstNvEncoderMultiPass::two-pass-quarter: + * + * Since: 1.24 + */ + {GST_NV_ENCODER_TWO_PASS_QUARTER_RESOLUTION, + "Two pass with quarter resolution encoding in first pass", + "two-pass-quarter"}, + + /** + * GstNvEncoderMultiPass::two-pass: + * + * Since: 1.24 + */ + {GST_NV_ENCODER_TWO_PASS_FULL_RESOLUTION, "Two pass", "two-pass"}, + {0, nullptr, nullptr} + }; + + GST_CUDA_CALL_ONCE_BEGIN { + type = g_enum_register_static ("GstNvEncoderMultiPass", modes); + } GST_CUDA_CALL_ONCE_END; + + return type; +} + +/** + * GstNvEncoderTune: + * + * Since: 1.24 + */ +GType +gst_nv_encoder_tune_get_type (void) +{ + static GType type = 0; + static const GEnumValue modes[] = { + /** + * GstNvEncoderTune::default: + * + * Since: 1.24 + */ + {GST_NV_ENCODER_TUNE_DEFAULT, "High quality when p1~7 preset is used. " + "Otherwise encoder will select it based on preset", "default"}, + + /** + * GstNvEncoderTune::high-quality: + * + * Since: 1.24 + */ + {GST_NV_ENCODER_TUNE_HIGH_QUALITY, "High quality", "high-quality"}, + + /** + * GstNvEncoderMultiPass::low-latency: + * + * Since: 1.24 + */ + {GST_NV_ENCODER_TUNE_LOW_LATENCY, "Low latency", "low-latency"}, + + /** + * GstNvEncoderMultiPass::ultra-low-latency: + * + * Since: 1.24 + */ + {GST_NV_ENCODER_TUNE_ULTRA_LOW_LATENCY, "Ultra low latency", + "ultra-low-latency"}, + + /** + * GstNvEncoderMultiPass::lossless: + * + * Since: 1.24 + */ + {GST_NV_ENCODER_TUNE_LOSSLESS, "Lossless", "lossless"}, + {0, nullptr, nullptr} + }; + + GST_CUDA_CALL_ONCE_BEGIN { + type = g_enum_register_static ("GstNvEncoderTune", modes); + } GST_CUDA_CALL_ONCE_END; + + return type; +} + GstNvEncoderClassData * gst_nv_encoder_class_data_new (void) { diff --git a/subprojects/gst-plugins-bad/sys/nvcodec/gstnvencoder.h b/subprojects/gst-plugins-bad/sys/nvcodec/gstnvencoder.h index 71a846f08d..df57bf858a 100644 --- a/subprojects/gst-plugins-bad/sys/nvcodec/gstnvencoder.h +++ b/subprojects/gst-plugins-bad/sys/nvcodec/gstnvencoder.h @@ -69,6 +69,13 @@ typedef enum GST_NV_ENCODER_PRESET_LOW_LATENCY_HP, GST_NV_ENCODER_PRESET_LOSSLESS_DEFAULT, GST_NV_ENCODER_PRESET_LOSSLESS_HP, + GST_NV_ENCODER_PRESET_P1, + GST_NV_ENCODER_PRESET_P2, + GST_NV_ENCODER_PRESET_P3, + GST_NV_ENCODER_PRESET_P4, + GST_NV_ENCODER_PRESET_P5, + GST_NV_ENCODER_PRESET_P6, + GST_NV_ENCODER_PRESET_P7, } GstNvEncoderPreset; #define GST_TYPE_NV_ENCODER_RC_MODE (gst_nv_encoder_rc_mode_get_type()) @@ -94,6 +101,27 @@ typedef enum GST_NV_ENCODER_SEI_DISABLED, } GstNvEncoderSeiInsertMode; +#define GST_TYPE_NV_ENCODER_MULTI_PASS (gst_nv_encoder_multi_pass_get_type ()) +GType gst_nv_encoder_multi_pass_get_type (void); +typedef enum +{ + GST_NV_ENCODER_MULTI_PASS_DEFAULT = 0, + GST_NV_ENCODER_MULTI_PASS_DISABLED = 1, + GST_NV_ENCODER_TWO_PASS_QUARTER_RESOLUTION = 2, + GST_NV_ENCODER_TWO_PASS_FULL_RESOLUTION = 3, +} GstNvEncoderMultiPass; + +#define GST_TYPE_NV_ENCODER_TUNE (gst_nv_encoder_tune_get_type ()) +GType gst_nv_encoder_tune_get_type (void); +typedef enum +{ + GST_NV_ENCODER_TUNE_DEFAULT = 0, + GST_NV_ENCODER_TUNE_HIGH_QUALITY = 1, + GST_NV_ENCODER_TUNE_LOW_LATENCY = 2, + GST_NV_ENCODER_TUNE_ULTRA_LOW_LATENCY = 3, + GST_NV_ENCODER_TUNE_LOSSLESS = 4, +} GstNvEncoderTune; + typedef struct { gint max_bframes; @@ -221,10 +249,16 @@ struct _GstNvEncoderClass GType gst_nv_encoder_get_type (void); -void gst_nv_encoder_preset_to_guid (GstNvEncoderPreset preset, - GUID * guid); +void gst_nv_encoder_preset_to_native (GstNvEncoderPreset preset, + GstNvEncoderTune tune, + GUID * preset_guid, + NV_ENC_TUNING_INFO * tune_info); + +void gst_nv_encoder_rc_mode_to_native (GstNvEncoderRCMode rc_mode, + GstNvEncoderMultiPass multipass, + NV_ENC_PARAMS_RC_MODE * rc_mode_native, + NV_ENC_MULTI_PASS * multipass_native); -NV_ENC_PARAMS_RC_MODE gst_nv_encoder_rc_mode_to_native (GstNvEncoderRCMode rc_mode); void gst_nv_encoder_set_device_mode (GstNvEncoder * encoder, GstNvEncoderDeviceMode mode, diff --git a/subprojects/gst-plugins-bad/sys/nvcodec/gstnvh264encoder.cpp b/subprojects/gst-plugins-bad/sys/nvcodec/gstnvh264encoder.cpp index 82db99cbf1..0070220621 100644 --- a/subprojects/gst-plugins-bad/sys/nvcodec/gstnvh264encoder.cpp +++ b/subprojects/gst-plugins-bad/sys/nvcodec/gstnvh264encoder.cpp @@ -66,6 +66,8 @@ enum /* init params */ PROP_PRESET, + PROP_TUNE, + PROP_MULTI_PASS, PROP_WEIGHTED_PRED, /* encoding config */ @@ -109,7 +111,9 @@ enum PROP_REPEAT_SEQUENCE_HEADER, }; -#define DEFAULT_PRESET GST_NV_ENCODER_PRESET_DEFAULT +#define DEFAULT_PRESET GST_NV_ENCODER_PRESET_P4 +#define DEFAULT_TUNE GST_NV_ENCODER_TUNE_DEFAULT +#define DEFAULT_MULTI_PASS GST_NV_ENCODER_MULTI_PASS_DEFAULT #define DEFAULT_WEIGHTED_PRED FALSE #define DEFAULT_GOP_SIZE 30 #define DEFAULT_B_FRAMES 0 @@ -152,6 +156,8 @@ typedef struct _GstNvH264Encoder gint64 adapter_luid; GstNvEncoderPreset preset; + GstNvEncoderMultiPass multipass; + GstNvEncoderTune tune; gboolean weighted_pred; gint gop_size; @@ -298,6 +304,14 @@ gst_nv_h264_encoder_class_init (GstNvH264EncoderClass * klass, gpointer data) g_param_spec_enum ("preset", "Encoding Preset", "Encoding Preset", GST_TYPE_NV_ENCODER_PRESET, DEFAULT_PRESET, param_flags)); + g_object_class_install_property (object_class, PROP_TUNE, + g_param_spec_enum ("tune", "Tune", + "Encoding tune", GST_TYPE_NV_ENCODER_TUNE, + DEFAULT_TUNE, param_flags)); + g_object_class_install_property (object_class, PROP_MULTI_PASS, + g_param_spec_enum ("multi-pass", "Multi Pass", + "Multi pass encoding", GST_TYPE_NV_ENCODER_MULTI_PASS, + DEFAULT_MULTI_PASS, param_flags)); if (dev_caps->weighted_prediction) { g_object_class_install_property (object_class, PROP_WEIGHTED_PRED, g_param_spec_boolean ("weighted-pred", "Weighted Pred", @@ -501,6 +515,8 @@ gst_nv_h264_encoder_init (GstNvH264Encoder * self) self->cuda_device_id = klass->cuda_device_id; self->adapter_luid = klass->adapter_luid; self->preset = DEFAULT_PRESET; + self->tune = DEFAULT_TUNE; + self->multipass = DEFAULT_MULTI_PASS; self->weighted_pred = DEFAULT_WEIGHTED_PRED; self->gop_size = DEFAULT_GOP_SIZE; self->bframes = DEFAULT_B_FRAMES; @@ -700,6 +716,23 @@ gst_nv_h264_encoder_set_property (GObject * object, guint prop_id, } break; } + case PROP_TUNE:{ + GstNvEncoderTune tune = (GstNvEncoderTune) g_value_get_enum (value); + if (tune != self->tune) { + self->tune = tune; + self->init_param_updated = TRUE; + } + break; + } + case PROP_MULTI_PASS:{ + GstNvEncoderMultiPass multipass = + (GstNvEncoderMultiPass) g_value_get_enum (value); + if (multipass != self->multipass) { + self->multipass = multipass; + self->init_param_updated = TRUE; + } + break; + } case PROP_WEIGHTED_PRED: update_boolean (self, &self->weighted_pred, value, UPDATE_INIT_PARAM); break; @@ -818,6 +851,12 @@ gst_nv_h264_encoder_get_property (GObject * object, guint prop_id, case PROP_PRESET: g_value_set_enum (value, self->preset); break; + case PROP_TUNE: + g_value_set_enum (value, self->tune); + break; + case PROP_MULTI_PASS: + g_value_set_enum (value, self->multipass); + break; case PROP_WEIGHTED_PRED: g_value_set_boolean (value, self->weighted_pred); break; @@ -1074,7 +1113,6 @@ gst_nv_h264_encoder_set_format (GstNvEncoder * encoder, NVENCSTATUS status; NV_ENC_PRESET_CONFIG preset_config = { 0, }; gint dar_n, dar_d; - GstNvEncoderRCMode rc_mode; NV_ENC_CONFIG_H264 *h264_config; NV_ENC_CONFIG_H264_VUI_PARAMETERS *vui; std::set < std::string > downstream_profiles; @@ -1216,13 +1254,14 @@ gst_nv_h264_encoder_set_format (GstNvEncoder * encoder, } } - gst_nv_encoder_preset_to_guid (self->preset, &init_params->presetGUID); + gst_nv_encoder_preset_to_native (self->preset, self->tune, + &init_params->presetGUID, &init_params->tuningInfo); preset_config.version = gst_nvenc_get_preset_config_version (); preset_config.presetCfg.version = gst_nvenc_get_config_version (); - status = NvEncGetEncodePresetConfig (session, NV_ENC_CODEC_H264_GUID, - init_params->presetGUID, &preset_config); + status = NvEncGetEncodePresetConfigEx (session, NV_ENC_CODEC_H264_GUID, + init_params->presetGUID, init_params->tuningInfo, &preset_config); if (!gst_nv_enc_result (status, self)) { GST_ERROR_OBJECT (self, "Failed to get preset config"); g_mutex_unlock (&self->prop_lock); @@ -1257,7 +1296,6 @@ gst_nv_h264_encoder_set_format (GstNvEncoder * encoder, } rc_params = &config->rcParams; - rc_mode = self->rc_mode; if (self->bitrate) rc_params->averageBitRate = self->bitrate * 1024; @@ -1296,7 +1334,10 @@ gst_nv_h264_encoder_set_format (GstNvEncoder * encoder, } } - if (rc_mode == GST_NV_ENCODER_RC_MODE_CONSTQP) { + gst_nv_encoder_rc_mode_to_native (self->rc_mode, self->multipass, + &rc_params->rateControlMode, &rc_params->multiPass); + + if (rc_params->rateControlMode == NV_ENC_PARAMS_RC_CONSTQP) { if (self->qp_i >= 0) rc_params->constQP.qpIntra = self->qp_i; if (self->qp_p >= 0) @@ -1305,8 +1346,6 @@ gst_nv_h264_encoder_set_format (GstNvEncoder * encoder, rc_params->constQP.qpInterB = self->qp_b; } - rc_params->rateControlMode = gst_nv_encoder_rc_mode_to_native (rc_mode); - if (self->spatial_aq) { rc_params->enableAQ = TRUE; rc_params->aqStrength = self->aq_strength; @@ -1885,6 +1924,17 @@ gst_nv_h264_encoder_create_class_data (GstObject * device, gpointer session, GstNvEncoderClassData *cdata; GstCaps *sink_caps; GstCaps *system_caps; + NV_ENC_PRESET_CONFIG preset_config = { 0, }; + + preset_config.version = gst_nvenc_get_preset_config_version (); + preset_config.presetCfg.version = gst_nvenc_get_config_version (); + + status = NvEncGetEncodePresetConfigEx (session, NV_ENC_CODEC_H264_GUID, + NV_ENC_PRESET_P4_GUID, NV_ENC_TUNING_INFO_HIGH_QUALITY, &preset_config); + if (status != NV_ENC_SUCCESS) { + GST_WARNING_OBJECT (device, "New preset is not supported"); + return nullptr; + } status = NvEncGetEncodeProfileGUIDs (session, NV_ENC_CODEC_H264_GUID, profile_guids, G_N_ELEMENTS (profile_guids), &profile_guid_count); diff --git a/subprojects/gst-plugins-bad/sys/nvcodec/gstnvh265encoder.cpp b/subprojects/gst-plugins-bad/sys/nvcodec/gstnvh265encoder.cpp index e8f8059e8d..5899edb4e1 100644 --- a/subprojects/gst-plugins-bad/sys/nvcodec/gstnvh265encoder.cpp +++ b/subprojects/gst-plugins-bad/sys/nvcodec/gstnvh265encoder.cpp @@ -66,6 +66,8 @@ enum /* init params */ PROP_PRESET, + PROP_TUNE, + PROP_MULTI_PASS, PROP_WEIGHTED_PRED, /* encoding config */ @@ -108,7 +110,9 @@ enum PROP_REPEAT_SEQUENCE_HEADER, }; -#define DEFAULT_PRESET GST_NV_ENCODER_PRESET_DEFAULT +#define DEFAULT_PRESET GST_NV_ENCODER_PRESET_P4 +#define DEFAULT_TUNE GST_NV_ENCODER_TUNE_DEFAULT +#define DEFAULT_MULTI_PASS GST_NV_ENCODER_MULTI_PASS_DEFAULT #define DEFAULT_WEIGHTED_PRED FALSE #define DEFAULT_GOP_SIZE 30 #define DEFAULT_B_FRAMES 0 @@ -158,6 +162,8 @@ typedef struct _GstNvH265Encoder gint64 adapter_luid; GstNvEncoderPreset preset; + GstNvEncoderMultiPass multipass; + GstNvEncoderTune tune; gboolean weighted_pred; gint gop_size; @@ -303,6 +309,14 @@ gst_nv_h265_encoder_class_init (GstNvH265EncoderClass * klass, gpointer data) g_param_spec_enum ("preset", "Encoding Preset", "Encoding Preset", GST_TYPE_NV_ENCODER_PRESET, DEFAULT_PRESET, param_flags)); + g_object_class_install_property (object_class, PROP_TUNE, + g_param_spec_enum ("tune", "Tune", + "Encoding tune", GST_TYPE_NV_ENCODER_TUNE, + DEFAULT_TUNE, param_flags)); + g_object_class_install_property (object_class, PROP_MULTI_PASS, + g_param_spec_enum ("multi-pass", "Multi Pass", + "Multi pass encoding", GST_TYPE_NV_ENCODER_MULTI_PASS, + DEFAULT_MULTI_PASS, param_flags)); if (dev_caps->weighted_prediction) { g_object_class_install_property (object_class, PROP_WEIGHTED_PRED, g_param_spec_boolean ("weighted-pred", "Weighted Pred", @@ -502,6 +516,8 @@ gst_nv_h265_encoder_init (GstNvH265Encoder * self) self->cuda_device_id = klass->cuda_device_id; self->adapter_luid = klass->adapter_luid; self->preset = DEFAULT_PRESET; + self->tune = DEFAULT_TUNE; + self->multipass = DEFAULT_MULTI_PASS; self->weighted_pred = DEFAULT_WEIGHTED_PRED; self->gop_size = DEFAULT_GOP_SIZE; self->bframes = DEFAULT_B_FRAMES; @@ -699,6 +715,23 @@ gst_nv_h265_encoder_set_property (GObject * object, guint prop_id, } break; } + case PROP_TUNE:{ + GstNvEncoderTune tune = (GstNvEncoderTune) g_value_get_enum (value); + if (tune != self->tune) { + self->tune = tune; + self->init_param_updated = TRUE; + } + break; + } + case PROP_MULTI_PASS:{ + GstNvEncoderMultiPass multipass = + (GstNvEncoderMultiPass) g_value_get_enum (value); + if (multipass != self->multipass) { + self->multipass = multipass; + self->init_param_updated = TRUE; + } + break; + } case PROP_WEIGHTED_PRED: update_boolean (self, &self->weighted_pred, value, UPDATE_INIT_PARAM); break; @@ -814,6 +847,12 @@ gst_nv_h265_encoder_get_property (GObject * object, guint prop_id, case PROP_PRESET: g_value_set_enum (value, self->preset); break; + case PROP_TUNE: + g_value_set_enum (value, self->tune); + break; + case PROP_MULTI_PASS: + g_value_set_enum (value, self->multipass); + break; case PROP_WEIGHTED_PRED: g_value_set_boolean (value, self->weighted_pred); break; @@ -1055,7 +1094,6 @@ gst_nv_h265_encoder_set_format (GstNvEncoder * encoder, NVENCSTATUS status; NV_ENC_PRESET_CONFIG preset_config = { 0, }; gint dar_n, dar_d; - GstNvEncoderRCMode rc_mode; NV_ENC_CONFIG_HEVC *hevc_config; NV_ENC_CONFIG_HEVC_VUI_PARAMETERS *vui; std::set < std::string > downstream_profiles; @@ -1203,13 +1241,14 @@ gst_nv_h265_encoder_set_format (GstNvEncoder * encoder, init_params->darHeight = dar_d; } - gst_nv_encoder_preset_to_guid (self->preset, &init_params->presetGUID); + gst_nv_encoder_preset_to_native (self->preset, self->tune, + &init_params->presetGUID, &init_params->tuningInfo); preset_config.version = gst_nvenc_get_preset_config_version (); preset_config.presetCfg.version = gst_nvenc_get_config_version (); - status = NvEncGetEncodePresetConfig (session, NV_ENC_CODEC_HEVC_GUID, - init_params->presetGUID, &preset_config); + status = NvEncGetEncodePresetConfigEx (session, NV_ENC_CODEC_HEVC_GUID, + init_params->presetGUID, init_params->tuningInfo, &preset_config); if (!gst_nv_enc_result (status, self)) { GST_ERROR_OBJECT (self, "Failed to get preset config"); g_mutex_unlock (&self->prop_lock); @@ -1236,7 +1275,6 @@ gst_nv_h265_encoder_set_format (GstNvEncoder * encoder, } rc_params = &config->rcParams; - rc_mode = self->rc_mode; if (self->bitrate) rc_params->averageBitRate = self->bitrate * 1024; @@ -1275,7 +1313,10 @@ gst_nv_h265_encoder_set_format (GstNvEncoder * encoder, } } - if (rc_mode == GST_NV_ENCODER_RC_MODE_CONSTQP) { + gst_nv_encoder_rc_mode_to_native (self->rc_mode, self->multipass, + &rc_params->rateControlMode, &rc_params->multiPass); + + if (rc_params->rateControlMode == NV_ENC_PARAMS_RC_CONSTQP) { if (self->qp_i >= 0) rc_params->constQP.qpIntra = self->qp_i; if (self->qp_p >= 0) @@ -1284,8 +1325,6 @@ gst_nv_h265_encoder_set_format (GstNvEncoder * encoder, rc_params->constQP.qpInterB = self->qp_b; } - rc_params->rateControlMode = gst_nv_encoder_rc_mode_to_native (rc_mode); - if (self->spatial_aq) { rc_params->enableAQ = TRUE; rc_params->aqStrength = self->aq_strength; @@ -1919,6 +1958,17 @@ gst_nv_h265_encoder_create_class_data (GstObject * device, gpointer session, GstNvEncoderClassData *cdata; GstCaps *sink_caps; GstCaps *system_caps; + NV_ENC_PRESET_CONFIG preset_config = { 0, }; + + preset_config.version = gst_nvenc_get_preset_config_version (); + preset_config.presetCfg.version = gst_nvenc_get_config_version (); + + status = NvEncGetEncodePresetConfigEx (session, NV_ENC_CODEC_HEVC_GUID, + NV_ENC_PRESET_P4_GUID, NV_ENC_TUNING_INFO_HIGH_QUALITY, &preset_config); + if (status != NV_ENC_SUCCESS) { + GST_WARNING_OBJECT (device, "New preset is not supported"); + return nullptr; + } status = NvEncGetEncodeProfileGUIDs (session, NV_ENC_CODEC_HEVC_GUID, profile_guids, G_N_ELEMENTS (profile_guids), &profile_guid_count);