This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TDA4VM: OpenVX "Select" Node

Part Number: TDA4VM

Tool/software:

Hello,

I need an OpenVX node that takes two inputs in and picks one to output - similar to this: https://registry.khronos.org/OpenVX/specs/1.2/html/dd/d0b/group__group__control__flow.html#gae28d45c2a30607e420e7eac1b28dda6d

I have written the code below in the "process" function of the node which copies the pixels directly from the correct source to the output; however, this process is too slow (running on c66) when dealing with 8mp images.  Is it possible to simply pass the correct image descriptor from the input to the output without copying the entire image buffer?

static vx_status VX_CALLBACK tivxImageSelectProcess(
       tivx_target_kernel_instance kernel,
       tivx_obj_desc_t *obj_desc[],
       uint16_t num_params, void *priv_arg)
{
    vx_status status = (vx_status)VX_SUCCESS;
    tivxImageSelectParams *prms = NULL;
    uint32_t i;
    tivx_obj_desc_image_t *in_true_desc;
    tivx_obj_desc_image_t *in_false_desc;
    tivx_obj_desc_image_t *out_desc;

    if ( (num_params != TIVX_KERNEL_IMAGE_SELECT_MAX_PARAMS)
        || (NULL == obj_desc[TIVX_KERNEL_IMAGE_SELECT_IN_TRUE_IDX])
        || (NULL == obj_desc[TIVX_KERNEL_IMAGE_SELECT_IN_FALSE_IDX])
        || (NULL == obj_desc[TIVX_KERNEL_IMAGE_SELECT_OUT_IDX])
    )
    {
        status = (vx_status)VX_FAILURE;
    }

    if((vx_status)VX_SUCCESS == status)
    {
        uint32_t size;
        in_true_desc = (tivx_obj_desc_image_t *)obj_desc[TIVX_KERNEL_IMAGE_SELECT_IN_TRUE_IDX];
        in_false_desc = (tivx_obj_desc_image_t *)obj_desc[TIVX_KERNEL_IMAGE_SELECT_IN_FALSE_IDX];
        out_desc = (tivx_obj_desc_image_t *)obj_desc[TIVX_KERNEL_IMAGE_SELECT_OUT_IDX];


        status = tivxGetTargetKernelInstanceContext(kernel,
            (void **)&prms, &size);
        if (((vx_status)VX_SUCCESS != status) || (NULL == prms) ||
            (sizeof(tivxImageSelectParams) != size))
        {
            status = (vx_status)VX_FAILURE;
        }
    }

    if((vx_status)VX_SUCCESS == status)
    {
        uint32_t planes = out_desc->planes;
        uint32_t plane = 0;

        void *in_true_target_ptr[TIVX_IMAGE_MAX_PLANES];
        void *in_false_target_ptr[TIVX_IMAGE_MAX_PLANES];
        void *out_target_ptr[TIVX_IMAGE_MAX_PLANES];

        // Check if it's supposed to be day or night:
        vx_bool daytime_local = prms->daytime_mode;

        for (plane = 0; plane < planes; plane++) {
            in_true_target_ptr[plane] = tivxMemShared2TargetPtr(&in_true_desc->mem_ptr[plane]);
            tivxCheckStatus(&status, tivxMemBufferMap(in_true_target_ptr[plane],
            in_true_desc->mem_size[plane], (vx_enum)VX_MEMORY_TYPE_HOST,
            (vx_enum)VX_READ_ONLY));

            in_false_target_ptr[plane] = tivxMemShared2TargetPtr(&in_false_desc->mem_ptr[plane]);
            tivxCheckStatus(&status, tivxMemBufferMap(in_false_target_ptr[plane],
            in_false_desc->mem_size[plane], (vx_enum)VX_MEMORY_TYPE_HOST,
            (vx_enum)VX_READ_ONLY));

            out_target_ptr[plane] = tivxMemShared2TargetPtr(&out_desc->mem_ptr[plane]);
            tivxCheckStatus(&status, tivxMemBufferMap(out_target_ptr[plane],
            out_desc->mem_size[plane], (vx_enum)VX_MEMORY_TYPE_HOST,
            (vx_enum)VX_WRITE_ONLY));
        }

        {
            VXLIB_bufParams2D_t vxlib_in_true[TIVX_IMAGE_MAX_PLANES];
            uint8_t *in_true_addr[TIVX_IMAGE_MAX_PLANES] = {0};
            VXLIB_bufParams2D_t vxlib_in_false[TIVX_IMAGE_MAX_PLANES];
            uint8_t *in_false_addr[TIVX_IMAGE_MAX_PLANES] = {0};
            VXLIB_bufParams2D_t vxlib_out[TIVX_IMAGE_MAX_PLANES];
            uint8_t *out_addr[TIVX_IMAGE_MAX_PLANES] = {0};

            tivxInitBufParams(in_true_desc, vxlib_in_true);
            tivxSetPointerLocation(in_true_desc, in_true_target_ptr, in_true_addr);
            tivxInitBufParams(in_false_desc, vxlib_in_false);
            tivxSetPointerLocation(in_false_desc, in_false_target_ptr, in_false_addr);
            tivxInitBufParams(out_desc, vxlib_out);
            tivxSetPointerLocation(out_desc, out_target_ptr, out_addr);

            // call kernel processing function
            vx_uint32 x, y, width, height;
            vx_uint8 *in_dt_pixel, *in_nt_pixel, *out_pixel;

            for(plane = 0; plane < planes; plane++)
            {
                width = out_desc->imagepatch_addr[plane].dim_x;
                height = out_desc->imagepatch_addr[plane].dim_y;
                int32_t out_stride_y = out_desc->imagepatch_addr[plane].stride_y;
                int32_t out_stride_x = out_desc->imagepatch_addr[plane].stride_x;
                int32_t in_dt_stride_y = in_true_desc->imagepatch_addr[plane].stride_y;
                int32_t in_nt_stride_y =in_false_desc->imagepatch_addr[plane].stride_y;
                int32_t out_step_y = out_desc->imagepatch_addr[plane].step_y;

                // printf("[%u] Iterating through image: height: %u width: %u\n", plane, height, width);
                // printf("[%u] Iterating through image: out stride y: %u - out stride x: %u\n", plane, out_stride_y, out_stride_x);
                // printf("[%u] step x: %u step y: %u\n", plane, out_desc->imagepatch_addr[plane].step_x, out_desc->imagepatch_addr[plane].step_y);
                // printf("[%u] scale x: %u scale y: %u\n", plane, out_desc->imagepatch_addr[plane].scale_x, out_desc->imagepatch_addr[plane].scale_y);
                // printf("[%u] mem size output: %u\n", plane, out_desc->mem_size[plane]);

                // We are just copying the image over
                for(y=0; y<height; y+=out_step_y)
                {
                    out_pixel = out_addr[plane];
                    in_dt_pixel = in_true_addr[plane];
                    in_nt_pixel = in_false_addr[plane];

                    for(x=0; x<width; x++)
                    {
                        if (daytime_local == vx_true_e)
                            *out_pixel = *in_dt_pixel;
                        else
                            *out_pixel = *in_nt_pixel;

                        in_dt_pixel++;
                        in_nt_pixel++;
                        out_pixel++;
                    }

                    out_addr[plane] += out_stride_y;
                    in_true_addr[plane] += in_dt_stride_y;
                    in_false_addr[plane] += in_nt_stride_y;
                }
            }

            plane = 0;
            for (plane = 0; plane < planes; plane++)
            {
                tivxCheckStatus(&status, tivxMemBufferUnmap(in_true_target_ptr[plane],
                in_true_desc->mem_size[plane], (vx_enum)VX_MEMORY_TYPE_HOST,
                    (vx_enum)VX_READ_ONLY));

                tivxCheckStatus(&status, tivxMemBufferUnmap(in_false_target_ptr[plane],
                in_false_desc->mem_size[plane], (vx_enum)VX_MEMORY_TYPE_HOST,
                    (vx_enum)VX_READ_ONLY));

                tivxCheckStatus(&status, tivxMemBufferUnmap(out_target_ptr[plane],
                out_desc->mem_size[plane], (vx_enum)VX_MEMORY_TYPE_HOST,
                    (vx_enum)VX_WRITE_ONLY));
            }

        }
    }

    return status;
}