From 6550232f6c8a69674563d0c860e7291bfcb64a9a Mon Sep 17 00:00:00 2001 From: "Cano Raphael (XC-AS/EPO3)" Date: Tue, 9 Sep 2025 10:21:15 +0200 Subject: [PATCH 1/8] add the import function for the vx_object_array --- utils/include/tivx_utils_ipc_ref_xfer.h | 49 ++++++ utils/source/tivx_utils_ipc_ref_xfer.c | 194 ++++++++++++++++++++++++ 2 files changed, 243 insertions(+) diff --git a/utils/include/tivx_utils_ipc_ref_xfer.h b/utils/include/tivx_utils_ipc_ref_xfer.h index 56c90453e..41306201d 100644 --- a/utils/include/tivx_utils_ipc_ref_xfer.h +++ b/utils/include/tivx_utils_ipc_ref_xfer.h @@ -189,6 +189,16 @@ typedef struct vx_size size; } user_data_object; + /*!< \brief structure containing information about object array + used when type is set to VX_TYPE_OBJECT_ARRAY + NOTE: assume the underlying type is vx_image */ + struct { + /*!< \brief The number of image objects */ + vx_uint32 num_items; + /*!< \brief VX type of the object, must be image */ + vx_enum item_type; + } object_array; + } object; /* Union to hold different types of metadata */ /*!< \brief structure containing information about raw image @@ -248,6 +258,24 @@ typedef struct } tivx_utils_ref_ipc_msg_t; +/** + * \brief Export the object array, so that the information + * could be transferred over Linux/QNX IPC mechanism to a remote process. + * This is just a wrapper for tivx_utils_export_ref_for_ipc_xfer. + * + * \param [in] ref A valid openVX reference for an object array of images + * \param [out] numMessages Number of IPC messages after export + * \param [out] ipcMsgHandle Exported object array metadata + * \param [out] ipcMsgArray Array of pointers to exported item data + * + * \return VX_SUCCESS on success, else failure + * + */ +vx_status vx_utils_export_ref_for_ipc_xfer_objarray(const vx_reference ref, + vx_uint32 *numMessages, + tivx_utils_ref_ipc_msg_t *ipcMsgHandle, + tivx_utils_ref_ipc_msg_t ipcMsgArray[]); + /** * \brief Export the internal handle information of a valid reference as a * buffer descriptor along with meta information so that the information @@ -273,6 +301,27 @@ typedef struct vx_status tivx_utils_export_ref_for_ipc_xfer(const vx_reference ref, tivx_utils_ref_ipc_msg_t *ipcMsg); +/** + * \brief Import the external handle information of a valid reference as a + * buffer descriptor along with meta information exchanged via Linux/ + * QNX IPC mechanism. + * + * \param [in] context A valid openVX context + * \param [in] ipcMsgHandle Exported object array information + * \param [in] ipcMsgArray Array of exported image information + * \param [in,out] ref A valid openVX reference to import. If *ref is NULL, + * then a new object will be allocated with the imported + * handles and returned. If *ref is not NULL then the object + * will be used to import the handles. + * + * \return VX_SUCCESS on success, else failure + * + */ +vx_status vx_utils_import_ref_from_ipc_xfer_objarray(vx_context context, + tivx_utils_ref_ipc_msg_t *ipcMsgHandle, + tivx_utils_ref_ipc_msg_t ipcMsgArray[], + vx_reference *ref); + /** * \brief Import the external handle information of a valid reference as a * buffer descriptor along with meta information exchanged via Linux/ diff --git a/utils/source/tivx_utils_ipc_ref_xfer.c b/utils/source/tivx_utils_ipc_ref_xfer.c index 9580f1a5e..38e50d60e 100644 --- a/utils/source/tivx_utils_ipc_ref_xfer.c +++ b/utils/source/tivx_utils_ipc_ref_xfer.c @@ -65,6 +65,99 @@ #include +vx_status vx_utils_export_ref_for_ipc_xfer_objarray(const vx_reference ref, + vx_uint32 *numMessages, + tivx_utils_ref_ipc_msg_t *ipcMsgHandle, + tivx_utils_ref_ipc_msg_t ipcMsgArray[]) +{ + vx_status vxStatus = VX_SUCCESS; + tivx_utils_ref_desc_t *refDesc = NULL; + vx_object_array objarr; + tivx_obj_desc_object_array_t *obj_desc; + vx_enum itemType; + uint32_t numItems = 0; + uint32_t i; + + /* Validate the arguments. */ + if (ref == NULL || numMessages == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "The parameter 'ref' is NULL.\n"); + vxStatus = (vx_status)VX_FAILURE; + } + else if (ipcMsgHandle == NULL || ipcMsgArray == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "One of ipcMsg* pointers is NULL.\n"); + vxStatus = (vx_status)VX_FAILURE; + } + + if (vxStatus == (vx_status)VX_SUCCESS) + { + refDesc = &ipcMsgHandle->refDesc; + + /* Validate object type and get metadata */ + if(ref->type == VX_TYPE_OBJECT_ARRAY) + { + objarr = (vx_object_array) ref; + obj_desc = (tivx_obj_desc_object_array_t *) objarr->base.obj_desc; + itemType = obj_desc->item_type; + numItems = obj_desc->num_items; + VX_PRINT(VX_ZONE_INFO, "Exporting object array of type %d\n", itemType); + + for(i = 0; i < numItems; i++) + { + VX_PRINT(VX_ZONE_INFO, "Item number - %d\n", i); + vx_reference itemRef = NULL; + itemRef = objarr->ref[i]; + if (itemRef == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "Cannot get current reference, aborting.\n"); + vxStatus = (vx_status)VX_FAILURE; + break; + } + + /* allocate memory for data reference, independent of graph state */ + vxStatus = ownReferenceAllocMem(itemRef); + if (vxStatus != (vx_status)VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR,"Memory allocation for data reference failed\n"); + break; + } + + vxStatus = tivx_utils_export_ref_for_ipc_xfer(itemRef, &ipcMsgArray[i]); + if (vxStatus != VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, "Cannot export one of the references, aborting\n"); + break; + } + } + } + else + { + VX_PRINT(VX_ZONE_ERROR, "Not an object array\n"); + vxStatus = (vx_status)VX_FAILURE; + } + } + + /* Object array itself does not have exportable planes ...*/ + + /* Export the object array metadata */ + if (vxStatus == (vx_status) VX_SUCCESS) + { + tivx_utils_meta_format_t *meta; + meta = &refDesc->meta; + + meta->type = ref->type; + meta->object.object_array.num_items = numItems; + meta->object.object_array.item_type = itemType; + + ipcMsgHandle->numFd = 0; + *numMessages = numItems; + VX_PRINT(VX_ZONE_INFO, "vx_utils_export_ref_for_ipc_xfer_objarray() successfull.\n"); + } + + return vxStatus; +} + vx_status tivx_utils_export_ref_for_ipc_xfer(const vx_reference ref, tivx_utils_ref_ipc_msg_t *ipcMsg) { @@ -257,6 +350,107 @@ vx_status tivx_utils_export_ref_for_ipc_xfer(const vx_reference ref, return vxStatus; } +vx_status vx_utils_import_ref_from_ipc_xfer_objarray(vx_context context, + tivx_utils_ref_ipc_msg_t *ipcMsgHandle, + tivx_utils_ref_ipc_msg_t ipcMsgArray[], + vx_reference *ref) +{ + tivx_utils_meta_format_t const *meta; + void *ptrs[VX_IPC_MAX_VX_PLANES] = {0}; + void *phyAddr[VX_IPC_MAX_VX_PLANES]; + tivx_utils_ref_desc_t *refDesc; + uint32_t numItems; + uint32_t i; + vx_status vxStatus = VX_SUCCESS; + + refDesc = (tivx_utils_ref_desc_t *)&ipcMsgHandle->refDesc; + + /* Validate the arguments. */ + if (context == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "The parameter 'context' is NULL.\n"); + vxStatus = (vx_status)VX_FAILURE; + } + else if (ref == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "The parameter 'ref' is NULL.\n"); + vxStatus = (vx_status)VX_FAILURE; + } + else if ((ipcMsgHandle == NULL) || (ipcMsgArray == NULL)) + { + VX_PRINT(VX_ZONE_ERROR, "One of the IPC message pointers is NULL.\n"); + vxStatus = (vx_status)VX_FAILURE; + } + + /* Check if we have been provided a valid reference to work with. */ + if ((vxStatus == (vx_status)VX_SUCCESS) && (*ref == NULL)) + { + meta = &refDesc->meta; + + if (meta->type == (vx_enum)VX_TYPE_OBJECT_ARRAY) + { + /* Import all the items from the array, gather the references */ + numItems = meta->object.object_array.num_items; + vx_object_array objArrayRefs; + vx_reference exemplarRef = NULL; + vxStatus = tivx_utils_import_ref_from_ipc_xfer(context, &ipcMsgArray[0], &exemplarRef); + if (vxStatus != VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, "Could not import the item reference\n"); + } + objArrayRefs = vxCreateObjectArray(context, exemplarRef, numItems); + vxReleaseReference(&exemplarRef); + + /* Import the remaining items */ + for(i = 0; i < numItems; i++) + { + for (i = 0; i < ipcMsgArray[i].numFd; i++) + { + /* Translate FD corresponding to plane[i]. */ + vxStatus = tivxMemTranslateFd((uint64_t)ipcMsgArray[i].fd[i], + refDesc->handleSizes[i], + &ptrs[i], + &phyAddr[i]); + + if (vxStatus != (vx_status)VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, "tivxMemTranslateFd() failed for " + "FD [%d]\n", i); + break; + } + } + if (vxStatus == (vx_status)VX_SUCCESS) + { + /* Import the reference handles. */ + vxStatus = + tivxReferenceImportHandle(vxGetObjectArrayItem(objArrayRefs, i), + (const void **)ptrs, + (const uint32_t *)refDesc->handleSizes, + ipcMsgArray[i].numFd); + + if (vxStatus != (vx_status)VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, + "tivxReferenceImportHandle() failed.\n"); + } + } + VX_PRINT(VX_ZONE_INFO, "Importing item reference %d\n", i); + } + if (vxStatus != (vx_status)VX_SUCCESS) + { + *ref = vxCastRefFromObjectArray(objArrayRefs); + } + } + } + else + { + VX_PRINT(VX_ZONE_ERROR, "the imported pbject is not a vx_objarray \n"); + vxStatus = (vx_status)VX_FAILURE; + } + + return vxStatus; +} + vx_status tivx_utils_import_ref_from_ipc_xfer(vx_context context, tivx_utils_ref_ipc_msg_t *ipcMsg, vx_reference *ref) From 7af6bd2a44ef99a0b73001bf4321a115d2a1de07 Mon Sep 17 00:00:00 2001 From: "Cano Raphael (XC-AS/EPO3)" Date: Tue, 9 Sep 2025 10:26:00 +0200 Subject: [PATCH 2/8] better handling of error case --- utils/source/tivx_utils_ipc_ref_xfer.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/utils/source/tivx_utils_ipc_ref_xfer.c b/utils/source/tivx_utils_ipc_ref_xfer.c index 38e50d60e..407c3115b 100644 --- a/utils/source/tivx_utils_ipc_ref_xfer.c +++ b/utils/source/tivx_utils_ipc_ref_xfer.c @@ -428,15 +428,16 @@ vx_status vx_utils_import_ref_from_ipc_xfer_objarray(vx_context c (const uint32_t *)refDesc->handleSizes, ipcMsgArray[i].numFd); + VX_PRINT(VX_ZONE_INFO, "Importing item reference %d\n", i); if (vxStatus != (vx_status)VX_SUCCESS) { VX_PRINT(VX_ZONE_ERROR, "tivxReferenceImportHandle() failed.\n"); + break; } - } - VX_PRINT(VX_ZONE_INFO, "Importing item reference %d\n", i); + } } - if (vxStatus != (vx_status)VX_SUCCESS) + if (vxStatus == (vx_status)VX_SUCCESS) { *ref = vxCastRefFromObjectArray(objArrayRefs); } @@ -444,7 +445,7 @@ vx_status vx_utils_import_ref_from_ipc_xfer_objarray(vx_context c } else { - VX_PRINT(VX_ZONE_ERROR, "the imported pbject is not a vx_objarray \n"); + VX_PRINT(VX_ZONE_ERROR, "the imported pbject is not a vx_object_array \n"); vxStatus = (vx_status)VX_FAILURE; } From 7bb3e4cbcf7e6fc8f387cdada2978272378feedc Mon Sep 17 00:00:00 2001 From: "Cano Raphael (XC-AS/EPO3)" Date: Tue, 9 Sep 2025 16:17:53 +0200 Subject: [PATCH 3/8] fixing issues after testing --- utils/source/tivx_utils_ipc_ref_xfer.c | 34 ++++++++++++++------------ 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/utils/source/tivx_utils_ipc_ref_xfer.c b/utils/source/tivx_utils_ipc_ref_xfer.c index 407c3115b..732476bbe 100644 --- a/utils/source/tivx_utils_ipc_ref_xfer.c +++ b/utils/source/tivx_utils_ipc_ref_xfer.c @@ -360,9 +360,10 @@ vx_status vx_utils_import_ref_from_ipc_xfer_objarray(vx_context c void *phyAddr[VX_IPC_MAX_VX_PLANES]; tivx_utils_ref_desc_t *refDesc; uint32_t numItems; - uint32_t i; + uint32_t i,j; vx_status vxStatus = VX_SUCCESS; + /* refdesc for the object array itself */ refDesc = (tivx_utils_ref_desc_t *)&ipcMsgHandle->refDesc; /* Validate the arguments. */ @@ -389,45 +390,47 @@ vx_status vx_utils_import_ref_from_ipc_xfer_objarray(vx_context c if (meta->type == (vx_enum)VX_TYPE_OBJECT_ARRAY) { - /* Import all the items from the array, gather the references */ + /* create the obj array based on the type of object contained into it */ numItems = meta->object.object_array.num_items; vx_object_array objArrayRefs; - vx_reference exemplarRef = NULL; - vxStatus = tivx_utils_import_ref_from_ipc_xfer(context, &ipcMsgArray[0], &exemplarRef); + vx_reference itemRef = NULL; + vxStatus = tivx_utils_import_ref_from_ipc_xfer(context, &ipcMsgArray[0], &itemRef); if (vxStatus != VX_SUCCESS) { VX_PRINT(VX_ZONE_ERROR, "Could not import the item reference\n"); - } - objArrayRefs = vxCreateObjectArray(context, exemplarRef, numItems); - vxReleaseReference(&exemplarRef); + } + objArrayRefs = vxCreateObjectArray(context, itemRef, numItems); + vxReleaseReference(&itemRef); /* Import the remaining items */ for(i = 0; i < numItems; i++) { - for (i = 0; i < ipcMsgArray[i].numFd; i++) + refDesc = (tivx_utils_ref_desc_t *)&ipcMsgArray[i].refDesc; + for (j = 0; j < ipcMsgArray[i].numFd; j++) { /* Translate FD corresponding to plane[i]. */ - vxStatus = tivxMemTranslateFd((uint64_t)ipcMsgArray[i].fd[i], - refDesc->handleSizes[i], - &ptrs[i], - &phyAddr[i]); + vxStatus = tivxMemTranslateFd((uint64_t)ipcMsgArray[i].fd[j], + refDesc->handleSizes[j], + &ptrs[j], + &phyAddr[j]); if (vxStatus != (vx_status)VX_SUCCESS) { VX_PRINT(VX_ZONE_ERROR, "tivxMemTranslateFd() failed for " - "FD [%d]\n", i); + "FD [%d]\n", j); break; } } if (vxStatus == (vx_status)VX_SUCCESS) { /* Import the reference handles. */ + itemRef = vxGetObjectArrayItem(objArrayRefs, i); vxStatus = - tivxReferenceImportHandle(vxGetObjectArrayItem(objArrayRefs, i), + tivxReferenceImportHandle(itemRef, (const void **)ptrs, (const uint32_t *)refDesc->handleSizes, ipcMsgArray[i].numFd); - + vxReleaseReference(&itemRef); VX_PRINT(VX_ZONE_INFO, "Importing item reference %d\n", i); if (vxStatus != (vx_status)VX_SUCCESS) { @@ -494,7 +497,6 @@ vx_status tivx_utils_import_ref_from_ipc_xfer(vx_context context, if (meta->type == (vx_enum)VX_TYPE_IMAGE) { vx_image obj; - obj = vxCreateImage(context, meta->object.img.width, meta->object.img.height, From a47176c9bca8b3c125e2054d957450ce8c1ee2a4 Mon Sep 17 00:00:00 2001 From: "Cano Raphael (XC-AS/EPO3)" Date: Tue, 9 Sep 2025 16:27:21 +0200 Subject: [PATCH 4/8] add the RAW image type to the union --- utils/include/tivx_utils_ipc_ref_xfer.h | 8 ++++---- utils/source/tivx_utils_ipc_ref_xfer.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/utils/include/tivx_utils_ipc_ref_xfer.h b/utils/include/tivx_utils_ipc_ref_xfer.h index 41306201d..e0bb67bfd 100644 --- a/utils/include/tivx_utils_ipc_ref_xfer.h +++ b/utils/include/tivx_utils_ipc_ref_xfer.h @@ -199,12 +199,12 @@ typedef struct vx_enum item_type; } object_array; + /*!< \brief structure containing information about raw image + used when type is set to TIVX_TYPE_RAW_IMAGE */ + tivx_raw_image_create_params_t raw_image; + } object; /* Union to hold different types of metadata */ - /*!< \brief structure containing information about raw image - used when type is set to TIVX_TYPE_RAW_IMAGE */ - tivx_raw_image_create_params_t raw_image; - } tivx_utils_meta_format_t; typedef struct diff --git a/utils/source/tivx_utils_ipc_ref_xfer.c b/utils/source/tivx_utils_ipc_ref_xfer.c index 732476bbe..4718d21cc 100644 --- a/utils/source/tivx_utils_ipc_ref_xfer.c +++ b/utils/source/tivx_utils_ipc_ref_xfer.c @@ -296,9 +296,9 @@ vx_status tivx_utils_export_ref_for_ipc_xfer(const vx_reference ref, obj_desc = (tivx_obj_desc_raw_image_t *)ref->obj_desc; - tivx_obj_desc_memcpy(&meta->raw_image, - &obj_desc->params, - sizeof(tivx_raw_image_create_params_t)); + tivx_obj_desc_memcpy(&meta->object.raw_image, + &obj_desc->params, + sizeof(tivx_raw_image_create_params_t)); } else if (meta->type == (vx_enum)VX_TYPE_PYRAMID) { @@ -616,7 +616,7 @@ vx_status tivx_utils_import_ref_from_ipc_xfer(vx_context context, tivx_raw_image_create_params_t *p; tivx_raw_image obj; - p = (tivx_raw_image_create_params_t *)&meta->raw_image; + p = (tivx_raw_image_create_params_t *)&meta->object.raw_image; obj = tivxCreateRawImage(context, p); From ed608d717b3876f371a392479848436e15e0d26e Mon Sep 17 00:00:00 2001 From: "Cano Raphael (XC-AS/EPO3)" Date: Wed, 10 Sep 2025 14:59:23 +0200 Subject: [PATCH 5/8] create common function for both export interfaces --- utils/include/tivx_utils_ipc_ref_xfer.h | 3 +- utils/source/tivx_utils_ipc_ref_xfer.c | 1498 ++++++++++++----------- 2 files changed, 756 insertions(+), 745 deletions(-) diff --git a/utils/include/tivx_utils_ipc_ref_xfer.h b/utils/include/tivx_utils_ipc_ref_xfer.h index e0bb67bfd..6c1cd749a 100644 --- a/utils/include/tivx_utils_ipc_ref_xfer.h +++ b/utils/include/tivx_utils_ipc_ref_xfer.h @@ -190,8 +190,7 @@ typedef struct } user_data_object; /*!< \brief structure containing information about object array - used when type is set to VX_TYPE_OBJECT_ARRAY - NOTE: assume the underlying type is vx_image */ + used when type is set to VX_TYPE_OBJECT_ARRAY */ struct { /*!< \brief The number of image objects */ vx_uint32 num_items; diff --git a/utils/source/tivx_utils_ipc_ref_xfer.c b/utils/source/tivx_utils_ipc_ref_xfer.c index 4718d21cc..0cb90ae23 100644 --- a/utils/source/tivx_utils_ipc_ref_xfer.c +++ b/utils/source/tivx_utils_ipc_ref_xfer.c @@ -1,743 +1,755 @@ -/* - * - * Copyright (c) 2021 Texas Instruments Incorporated - * - * All rights reserved not granted herein. - * - * Limited License. - * - * Texas Instruments Incorporated grants a world-wide, royalty-free, non-exclusive - * license under copyrights and patents it now or hereafter owns or controls to make, - * have made, use, import, offer to sell and sell ("Utilize") this software subject to the - * terms herein. With respect to the foregoing patent license, such license is granted - * solely to the extent that any such patent is necessary to Utilize the software alone. - * The patent license shall not apply to any combinations which include this software, - * other than combinations with devices manufactured by or for TI ("TI Devices"). - * No hardware patent is licensed hereunder. - * - * Redistributions must preserve existing copyright notices and reproduce this license - * (including the above copyright notice and the disclaimer and (if applicable) source - * code license limitations below) in the documentation and/or other materials provided - * with the distribution - * - * Redistribution and use in binary form, without modification, are permitted provided - * that the following conditions are met: - * - * * No reverse engineering, decompilation, or disassembly of this software is - * permitted with respect to any software provided in binary form. - * - * * any redistribution and use are licensed by TI for use only with TI Devices. - * - * * Nothing shall obligate TI to provide you with source code for the software - * licensed and provided to you in object code. - * - * If software source code is provided to you, modification and redistribution of the - * source code are permitted provided that the following conditions are met: - * - * * any redistribution and use of the source code, including any resulting derivative - * works, are licensed by TI for use only with TI Devices. - * - * * any redistribution and use of any object code compiled from the source code - * and any resulting derivative works, are licensed by TI for use only with TI Devices. - * - * Neither the name of Texas Instruments Incorporated nor the names of its suppliers - * - * may be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * DISCLAIMER. - * - * THIS SOFTWARE IS PROVIDED BY TI AND TI'S LICENSORS "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL TI AND TI'S LICENSORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include -#include - -#include - -vx_status vx_utils_export_ref_for_ipc_xfer_objarray(const vx_reference ref, - vx_uint32 *numMessages, - tivx_utils_ref_ipc_msg_t *ipcMsgHandle, - tivx_utils_ref_ipc_msg_t ipcMsgArray[]) -{ - vx_status vxStatus = VX_SUCCESS; - tivx_utils_ref_desc_t *refDesc = NULL; - vx_object_array objarr; - tivx_obj_desc_object_array_t *obj_desc; - vx_enum itemType; - uint32_t numItems = 0; - uint32_t i; - - /* Validate the arguments. */ - if (ref == NULL || numMessages == NULL) - { - VX_PRINT(VX_ZONE_ERROR, "The parameter 'ref' is NULL.\n"); - vxStatus = (vx_status)VX_FAILURE; - } - else if (ipcMsgHandle == NULL || ipcMsgArray == NULL) - { - VX_PRINT(VX_ZONE_ERROR, "One of ipcMsg* pointers is NULL.\n"); - vxStatus = (vx_status)VX_FAILURE; - } - - if (vxStatus == (vx_status)VX_SUCCESS) - { - refDesc = &ipcMsgHandle->refDesc; - - /* Validate object type and get metadata */ - if(ref->type == VX_TYPE_OBJECT_ARRAY) - { - objarr = (vx_object_array) ref; - obj_desc = (tivx_obj_desc_object_array_t *) objarr->base.obj_desc; - itemType = obj_desc->item_type; - numItems = obj_desc->num_items; - VX_PRINT(VX_ZONE_INFO, "Exporting object array of type %d\n", itemType); - - for(i = 0; i < numItems; i++) - { - VX_PRINT(VX_ZONE_INFO, "Item number - %d\n", i); - vx_reference itemRef = NULL; - itemRef = objarr->ref[i]; - if (itemRef == NULL) - { - VX_PRINT(VX_ZONE_ERROR, "Cannot get current reference, aborting.\n"); - vxStatus = (vx_status)VX_FAILURE; - break; - } - - /* allocate memory for data reference, independent of graph state */ - vxStatus = ownReferenceAllocMem(itemRef); - if (vxStatus != (vx_status)VX_SUCCESS) - { - VX_PRINT(VX_ZONE_ERROR,"Memory allocation for data reference failed\n"); - break; - } - - vxStatus = tivx_utils_export_ref_for_ipc_xfer(itemRef, &ipcMsgArray[i]); - if (vxStatus != VX_SUCCESS) - { - VX_PRINT(VX_ZONE_ERROR, "Cannot export one of the references, aborting\n"); - break; - } - } - } - else - { - VX_PRINT(VX_ZONE_ERROR, "Not an object array\n"); - vxStatus = (vx_status)VX_FAILURE; - } - } - - /* Object array itself does not have exportable planes ...*/ - - /* Export the object array metadata */ - if (vxStatus == (vx_status) VX_SUCCESS) - { - tivx_utils_meta_format_t *meta; - meta = &refDesc->meta; - - meta->type = ref->type; - meta->object.object_array.num_items = numItems; - meta->object.object_array.item_type = itemType; - - ipcMsgHandle->numFd = 0; - *numMessages = numItems; - VX_PRINT(VX_ZONE_INFO, "vx_utils_export_ref_for_ipc_xfer_objarray() successfull.\n"); - } - - return vxStatus; -} - -vx_status tivx_utils_export_ref_for_ipc_xfer(const vx_reference ref, - tivx_utils_ref_ipc_msg_t *ipcMsg) -{ - void *ptrs[VX_IPC_MAX_VX_PLANES]; - tivx_utils_ref_desc_t *refDesc; - uint32_t numEntries; - vx_status vxStatus = VX_SUCCESS; - - /* Validate the arguments. */ - if (ref == NULL) - { - /* More thorough checks on ref done inside tivxReferenceExportHandle() - * below. - */ - VX_PRINT(VX_ZONE_ERROR, "The parameter 'ref' is NULL.\n"); - vxStatus = (vx_status)VX_FAILURE; - } - else if (ipcMsg == NULL) - { - VX_PRINT(VX_ZONE_ERROR, "The parameter 'ipcMsg' is NULL.\n"); - vxStatus = (vx_status)VX_FAILURE; - } - - if (vxStatus == (vx_status)VX_SUCCESS) - { - refDesc = &ipcMsg->refDesc; - - /* Export the handles. */ - vxStatus = tivxReferenceExportHandle(ref, - ptrs, - refDesc->handleSizes, - VX_IPC_MAX_VX_PLANES, - &numEntries); - - if (vxStatus != (vx_status)VX_SUCCESS) - { - VX_PRINT(VX_ZONE_ERROR, "tivxReferenceExportHandle() failed.\n"); - } - } - - if (vxStatus == (vx_status)VX_SUCCESS) - { - tivx_utils_meta_format_t *meta; - void *phyAddr; - uint64_t fd64; - uint32_t i; - - meta = &refDesc->meta; - meta->type = ref->type; - - if (meta->type == (vx_enum)VX_TYPE_IMAGE) - { - tivx_obj_desc_image_t *obj_desc; - - obj_desc = (tivx_obj_desc_image_t *)ref->obj_desc; - - meta->object.img.width = obj_desc->width; - meta->object.img.height = obj_desc->height; - meta->object.img.format = obj_desc->format; - meta->object.img.planes = obj_desc->planes; - - /* Just translate plane[0] pointer. */ - numEntries = 1; - } - else if (meta->type == (vx_enum)VX_TYPE_TENSOR) - { - tivx_obj_desc_tensor_t *obj_desc; - int32_t k; - - obj_desc = (tivx_obj_desc_tensor_t *)ref->obj_desc; - - meta->object.tensor.number_of_dimensions = obj_desc->number_of_dimensions; - meta->object.tensor.data_type = obj_desc->data_type; - meta->object.tensor.fixed_point_position = obj_desc->fixed_point_position; - - for (k = 0; k < meta->object.tensor.number_of_dimensions; k++) - { - meta->object.tensor.dimensions[k] = obj_desc->dimensions[k]; - } - } - else if (meta->type == (vx_enum)VX_TYPE_USER_DATA_OBJECT) - { - tivx_obj_desc_user_data_object_t *obj_desc; - - obj_desc = (tivx_obj_desc_user_data_object_t *)ref->obj_desc; - - meta->object.user_data_object.size = obj_desc->mem_size; - - memcpy(meta->object.user_data_object.type_name, - (const void *)obj_desc->type_name, - sizeof(obj_desc->type_name)); - } - else if (meta->type == (vx_enum)VX_TYPE_ARRAY) - { - tivx_obj_desc_array_t *obj_desc; - - obj_desc = (tivx_obj_desc_array_t *)ref->obj_desc; - - meta->object.arr.item_type = obj_desc->item_type; - meta->object.arr.capacity = obj_desc->capacity; - } - else if (meta->type == (vx_enum)VX_TYPE_CONVOLUTION) - { - tivx_obj_desc_convolution_t *obj_desc; - - obj_desc = (tivx_obj_desc_convolution_t *)ref->obj_desc; - - meta->object.conv.cols = obj_desc->columns; - meta->object.conv.rows = obj_desc->rows; - - } - else if (meta->type == (vx_enum)VX_TYPE_MATRIX) - { - tivx_obj_desc_matrix_t *obj_desc; - - obj_desc = (tivx_obj_desc_matrix_t *)ref->obj_desc; - - meta->object.mat.type = obj_desc->data_type; - meta->object.mat.cols = obj_desc->columns; - meta->object.mat.rows = obj_desc->rows; - } - else if (meta->type == (vx_enum)VX_TYPE_DISTRIBUTION) - { - tivx_obj_desc_distribution_t *obj_desc; - - obj_desc = (tivx_obj_desc_distribution_t *)ref->obj_desc; - - meta->object.dist.bins = obj_desc->num_bins; - meta->object.dist.offset = obj_desc->offset; - meta->object.dist.range = obj_desc->range; - - } - else if (meta->type == (vx_enum)TIVX_TYPE_RAW_IMAGE) - { - tivx_obj_desc_raw_image_t *obj_desc; - - obj_desc = (tivx_obj_desc_raw_image_t *)ref->obj_desc; - - tivx_obj_desc_memcpy(&meta->object.raw_image, - &obj_desc->params, - sizeof(tivx_raw_image_create_params_t)); - } - else if (meta->type == (vx_enum)VX_TYPE_PYRAMID) - { - tivx_obj_desc_pyramid_t *obj_desc; - tivx_obj_desc_image_t *img_obj_desc; - vx_reference img_ref; - vx_pyramid pyramid; - - pyramid = (vx_pyramid)ref; - obj_desc = (tivx_obj_desc_pyramid_t *)ref->obj_desc; - img_ref = (vx_reference)pyramid->img[0]; - img_obj_desc = (tivx_obj_desc_image_t *)img_ref->obj_desc; - - meta->object.pmd.levels = obj_desc->num_levels; - meta->object.pmd.width = obj_desc->width; - meta->object.pmd.height = obj_desc->height; - meta->object.pmd.scale = obj_desc->scale; - meta->object.pmd.format = obj_desc->format; - meta->object.pmd.planes = img_obj_desc->planes; - - numEntries = meta->object.pmd.levels; - } - else - { - VX_PRINT(VX_ZONE_ERROR, "Unsupported type [%d].\n", meta->type); - vxStatus = (vx_status)VX_FAILURE; - } - - ipcMsg->numFd = numEntries; - - for (i = 0; i < numEntries; i++) - { - vxStatus = tivxMemTranslateVirtAddr(ptrs[i], - &fd64, - &phyAddr); - - if (vxStatus != (vx_status) VX_SUCCESS) - { - VX_PRINT(VX_ZONE_ERROR, - "tivxMemTranslateVirtAddr() failed for " - "plane [%d]\n", i); - break; - } - - ipcMsg->fd[i] = fd64; - } - } - - return vxStatus; -} - -vx_status vx_utils_import_ref_from_ipc_xfer_objarray(vx_context context, - tivx_utils_ref_ipc_msg_t *ipcMsgHandle, - tivx_utils_ref_ipc_msg_t ipcMsgArray[], - vx_reference *ref) -{ - tivx_utils_meta_format_t const *meta; - void *ptrs[VX_IPC_MAX_VX_PLANES] = {0}; - void *phyAddr[VX_IPC_MAX_VX_PLANES]; - tivx_utils_ref_desc_t *refDesc; - uint32_t numItems; - uint32_t i,j; - vx_status vxStatus = VX_SUCCESS; - - /* refdesc for the object array itself */ - refDesc = (tivx_utils_ref_desc_t *)&ipcMsgHandle->refDesc; - - /* Validate the arguments. */ - if (context == NULL) - { - VX_PRINT(VX_ZONE_ERROR, "The parameter 'context' is NULL.\n"); - vxStatus = (vx_status)VX_FAILURE; - } - else if (ref == NULL) - { - VX_PRINT(VX_ZONE_ERROR, "The parameter 'ref' is NULL.\n"); - vxStatus = (vx_status)VX_FAILURE; - } - else if ((ipcMsgHandle == NULL) || (ipcMsgArray == NULL)) - { - VX_PRINT(VX_ZONE_ERROR, "One of the IPC message pointers is NULL.\n"); - vxStatus = (vx_status)VX_FAILURE; - } - - /* Check if we have been provided a valid reference to work with. */ - if ((vxStatus == (vx_status)VX_SUCCESS) && (*ref == NULL)) - { - meta = &refDesc->meta; - - if (meta->type == (vx_enum)VX_TYPE_OBJECT_ARRAY) - { - /* create the obj array based on the type of object contained into it */ - numItems = meta->object.object_array.num_items; - vx_object_array objArrayRefs; - vx_reference itemRef = NULL; - vxStatus = tivx_utils_import_ref_from_ipc_xfer(context, &ipcMsgArray[0], &itemRef); - if (vxStatus != VX_SUCCESS) - { - VX_PRINT(VX_ZONE_ERROR, "Could not import the item reference\n"); - } - objArrayRefs = vxCreateObjectArray(context, itemRef, numItems); - vxReleaseReference(&itemRef); - - /* Import the remaining items */ - for(i = 0; i < numItems; i++) - { - refDesc = (tivx_utils_ref_desc_t *)&ipcMsgArray[i].refDesc; - for (j = 0; j < ipcMsgArray[i].numFd; j++) - { - /* Translate FD corresponding to plane[i]. */ - vxStatus = tivxMemTranslateFd((uint64_t)ipcMsgArray[i].fd[j], - refDesc->handleSizes[j], - &ptrs[j], - &phyAddr[j]); - - if (vxStatus != (vx_status)VX_SUCCESS) - { - VX_PRINT(VX_ZONE_ERROR, "tivxMemTranslateFd() failed for " - "FD [%d]\n", j); - break; - } - } - if (vxStatus == (vx_status)VX_SUCCESS) - { - /* Import the reference handles. */ - itemRef = vxGetObjectArrayItem(objArrayRefs, i); - vxStatus = - tivxReferenceImportHandle(itemRef, - (const void **)ptrs, - (const uint32_t *)refDesc->handleSizes, - ipcMsgArray[i].numFd); - vxReleaseReference(&itemRef); - VX_PRINT(VX_ZONE_INFO, "Importing item reference %d\n", i); - if (vxStatus != (vx_status)VX_SUCCESS) - { - VX_PRINT(VX_ZONE_ERROR, - "tivxReferenceImportHandle() failed.\n"); - break; - } - } - } - if (vxStatus == (vx_status)VX_SUCCESS) - { - *ref = vxCastRefFromObjectArray(objArrayRefs); - } - } - } - else - { - VX_PRINT(VX_ZONE_ERROR, "the imported pbject is not a vx_object_array \n"); - vxStatus = (vx_status)VX_FAILURE; - } - - return vxStatus; -} - -vx_status tivx_utils_import_ref_from_ipc_xfer(vx_context context, - tivx_utils_ref_ipc_msg_t *ipcMsg, - vx_reference *ref) -{ - void *ptrs[VX_IPC_MAX_VX_PLANES] = {0}; - void *phyAddr[VX_IPC_MAX_VX_PLANES]; - tivx_utils_meta_format_t const *meta; - tivx_utils_ref_desc_t *refDesc; - uint32_t i; - vx_status vxStatus = VX_SUCCESS; - - refDesc = (tivx_utils_ref_desc_t *)&ipcMsg->refDesc; - - /* Validate the arguments. */ - if (context == NULL) - { - VX_PRINT(VX_ZONE_ERROR, "The parameter 'context' is NULL.\n"); - vxStatus = (vx_status)VX_FAILURE; - } - else if (ref == NULL) - { - VX_PRINT(VX_ZONE_ERROR, "The parameter 'ref' is NULL.\n"); - vxStatus = (vx_status)VX_FAILURE; - } - else if (ipcMsg == NULL) - { - VX_PRINT(VX_ZONE_ERROR, "The parameter 'ipcMsg' is NULL.\n"); - vxStatus = (vx_status)VX_FAILURE; - } - - /* Check if we have been provided a valid reference to work with. If not, - * create one and then proceed. - */ - if ((vxStatus == (vx_status)VX_SUCCESS) && (*ref == NULL)) - { - vx_reference lRef = NULL; - - meta = &refDesc->meta; - - if (meta->type == (vx_enum)VX_TYPE_IMAGE) - { - vx_image obj; - obj = vxCreateImage(context, - meta->object.img.width, - meta->object.img.height, - meta->object.img.format); - - if (obj == NULL) - { - VX_PRINT(VX_ZONE_ERROR, "vxCreateImage() failed.\n"); - vxStatus = VX_FAILURE; - } - - lRef = (vx_reference)obj; - } - else if (meta->type == (vx_enum)VX_TYPE_TENSOR) - { - vx_tensor obj; - - obj = vxCreateTensor(context, - meta->object.tensor.number_of_dimensions, - meta->object.tensor.dimensions, - meta->object.tensor.data_type, - meta->object.tensor.fixed_point_position); - - if (obj == NULL) - { - VX_PRINT(VX_ZONE_ERROR, "vxCreateTensor() failed.\n"); - vxStatus = VX_FAILURE; - } - - lRef = (vx_reference)obj; - } - else if (meta->type == (vx_enum)VX_TYPE_USER_DATA_OBJECT) - { - vx_user_data_object obj; - - obj = vxCreateUserDataObject(context, - meta->object.user_data_object.type_name, - meta->object.user_data_object.size, - NULL); - - if (obj == NULL) - { - VX_PRINT(VX_ZONE_ERROR, "vxCreateUserDataObject() failed.\n"); - vxStatus = VX_FAILURE; - } - - lRef = (vx_reference)obj; - } - else if (meta->type == (vx_enum)VX_TYPE_ARRAY) - { - vx_array obj; - - obj = vxCreateArray(context, - meta->object.arr.item_type, - meta->object.arr.capacity); - - if (obj == NULL) - { - VX_PRINT(VX_ZONE_ERROR, "vxCreateArray() failed.\n"); - vxStatus = VX_FAILURE; - } - - lRef = (vx_reference)obj; - } - else if (meta->type == (vx_enum)VX_TYPE_CONVOLUTION) - { - vx_convolution obj; - - obj = vxCreateConvolution(context, - meta->object.conv.cols, - meta->object.conv.rows); - - if (obj == NULL) - { - VX_PRINT(VX_ZONE_ERROR, "vxCreateConvolution() failed.\n"); - vxStatus = VX_FAILURE; - } - - lRef = (vx_reference)obj; - } - else if (meta->type == (vx_enum)VX_TYPE_MATRIX) - { - vx_matrix obj; - - obj = vxCreateMatrix(context, - meta->object.mat.type, - meta->object.mat.cols, - meta->object.mat.rows); - - if (obj == NULL) - { - VX_PRINT(VX_ZONE_ERROR, "vxCreateMatrix() failed.\n"); - vxStatus = VX_FAILURE; - } - - lRef = (vx_reference)obj; - } - else if (meta->type == (vx_enum)VX_TYPE_DISTRIBUTION) - { - vx_distribution obj; - - obj = vxCreateDistribution(context, - meta->object.dist.bins, - meta->object.dist.offset, - meta->object.dist.range); - - if (obj == NULL) - { - VX_PRINT(VX_ZONE_ERROR, "vxCreateDistribution() failed.\n"); - vxStatus = VX_FAILURE; - } - - lRef = (vx_reference)obj; - } - else if (meta->type == (vx_enum)TIVX_TYPE_RAW_IMAGE) - { - tivx_raw_image_create_params_t *p; - tivx_raw_image obj; - - p = (tivx_raw_image_create_params_t *)&meta->object.raw_image; - - obj = tivxCreateRawImage(context, p); - - if (obj == NULL) - { - VX_PRINT(VX_ZONE_ERROR, "tivxCreateRawImage() failed.\n"); - vxStatus = VX_FAILURE; - } - - lRef = (vx_reference)obj; - } - else if (meta->type == (vx_enum)VX_TYPE_PYRAMID) - { - vx_pyramid obj; - - obj = vxCreatePyramid(context, - meta->object.pmd.levels, - meta->object.pmd.scale, - meta->object.pmd.width, - meta->object.pmd.height, - meta->object.pmd.format); - - if (obj == NULL) - { - VX_PRINT(VX_ZONE_ERROR, "vxCreatePyramid() failed.\n"); - vxStatus = VX_FAILURE; - } - - lRef = (vx_reference)obj; - } - else - { - VX_PRINT(VX_ZONE_ERROR, "Unsupported type [%d].\n", meta->type); - vxStatus = (vx_status)VX_FAILURE; - } - - if (vxStatus == (vx_status)VX_SUCCESS) - { - *ref = lRef; - } - } - - if (vxStatus == (vx_status)VX_SUCCESS) - { - for (i = 0; i < ipcMsg->numFd; i++) - { - /* Translate FD corresponding to plane[i]. */ - vxStatus = tivxMemTranslateFd((uint64_t)ipcMsg->fd[i], - refDesc->handleSizes[i], - &ptrs[i], - &phyAddr[i]); - - if (vxStatus != (vx_status)VX_SUCCESS) - { - VX_PRINT(VX_ZONE_ERROR, "tivxMemTranslateFd() failed for " - "FD [%d]\n", i); - break; - } - } - } - - if (vxStatus == (vx_status)VX_SUCCESS) - { - /* Import the reference handles. */ - vxStatus = - tivxReferenceImportHandle(*ref, - (const void **)ptrs, - (const uint32_t *)refDesc->handleSizes, - ipcMsg->numFd); - - if (vxStatus != (vx_status)VX_SUCCESS) - { - VX_PRINT(VX_ZONE_ERROR, - "tivxReferenceImportHandle() failed.\n"); - } - } - - return vxStatus; -} - -vx_bool tivx_utils_compare_refs_from_ipc_xfer(tivx_utils_ref_ipc_msg_t *ipcMsg1, - tivx_utils_ref_ipc_msg_t *ipcMsg2) -{ - vx_bool ret = (vx_bool)vx_false_e; - vx_status vxStatus = (vx_status)VX_SUCCESS; - - if (ipcMsg1 == NULL) - { - VX_PRINT(VX_ZONE_ERROR, "The parameter 'ipcMsg1' is NULL.\n"); - vxStatus = (vx_status)VX_FAILURE; - } - - if (ipcMsg2 == NULL) - { - VX_PRINT(VX_ZONE_ERROR, "The parameter 'ipcMsg2' is NULL.\n"); - vxStatus = (vx_status)VX_FAILURE; - } - - if ((vx_status)VX_SUCCESS == vxStatus) - { - if (ipcMsg1->numFd != ipcMsg2->numFd) - { - VX_PRINT(VX_ZONE_INFO, "ipcMsg1->numFd (%d) does not match ipcMsg2->numFd (%d).\n", ipcMsg1->numFd, ipcMsg2->numFd); - vxStatus = (vx_status)VX_FAILURE; - } - } - - if ((vx_status)VX_SUCCESS == vxStatus) - { - uint32_t i; - tivx_utils_ref_desc_t *refDesc1, *refDesc2; - - refDesc1 = &ipcMsg1->refDesc; - refDesc2 = &ipcMsg2->refDesc; - - for (i = 0; i < ipcMsg1->numFd; i++) - { - /* Compare FD of ipcMsg1 and ipcMsg2. */ - ret |= tivxMemCompareFd((uint64_t)ipcMsg1->fd[i], (uint64_t)ipcMsg2->fd[i], refDesc1->handleSizes[i], refDesc2->handleSizes[i]); - } - } - - return ret; -} +/* + * + * Copyright (c) 2021 Texas Instruments Incorporated + * + * All rights reserved not granted herein. + * + * Limited License. + * + * Texas Instruments Incorporated grants a world-wide, royalty-free, non-exclusive + * license under copyrights and patents it now or hereafter owns or controls to make, + * have made, use, import, offer to sell and sell ("Utilize") this software subject to the + * terms herein. With respect to the foregoing patent license, such license is granted + * solely to the extent that any such patent is necessary to Utilize the software alone. + * The patent license shall not apply to any combinations which include this software, + * other than combinations with devices manufactured by or for TI ("TI Devices"). + * No hardware patent is licensed hereunder. + * + * Redistributions must preserve existing copyright notices and reproduce this license + * (including the above copyright notice and the disclaimer and (if applicable) source + * code license limitations below) in the documentation and/or other materials provided + * with the distribution + * + * Redistribution and use in binary form, without modification, are permitted provided + * that the following conditions are met: + * + * * No reverse engineering, decompilation, or disassembly of this software is + * permitted with respect to any software provided in binary form. + * + * * any redistribution and use are licensed by TI for use only with TI Devices. + * + * * Nothing shall obligate TI to provide you with source code for the software + * licensed and provided to you in object code. + * + * If software source code is provided to you, modification and redistribution of the + * source code are permitted provided that the following conditions are met: + * + * * any redistribution and use of the source code, including any resulting derivative + * works, are licensed by TI for use only with TI Devices. + * + * * any redistribution and use of any object code compiled from the source code + * and any resulting derivative works, are licensed by TI for use only with TI Devices. + * + * Neither the name of Texas Instruments Incorporated nor the names of its suppliers + * + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * DISCLAIMER. + * + * THIS SOFTWARE IS PROVIDED BY TI AND TI'S LICENSORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TI AND TI'S LICENSORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include + +#include + +vx_status vx_utils_export_ref_for_ipc_xfer_objarray(const vx_reference ref, + vx_uint32 *numMessages, + tivx_utils_ref_ipc_msg_t *ipcMsgHandle, + tivx_utils_ref_ipc_msg_t ipcMsgArray[]) +{ + vx_status vxStatus = VX_SUCCESS; + tivx_utils_ref_desc_t *refDesc = NULL; + vx_object_array objarr; + tivx_obj_desc_object_array_t *obj_desc; + vx_enum itemType; + uint32_t numItems = 0; + uint32_t i; + + /* Validate the arguments. */ + if (ref == NULL || numMessages == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "The parameter 'ref' is NULL.\n"); + vxStatus = (vx_status)VX_FAILURE; + } + else if (ipcMsgHandle == NULL || ipcMsgArray == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "One of ipcMsg* pointers is NULL.\n"); + vxStatus = (vx_status)VX_FAILURE; + } + + if (vxStatus == (vx_status)VX_SUCCESS) + { + refDesc = &ipcMsgHandle->refDesc; + + /* Validate object type and get metadata */ + if(ref->type == VX_TYPE_OBJECT_ARRAY) + { + objarr = (vx_object_array) ref; + obj_desc = (tivx_obj_desc_object_array_t *) objarr->base.obj_desc; + itemType = obj_desc->item_type; + numItems = obj_desc->num_items; + VX_PRINT(VX_ZONE_INFO, "Exporting object array of type %d\n", itemType); + + for(i = 0; i < numItems; i++) + { + VX_PRINT(VX_ZONE_INFO, "Item number - %d\n", i); + vx_reference itemRef = NULL; + itemRef = objarr->ref[i]; + if (itemRef == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "Cannot get current reference, aborting.\n"); + vxStatus = (vx_status)VX_FAILURE; + break; + } + + /* allocate memory for data reference, independent of graph state */ + vxStatus = ownReferenceAllocMem(itemRef); + if (vxStatus != (vx_status)VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR,"Memory allocation for data reference failed\n"); + break; + } + + vxStatus = tivx_utils_export_ref_for_ipc_xfer(itemRef, &ipcMsgArray[i]); + if (vxStatus != VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, "Cannot export one of the references, aborting\n"); + break; + } + } + } + else + { + VX_PRINT(VX_ZONE_ERROR, "Not an object array\n"); + vxStatus = (vx_status)VX_FAILURE; + } + } + + /* Object array itself does not have exportable planes ...*/ + + /* Export the object array metadata */ + if (vxStatus == (vx_status) VX_SUCCESS) + { + tivx_utils_meta_format_t *meta; + meta = &refDesc->meta; + + meta->type = ref->type; + meta->object.object_array.num_items = numItems; + meta->object.object_array.item_type = itemType; + + ipcMsgHandle->numFd = 0; + *numMessages = numItems; + VX_PRINT(VX_ZONE_INFO, "vx_utils_export_ref_for_ipc_xfer_objarray() successfull.\n"); + } + + return vxStatus; +} + +vx_status tivx_utils_export_ref_for_ipc_xfer(const vx_reference ref, + tivx_utils_ref_ipc_msg_t *ipcMsg) +{ + void *ptrs[VX_IPC_MAX_VX_PLANES]; + tivx_utils_ref_desc_t *refDesc; + uint32_t numEntries; + vx_status vxStatus = VX_SUCCESS; + + /* Validate the arguments. */ + if (ref == NULL) + { + /* More thorough checks on ref done inside tivxReferenceExportHandle() + * below. + */ + VX_PRINT(VX_ZONE_ERROR, "The parameter 'ref' is NULL.\n"); + vxStatus = (vx_status)VX_FAILURE; + } + else if (ipcMsg == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "The parameter 'ipcMsg' is NULL.\n"); + vxStatus = (vx_status)VX_FAILURE; + } + + if (vxStatus == (vx_status)VX_SUCCESS) + { + refDesc = &ipcMsg->refDesc; + + /* Export the handles. */ + vxStatus = tivxReferenceExportHandle(ref, + ptrs, + refDesc->handleSizes, + VX_IPC_MAX_VX_PLANES, + &numEntries); + + if (vxStatus != (vx_status)VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, "tivxReferenceExportHandle() failed.\n"); + } + } + + if (vxStatus == (vx_status)VX_SUCCESS) + { + tivx_utils_meta_format_t *meta; + void *phyAddr; + uint64_t fd64; + uint32_t i; + + meta = &refDesc->meta; + meta->type = ref->type; + + if (meta->type == (vx_enum)VX_TYPE_IMAGE) + { + tivx_obj_desc_image_t *obj_desc; + + obj_desc = (tivx_obj_desc_image_t *)ref->obj_desc; + + meta->object.img.width = obj_desc->width; + meta->object.img.height = obj_desc->height; + meta->object.img.format = obj_desc->format; + meta->object.img.planes = obj_desc->planes; + + /* Just translate plane[0] pointer. */ + numEntries = 1; + } + else if (meta->type == (vx_enum)VX_TYPE_TENSOR) + { + tivx_obj_desc_tensor_t *obj_desc; + int32_t k; + + obj_desc = (tivx_obj_desc_tensor_t *)ref->obj_desc; + + meta->object.tensor.number_of_dimensions = obj_desc->number_of_dimensions; + meta->object.tensor.data_type = obj_desc->data_type; + meta->object.tensor.fixed_point_position = obj_desc->fixed_point_position; + + for (k = 0; k < meta->object.tensor.number_of_dimensions; k++) + { + meta->object.tensor.dimensions[k] = obj_desc->dimensions[k]; + } + } + else if (meta->type == (vx_enum)VX_TYPE_USER_DATA_OBJECT) + { + tivx_obj_desc_user_data_object_t *obj_desc; + + obj_desc = (tivx_obj_desc_user_data_object_t *)ref->obj_desc; + + meta->object.user_data_object.size = obj_desc->mem_size; + + memcpy(meta->object.user_data_object.type_name, + (const void *)obj_desc->type_name, + sizeof(obj_desc->type_name)); + } + else if (meta->type == (vx_enum)VX_TYPE_ARRAY) + { + tivx_obj_desc_array_t *obj_desc; + + obj_desc = (tivx_obj_desc_array_t *)ref->obj_desc; + + meta->object.arr.item_type = obj_desc->item_type; + meta->object.arr.capacity = obj_desc->capacity; + } + else if (meta->type == (vx_enum)VX_TYPE_CONVOLUTION) + { + tivx_obj_desc_convolution_t *obj_desc; + + obj_desc = (tivx_obj_desc_convolution_t *)ref->obj_desc; + + meta->object.conv.cols = obj_desc->columns; + meta->object.conv.rows = obj_desc->rows; + + } + else if (meta->type == (vx_enum)VX_TYPE_MATRIX) + { + tivx_obj_desc_matrix_t *obj_desc; + + obj_desc = (tivx_obj_desc_matrix_t *)ref->obj_desc; + + meta->object.mat.type = obj_desc->data_type; + meta->object.mat.cols = obj_desc->columns; + meta->object.mat.rows = obj_desc->rows; + } + else if (meta->type == (vx_enum)VX_TYPE_DISTRIBUTION) + { + tivx_obj_desc_distribution_t *obj_desc; + + obj_desc = (tivx_obj_desc_distribution_t *)ref->obj_desc; + + meta->object.dist.bins = obj_desc->num_bins; + meta->object.dist.offset = obj_desc->offset; + meta->object.dist.range = obj_desc->range; + + } + else if (meta->type == (vx_enum)TIVX_TYPE_RAW_IMAGE) + { + tivx_obj_desc_raw_image_t *obj_desc; + + obj_desc = (tivx_obj_desc_raw_image_t *)ref->obj_desc; + + tivx_obj_desc_memcpy(&meta->object.raw_image, + &obj_desc->params, + sizeof(tivx_raw_image_create_params_t)); + } + else if (meta->type == (vx_enum)VX_TYPE_PYRAMID) + { + tivx_obj_desc_pyramid_t *obj_desc; + tivx_obj_desc_image_t *img_obj_desc; + vx_reference img_ref; + vx_pyramid pyramid; + + pyramid = (vx_pyramid)ref; + obj_desc = (tivx_obj_desc_pyramid_t *)ref->obj_desc; + img_ref = (vx_reference)pyramid->img[0]; + img_obj_desc = (tivx_obj_desc_image_t *)img_ref->obj_desc; + + meta->object.pmd.levels = obj_desc->num_levels; + meta->object.pmd.width = obj_desc->width; + meta->object.pmd.height = obj_desc->height; + meta->object.pmd.scale = obj_desc->scale; + meta->object.pmd.format = obj_desc->format; + meta->object.pmd.planes = img_obj_desc->planes; + + numEntries = meta->object.pmd.levels; + } + else + { + VX_PRINT(VX_ZONE_ERROR, "Unsupported type [%d].\n", meta->type); + vxStatus = (vx_status)VX_FAILURE; + } + + ipcMsg->numFd = numEntries; + + for (i = 0; i < numEntries; i++) + { + vxStatus = tivxMemTranslateVirtAddr(ptrs[i], + &fd64, + &phyAddr); + + if (vxStatus != (vx_status) VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, + "tivxMemTranslateVirtAddr() failed for " + "plane [%d]\n", i); + break; + } + + ipcMsg->fd[i] = fd64; + } + } + + return vxStatus; +} + +static vx_status vx_utils_ref_from_ipc_xfer(vx_context context, + tivx_utils_ref_ipc_msg_t *ipcMsg, + vx_reference *ref) +{ + vx_status vxStatus = VX_SUCCESS; + tivx_utils_ref_desc_t *refDesc; + tivx_utils_meta_format_t const *meta; + + refDesc = (tivx_utils_ref_desc_t *)&ipcMsg->refDesc; + + /* Validate the arguments. */ + if (context == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "The parameter 'context' is NULL.\n"); + vxStatus = (vx_status)VX_FAILURE; + } + else if (ref == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "The parameter 'ref' is NULL.\n"); + vxStatus = (vx_status)VX_FAILURE; + } + else if (ipcMsg == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "The parameter 'ipcMsg' is NULL.\n"); + vxStatus = (vx_status)VX_FAILURE; + } + + /* Check if we have been provided a valid reference to work with. If not, + * create one and then proceed. + */ + if ((vxStatus == (vx_status)VX_SUCCESS) && (*ref == NULL)) + { + vx_reference lRef = NULL; + + meta = &refDesc->meta; + + if (meta->type == (vx_enum)VX_TYPE_IMAGE) + { + vx_image obj; + obj = vxCreateImage(context, + meta->object.img.width, + meta->object.img.height, + meta->object.img.format); + + if (obj == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "vxCreateImage() failed.\n"); + vxStatus = VX_FAILURE; + } + + lRef = (vx_reference)obj; + } + else if (meta->type == (vx_enum)VX_TYPE_TENSOR) + { + vx_tensor obj; + + obj = vxCreateTensor(context, + meta->object.tensor.number_of_dimensions, + meta->object.tensor.dimensions, + meta->object.tensor.data_type, + meta->object.tensor.fixed_point_position); + + if (obj == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "vxCreateTensor() failed.\n"); + vxStatus = VX_FAILURE; + } + + lRef = (vx_reference)obj; + } + else if (meta->type == (vx_enum)VX_TYPE_USER_DATA_OBJECT) + { + vx_user_data_object obj; + + obj = vxCreateUserDataObject(context, + meta->object.user_data_object.type_name, + meta->object.user_data_object.size, + NULL); + + if (obj == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "vxCreateUserDataObject() failed.\n"); + vxStatus = VX_FAILURE; + } + + lRef = (vx_reference)obj; + } + else if (meta->type == (vx_enum)VX_TYPE_ARRAY) + { + vx_array obj; + + obj = vxCreateArray(context, + meta->object.arr.item_type, + meta->object.arr.capacity); + + if (obj == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "vxCreateArray() failed.\n"); + vxStatus = VX_FAILURE; + } + + lRef = (vx_reference)obj; + } + else if (meta->type == (vx_enum)VX_TYPE_CONVOLUTION) + { + vx_convolution obj; + + obj = vxCreateConvolution(context, + meta->object.conv.cols, + meta->object.conv.rows); + + if (obj == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "vxCreateConvolution() failed.\n"); + vxStatus = VX_FAILURE; + } + + lRef = (vx_reference)obj; + } + else if (meta->type == (vx_enum)VX_TYPE_MATRIX) + { + vx_matrix obj; + + obj = vxCreateMatrix(context, + meta->object.mat.type, + meta->object.mat.cols, + meta->object.mat.rows); + + if (obj == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "vxCreateMatrix() failed.\n"); + vxStatus = VX_FAILURE; + } + + lRef = (vx_reference)obj; + } + else if (meta->type == (vx_enum)VX_TYPE_DISTRIBUTION) + { + vx_distribution obj; + + obj = vxCreateDistribution(context, + meta->object.dist.bins, + meta->object.dist.offset, + meta->object.dist.range); + + if (obj == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "vxCreateDistribution() failed.\n"); + vxStatus = VX_FAILURE; + } + + lRef = (vx_reference)obj; + } + else if (meta->type == (vx_enum)TIVX_TYPE_RAW_IMAGE) + { + tivx_raw_image_create_params_t *p; + tivx_raw_image obj; + + p = (tivx_raw_image_create_params_t *)&meta->object.raw_image; + + obj = tivxCreateRawImage(context, p); + + if (obj == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "tivxCreateRawImage() failed.\n"); + vxStatus = VX_FAILURE; + } + + lRef = (vx_reference)obj; + } + else if (meta->type == (vx_enum)VX_TYPE_PYRAMID) + { + vx_pyramid obj; + + obj = vxCreatePyramid(context, + meta->object.pmd.levels, + meta->object.pmd.scale, + meta->object.pmd.width, + meta->object.pmd.height, + meta->object.pmd.format); + + if (obj == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "vxCreatePyramid() failed.\n"); + vxStatus = VX_FAILURE; + } + + lRef = (vx_reference)obj; + } + else + { + VX_PRINT(VX_ZONE_ERROR, "Unsupported type [%d].\n", meta->type); + vxStatus = (vx_status)VX_FAILURE; + } + + if (vxStatus == (vx_status)VX_SUCCESS) + { + *ref = lRef; + } + } + return vxStatus; +} + +vx_status vx_utils_import_ref_from_ipc_xfer_objarray(vx_context context, + tivx_utils_ref_ipc_msg_t *ipcMsgHandle, + tivx_utils_ref_ipc_msg_t ipcMsgArray[], + vx_reference *ref) +{ + tivx_utils_meta_format_t const *meta; + void *ptrs[VX_IPC_MAX_VX_PLANES] = {0}; + void *phyAddr[VX_IPC_MAX_VX_PLANES]; + tivx_utils_ref_desc_t *refDesc; + uint32_t numItems; + uint32_t i,j; + vx_status vxStatus = VX_SUCCESS; + + /* refdesc for the object array itself */ + refDesc = (tivx_utils_ref_desc_t *)&ipcMsgHandle->refDesc; + + /* Validate the arguments. */ + if (context == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "The parameter 'context' is NULL.\n"); + vxStatus = (vx_status)VX_FAILURE; + } + else if (ref == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "The parameter 'ref' is NULL.\n"); + vxStatus = (vx_status)VX_FAILURE; + } + else if ((ipcMsgHandle == NULL) || (ipcMsgArray == NULL)) + { + VX_PRINT(VX_ZONE_ERROR, "One of the IPC message pointers is NULL.\n"); + vxStatus = (vx_status)VX_FAILURE; + } + + /* Check if we have been provided a valid reference to work with. */ + if ((vxStatus == (vx_status)VX_SUCCESS) && (*ref == NULL)) + { + meta = &refDesc->meta; + + if (meta->type == (vx_enum)VX_TYPE_OBJECT_ARRAY) + { + /* create the obj array based on the type of object contained into it */ + numItems = meta->object.object_array.num_items; + vx_object_array objArrayRefs; + vx_reference itemRef = NULL; + vxStatus = vx_utils_ref_from_ipc_xfer(context, &ipcMsgArray[0], &itemRef); + if (vxStatus != VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, "Could not import the item reference\n"); + } + objArrayRefs = vxCreateObjectArray(context, itemRef, numItems); + vxReleaseReference(&itemRef); + + /* Import the remaining items */ + for(i = 0; i < numItems; i++) + { + refDesc = (tivx_utils_ref_desc_t *)&ipcMsgArray[i].refDesc; + for (j = 0; j < ipcMsgArray[i].numFd; j++) + { + /* Translate FD corresponding to plane[i]. */ + vxStatus = tivxMemTranslateFd((uint64_t)ipcMsgArray[i].fd[j], + refDesc->handleSizes[j], + &ptrs[j], + &phyAddr[j]); + + if (vxStatus != (vx_status)VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, "tivxMemTranslateFd() failed for " + "FD [%d]\n", j); + break; + } + } + if (vxStatus == (vx_status)VX_SUCCESS) + { + /* Import the reference handles. */ + itemRef = vxGetObjectArrayItem(objArrayRefs, i); + vxStatus = + tivxReferenceImportHandle(itemRef, + (const void **)ptrs, + (const uint32_t *)refDesc->handleSizes, + ipcMsgArray[i].numFd); + vxReleaseReference(&itemRef); + VX_PRINT(VX_ZONE_INFO, "Importing item reference %d\n", i); + if (vxStatus != (vx_status)VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, + "tivxReferenceImportHandle() failed.\n"); + break; + } + } + } + if (vxStatus == (vx_status)VX_SUCCESS) + { + *ref = vxCastRefFromObjectArray(objArrayRefs); + } + } + } + else + { + VX_PRINT(VX_ZONE_ERROR, "the imported pbject is not a vx_object_array \n"); + vxStatus = (vx_status)VX_FAILURE; + } + + return vxStatus; +} + +vx_status tivx_utils_import_ref_from_ipc_xfer(vx_context context, + tivx_utils_ref_ipc_msg_t *ipcMsg, + vx_reference *ref) +{ + void *ptrs[VX_IPC_MAX_VX_PLANES] = {0}; + void *phyAddr[VX_IPC_MAX_VX_PLANES]; + tivx_utils_ref_desc_t *refDesc; + uint32_t i; + vx_status vxStatus = VX_SUCCESS; + + refDesc = (tivx_utils_ref_desc_t *)&ipcMsg->refDesc; + vxStatus = vx_utils_ref_from_ipc_xfer(context, ipcMsg, ref); + + if (vxStatus == (vx_status)VX_SUCCESS) + { + for (i = 0; i < ipcMsg->numFd; i++) + { + /* Translate FD corresponding to plane[i]. */ + vxStatus = tivxMemTranslateFd((uint64_t)ipcMsg->fd[i], + refDesc->handleSizes[i], + &ptrs[i], + &phyAddr[i]); + + if (vxStatus != (vx_status)VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, "tivxMemTranslateFd() failed for " + "FD [%d]\n", i); + break; + } + } + } + + if (vxStatus == (vx_status)VX_SUCCESS) + { + /* Import the reference handles. */ + vxStatus = + tivxReferenceImportHandle(*ref, + (const void **)ptrs, + (const uint32_t *)refDesc->handleSizes, + ipcMsg->numFd); + + if (vxStatus != (vx_status)VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, + "tivxReferenceImportHandle() failed.\n"); + } + } + + return vxStatus; +} + +vx_bool tivx_utils_compare_refs_from_ipc_xfer(tivx_utils_ref_ipc_msg_t *ipcMsg1, + tivx_utils_ref_ipc_msg_t *ipcMsg2) +{ + vx_bool ret = (vx_bool)vx_false_e; + vx_status vxStatus = (vx_status)VX_SUCCESS; + + if (ipcMsg1 == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "The parameter 'ipcMsg1' is NULL.\n"); + vxStatus = (vx_status)VX_FAILURE; + } + + if (ipcMsg2 == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "The parameter 'ipcMsg2' is NULL.\n"); + vxStatus = (vx_status)VX_FAILURE; + } + + if ((vx_status)VX_SUCCESS == vxStatus) + { + if (ipcMsg1->numFd != ipcMsg2->numFd) + { + VX_PRINT(VX_ZONE_INFO, "ipcMsg1->numFd (%d) does not match ipcMsg2->numFd (%d).\n", ipcMsg1->numFd, ipcMsg2->numFd); + vxStatus = (vx_status)VX_FAILURE; + } + } + + if ((vx_status)VX_SUCCESS == vxStatus) + { + uint32_t i; + tivx_utils_ref_desc_t *refDesc1, *refDesc2; + + refDesc1 = &ipcMsg1->refDesc; + refDesc2 = &ipcMsg2->refDesc; + + for (i = 0; i < ipcMsg1->numFd; i++) + { + /* Compare FD of ipcMsg1 and ipcMsg2. */ + ret |= tivxMemCompareFd((uint64_t)ipcMsg1->fd[i], (uint64_t)ipcMsg2->fd[i], refDesc1->handleSizes[i], refDesc2->handleSizes[i]); + } + } + + return ret; +} From d2a324279f85f50e694a02a973d3f162aae6194f Mon Sep 17 00:00:00 2001 From: "Cano Raphael (XC-AS/EPO3)" Date: Tue, 21 Oct 2025 13:31:50 +0200 Subject: [PATCH 6/8] add tivx, change documentation, reorganize the import array function --- utils/include/tivx_utils_ipc_ref_xfer.h | 14 +-- utils/source/tivx_utils_ipc_ref_xfer.c | 120 +++++++++++++----------- 2 files changed, 72 insertions(+), 62 deletions(-) diff --git a/utils/include/tivx_utils_ipc_ref_xfer.h b/utils/include/tivx_utils_ipc_ref_xfer.h index 6c1cd749a..b230437ab 100644 --- a/utils/include/tivx_utils_ipc_ref_xfer.h +++ b/utils/include/tivx_utils_ipc_ref_xfer.h @@ -192,9 +192,9 @@ typedef struct /*!< \brief structure containing information about object array used when type is set to VX_TYPE_OBJECT_ARRAY */ struct { - /*!< \brief The number of image objects */ + /*!< \brief The number of OVX objects */ vx_uint32 num_items; - /*!< \brief VX type of the object, must be image */ + /*!< \brief VX type of the object */ vx_enum item_type; } object_array; @@ -262,7 +262,7 @@ typedef struct * could be transferred over Linux/QNX IPC mechanism to a remote process. * This is just a wrapper for tivx_utils_export_ref_for_ipc_xfer. * - * \param [in] ref A valid openVX reference for an object array of images + * \param [in] ref A valid openVX reference for an object array of OpenVX objects * \param [out] numMessages Number of IPC messages after export * \param [out] ipcMsgHandle Exported object array metadata * \param [out] ipcMsgArray Array of pointers to exported item data @@ -270,7 +270,7 @@ typedef struct * \return VX_SUCCESS on success, else failure * */ -vx_status vx_utils_export_ref_for_ipc_xfer_objarray(const vx_reference ref, +vx_status tivx_utils_export_ref_for_ipc_xfer_objarray(const vx_reference ref, vx_uint32 *numMessages, tivx_utils_ref_ipc_msg_t *ipcMsgHandle, tivx_utils_ref_ipc_msg_t ipcMsgArray[]); @@ -307,16 +307,16 @@ vx_status tivx_utils_export_ref_for_ipc_xfer(const vx_reference ref, * * \param [in] context A valid openVX context * \param [in] ipcMsgHandle Exported object array information - * \param [in] ipcMsgArray Array of exported image information + * \param [in] ipcMsgArray Array of exported objects information * \param [in,out] ref A valid openVX reference to import. If *ref is NULL, - * then a new object will be allocated with the imported + * then a new object array will be allocated with the imported * handles and returned. If *ref is not NULL then the object * will be used to import the handles. * * \return VX_SUCCESS on success, else failure * */ -vx_status vx_utils_import_ref_from_ipc_xfer_objarray(vx_context context, +vx_status tivx_utils_import_ref_from_ipc_xfer_objarray(vx_context context, tivx_utils_ref_ipc_msg_t *ipcMsgHandle, tivx_utils_ref_ipc_msg_t ipcMsgArray[], vx_reference *ref); diff --git a/utils/source/tivx_utils_ipc_ref_xfer.c b/utils/source/tivx_utils_ipc_ref_xfer.c index 0cb90ae23..9fda80be1 100644 --- a/utils/source/tivx_utils_ipc_ref_xfer.c +++ b/utils/source/tivx_utils_ipc_ref_xfer.c @@ -65,7 +65,7 @@ #include -vx_status vx_utils_export_ref_for_ipc_xfer_objarray(const vx_reference ref, +vx_status tivx_utils_export_ref_for_ipc_xfer_objarray(const vx_reference ref, vx_uint32 *numMessages, tivx_utils_ref_ipc_msg_t *ipcMsgHandle, tivx_utils_ref_ipc_msg_t ipcMsgArray[]) @@ -152,7 +152,7 @@ vx_status vx_utils_export_ref_for_ipc_xfer_objarray(const vx_reference ref, ipcMsgHandle->numFd = 0; *numMessages = numItems; - VX_PRINT(VX_ZONE_INFO, "vx_utils_export_ref_for_ipc_xfer_objarray() successfull.\n"); + VX_PRINT(VX_ZONE_INFO, "tivx_utils_export_ref_for_ipc_xfer_objarray() successful.\n"); } return vxStatus; @@ -350,7 +350,7 @@ vx_status tivx_utils_export_ref_for_ipc_xfer(const vx_reference ref, return vxStatus; } -static vx_status vx_utils_ref_from_ipc_xfer(vx_context context, +static vx_status vx_utils_ref_from_ipc_xfer(vx_context context, tivx_utils_ref_ipc_msg_t *ipcMsg, vx_reference *ref) { @@ -553,7 +553,7 @@ static vx_status vx_utils_ref_from_ipc_xfer(vx_context context, return vxStatus; } -vx_status vx_utils_import_ref_from_ipc_xfer_objarray(vx_context context, +vx_status tivx_utils_import_ref_from_ipc_xfer_objarray(vx_context context, tivx_utils_ref_ipc_msg_t *ipcMsgHandle, tivx_utils_ref_ipc_msg_t ipcMsgArray[], vx_reference *ref) @@ -587,72 +587,82 @@ vx_status vx_utils_import_ref_from_ipc_xfer_objarray(vx_context c } /* Check if we have been provided a valid reference to work with. */ - if ((vxStatus == (vx_status)VX_SUCCESS) && (*ref == NULL)) + if (vxStatus == (vx_status)VX_SUCCESS) { - meta = &refDesc->meta; - if (meta->type == (vx_enum)VX_TYPE_OBJECT_ARRAY) { - /* create the obj array based on the type of object contained into it */ + meta = &refDesc->meta; numItems = meta->object.object_array.num_items; - vx_object_array objArrayRefs; - vx_reference itemRef = NULL; - vxStatus = vx_utils_ref_from_ipc_xfer(context, &ipcMsgArray[0], &itemRef); - if (vxStatus != VX_SUCCESS) + + if (*ref == NULL) { - VX_PRINT(VX_ZONE_ERROR, "Could not import the item reference\n"); + /* create the obj array based on the type of object contained into it */ + vx_reference itemRef = NULL; + vx_object_array objArrayRefs; + vxStatus = vx_utils_ref_from_ipc_xfer(context, &ipcMsgArray[0], &itemRef); + if (vxStatus != VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, "Could not import the item reference\n"); + } + objArrayRefs = vxCreateObjectArray(context, itemRef, numItems); + vxReleaseReference(&itemRef); + *ref = vxCastRefFromObjectArray(objArrayRefs); } - objArrayRefs = vxCreateObjectArray(context, itemRef, numItems); - vxReleaseReference(&itemRef); - - /* Import the remaining items */ - for(i = 0; i < numItems; i++) + /* check if the input array items are from the same type of the imported ones */ + vx_reference item = vxGetObjectArrayItem(*ref, 0); + if (item->type != ipcMsgArray[0].refDesc.meta.type) { - refDesc = (tivx_utils_ref_desc_t *)&ipcMsgArray[i].refDesc; - for (j = 0; j < ipcMsgArray[i].numFd; j++) + VX_PRINT(VX_ZONE_ERROR, "The input object array items are not of the same type as the exported ones\n"); + vxStatus = (vx_status)VX_FAILURE; + } + else + { + /* Import the remaining items */ + for(i = 0; i < numItems; i++) { - /* Translate FD corresponding to plane[i]. */ - vxStatus = tivxMemTranslateFd((uint64_t)ipcMsgArray[i].fd[j], - refDesc->handleSizes[j], - &ptrs[j], - &phyAddr[j]); - - if (vxStatus != (vx_status)VX_SUCCESS) + refDesc = (tivx_utils_ref_desc_t *)&ipcMsgArray[i].refDesc; + for (j = 0; j < ipcMsgArray[i].numFd; j++) { - VX_PRINT(VX_ZONE_ERROR, "tivxMemTranslateFd() failed for " - "FD [%d]\n", j); - break; + /* Translate FD corresponding to plane[i]. */ + vxStatus = tivxMemTranslateFd((uint64_t)ipcMsgArray[i].fd[j], + refDesc->handleSizes[j], + &ptrs[j], + &phyAddr[j]); + + if (vxStatus != (vx_status)VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, "tivxMemTranslateFd() failed for " + "FD [%d]\n", j); + break; + } } - } - if (vxStatus == (vx_status)VX_SUCCESS) - { - /* Import the reference handles. */ - itemRef = vxGetObjectArrayItem(objArrayRefs, i); - vxStatus = - tivxReferenceImportHandle(itemRef, - (const void **)ptrs, - (const uint32_t *)refDesc->handleSizes, - ipcMsgArray[i].numFd); - vxReleaseReference(&itemRef); - VX_PRINT(VX_ZONE_INFO, "Importing item reference %d\n", i); - if (vxStatus != (vx_status)VX_SUCCESS) + if (vxStatus == (vx_status)VX_SUCCESS) { - VX_PRINT(VX_ZONE_ERROR, - "tivxReferenceImportHandle() failed.\n"); - break; + /* Import the reference handles. */ + vx_reference item = vxGetObjectArrayItem(*ref, i); + vxStatus = + tivxReferenceImportHandle(item, + (const void **)ptrs, + (const uint32_t *)refDesc->handleSizes, + ipcMsgArray[i].numFd); + vxReleaseReference(&item); + VX_PRINT(VX_ZONE_INFO, "Importing item reference %d\n", i); + if (vxStatus != (vx_status)VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, + "tivxReferenceImportHandle() failed.\n"); + break; + } } } } - if (vxStatus == (vx_status)VX_SUCCESS) - { - *ref = vxCastRefFromObjectArray(objArrayRefs); - } + vxReleaseReference(&item); } - } - else - { - VX_PRINT(VX_ZONE_ERROR, "the imported pbject is not a vx_object_array \n"); - vxStatus = (vx_status)VX_FAILURE; + else + { + VX_PRINT(VX_ZONE_ERROR, "the imported object is not a vx_object_array \n"); + vxStatus = (vx_status)VX_FAILURE; + } } return vxStatus; From 6708ad12b74bacf547df7d710576b946976dfcb5 Mon Sep 17 00:00:00 2001 From: "Cano Raphael (XC-AS/EPO3)" Date: Tue, 21 Oct 2025 23:25:15 +0200 Subject: [PATCH 7/8] small improvements, adding a test for the array import and exports --- conformance_tests/test_tiovx/test_tivxMem.c | 201 ++++++++++++++++++++ utils/source/tivx_utils_ipc_ref_xfer.c | 11 +- 2 files changed, 206 insertions(+), 6 deletions(-) diff --git a/conformance_tests/test_tiovx/test_tivxMem.c b/conformance_tests/test_tiovx/test_tivxMem.c index ad16d884f..9a672ed93 100644 --- a/conformance_tests/test_tiovx/test_tivxMem.c +++ b/conformance_tests/test_tiovx/test_tivxMem.c @@ -38,6 +38,7 @@ #define TIVX_TEST_MAX_PYRAMID_LEVELS (4) #define TIVX_TEST_MATRIX_SIZE (8) +#define TIVX_OBJECT_ARRAY_NUM_ITEMS (10) extern uint32_t appMemGetNumAllocs(); /* Note: since these are specific to QNX, only defining them for QNX */ @@ -397,6 +398,39 @@ static vx_reference testTivxMemAllocObject(vx_context context, vx_enum type, uin ref = (vx_reference)pyramid; } + else if (type == (vx_enum)VX_TYPE_OBJECT_ARRAY) + { + vx_object_array obj_array; + vx_image images_exp; + uint32_t i; + + images_exp = vxCreateImage(context, 64, 48, VX_DF_IMAGE_U8); + obj_array = vxCreateObjectArray(context, (vx_reference)images_exp, TIVX_OBJECT_ARRAY_NUM_ITEMS); + vxReleaseImage(&images_exp); + + if (obj_array == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "vxCreateObjectArray() failed.\n"); + } + else if (alloc_handle == 1) + { + vx_image image; + vx_imagepatch_addressing_t addr; + vx_uint8 *pdata = 0; + vx_rectangle_t rect = {0, 0, 64, 48}; + vx_map_id map_id; + for (i = 0; i < TIVX_OBJECT_ARRAY_NUM_ITEMS; i++) + { + image = (vx_image)vxGetObjectArrayItem(obj_array, 0); + vxMapImagePatch(image, &rect, 0, &map_id, &addr, (void **)&pdata, + VX_READ_AND_WRITE, VX_MEMORY_TYPE_HOST, 0); + vxUnmapImagePatch(image, map_id); + vxReleaseImage(&image); + } + } + + ref = (vx_reference)obj_array; + } else { VX_PRINT(VX_ZONE_ERROR, "Unsupported type [%d].\n", type); @@ -494,6 +528,11 @@ static vx_status testTivxMemFreeObject(vx_reference ref, vx_enum type, uint32_t vx_pyramid pyramid = (vx_pyramid)ref; vxStatus = vxReleasePyramid(&pyramid); } + else if (type == (vx_enum)VX_TYPE_OBJECT_ARRAY) + { + vx_object_array obj_array = (vx_object_array)ref; + vxStatus = vxReleaseObjectArray(&obj_array); + } else { VX_PRINT(VX_ZONE_ERROR, "Unsupported type [%d].\n", type); @@ -1720,6 +1759,167 @@ TEST_WITH_ARG(tivxMem, testReferenceImportExportIpcValidObj, TestArg, TEST_PARAM TIVX_TEST_UPDATE_STATUS(testFail); } +TEST(tivxMem, testReferenceImportExportIpcArrayObj) +{ + vx_context context = context_->vx_context_; + tivx_utils_ref_ipc_msg_t ipcMsg1, ipcMsg2; + tivx_utils_ref_ipc_msg_t ipcMsg1Array[TIVX_OBJECT_ARRAY_NUM_ITEMS], ipcMsg2Array[TIVX_OBJECT_ARRAY_NUM_ITEMS]; + + vx_reference ref[2] = {NULL}; + uint32_t testFail = 0; + uint32_t numEntries1; + uint32_t numEntries2; + uint32_t i; + vx_status vxStatus; + vx_bool refCompare; + uint32_t numAllocInitial, numAllocFinal; +#if defined(QNX) + uint32_t numMapsInitial, numMapsFinal; + uint32_t numBufsInitial, numBufsFinal; +#endif + + numAllocInitial = appMemGetNumAllocs(); +#if defined(QNX) + numMapsInitial = appMemGetNumMaps(); + numBufsInitial = appMemGetNumBufElements(); +#endif + + /* Allocate object. This objects should have + * internal memory allocated after the respective data object + * map/unmap calls are made within the testTivxMemAllocObject + * function. + */ + ref[0] = testTivxMemAllocObject(context, VX_TYPE_OBJECT_ARRAY, 0, 1); + + if (ref[0] == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "testTivxMemAllocObject() failed.\n"); + TIVX_TEST_FAIL_CLEANUP(testFail); + } + + /* Create the IPC messages with the object export. */ + vxStatus = tivx_utils_export_ref_for_ipc_xfer_objarray(ref[0], &numEntries1, &ipcMsg1, ipcMsg1Array); + + if (vxStatus != (vx_status)VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, "tivx_utils_export_ref_for_ipc_xfer_objarray() failed.\n"); + TIVX_TEST_FAIL_CLEANUP(testFail); + } + + /* import the object in the second object from ref0 to ref1*/ + vxStatus = tivx_utils_import_ref_from_ipc_xfer_objarray(context, &ipcMsg1, ipcMsg1Array, &ref[1]); + + if (vxStatus != (vx_status)VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, "tivx_utils_export_ref_for_ipc_xfer_objarray() failed.\n"); + TIVX_TEST_FAIL_CLEANUP(testFail); + } + + /* export the newly created object */ + vxStatus = tivx_utils_export_ref_for_ipc_xfer_objarray(ref[1], &numEntries2, &ipcMsg2, ipcMsg2Array); + + /* Compare the references to a different ipcMsg transfer */ + refCompare = tivx_utils_compare_refs_from_ipc_xfer(&ipcMsg1, &ipcMsg2); + + if (refCompare != (vx_bool)vx_false_e) + { + VX_PRINT(VX_ZONE_ERROR, "tivx_utils_compare_refs_from_ipc_xfer() failed.\n"); + TIVX_TEST_FAIL_CLEANUP(testFail); + } + + /* compare the content of the array itself */ + if (numEntries1 != numEntries2) + { + VX_PRINT(VX_ZONE_ERROR, "numEntries1 and numEntries2 do not match.\n"); + TIVX_TEST_FAIL_CLEANUP(testFail); + } + + for (i = 0; i < numEntries1; i++) + { + refCompare = tivx_utils_compare_refs_from_ipc_xfer(&ipcMsg1Array[i], &ipcMsg2Array[i]); + + if (refCompare != (vx_bool)vx_true_e) + { + VX_PRINT(VX_ZONE_ERROR, "tivx_utils_compare_refs_from_ipc_xfer() for array item %d failed.\n", i); + TIVX_TEST_FAIL_CLEANUP(testFail); + } + } + +cleanup: + + /* Two objects have the same handles, which will cause issues when the + * objects are released. We need to remove the handles from one of the + * objects. Let us remove them from obj[0]. We do this by importing NULL + * handles. + */ + + for (i = 0; i < numEntries1; i++) + { + void *virtAddr[TIVX_TEST_MAX_NUM_ADDR] = {NULL}; + uint32_t size[TIVX_TEST_MAX_NUM_ADDR]; + vx_bool is_allocated; + vx_reference lref = vxGetObjectArrayItem((vx_object_array)ref[0], i); + /* Import NULL handles into the object indey i */ + vxStatus = tivxReferenceImportHandle(lref, + (const void **)virtAddr, + (const uint32_t *)size, + 1); + if (vxStatus != (vx_status)VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, "tivxReferenceImportHandle(NULL) failed.\n"); + } + + vxQueryReference(lref, TIVX_REFERENCE_BUFFER_IS_ALLOCATED, &is_allocated, sizeof(is_allocated)); + + if (is_allocated!=vx_false_e) + { + VX_PRINT(VX_ZONE_ERROR, "reference is marked as allocated.\n"); + vxStatus = VX_FAILURE; + } + vxReleaseReference(&lref); + } + + /* Free the objects. */ + for (i = 0; i < 2; i++) + { + vxStatus = testTivxMemFreeObject(ref[i], VX_TYPE_OBJECT_ARRAY, 1, 0); + + if (vxStatus != (vx_status)VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, "testTivxMemFreeObject(%d) failed.\n", i); + testFail = 1; + } + } + + numAllocFinal = appMemGetNumAllocs(); +#if defined(QNX) + numMapsFinal = appMemGetNumMaps(); + numBufsFinal = appMemGetNumBufElements(); +#endif + + if (numAllocInitial != numAllocFinal) + { + VX_PRINT(VX_ZONE_ERROR, "numAllocInitial [%d] does not equal numAllocFinal [%d]\n", numAllocInitial, numAllocFinal); + testFail = 1; + } + +#if defined(QNX) + if (numMapsInitial != numMapsFinal) + { + VX_PRINT(VX_ZONE_ERROR, "numMapsInitial [%d] does not equal numMapsFinal [%d]\n", numMapsInitial, numMapsFinal); + testFail = 1; + } + + if (numBufsInitial != numBufsFinal) + { + VX_PRINT(VX_ZONE_ERROR, "numBufsInitial [%d] does not equal numBufsFinal [%d]\n", numBufsInitial, numBufsFinal); + testFail = 1; + } +#endif + + TIVX_TEST_UPDATE_STATUS(testFail); +} + TEST(tivxMem, testReferenceImportNeg) { vx_context context = context_->vx_context_; @@ -2033,6 +2233,7 @@ TESTCASE_TESTS(tivxMem, testReferenceExportMultipleAddrSameRef, testReferenceImportExportIpcNullObj, testReferenceImportExportIpcValidObj, + testReferenceImportExportIpcArrayObj, testReferenceImportNeg, testReferenceExportNeg, testSubimageNeg, diff --git a/utils/source/tivx_utils_ipc_ref_xfer.c b/utils/source/tivx_utils_ipc_ref_xfer.c index 9fda80be1..6482a782c 100644 --- a/utils/source/tivx_utils_ipc_ref_xfer.c +++ b/utils/source/tivx_utils_ipc_ref_xfer.c @@ -589,11 +589,10 @@ vx_status tivx_utils_import_ref_from_ipc_xfer_objarray(vx_context co /* Check if we have been provided a valid reference to work with. */ if (vxStatus == (vx_status)VX_SUCCESS) { + meta = &refDesc->meta; if (meta->type == (vx_enum)VX_TYPE_OBJECT_ARRAY) { - meta = &refDesc->meta; numItems = meta->object.object_array.num_items; - if (*ref == NULL) { /* create the obj array based on the type of object contained into it */ @@ -609,8 +608,8 @@ vx_status tivx_utils_import_ref_from_ipc_xfer_objarray(vx_context co *ref = vxCastRefFromObjectArray(objArrayRefs); } /* check if the input array items are from the same type of the imported ones */ - vx_reference item = vxGetObjectArrayItem(*ref, 0); - if (item->type != ipcMsgArray[0].refDesc.meta.type) + vx_reference itemRef = vxGetObjectArrayItem(vxCastRefAsObjectArray(*ref, NULL), 0); + if (itemRef->type != ipcMsgArray[0].refDesc.meta.type) { VX_PRINT(VX_ZONE_ERROR, "The input object array items are not of the same type as the exported ones\n"); vxStatus = (vx_status)VX_FAILURE; @@ -639,7 +638,7 @@ vx_status tivx_utils_import_ref_from_ipc_xfer_objarray(vx_context co if (vxStatus == (vx_status)VX_SUCCESS) { /* Import the reference handles. */ - vx_reference item = vxGetObjectArrayItem(*ref, i); + vx_reference item = vxGetObjectArrayItem(vxCastRefAsObjectArray(*ref, NULL), i); vxStatus = tivxReferenceImportHandle(item, (const void **)ptrs, @@ -656,7 +655,7 @@ vx_status tivx_utils_import_ref_from_ipc_xfer_objarray(vx_context co } } } - vxReleaseReference(&item); + vxReleaseReference(&itemRef); } else { From 69c4df8a9baa6ca21146b43c61db8e70e8dfe87a Mon Sep 17 00:00:00 2001 From: "Cano Raphael (XC-AS/EPO3)" Date: Wed, 22 Oct 2025 22:17:47 +0200 Subject: [PATCH 8/8] add new test for the export to an non-null object, test renaming --- conformance_tests/test_tiovx/test_tivxMem.c | 278 +++++++++++++++++++- 1 file changed, 276 insertions(+), 2 deletions(-) diff --git a/conformance_tests/test_tiovx/test_tivxMem.c b/conformance_tests/test_tiovx/test_tivxMem.c index 9a672ed93..c93ea0346 100644 --- a/conformance_tests/test_tiovx/test_tivxMem.c +++ b/conformance_tests/test_tiovx/test_tivxMem.c @@ -1759,7 +1759,7 @@ TEST_WITH_ARG(tivxMem, testReferenceImportExportIpcValidObj, TestArg, TEST_PARAM TIVX_TEST_UPDATE_STATUS(testFail); } -TEST(tivxMem, testReferenceImportExportIpcArrayObj) +TEST(tivxMem, testReferenceImportExportIpcNullArrayObj) { vx_context context = context_->vx_context_; tivx_utils_ref_ipc_msg_t ipcMsg1, ipcMsg2; @@ -1920,6 +1920,279 @@ TEST(tivxMem, testReferenceImportExportIpcArrayObj) TIVX_TEST_UPDATE_STATUS(testFail); } +TEST(tivxMem, testReferenceImportExportIpcValidArrayObj) +{ + vx_context context = context_->vx_context_; + tivx_utils_ref_ipc_msg_t ipcMsg1, ipcMsg2; + tivx_utils_ref_ipc_msg_t ipcMsg1Array[TIVX_OBJECT_ARRAY_NUM_ITEMS], ipcMsg2Array[TIVX_OBJECT_ARRAY_NUM_ITEMS]; + + vx_reference ref[2] = {NULL}; + uint32_t testFail = 0; + uint32_t maxNumAddr; + uint32_t arraySize1; + uint32_t arraySize2; + uint32_t i; + vx_status vxStatus; + vx_bool refCompare; + uint32_t numAllocInitial, numAllocFinal; +#if defined(QNX) + uint32_t numMapsInitial, numMapsFinal; + uint32_t numBufsInitial, numBufsFinal; +#endif + + numAllocInitial = appMemGetNumAllocs(); +#if defined(QNX) + numMapsInitial = appMemGetNumMaps(); + numBufsInitial = appMemGetNumBufElements(); +#endif + + /* Allocate object. This objects should have + * internal memory allocated after the respective data object + * map/unmap calls are made within the testTivxMemAllocObject + * function. + */ + for (i = 0; i < 2; i++) + { + ref[i] = testTivxMemAllocObject(context, VX_TYPE_OBJECT_ARRAY, 1, 1); + if (ref[i] == NULL) + { + VX_PRINT(VX_ZONE_ERROR, "testTivxMemAllocObject() failed.\n"); + TIVX_TEST_FAIL_CLEANUP(testFail); + } + } + + /* Create the IPC messages with the object export. */ + vxStatus = tivx_utils_export_ref_for_ipc_xfer_objarray(ref[0], &arraySize1, &ipcMsg1, ipcMsg1Array); + if (vxStatus != (vx_status)VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, "tivx_utils_export_ref_for_ipc_xfer_objarray() failed.\n"); + TIVX_TEST_FAIL_CLEANUP(testFail); + } + + vxStatus = tivx_utils_export_ref_for_ipc_xfer_objarray(ref[1], &arraySize2, &ipcMsg2, ipcMsg2Array); + if (vxStatus != (vx_status)VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, "tivx_utils_export_ref_for_ipc_xfer_objarray() failed.\n"); + TIVX_TEST_FAIL_CLEANUP(testFail); + } + + /* compare them, they should be different */ + uint32_t minArraySize = arraySize1 < arraySize2 ? arraySize1 : arraySize2; + + /* compare the content of the array itself */ + for (i = 0; i < minArraySize; i++) + { + refCompare = tivx_utils_compare_refs_from_ipc_xfer(&ipcMsg1Array[i], &ipcMsg2Array[i]); + + if (refCompare == (vx_bool)vx_true_e) + { + VX_PRINT(VX_ZONE_ERROR, "tivx_utils_compare_refs_from_ipc_xfer() for array item %d failed.\n", i); + TIVX_TEST_FAIL_CLEANUP(testFail); + } + } + + /* Export handle of each object array object to free them prior to import */ + for (i = 0; i < arraySize2; i++) + { + void *virtAddr[TIVX_TEST_MAX_NUM_ADDR] = {NULL}; + uint32_t size[TIVX_TEST_MAX_NUM_ADDR]; + uint32_t numEntries; + vx_bool is_allocated; + maxNumAddr = TIVX_TEST_MAX_NUM_ADDR; + vx_object_array array = (vx_object_array)ref[1]; + vx_reference lref = vxGetObjectArrayItem(array, i); + + vxStatus = tivxReferenceExportHandle(lref, + virtAddr, + size, + maxNumAddr, + &numEntries); + if (vxStatus != (vx_status)VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, "tivxReferenceExportHandle() failed.\n"); + TIVX_TEST_FAIL_CLEANUP(testFail); + } + + vx_enum region = TIVX_MEM_EXTERNAL; + for (uint32_t j = 0; j < TIVX_TEST_MAX_NUM_ADDR; j++) + { + if (virtAddr[j] != NULL) + { + vxStatus = tivxMemFree(virtAddr[j], size[j], region); + + if (vxStatus != (vx_status)VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, "tivxMemFree() failed.\n"); + TIVX_TEST_FAIL_CLEANUP(testFail); + } + } + } + vxReleaseReference(&lref); + } + + /* import the object in the second object so from ref0 into the empty already exisiting object */ + vxStatus = tivx_utils_import_ref_from_ipc_xfer_objarray(context, &ipcMsg1, ipcMsg1Array, &ref[1]); + + if (vxStatus != (vx_status)VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, "tivx_utils_export_ref_for_ipc_xfer_objarray() failed.\n"); + TIVX_TEST_FAIL_CLEANUP(testFail); + } + + /* export the newly created object */ + vxStatus = tivx_utils_export_ref_for_ipc_xfer_objarray(ref[1], &arraySize2, &ipcMsg2, ipcMsg2Array); + + /* Compare the references to a different ipcMsg transfer */ + refCompare = tivx_utils_compare_refs_from_ipc_xfer(&ipcMsg1, &ipcMsg2); + + if (refCompare != (vx_bool)vx_false_e) + { + VX_PRINT(VX_ZONE_ERROR, "tivx_utils_compare_refs_from_ipc_xfer() failed.\n"); + TIVX_TEST_FAIL_CLEANUP(testFail); + } + + /* compare the content of the array itself */ + if (arraySize1 != arraySize2) + { + VX_PRINT(VX_ZONE_ERROR, "arraySize1 and arraySize2 do not match.\n"); + TIVX_TEST_FAIL_CLEANUP(testFail); + } + + for (i = 0; i < arraySize1; i++) + { + refCompare = tivx_utils_compare_refs_from_ipc_xfer(&ipcMsg1Array[i], &ipcMsg2Array[i]); + + if (refCompare != (vx_bool)vx_true_e) + { + VX_PRINT(VX_ZONE_ERROR, "tivx_utils_compare_refs_from_ipc_xfer() for array item %d failed.\n", i); + TIVX_TEST_FAIL_CLEANUP(testFail); + } + + void *virtAddr1[TIVX_TEST_MAX_NUM_ADDR] = {NULL}; + void *virtAddr2[TIVX_TEST_MAX_NUM_ADDR] = {NULL}; + uint32_t size[TIVX_TEST_MAX_NUM_ADDR]; + uint32_t virtAddrEntries1, virtAddrEntries2; + vx_reference lref1 = vxGetObjectArrayItem((vx_object_array)ref[0], i); + vx_reference lref2 = vxGetObjectArrayItem((vx_object_array)ref[1], i); + /* Export the handles from obj[0]. */ + maxNumAddr = TIVX_TEST_MAX_NUM_ADDR; + + vxStatus = tivxReferenceExportHandle(lref1, + virtAddr1, + size, + maxNumAddr, + &virtAddrEntries1); + + if (vxStatus != (vx_status)VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, "tivxReferenceExportHandle() failed.\n"); + TIVX_TEST_FAIL_CLEANUP(testFail); + } + /* Export the handles from obj[1]. */ + vxStatus = tivxReferenceExportHandle(lref2, + virtAddr2, + size, + maxNumAddr, + &virtAddrEntries2); + + if (vxStatus != (vx_status)VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, "tivxReferenceExportHandle() failed.\n"); + TIVX_TEST_FAIL_CLEANUP(testFail); + } + + /* Check the number of entries. These should match. */ + if (virtAddrEntries1 != virtAddrEntries2) + { + VX_PRINT(VX_ZONE_ERROR, "Number of entries do not match.\n"); + TIVX_TEST_FAIL_CLEANUP(testFail); + } + + /* Compare the addresses exported from the objects. These should match. */ + for (uint32_t j = 0; j < virtAddrEntries2; j++) + { + if (virtAddr1[j] != virtAddr2[j]) + { + VX_PRINT(VX_ZONE_ERROR, "Address entry [%d] mis-match.\n", j); + TIVX_TEST_FAIL_CLEANUP(testFail); + } + } + vxReleaseReference(&lref1); + vxReleaseReference(&lref2); + } +cleanup: + + /* Two objects have the same handles, which will cause issues when the + * objects are released. We need to remove the handles from one of the + * objects. Let us remove them from obj[0]. We do this by importing NULL + * handles. + */ + for (i = 0; i < arraySize1; i++) + { + void *virtAddr[TIVX_TEST_MAX_NUM_ADDR] = {NULL}; + uint32_t size[TIVX_TEST_MAX_NUM_ADDR]; + vx_bool is_allocated; + vx_reference lref = vxGetObjectArrayItem((vx_object_array)ref[0], i); + /* Import NULL handles into the object indey i */ + vxStatus = tivxReferenceImportHandle(lref, + (const void **)virtAddr, + (const uint32_t *)size, + 1); + if (vxStatus != (vx_status)VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, "tivxReferenceImportHandle(NULL) failed.\n"); + } + + vxQueryReference(lref, TIVX_REFERENCE_BUFFER_IS_ALLOCATED, &is_allocated, sizeof(is_allocated)); + + if (is_allocated!=vx_false_e) + { + VX_PRINT(VX_ZONE_ERROR, "reference is marked as allocated.\n"); + vxStatus = VX_FAILURE; + } + vxReleaseReference(&lref); + } + /* Free the OVX object arrays */ + for (i = 0; i < 2; i++) + { + vxStatus = testTivxMemFreeObject(ref[i], VX_TYPE_OBJECT_ARRAY, 1, 0); + + if (vxStatus != (vx_status)VX_SUCCESS) + { + VX_PRINT(VX_ZONE_ERROR, "testTivxMemFreeObject(%d) failed.\n", i); + testFail = 1; + } + } + + numAllocFinal = appMemGetNumAllocs(); +#if defined(QNX) + numMapsFinal = appMemGetNumMaps(); + numBufsFinal = appMemGetNumBufElements(); +#endif + + if (numAllocInitial != numAllocFinal) + { + VX_PRINT(VX_ZONE_ERROR, "numAllocInitial [%d] does not equal numAllocFinal [%d]\n", numAllocInitial, numAllocFinal); + testFail = 1; + } + +#if defined(QNX) + if (numMapsInitial != numMapsFinal) + { + VX_PRINT(VX_ZONE_ERROR, "numMapsInitial [%d] does not equal numMapsFinal [%d]\n", numMapsInitial, numMapsFinal); + testFail = 1; + } + + if (numBufsInitial != numBufsFinal) + { + VX_PRINT(VX_ZONE_ERROR, "numBufsInitial [%d] does not equal numBufsFinal [%d]\n", numBufsInitial, numBufsFinal); + testFail = 1; + } +#endif + + TIVX_TEST_UPDATE_STATUS(testFail); +} + TEST(tivxMem, testReferenceImportNeg) { vx_context context = context_->vx_context_; @@ -2233,7 +2506,8 @@ TESTCASE_TESTS(tivxMem, testReferenceExportMultipleAddrSameRef, testReferenceImportExportIpcNullObj, testReferenceImportExportIpcValidObj, - testReferenceImportExportIpcArrayObj, + testReferenceImportExportIpcNullArrayObj, + testReferenceImportExportIpcValidArrayObj, testReferenceImportNeg, testReferenceExportNeg, testSubimageNeg,