tensormeta: Check dimensions when retrieving tensor
Modify the API to retrieve the tensor meta to check for the dimensions as well. Also fix an API mistake, the buffer whose dimensions should be checheck is the one inside the GstTensor, not another buffer some outside. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/9411>
This commit is contained in:
parent
5f52eaae83
commit
2c3f2747d6
@ -11,6 +11,6 @@ variables:
|
||||
|
||||
CHECKS_TAG: '2025-05-24.0'
|
||||
|
||||
ABI_CHECK_TAG: '2025-07-15.0'
|
||||
ABI_CHECK_TAG: '2025-07-16.0'
|
||||
|
||||
WINDOWS_TAG: '2025-07-03.0'
|
||||
|
@ -1513,8 +1513,7 @@ Validate whether the #GstBuffer has enough size to hold the tensor data.</doc>
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gsttensor.h"/>
|
||||
<return-value transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gsttensor.c">TRUE if the #GstTensor has the reading order from the memory matching @order,
|
||||
dimensions matching @num_dims, data type matching @data_type and the #GstBuffer mathcing @data
|
||||
has enough size to hold the tensor data.
|
||||
dimensions matching @num_dims, data type matching @data_type
|
||||
Otherwise FALSE will be returned.</doc>
|
||||
<type name="gboolean" c:type="gboolean"/>
|
||||
</return-value>
|
||||
@ -1523,6 +1522,10 @@ Otherwise FALSE will be returned.</doc>
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gsttensor.c">A #GstTensor</doc>
|
||||
<type name="Tensor" c:type="const GstTensor*"/>
|
||||
</instance-parameter>
|
||||
<parameter name="data_type" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gsttensor.c">The data type of the tensor</doc>
|
||||
<type name="TensorDataType" c:type="GstTensorDataType"/>
|
||||
</parameter>
|
||||
<parameter name="order" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gsttensor.c">The order of the tensor to read from the memory</doc>
|
||||
<type name="TensorDimOrder" c:type="GstTensorDimOrder"/>
|
||||
@ -1531,13 +1534,11 @@ Otherwise FALSE will be returned.</doc>
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gsttensor.c">The number of dimensions that the tensor can have</doc>
|
||||
<type name="gsize" c:type="gsize"/>
|
||||
</parameter>
|
||||
<parameter name="data_type" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gsttensor.c">The data type of the tensor</doc>
|
||||
<type name="TensorDataType" c:type="GstTensorDataType"/>
|
||||
</parameter>
|
||||
<parameter name="data" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gsttensor.c">#GstBuffer holding tensor data</doc>
|
||||
<type name="Gst.Buffer" c:type="GstBuffer*"/>
|
||||
<parameter name="dims" transfer-ownership="none" nullable="1" allow-none="1">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gsttensor.c">An optional array of dimensions, where G_MAXSIZE means ANY.</doc>
|
||||
<array length="2" zero-terminated="0" c:type="const gsize*">
|
||||
<type name="gsize" c:type="gsize"/>
|
||||
</array>
|
||||
</parameter>
|
||||
</parameters>
|
||||
</method>
|
||||
@ -1765,16 +1766,14 @@ Otherwise NULL will be returned.</doc>
|
||||
</parameters>
|
||||
</method>
|
||||
<method name="get_typed_tensor" c:identifier="gst_tensor_meta_get_typed_tensor" version="1.28">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gsttensormeta.c">Get the first tensor from the #GstTensorMeta identified by @tensor_id, mathcing
|
||||
the reading order, dimensions and the data type.
|
||||
Validate whether the #GstBuffer has enough size to hold the tensor data.</doc>
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gsttensormeta.c">Get the first tensor from the #GstTensorMeta identified by
|
||||
@tensor_id, matching the reading order, dimensions and the data
|
||||
type and optionally the dimensions. Validate whether the
|
||||
#GstBuffer has enough size to hold the tensor data.</doc>
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gsttensormeta.h"/>
|
||||
<return-value transfer-ownership="none" nullable="1">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gsttensormeta.c">a GstTensor with id matching @tensor_id,
|
||||
reading order from the memory matching @order, dimensions matching @num_dims,
|
||||
data type matching @data_type. The #GstBuffer mathcing @data should
|
||||
have enough size to hold the tensor data.
|
||||
Otherwise NULL will be returned.</doc>
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gsttensormeta.c">a matching #GstTensor,
|
||||
otherwise NULL</doc>
|
||||
<type name="Tensor" c:type="const GstTensor*"/>
|
||||
</return-value>
|
||||
<parameters>
|
||||
@ -1786,6 +1785,10 @@ Otherwise NULL will be returned.</doc>
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gsttensormeta.c">A #GQuark identifying the tensor-encoding</doc>
|
||||
<type name="GLib.Quark" c:type="GQuark"/>
|
||||
</parameter>
|
||||
<parameter name="data_type" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gsttensormeta.c">The data type of the tensor</doc>
|
||||
<type name="TensorDataType" c:type="GstTensorDataType"/>
|
||||
</parameter>
|
||||
<parameter name="order" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gsttensormeta.c">The order of the tensor to read from the memory</doc>
|
||||
<type name="TensorDimOrder" c:type="GstTensorDimOrder"/>
|
||||
@ -1794,13 +1797,11 @@ Otherwise NULL will be returned.</doc>
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gsttensormeta.c">The number of dimensions that the tensor can have</doc>
|
||||
<type name="gsize" c:type="gsize"/>
|
||||
</parameter>
|
||||
<parameter name="data_type" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gsttensormeta.c">The data type of the tensor</doc>
|
||||
<type name="TensorDataType" c:type="GstTensorDataType"/>
|
||||
</parameter>
|
||||
<parameter name="data" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gsttensormeta.c">#GstBuffer holding tensor data</doc>
|
||||
<type name="Gst.Buffer" c:type="GstBuffer*"/>
|
||||
<parameter name="dims" transfer-ownership="none" nullable="1" allow-none="1">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gsttensormeta.c">An optional array of dimensions, where G_MAXSIZE means ANY.</doc>
|
||||
<array length="3" zero-terminated="0" c:type="const gsize*">
|
||||
<type name="gsize" c:type="gsize"/>
|
||||
</array>
|
||||
</parameter>
|
||||
</parameters>
|
||||
</method>
|
||||
|
@ -263,24 +263,23 @@ gst_tensor_data_type_get_name (GstTensorDataType data_type)
|
||||
/**
|
||||
* gst_tensor_check_type:
|
||||
* @tensor: A #GstTensor
|
||||
* @data_type: The data type of the tensor
|
||||
* @order: The order of the tensor to read from the memory
|
||||
* @num_dims: The number of dimensions that the tensor can have
|
||||
* @data_type: The data type of the tensor
|
||||
* @data: #GstBuffer holding tensor data
|
||||
* @dims: (array length=num_dims)(nullable): An optional array of dimensions, where G_MAXSIZE means ANY.
|
||||
*
|
||||
* Validate the tensor whether it mathces the reading order, dimensions and the data type.
|
||||
* Validate whether the #GstBuffer has enough size to hold the tensor data.
|
||||
*
|
||||
* Returns: TRUE if the #GstTensor has the reading order from the memory matching @order,
|
||||
* dimensions matching @num_dims, data type matching @data_type and the #GstBuffer mathcing @data
|
||||
* has enough size to hold the tensor data.
|
||||
* dimensions matching @num_dims, data type matching @data_type
|
||||
* Otherwise FALSE will be returned.
|
||||
*
|
||||
* Since: 1.28
|
||||
*/
|
||||
gboolean
|
||||
gst_tensor_check_type (const GstTensor * tensor, GstTensorDimOrder order,
|
||||
gsize num_dims, GstTensorDataType data_type, GstBuffer * data)
|
||||
gst_tensor_check_type (const GstTensor * tensor, GstTensorDataType data_type,
|
||||
GstTensorDimOrder order, gsize num_dims, const gsize * dims)
|
||||
{
|
||||
gsize num_elements = 1, tensor_size, i;
|
||||
|
||||
@ -304,16 +303,25 @@ gst_tensor_check_type (const GstTensor * tensor, GstTensorDimOrder order,
|
||||
|
||||
for (i = 0; i < tensor->num_dims; i++) {
|
||||
num_elements *= tensor->dims[i];
|
||||
|
||||
if (dims) {
|
||||
if (dims[i] != G_MAXSIZE && dims[i] != tensor->dims[i]) {
|
||||
GST_DEBUG ("Tensor has dim[%zu]=%zu but expect dim[%zu]=%zu",
|
||||
i, tensor->dims[i], i, dims[i]);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tensor_size = size_for_elements (tensor->data_type, num_elements);
|
||||
|
||||
if (gst_buffer_get_size (data) < tensor_size) {
|
||||
GST_DEBUG ("Expected buffer of size %zu (%zu elements),"
|
||||
if (gst_buffer_get_size (tensor->data) < tensor_size) {
|
||||
GST_ERROR ("Expected buffer of size %zu (%zu elements),"
|
||||
" but buffer has size %zu", tensor_size, num_elements,
|
||||
gst_buffer_get_size (data));
|
||||
gst_buffer_get_size (tensor->data));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -221,8 +221,9 @@ GST_ANALYTICS_META_API
|
||||
const gchar *gst_tensor_data_type_get_name (GstTensorDataType data_type);
|
||||
|
||||
GST_ANALYTICS_META_API
|
||||
gboolean gst_tensor_check_type(const GstTensor * tensor, GstTensorDimOrder order,
|
||||
gsize num_dims, GstTensorDataType data_type, GstBuffer * data);
|
||||
gboolean gst_tensor_check_type(const GstTensor * tensor,
|
||||
GstTensorDataType data_type, GstTensorDimOrder order, gsize num_dims,
|
||||
const gsize *dims);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -210,27 +210,25 @@ gst_tensor_meta_get_by_id (GstTensorMeta * tmeta, GQuark id)
|
||||
* gst_tensor_meta_get_typed_tensor:
|
||||
* @tmeta: A #GstTensorMeta
|
||||
* @tensor_id: A #GQuark identifying the tensor-encoding
|
||||
* @data_type: The data type of the tensor
|
||||
* @order: The order of the tensor to read from the memory
|
||||
* @num_dims: The number of dimensions that the tensor can have
|
||||
* @data_type: The data type of the tensor
|
||||
* @data: #GstBuffer holding tensor data
|
||||
* @dims: (array length=num_dims)(nullable): An optional array of dimensions, where G_MAXSIZE means ANY.
|
||||
*
|
||||
* Get the first tensor from the #GstTensorMeta identified by @tensor_id, mathcing
|
||||
* the reading order, dimensions and the data type.
|
||||
* Validate whether the #GstBuffer has enough size to hold the tensor data.
|
||||
* Get the first tensor from the #GstTensorMeta identified by
|
||||
* @tensor_id, matching the reading order, dimensions and the data
|
||||
* type and optionally the dimensions. Validate whether the
|
||||
* #GstBuffer has enough size to hold the tensor data.
|
||||
*
|
||||
* Return: (nullable) (transfer none): a GstTensor with id matching @tensor_id,
|
||||
* reading order from the memory matching @order, dimensions matching @num_dims,
|
||||
* data type matching @data_type. The #GstBuffer mathcing @data should
|
||||
* have enough size to hold the tensor data.
|
||||
* Otherwise NULL will be returned.
|
||||
* Return: (nullable) (transfer none): a matching #GstTensor,
|
||||
* otherwise NULL
|
||||
*
|
||||
* Since: 1.28
|
||||
*/
|
||||
const GstTensor *
|
||||
gst_tensor_meta_get_typed_tensor (GstTensorMeta * tmeta,
|
||||
GQuark tensor_id, GstTensorDimOrder order, gsize num_dims,
|
||||
GstTensorDataType data_type, GstBuffer * data)
|
||||
GQuark tensor_id, GstTensorDataType data_type, GstTensorDimOrder order,
|
||||
gsize num_dims, const gsize * dims)
|
||||
{
|
||||
const GstTensor *tensor;
|
||||
|
||||
@ -239,7 +237,7 @@ gst_tensor_meta_get_typed_tensor (GstTensorMeta * tmeta,
|
||||
if (tensor == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!gst_tensor_check_type (tensor, order, num_dims, data_type, data))
|
||||
if (!gst_tensor_check_type (tensor, data_type, order, num_dims, dims))
|
||||
return NULL;
|
||||
|
||||
return tensor;
|
||||
|
@ -84,7 +84,8 @@ const GstTensor *gst_tensor_meta_get_by_id (GstTensorMeta *tmeta, GQuark id);
|
||||
|
||||
GST_ANALYTICS_META_API
|
||||
const GstTensor *gst_tensor_meta_get_typed_tensor (GstTensorMeta * tmeta,
|
||||
GQuark tensor_id, GstTensorDimOrder order, gsize num_dims, GstTensorDataType data_type, GstBuffer * data);
|
||||
GQuark tensor_id, GstTensorDataType data_type, GstTensorDimOrder order,
|
||||
gsize num_dims, const gsize * dims);
|
||||
|
||||
GST_ANALYTICS_META_API
|
||||
const GstTensor *gst_tensor_meta_get (GstTensorMeta *tmeta, gsize index);
|
||||
|
@ -308,6 +308,8 @@ gst_face_detector_tensor_decoder_get_tensor_meta (GstFaceDetectorTensorDecoder
|
||||
const GstTensor ** scores_tensor)
|
||||
{
|
||||
GstTensorMeta *tensor_meta;
|
||||
static const gsize BOXES_DIMS[] = { 1, G_MAXSIZE, 4 };
|
||||
static const gsize SCORES_DIMS[] = { 1, G_MAXSIZE, 2 };
|
||||
|
||||
g_return_val_if_fail (boxes_tensor != NULL, FALSE);
|
||||
g_return_val_if_fail (scores_tensor != NULL, FALSE);
|
||||
@ -330,7 +332,13 @@ gst_face_detector_tensor_decoder_get_tensor_meta (GstFaceDetectorTensorDecoder
|
||||
* 3 dimensions and the data type matching with GST_TENSOR_DATA_TYPE_FLOAT32 */
|
||||
*boxes_tensor =
|
||||
gst_tensor_meta_get_typed_tensor (tensor_meta, BOXES_TENSOR_ID_QUARK,
|
||||
GST_TENSOR_DIM_ORDER_ROW_MAJOR, 3, GST_TENSOR_DATA_TYPE_FLOAT32, buf);
|
||||
GST_TENSOR_DATA_TYPE_FLOAT32, GST_TENSOR_DIM_ORDER_ROW_MAJOR, 3,
|
||||
BOXES_DIMS);
|
||||
|
||||
if (*boxes_tensor == NULL) {
|
||||
GST_WARNING_OBJECT (self, "Can't retrieve boxes tensor");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Retrieve the tensor that has a tensor-id matching
|
||||
* SCORES_TENSOR_ID_QUARK in the GstTensorMeta along with
|
||||
@ -338,10 +346,13 @@ gst_face_detector_tensor_decoder_get_tensor_meta (GstFaceDetectorTensorDecoder
|
||||
* 3 dimensions and the data type matching with GST_TENSOR_DATA_TYPE_FLOAT32 */
|
||||
*scores_tensor =
|
||||
gst_tensor_meta_get_typed_tensor (tensor_meta, SCORES_TENSOR_ID_QUARK,
|
||||
GST_TENSOR_DIM_ORDER_ROW_MAJOR, 3, GST_TENSOR_DATA_TYPE_FLOAT32, buf);
|
||||
GST_TENSOR_DATA_TYPE_FLOAT32, GST_TENSOR_DIM_ORDER_ROW_MAJOR, 3,
|
||||
SCORES_DIMS);
|
||||
|
||||
if (*boxes_tensor == NULL || *scores_tensor == NULL)
|
||||
if (*scores_tensor == NULL) {
|
||||
GST_WARNING_OBJECT (self, "Can't retrieve boxes tensor");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -644,7 +655,7 @@ gst_face_detector_tensor_decoder_transform_ip (GstBaseTransform * trans,
|
||||
if (!gst_face_detector_tensor_decoder_get_tensor_meta (self, buf,
|
||||
&boxes_tensor, &scores_tensor)) {
|
||||
GST_ELEMENT_ERROR (self, STREAM, DECODE, (NULL),
|
||||
("Tensor doens't have the expected data type or shape."));
|
||||
("Tensor doesn't have the expected data type or shape."));
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user