GstVulkanEncoderPicture *slots[32];
+ guint32 quality;
+
gboolean started;
gboolean session_reset;
{
GstVulkanEncoderPrivate *priv;
VkVideoSessionParametersCreateInfoKHR session_params_info;
+ VkVideoEncodeQualityLevelInfoKHR quality_info;
VkResult res;
VkVideoSessionParametersKHR session_params;
return NULL;
/* *INDENT-OFF* */
+ quality_info = (VkVideoEncodeQualityLevelInfoKHR) {
+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR,
+ .pNext = params,
+ .qualityLevel = priv->quality,
+ };
session_params_info = (VkVideoSessionParametersCreateInfoKHR) {
.sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR,
- .pNext = params,
+ .pNext = &quality_info,
.videoSession = priv->session.session->handle,
};
/* *INDENT-ON* */
return gst_caps_ref (priv->profile_caps);
}
+/**
+ * gst_vulkan_encoder_quality_level:
+ * @self: a #GstVulkanEncoder
+ *
+ * Get the current encoding quality level.
+ *
+ * Returns: whether the encoder has started, it will return the quality level;
+ * otherwise it will return -1
+ */
+gint32
+gst_vulkan_encoder_quality_level (GstVulkanEncoder * self)
+{
+ GstVulkanEncoderPrivate *priv;
+
+ g_return_val_if_fail (GST_IS_VULKAN_ENCODER (self), -1);
+
+ priv = gst_vulkan_encoder_get_instance_private (self);
+
+ if (!priv->started)
+ return -1;
+
+ return priv->quality;
+}
+
/**
* gst_vulkan_encoder_stop:
* @self: a #GstVulkanEncoder
* gst_vulkan_encoder_start:
* @self: a #GstVulkanEncoder
* @profile: a #GstVulkanVideoProfile
+ * @codec_quality_props: codec specific quality structure to fetch
* @error: (out) : an error result in case of failure or %NULL
*
* Start the encoding session according to a valid Vulkan profile
*/
gboolean
gst_vulkan_encoder_start (GstVulkanEncoder * self,
- GstVulkanVideoProfile * profile, GError ** error)
+ GstVulkanVideoProfile * profile,
+ GstVulkanEncoderQualityProperties * codec_quality_props, GError ** error)
{
GstVulkanEncoderPrivate *priv;
VkResult res;
int codec_idx;
GstVulkanCommandPool *cmd_pool;
VkQueryPoolVideoEncodeFeedbackCreateInfoKHR query_create;
+ VkPhysicalDeviceVideoEncodeQualityLevelInfoKHR quality_info;
+ VkVideoEncodeQualityLevelPropertiesKHR quality_props;
GError *query_err = NULL;
g_return_val_if_fail (GST_IS_VULKAN_ENCODER (self), FALSE);
g_return_val_if_fail (profile != NULL, FALSE);
+ g_return_val_if_fail (codec_quality_props != NULL, FALSE);
priv = gst_vulkan_encoder_get_instance_private (self);
!(priv->caps.
caps.flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR);
+ if (codec_quality_props->quality_level >= 0) {
+ priv->quality = MIN (codec_quality_props->quality_level,
+ priv->caps.encoder.caps.maxQualityLevels - 1);
+ } else {
+ priv->quality = priv->caps.encoder.caps.maxQualityLevels / 2;
+ }
+
+ /* *INDENT-OFF* */
+ quality_info = (VkPhysicalDeviceVideoEncodeQualityLevelInfoKHR) {
+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR,
+ .pVideoProfile = &profile->profile,
+ .qualityLevel = priv->quality,
+ };
+ quality_props = (VkVideoEncodeQualityLevelPropertiesKHR) {
+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUALITY_LEVEL_PROPERTIES_KHR,
+ .pNext = &codec_quality_props->codec,
+ };
+ /* *INDENT-ON* */
+
+ res = priv->vk.GetPhysicalDeviceVideoEncodeQualityLevelProperties (gpu,
+ &quality_info, &quality_props);
+ if (gst_vulkan_error_to_g_error (res, error,
+ "vketPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR")
+ != VK_SUCCESS)
+ goto failed;
/* *INDENT-OFF* */
session_create = (VkVideoSessionCreateInfoKHR) {
VkVideoReferenceSlotInfoKHR ref_slots[37];
GstVulkanCommandBuffer *cmd_buf;
GArray *barriers;
+ VkVideoEncodeQualityLevelInfoKHR quality_info;
g_return_val_if_fail (GST_IS_VULKAN_ENCODER (self), FALSE);
g_return_val_if_fail (info != NULL && pic != NULL, FALSE);
goto bail;
/* *INDENT-OFF* */
+ quality_info = (VkVideoEncodeQualityLevelInfoKHR) {
+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR,
+ .pNext = NULL,
+ .qualityLevel = priv->quality,
+ };
coding_ctrl = (VkVideoCodingControlInfoKHR) {
.sType = VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR,
- .flags = VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR,
+ .pNext = &quality_info,
+ .flags = VK_VIDEO_CODING_CONTROL_ENCODE_QUALITY_LEVEL_BIT_KHR
+ | VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR,
};
/* *INDENT-ON* */
typedef struct _GstVulkanEncoder GstVulkanEncoder;
typedef struct _GstVulkanEncoderClass GstVulkanEncoderClass;
+typedef struct _GstVulkanEncoderQualityPoperties GstVulkanEncoderQualityProperties;
typedef union _GstVulkanEncoderParameters GstVulkanEncoderParameters;
typedef union _GstVulkanEncoderParametersOverrides GstVulkanEncoderParametersOverrides;
typedef union _GstVulkanEncoderParametersFeedback GstVulkanEncoderParametersFeedback;
VkVideoEncodeH265SessionParametersFeedbackInfoKHR h265;
};
+struct _GstVulkanEncoderQualityPoperties
+{
+ gint32 quality_level;
+ union
+ {
+ VkVideoEncodeH264QualityLevelPropertiesKHR h264;
+ VkVideoEncodeH265QualityLevelPropertiesKHR h265;
+ } codec;
+};
+
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GstVulkanEncoder, gst_object_unref)
GST_VULKAN_API
GST_VULKAN_API
gboolean gst_vulkan_encoder_start (GstVulkanEncoder * self,
GstVulkanVideoProfile * profile,
+ GstVulkanEncoderQualityProperties * codec_quality_props,
GError ** error);
GST_VULKAN_API
gboolean gst_vulkan_encoder_stop (GstVulkanEncoder * self);
GstVulkanVideoCapabilities * caps);
GST_VULKAN_API
GstCaps * gst_vulkan_encoder_profile_caps (GstVulkanEncoder * self);
+GST_VULKAN_API
+gint32 gst_vulkan_encoder_quality_level (GstVulkanEncoder * self);
+
GST_VULKAN_API
gboolean gst_vulkan_encoder_picture_init (GstVulkanEncoderPicture * pic,
GstVulkanEncoder * self,
V(CmdEndVideoCoding) \
V(CmdDecodeVideo) \
V(CmdEncodeVideo) \
- V(GetEncodedVideoSessionParameters)
+ V(GetEncodedVideoSessionParameters) \
+ V(GetPhysicalDeviceVideoEncodeQualityLevelProperties)
struct _GstVulkanVideoFunctions
{
StdVideoH264ProfileIdc profile_idc = STD_VIDEO_H264_PROFILE_IDC_HIGH;
GstVulkanEncoderParameters enc_params;
VkVideoEncodeH264SessionParametersAddInfoKHR params_add;
+ GstVulkanEncoderQualityProperties quality_props;
+ /* *INDENT-OFF* */
profile = (GstVulkanVideoProfile) {
- /* *INDENT-OFF* */
.profile = {
.sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR,
.pNext = &profile.usage.encode,
.sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_INFO_KHR,
.stdProfileIdc = profile_idc,
}
- /* *INDENT-ON* */
};
+ quality_props = (GstVulkanEncoderQualityProperties) {
+ .quality_level = -1,
+ .codec.h264 = {
+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_QUALITY_LEVEL_PROPERTIES_KHR,
+ },
+ };
+ /* *INDENT-ON* */
for (i = 0; i < instance->n_physical_devices; i++) {
GstVulkanDevice *device = gst_vulkan_device_new_with_index (instance, i);
return NULL;
}
- fail_unless (gst_vulkan_encoder_start (enc, &profile, &err));
+ fail_unless (gst_vulkan_encoder_quality_level (enc) == -1);
+
+ fail_unless (gst_vulkan_encoder_start (enc, &profile, &quality_props, &err));
+
+ fail_unless (gst_vulkan_encoder_quality_level (enc) > -1);
mbAlignedWidth = GST_ROUND_UP_16 (width);
mbAlignedHeight = GST_ROUND_UP_16 (height);
h264_std_sps.frame_crop_right_offset = mbAlignedWidth - width;
h264_std_sps.frame_crop_bottom_offset = mbAlignedHeight - height;
+ /* *INDENT-OFF* */
params_add = (VkVideoEncodeH264SessionParametersAddInfoKHR) {
- /* *INDENT-OFF* */
.sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_ADD_INFO_KHR,
.pStdSPSs = &h264_std_sps,
.stdSPSCount = 1,
.pStdPPSs = &h264_std_pps,
.stdPPSCount = 1,
- /* *INDENT-ON* */
};
-
enc_params.h264 = (VkVideoEncodeH264SessionParametersCreateInfoKHR) {
- /* *INDENT-OFF* */
.sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR,
.maxStdSPSCount = 1,
.maxStdPPSCount = 1,
.pParametersAddInfo = ¶ms_add
- /* *INDENT-ON* */
};
+ /* *INDENT-ON* */
fail_unless (gst_vulkan_encoder_update_video_session_parameters (enc,
&enc_params, &err));
gint min_ctb_size = 64, max_ctb_size = 16;
gint max_tb_size = 0, min_tb_size = 0;
gint max_transform_hierarchy;
+ GstVulkanEncoderQualityProperties quality_props;
+ /* *INDENT-OFF* */
profile = (GstVulkanVideoProfile) {
- /* *INDENT-OFF* */
.profile = {
.sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR,
.pNext = &profile.codec,
.sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PROFILE_INFO_KHR,
.stdProfileIdc = profile_idc,
}
- /* *INDENT-ON* */
};
+ quality_props = (GstVulkanEncoderQualityProperties) {
+ .quality_level = -1,
+ .codec.h265 = {
+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_QUALITY_LEVEL_PROPERTIES_KHR,
+ },
+ };
+ /* *INDENT-ON* */
for (i = 0; i < instance->n_physical_devices; i++) {
GstVulkanDevice *device = gst_vulkan_device_new_with_index (instance, i);
return NULL;
}
- fail_unless (gst_vulkan_encoder_start (enc, &profile, &err));
+ fail_unless (gst_vulkan_encoder_quality_level (enc) == -1);
- fail_unless (gst_vulkan_encoder_caps (enc, &enc_caps));
+ fail_unless (gst_vulkan_encoder_start (enc, &profile, &quality_props, &err));
+
+ fail_unless (gst_vulkan_encoder_quality_level (enc) > -1);
+ fail_unless (gst_vulkan_encoder_caps (enc, &enc_caps));
if (enc_caps.encoder.codec.h265.ctbSizes
& VK_VIDEO_ENCODE_H265_CTB_SIZE_64_BIT_KHR)
h265_std_pps.pps_seq_parameter_set_id = sps_id;
h265_std_pps.pps_pic_parameter_set_id = pps_id;
+ /* *INDENT-OFF* */
params_add = (VkVideoEncodeH265SessionParametersAddInfoKHR) {
- /* *INDENT-OFF* */
.sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_ADD_INFO_KHR,
.pStdVPSs = &h265_std_vps,
.stdVPSCount = 1,
.stdSPSCount = 1,
.pStdPPSs = &h265_std_pps,
.stdPPSCount = 1,
- /* *INDENT-ON* */
};
-
enc_params.h265 = (VkVideoEncodeH265SessionParametersCreateInfoKHR) {
- /* *INDENT-OFF* */
.sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR,
.maxStdVPSCount = 1,
.maxStdSPSCount = 1,
.maxStdPPSCount = 1,
.pParametersAddInfo = ¶ms_add
- /* *INDENT-ON* */
};
+ /* *INDENT-ON* */
fail_unless (gst_vulkan_encoder_update_video_session_parameters (enc,
&enc_params, &err));