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: TDA4AVM: M2M node verify failed

Part Number: TDA4VM

Hi, TI engineer,

After adding M2M node, I got below erorrs, how to solve this problem?

 

attach our board and sdk version information:

rtos: 08_04_00_06

linux: 08_04_00_11

boot mode: HLOS boot

  • Hi,

    Could you please enable the remote core logs?

    i.e., please run ./vision_apps_init.sh before running the application in order to get the logs from MCU2_0 core.

    This could provide more information about the issue.

    Regards,
    Nikhil

  • Hi,

    Could you please enable the remote core logs?

    i.e., please run ./vision_apps_init.sh before running the application in order to get the logs from MCU2_0 core.

    This could provide more information about the issue.

    Regards,
    Nikhil

  • Hi xie jc,

    But DSS M2M node is enabled in the vision apps, are there any crash on mcu2_0? Are you able to create any other node on mcu2_0? 

    [MCU2_0]     15.048430 s: DSS: M2M Path is enabled !!!

    Regards,

    Brijesh

  • If you could also try removing DSS M2M input and/or output as graph parameter.

    Regards,

    Brijesh

  • before adding m2m node,  using csitx node to display is ok, the flow is   "read uyvy picture -> csitx node"

    Regards

  • Have you included Display in your makefile (BUILD_DISPLAY)? Because without display, DSS M2M cannot be used. 

    Regards,

    Brijesh

  • I search "BUILD_DISPLAY" in vision_apps path,  but can not found desciption of this macro, where should i add this macro?

  • I try this test

    Regards

  • Which SDK are you using? SDK08.04?

    For this release, can you please check if you are calling tivxHwaLoadKernels API?  Because this API registers Display M2M kernel in OpenVX framework.

    Regards,

    Brijesh

  •   

    yes we call this function

    Regards

  • sdk version we are using:

    rtos: 08_04_00_06

    linux: 08_04_00_11

  • Hi xie jc,

    I see it is returning error -8. As per fvid2 errors, it means EAGAIN error, which means it is already opened. Which input pipeline are you using for the DSS M2M path? or are you using DSS for the display path? 

    Do you have CCS + JTAG available on this board? We can put breakpoint on create API of node and see where it is returning error.

    Regards,

    Brijesh 

  • Hi, Brijesh,

    Which input pipeline are you using for the DSS M2M path? or are you using DSS for the display path? 

    I don't quite understand you.  the data flow is:    "uyvy picture ->(m2m input) -> m2m -> m2m output(rgbx) -> csitx"

  • Hi xie jc,

    There are 4 video pipelines in the display, one of them is being used in the display m2m path as input path. Now which input pipeline are you using here in the m2m path? please check pipe id parameter in the display m2m parameters, this is used to tell the driver which input pipe to be used.

    Regards,

    Brijesh

  • Hi, Brijesh,

    I am using M2M1.

    Regards.

  • Hi xie jc,

    I means below highlighted parameters.


    typedef struct {
    /*! Write-back pipeline to use. IDs=> 0: Write-back pipe-line1 */
    uint32_t instId;
    /*! Number of pipe-lines to be used,
    should be set to '1' as blending is not supported currently */
    uint32_t numPipe;
    /*! IDs of pipe-lines to be used,
    IDs=> 0:VID1, 1:VIDL1, 2:VID2 */
    uint32_t pipeId[TIVX_DISPLAY_M2M_MAX_PIPE];
    /*! Overlay to be used. IDs=> 0:Overlay1 1:Overlay2 2:Overlay3 3:Overlay4 */
    uint32_t overlayId;
    } tivx_display_m2m_params_t;

    Regards,

    Brijesh

  • Hi, Brejesh,

    :

    Regards.

  • Hi,

    Can you please try below parameters? If this also does not work, we will have to connect CCS and check why DSS M2M is failing. 

     tivx_display_m2m_params_init(&fmtObj->m2m_params);
     fmtObj->m2m_params.instId = 0u;
     /* Only one pipeline is supported */
     fmtObj->m2m_params.numPipe = 1u;
     fmtObj->m2m_params.pipeId[0U] = 3u;
     fmtObj->m2m_params.overlayId = 3u;

    Regards,

    Brijesh

  • Hi, Brejesh:

    Can you please try below parameters? If this also does not work, we will have to connect CCS and check why DSS M2M is failing. 

     tivx_display_m2m_params_init(&fmtObj->m2m_params);
     fmtObj->m2m_params.instId = 0u;
     /* Only one pipeline is supported */
     fmtObj->m2m_params.numPipe = 1u;
     fmtObj->m2m_params.pipeId[0U] = 3u;
     fmtObj->m2m_params.overlayId = 3u;

    This parameters is what i am using now.. 

    Regards.

  • Hi xie jc,

    ok, can you please put some print statements in the tivxDisplayM2MCreate API in the file tiovx\kernels_j7\hwa\display_m2m\vx_display_m2m_target.c to see if this API is getting called and if it is, then lets see where it is failing?

    Regards,

    Brijesh

  • Regards.

  • Yes, please do "make  sdk" and then "make linux_fs_install_sd".

  • Hi, Brijesh,

    I add some debug in csitx and m2m node target.c file

    /*
     *
     * Copyright (c) 2020 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 <stdio.h>
    #include "TI/tivx.h"
    #include "TI/tivx_event.h"
    #include "VX/vx.h"
    #include "tivx_hwa_kernels.h"
    #include "tivx_kernel_csitx.h"
    #include "TI/tivx_target_kernel.h"
    #include "tivx_kernels_target_utils.h"
    #include "tivx_hwa_csitx_priv.h"
    
    #include <TI/tivx_queue.h>
    #include <ti/drv/fvid2/fvid2.h>
    #include <ti/drv/csitx/csitx.h>
    
    
    #define CSITX_INST_ID_INVALID                         (0xFFFFU)
    
    #define CAPTURE_OUT_CSI_DT_INVALID                    (0xFFFFFFFFU)
    
    typedef struct tivxCsitxParams_t tivxCsitxParams;
    
    typedef struct
    {
        uint32_t instId;
        /**< Csitx Drv Instance ID. */
        uint8_t numCh;
        /**< Number of channels processed on given CSITX DRV instance. */
        uint32_t chVcMap[TIVX_CSITX_MAX_CH];
        /**< Virtual ID for channels for current csitx instance. */
        Fvid2_Handle drvHandle;
        /**< FVID2 csitx driver handle. */
        Csitx_CreateParams createPrms;
        /**< Csitx create time parameters */
        Csitx_CreateStatus createStatus;
        /**< Csitx create time status */
        Fvid2_CbParams drvCbPrms;
        /**< Csitx callback params */
        Csitx_InstStatus csitxStatus;
        /**< CSITX Transmit status. */
        tivxCsitxParams *csitxParams;
        /**< Reference to csitx node parameters. */
    } tivxCsitxInstParams;
    
    struct tivxCsitxParams_t
    {
        tivxCsitxInstParams instParams[TIVX_CSITX_MAX_INST];
        /* Csitx Instance parameters */
        uint32_t numOfInstUsed;
        /**< Number of CSITX DRV instances used in current TIOVX Node. */
        uint8_t numCh;
        /**< Number of channels processed on given csitx node instance. */
        tivx_obj_desc_t *img_obj_desc[TIVX_CSITX_MAX_CH];
        /*  Transmit Images */
        uint8_t steady_state_started;
        /**< Flag indicating whether or not steady state has begun. */
        tivx_event  frame_available;
        /**< Following Queues i.e. freeFvid2FrameQ, pendingFrameQ, fvid2_free_q_mem,
         *   fvid2Frames, and pending_frame_free_q_mem are for given instance of the
         *   Node. If Node instance contains more than 1 instances of the CSITX DRV
         *   instances, then first 'n' channels are for first instance of the driver
         *   then n channels for next driver and so on... */
        /**< Event indicating when a frame is available. */
        tivx_queue freeFvid2FrameQ[TIVX_CSITX_MAX_CH];
        /**< Internal FVID2 queue */
        tivx_queue pendingFrameQ[TIVX_CSITX_MAX_CH];
        /**< Internal pending frame queue */
        uintptr_t fvid2_free_q_mem[TIVX_CSITX_MAX_CH][TIVX_CSITX_MAX_NUM_BUFS];
        /**< FVID2 queue mem */
        Fvid2_Frame fvid2Frames[TIVX_CSITX_MAX_CH][TIVX_CSITX_MAX_NUM_BUFS];
        /**< FVID2 frame structs */
        uintptr_t pending_frame_free_q_mem[TIVX_CSITX_MAX_CH][TIVX_CSITX_MAX_NUM_BUFS];
        /**< pending frame queue mem */
    };
    
    static tivx_target_kernel vx_csitx_target_kernel = NULL;
    
    static vx_status csitxDrvCallback(Fvid2_Handle handle, void *appData, void *reserved);
    static uint32_t tivxCsitxExtractOutCsiDataType(uint32_t format);
    static uint32_t tivxCsitxExtractCcsFormat(uint32_t format);
    static uint32_t tivxCsitxExtractDataFormat(uint32_t format);
    
    static vx_status tivxCsitxEnqueueFrameToDriver(
           tivx_obj_desc_object_array_t *input_desc,
           tivxCsitxParams *prms);
    
    static vx_status tivxCsitxSetCreateParams(
           tivxCsitxParams *prms,
           tivx_obj_desc_user_data_object_t *obj_desc);
    
    static vx_status VX_CALLBACK tivxCsitxProcess(
           tivx_target_kernel_instance kernel,
           tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg);
    static vx_status VX_CALLBACK tivxCsitxCreate(
           tivx_target_kernel_instance kernel,
           tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg);
    static vx_status VX_CALLBACK tivxCsitxDelete(
           tivx_target_kernel_instance kernel,
           tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg);
    static vx_status VX_CALLBACK tivxCsitxControl(
           tivx_target_kernel_instance kernel,
           uint32_t node_cmd_id, tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg);
    
    static vx_status tivxCsitxGetStatistics(tivxCsitxParams *prms,
        tivx_obj_desc_user_data_object_t *usr_data_obj);
    static void tivxCsitxCopyStatistics(tivxCsitxParams *prms,
        tivx_csitx_statistics_t *csitx_status_prms);
    static void tivxCsitxGetChannelIndices(tivxCsitxParams *prms,
                                             uint32_t instId,
                                             uint32_t *startChIdx,
                                             uint32_t *endChIdx);
    static uint32_t tivxCsitxGetNodeChannelNum(tivxCsitxParams *prms,
                                                 uint32_t instId,
                                                 uint32_t chId);
    static uint32_t tivxCsitxMapInstId(uint32_t instId);
    static void tivxCsitxPrintStatus(tivxCsitxInstParams *prms);
    
    /**
     *******************************************************************************
     *
     * \brief Callback function from driver to application
     *
     * Callback function gets called from Driver to application on transmission of
     * a frame
     *
     * \param  handle       [IN] Driver handle for which callback has come.
     * \param  appData      [IN] Application specific data which is registered
     *                           during the callback registration.
     * \param  reserved     [IN] Reserved.
     *
     * \return  SYSTEM_LINK_STATUS_SOK on success
     *
     *******************************************************************************
     */
    static vx_status csitxDrvCallback(Fvid2_Handle handle, void *appData, void *reserved)
    {
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug1: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        tivxCsitxParams *prms = (tivxCsitxParams*)appData;
    
        tivxEventPost(prms->frame_available);
    
        return (vx_status)VX_SUCCESS;
    }
    
    
    static vx_status tivxCsitxEnqueueFrameToDriver(
           tivx_obj_desc_object_array_t *input_desc,
           tivxCsitxParams *prms)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        int32_t fvid2_status = FVID2_SOK;
        void *input_image_target_ptr;
        uint64_t transmit_frame;
        uint32_t chId = 0U;
        static Fvid2_FrameList frmList;
        Fvid2_Frame *fvid2Frame;
        uint32_t startChIdx, endChIdx, instIdx;
        tivxCsitxInstParams *instParams;
    
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug7: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        tivxGetObjDescList(input_desc->obj_desc_id, (tivx_obj_desc_t **)prms->img_obj_desc,
                           prms->numCh);
    
        /* Prepare and queue frame-list for each instance */
        for (instIdx = 0U ; instIdx < prms->numOfInstUsed ; instIdx++)
        {
            instParams = &prms->instParams[instIdx];
            tivxCsitxGetChannelIndices(prms, instIdx, &startChIdx, &endChIdx);
            frmList.numFrames = instParams->numCh;
            for (chId = startChIdx ; chId < endChIdx ; chId++)
            {
                if ((vx_enum)TIVX_OBJ_DESC_RAW_IMAGE == (vx_enum)prms->img_obj_desc[0]->type)
                {
                    tivx_obj_desc_raw_image_t *raw_image;
    
                    raw_image = (tivx_obj_desc_raw_image_t *)prms->img_obj_desc[chId];
    
                    input_image_target_ptr = tivxMemShared2TargetPtr(&raw_image->mem_ptr[0]);
    
    
                    transmit_frame = ((uintptr_t)input_image_target_ptr +
                        (uint64_t)tivxComputePatchOffset(0, 0, &raw_image->imagepatch_addr[0U]));
                }
                else
                {
                    tivx_obj_desc_image_t *image;
                    image = (tivx_obj_desc_image_t *)prms->img_obj_desc[chId];
    
                    input_image_target_ptr = tivxMemShared2TargetPtr(&image->mem_ptr[0]);
    
                    transmit_frame = ((uintptr_t)input_image_target_ptr +
                        (uint64_t)tivxComputePatchOffset(0, 0, &image->imagepatch_addr[0U]));
                }
    
                tivxQueueGet(&prms->freeFvid2FrameQ[chId], (uintptr_t*)&fvid2Frame, TIVX_EVENT_TIMEOUT_NO_WAIT);
    
                if (NULL != fvid2Frame)
                {
                    /* Put into frame list as it is for same driver instance */
                    frmList.frames[(chId - startChIdx)]           = fvid2Frame;
                    frmList.frames[(chId - startChIdx)]->chNum    = (chId - startChIdx);
                    frmList.frames[(chId - startChIdx)]->addr[0U] = transmit_frame;
                    frmList.frames[(chId - startChIdx)]->appData  = input_desc;
                }
                else
                {
                    VX_PRINT(VX_ZONE_ERROR, " CSITX: Could not retrieve buffer from buffer queue!!!\n");
                }
            }
    
            /* All the frames from frame-list */
            fvid2_status = Fvid2_queue(instParams->drvHandle, &frmList, 0);
            if (FVID2_SOK != fvid2_status)
            {
                status = (vx_status)VX_FAILURE;
                VX_PRINT(VX_ZONE_ERROR, " CSITX: ERROR: Frame could not be queued for frame %d !!!\n", chId);
                break;
            }
        }
    
        return status;
    }
    
    
    static uint32_t tivxCsitxExtractOutCsiDataType(uint32_t format)
    {
        uint32_t outCsiDataType;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug10: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        switch (format)
        {
            case (vx_df_image)VX_DF_IMAGE_RGB:
                outCsiDataType = FVID2_CSI2_DF_RGB888;
                break;
            case (vx_df_image)VX_DF_IMAGE_RGBX:
                outCsiDataType = FVID2_CSI2_DF_RGB888;
                break;
            case (vx_df_image)VX_DF_IMAGE_U16:
            case (uint32_t)TIVX_RAW_IMAGE_P12_BIT:
                outCsiDataType = FVID2_CSI2_DF_RAW12;
                break;
            case (vx_df_image)VX_DF_IMAGE_UYVY:
            case (vx_df_image)VX_DF_IMAGE_YUYV:
                outCsiDataType = FVID2_CSI2_DF_YUV422_8B;
                break;
            default:
                outCsiDataType = CAPTURE_OUT_CSI_DT_INVALID;
                break;
        }
    
        return outCsiDataType;
    }
    
    static uint32_t tivxCsitxExtractOutCsiDataTypeFromRawImg(tivx_obj_desc_raw_image_t *raw_img)
    {
        uint32_t inCsiDataType = CAPTURE_OUT_CSI_DT_INVALID;
        tivx_raw_image_create_params_t *params = &raw_img->params;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug11: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        if (TIVX_RAW_IMAGE_16_BIT == params->format[0].pixel_container)
        {
            switch (params->format[0].msb)
            {
                case 9u:
                    inCsiDataType = FVID2_CSI2_DF_RAW10;
                break;
                case 11u:
                    inCsiDataType = FVID2_CSI2_DF_RAW12;
                break;
                case 13u:
                    inCsiDataType = FVID2_CSI2_DF_RAW14;
                break;
                case 15u:
                    inCsiDataType = FVID2_CSI2_DF_RAW16;
                break;
                default:
                    break;
            }
        }
        else if (TIVX_RAW_IMAGE_8_BIT == params->format[0].pixel_container)
        {
            switch (params->format[0].msb)
            {
                case 5u:
                    inCsiDataType = FVID2_CSI2_DF_RAW6;
                break;
                case 6u:
                    inCsiDataType = FVID2_CSI2_DF_RAW7;
                break;
                case 7u:
                    inCsiDataType = FVID2_CSI2_DF_RAW8;
                break;
                default:
                    break;
            }
        }
        else if (TIVX_RAW_IMAGE_P12_BIT == params->format[0].pixel_container)
        {
            if (12u == params->format[0].msb)
            {
                inCsiDataType = FVID2_CSI2_DF_RAW12;
            }
        }
        else
        {
            /* Don Nothing */
        }
    
        return (inCsiDataType);
    }
    
    static uint32_t tivxCsitxExtractCcsFormat(uint32_t format)
    {
        uint32_t ccsFormat = FVID2_CCSF_BITS12_PACKED;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug8: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        switch (format)
        {
            case (uint32_t)TIVX_RAW_IMAGE_P12_BIT:
                ccsFormat = FVID2_CCSF_BITS12_PACKED;
                break;
            case (vx_enum)TIVX_RAW_IMAGE_16_BIT:
            case (vx_df_image)VX_DF_IMAGE_U16:
            case (vx_df_image)VX_DF_IMAGE_UYVY:
            case (vx_df_image)VX_DF_IMAGE_YUYV:
                ccsFormat = FVID2_CCSF_BITS12_UNPACKED16;
                break;
            default:
                ccsFormat = FVID2_CCSF_MAX;
                break;
        }
    
        return ccsFormat;
    }
    
    static uint32_t tivxCsitxMapInstId(uint32_t instId)
    {
        uint32_t drvInstId = CSITX_INST_ID_INVALID;
        VX_PRINT(VX_ZONE_ERROR, "cyhdebug15: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        switch (instId)
        {
            case 0:
                drvInstId = CSITX_INSTANCE_ID_0;
                break;
            default:
                /* do nothing */
                break;
        }
    
        return (drvInstId);
    }
    
    static uint32_t tivxCsitxExtractDataFormat(uint32_t format)
    {
        uint32_t dataFormat = FVID2_DF_BGRX32_8888;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug9: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        switch (format)
        {
            case (vx_df_image)VX_DF_IMAGE_RGBX:
                dataFormat = FVID2_DF_BGRX32_8888;
                break;
            case (vx_df_image)VX_DF_IMAGE_UYVY:
                dataFormat = FVID2_DF_YUV422I_UYVY;
                break;
            case (vx_df_image)VX_DF_IMAGE_YUYV:
                dataFormat = FVID2_DF_YUV422I_YUYV;
                break;
            default:
                /* do nothing */
                break;
        }
    
        return dataFormat;
    }
    
    static vx_status tivxCsitxSetCreateParams(
           tivxCsitxParams *prms,
           tivx_obj_desc_user_data_object_t *obj_desc)
    {
        uint32_t loopCnt = 0U, i, format, width, height, planes, stride[TIVX_IMAGE_MAX_PLANES];
        void *csitx_config_target_ptr;
        tivx_csitx_params_t *params;
        uint32_t chIdx, instId = 0U, instIdx;
        Csitx_CreateParams *createParams;
        tivx_obj_desc_raw_image_t *raw_image = NULL;
        vx_status status = (vx_status)VX_SUCCESS;
    
        csitx_config_target_ptr = tivxMemShared2TargetPtr(&obj_desc->mem_ptr);
    
        tivxCheckStatus(&status, tivxMemBufferMap(csitx_config_target_ptr, obj_desc->mem_size,
            (vx_enum)VX_MEMORY_TYPE_HOST, (vx_enum)VX_READ_ONLY));
    
        params = (tivx_csitx_params_t *)csitx_config_target_ptr;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug18: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        /* Scan through all the channels provided in the Node instance and prepare CSITX DRV instance data/cfg */
        for (chIdx = 0U ; chIdx < params->numCh ; chIdx++)
        {
            instId = params->chInstMap[chIdx];
            prms->instParams[instId].chVcMap[prms->instParams[instId].numCh] = params->chVcNum[chIdx];
            prms->instParams[instId].numCh++;
        }
    
        if ((vx_enum)TIVX_OBJ_DESC_RAW_IMAGE == (vx_enum)prms->img_obj_desc[0]->type)
        {
            raw_image = (tivx_obj_desc_raw_image_t *)prms->img_obj_desc[0];
            format = raw_image->params.format[0].pixel_container; /* TODO: Question: what should be done when this is different per exposure */
            width = raw_image->params.width;
            height = raw_image->params.height + (raw_image->params.meta_height_before + raw_image->params.meta_height_after);
            planes = raw_image->params.num_exposures;
            for (i = 0; i < planes; i++)
            {
                stride[i] = (uint32_t)raw_image->imagepatch_addr[i].stride_y;
            }
        }
        else
        {
            tivx_obj_desc_image_t *image;
            image = (tivx_obj_desc_image_t *)prms->img_obj_desc[0];
            format = image->format;
            width = image->imagepatch_addr[0].dim_x;
            height = image->imagepatch_addr[0].dim_y;
            planes = image->planes;
            for (i = 0; i < planes; i++)
            {
                stride[i] = (uint32_t)image->imagepatch_addr[i].stride_y;
            }
        }
    
        /* Do following for each CSITX DRV instance in the current Node */
        for (instIdx = 0U ; instIdx < params->numInst ; instIdx++)
        {
            prms->instParams[instIdx].csitxParams = prms;
            /* set instance configuration parameters */
            createParams = &prms->instParams[instIdx].createPrms;
            Csitx_createParamsInit(createParams);
            /* Initialize transmit instance status */
            Csitx_instStatusInit(&prms->instParams[instIdx].csitxStatus);
    
            /* set module configuration parameters */
            createParams->instCfg.rxCompEnable = params->instCfg[instIdx].rxCompEnable;
            createParams->instCfg.rxv1p3MapEnable = params->instCfg[instIdx].rxv1p3MapEnable;
            createParams->instCfg.dphyCfg.laneBandSpeed = params->instCfg[instIdx].laneBandSpeed;
            createParams->instCfg.dphyCfg.laneSpeedMbps = params->instCfg[instIdx].laneSpeedMbps;
            createParams->instCfg.numDataLanes = params->instCfg[instIdx].numDataLanes;
            for (loopCnt = 0U ;
                 loopCnt < createParams->instCfg.numDataLanes ;
                 loopCnt++)
            {
                createParams->instCfg.lanePolarityCtrl[loopCnt] = params->instCfg[instIdx].lanePolarityCtrl[loopCnt];
            }
    
            createParams->numCh = prms->instParams[instIdx].numCh;
            for (loopCnt = 0U ; loopCnt < createParams->numCh ; loopCnt++)
            {
                createParams->chCfg[loopCnt].chId = loopCnt;
                createParams->chCfg[loopCnt].chType = CSITX_CH_TYPE_TX;
                createParams->chCfg[loopCnt].vcNum = prms->instParams[instIdx].chVcMap[loopCnt];
    
                if ((vx_enum)TIVX_OBJ_DESC_RAW_IMAGE == (vx_enum)prms->img_obj_desc[0]->type)
                {
                    if (NULL != raw_image)
                    {
                        createParams->chCfg[loopCnt].outCsiDataType =
                            tivxCsitxExtractOutCsiDataTypeFromRawImg(raw_image);
                    }
                }
                else
                {
                    createParams->chCfg[loopCnt].outCsiDataType =
                        tivxCsitxExtractOutCsiDataType(format);
                }
                createParams->chCfg[loopCnt].inFmt.width =
                    width;
                createParams->chCfg[loopCnt].inFmt.height =
                    height;
                for (i = 0; i < planes; i ++)
                {
                    createParams->chCfg[loopCnt].inFmt.pitch[i] =
                        stride[i];
                }
    
                createParams->chCfg[loopCnt].inFmt.dataFormat =
                    tivxCsitxExtractDataFormat(format);
                createParams->chCfg[loopCnt].inFmt.ccsFormat =
                    tivxCsitxExtractCcsFormat(format);
    
                createParams->chCfg[loopCnt].vBlank = params->instCfg[instIdx].vBlank;
                createParams->chCfg[loopCnt].hBlank = params->instCfg[instIdx].hBlank;
                createParams->chCfg[loopCnt].startDelayPeriod = params->instCfg[instIdx].startDelayPeriod;
    
            }
    
            /* set instance to be used for csitx */
            prms->instParams[instIdx].instId = tivxCsitxMapInstId(params->instId[instIdx]);
            prms->numOfInstUsed++;
        }
    
        tivxCheckStatus(&status, tivxMemBufferUnmap(csitx_config_target_ptr,
           obj_desc->mem_size, (vx_enum)VX_MEMORY_TYPE_HOST,
           (vx_enum)VX_READ_ONLY));
    
        return status;
    }
    
    
    static vx_status VX_CALLBACK tivxCsitxProcess(
           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;
        int32_t fvid2_status = FVID2_SOK;
        static Fvid2_FrameList frmList;
        Fvid2_Frame *fvid2Frame;
        tivxCsitxParams *prms = NULL;
        tivxCsitxInstParams *instParams;
        tivx_obj_desc_object_array_t *input_desc;
        tivx_obj_desc_object_array_t *desc;
        vx_uint32 size, frmIdx = 0U, chId = 0U;
        uint32_t instIdx;
        vx_enum state;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug17: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        if ( (num_params != TIVX_KERNEL_CSITX_MAX_PARAMS)
            || (NULL == obj_desc[TIVX_KERNEL_CSITX_CONFIGURATION_IDX])
            || (NULL == obj_desc[TIVX_KERNEL_CSITX_INPUT_IDX])
        )
        {
            status = (vx_status)VX_FAILURE;
        }
    
        if((vx_status)VX_SUCCESS == status)
        {
            input_desc = (tivx_obj_desc_object_array_t *)obj_desc[TIVX_KERNEL_CSITX_INPUT_IDX];
    
            status = tivxGetTargetKernelInstanceContext(kernel,
                (void **)&prms, &size);
    
            if (((vx_status)VX_SUCCESS != status) || (NULL == prms) ||
                (sizeof(tivxCsitxParams) != size))
            {
                status = (vx_status)VX_FAILURE;
            }
            else
            {
                status = tivxGetTargetKernelInstanceState(kernel, &state);
            }
        }
    
        if((vx_status)VX_SUCCESS == status)
        {
    
            /* Steady state: provides a buffer and receives a buffer */
            if ((vx_enum)VX_NODE_STATE_STEADY == state)
            {
                /* Providing buffers to csitx driver */
                status = tivxCsitxEnqueueFrameToDriver(input_desc, prms);
    
                if ((vx_status)VX_SUCCESS != status)
                {
                    status = (vx_status)VX_FAILURE;
                    VX_PRINT(VX_ZONE_ERROR, " CSITX: ERROR: Enqueue Frame to Driver failed !!!\n");
                }
    
                /* Starts FVID2 on initial frame */
                if ((vx_status)VX_SUCCESS == status)
                {
                    if (0U == prms->steady_state_started)
                    {
                        /* start all driver instances in the node */
                        for (instIdx = 0U ; instIdx < prms->numOfInstUsed ; instIdx++)
                        {
                            fvid2_status = Fvid2_start(prms->instParams[instIdx].drvHandle, NULL);
                            if (FVID2_SOK != fvid2_status)
                            {
                                status = (vx_status)VX_FAILURE;
                                VX_PRINT(VX_ZONE_ERROR, " CSITX: ERROR: Could not start FVID2 !!!\n");
                                break;
                            }
                        }
    
                        if((vx_status)VX_SUCCESS == status)
                        {
                            prms->steady_state_started = 1;
                        }
                    }
                }
    
                /* Pends until a frame is available then dequeue frames from csitx driver */
                if ((vx_status)VX_SUCCESS == status)
                {
                    tivx_obj_desc_t *tmp_desc[TIVX_CSITX_MAX_CH] = {NULL};
    
                    uint32_t is_all_ch_frame_available = 0;
    
                    for(chId = 0U ; chId < prms->numCh ; chId++)
                    {
                        tmp_desc[chId] = NULL;
                    }
    
                    while(is_all_ch_frame_available == 0U)
                    {
                        is_all_ch_frame_available = 1;
                        for(chId = 0U ; chId < prms->numCh ; chId++)
                        {
                            tivxQueuePeek(&prms->pendingFrameQ[chId], (uintptr_t*)&tmp_desc[chId]);
                            if(NULL==tmp_desc[chId])
                            {
                                is_all_ch_frame_available = 0;
                            }
                        }
    
                        if(is_all_ch_frame_available == 0U)
                        {
                            tivxEventWait(prms->frame_available, TIVX_EVENT_TIMEOUT_WAIT_FOREVER);
    
                            for (instIdx = 0U ; instIdx < prms->numOfInstUsed ; instIdx++)
                            {
                                instParams = &prms->instParams[instIdx];
                                fvid2_status = Fvid2_dequeue(instParams->drvHandle,
                                                             &frmList,
                                                             0,
                                                             FVID2_TIMEOUT_NONE);
    
                                if(FVID2_SOK == fvid2_status)
                                {
                                    for(frmIdx=0; frmIdx < frmList.numFrames; frmIdx++)
                                    {
                                        fvid2Frame = frmList.frames[frmIdx];
                                        chId = tivxCsitxGetNodeChannelNum(
                                                            prms,
                                                            instIdx,
                                                            fvid2Frame->chNum);
                                        desc = (tivx_obj_desc_object_array_t *)fvid2Frame->appData;
    
                                        tivxQueuePut(&prms->freeFvid2FrameQ[chId], (uintptr_t)fvid2Frame, TIVX_EVENT_TIMEOUT_NO_WAIT);
                                        tivxQueuePut(&prms->pendingFrameQ[chId], (uintptr_t)desc, TIVX_EVENT_TIMEOUT_NO_WAIT);
                                    }
                                }
                                else if (fvid2_status == FVID2_ENO_MORE_BUFFERS)
                                {
                                    /* continue: move onto next driver instance
                                      within node as current driver instance did
                                      not generate this CB */
                                }
                                else
                                {
                                    if (FVID2_EAGAIN != fvid2_status)
                                    {
                                        status = (vx_status)VX_FAILURE;
                                        VX_PRINT(VX_ZONE_ERROR,
                                            " CSITX: ERROR: FVID2 Dequeue failed !!!\n");
                                    }
                                }
                            }
                        }
                    }
    
                    for(chId = 0U ; chId < prms->numCh ; chId++)
                    {
                        tivxQueueGet(&prms->pendingFrameQ[chId], (uintptr_t*)&tmp_desc[chId], TIVX_EVENT_TIMEOUT_NO_WAIT);
                    }
                    /* all values in tmp_desc[] should be same */
                    obj_desc[TIVX_KERNEL_CSITX_INPUT_IDX] = (tivx_obj_desc_t *)tmp_desc[0];
                }
            }
            /* Pipe-up state: only provides a buffer; does not receive a buffer */
            else
            {
                status = tivxCsitxEnqueueFrameToDriver(input_desc, prms);
            }
        }
    
        return status;
    }
    
    static vx_status VX_CALLBACK tivxCsitxCreate(
           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;
        tivx_obj_desc_user_data_object_t *configuration_desc;
        tivx_obj_desc_object_array_t *input_desc;
        tivxCsitxParams *prms = NULL;
        uint32_t chId, bufId, instIdx;
        tivxCsitxInstParams *instParams;
    
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug5: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
    
        if ( (num_params != TIVX_KERNEL_CSITX_MAX_PARAMS)
            || (NULL == obj_desc[TIVX_KERNEL_CSITX_CONFIGURATION_IDX])
            || (NULL == obj_desc[TIVX_KERNEL_CSITX_INPUT_IDX])
        )
        {
            status = (vx_status)VX_FAILURE;
        }
        else
        {
            configuration_desc = (tivx_obj_desc_user_data_object_t *)obj_desc[TIVX_KERNEL_CSITX_CONFIGURATION_IDX];
            input_desc = (tivx_obj_desc_object_array_t *)obj_desc[TIVX_KERNEL_CSITX_INPUT_IDX];
    
            prms = tivxMemAlloc(sizeof(tivxCsitxParams), (vx_enum)TIVX_MEM_EXTERNAL);
    
            if (NULL != prms)
            {
                memset(prms, 0, sizeof(tivxCsitxParams));
            }
            else
            {
                VX_PRINT(VX_ZONE_ERROR, " CSITX: ERROR: Could allocate memory !!!\n");
                status = (vx_status)VX_ERROR_NO_MEMORY;
            }
    
            if ((vx_status)VX_SUCCESS == status)
            {
                /* Initialize steady_state_started to 0 */
                prms->steady_state_started = 0;
    
                /* Set number of channels to number of items in input object array */
                prms->numCh = (uint8_t)input_desc->num_items;
    
                if (prms->numCh > TIVX_CSITX_MAX_CH)
                {
                    status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
                    VX_PRINT(VX_ZONE_ERROR, "Object descriptor number of channels exceeds max value allowed by csitx!!!\r\n");
                }
            }
    
            /* Setting CSITX transmit parameters */
            if ((vx_status)VX_SUCCESS == status)
            {
                tivxGetObjDescList(input_desc->obj_desc_id, (tivx_obj_desc_t **)prms->img_obj_desc,
                               prms->numCh);
    
                tivxCsitxSetCreateParams(prms, configuration_desc);
            }
    
            /* Creating frame available event */
            if ((vx_status)VX_SUCCESS == status)
            {
                status = tivxEventCreate(&prms->frame_available);
    
                if ((vx_status)VX_SUCCESS != status)
                {
                    VX_PRINT(VX_ZONE_ERROR, "Event creation failed in csitx!!!\r\n");
                }
            }
    
            /* Creating FVID2 handle */
            if ((vx_status)VX_SUCCESS == status)
            {
                for (instIdx = 0U ; instIdx < prms->numOfInstUsed ; instIdx++)
                {
                    instParams = &prms->instParams[instIdx];
                    Fvid2CbParams_init(&instParams->drvCbPrms);
    
                    instParams->drvCbPrms.cbFxn   = (Fvid2_CbFxn) &csitxDrvCallback;
                    instParams->drvCbPrms.appData = prms;
    
                    instParams->drvHandle = Fvid2_create(CSITX_TX_DRV_ID,
                                                         instParams->instId,
                                                         &instParams->createPrms,
                                                         &instParams->createStatus,
                                                         &instParams->drvCbPrms);
    
                    if ((NULL == instParams->drvHandle) ||
                        (instParams->createStatus.retVal != FVID2_SOK))
                    {
                        VX_PRINT(VX_ZONE_ERROR, ": Csitx Create Failed!!!\r\n");
                        status = (vx_status)VX_FAILURE;
                    }
                }
            }
    
            /* Creating FVID2 frame Q */
            if ((vx_status)VX_SUCCESS == status)
            {
                for(chId = 0u ; chId < prms->numCh ; chId++)
                {
                    status = tivxQueueCreate(&prms->freeFvid2FrameQ[chId], TIVX_CSITX_MAX_NUM_BUFS, prms->fvid2_free_q_mem[chId], 0);
    
                    if ((vx_status)VX_SUCCESS != status)
                    {
                        VX_PRINT(VX_ZONE_ERROR, ": Csitx free queue create failed!!!\r\n");
                        break;
                    }
    
                    for(bufId = 0u ; bufId < (TIVX_CSITX_MAX_NUM_BUFS) ; bufId++)
                    {
                        tivxQueuePut(&prms->freeFvid2FrameQ[chId], (uintptr_t)&prms->fvid2Frames[chId][bufId], TIVX_EVENT_TIMEOUT_NO_WAIT);
                    }
                }
            }
    
            /* Creating pending frame Q */
            if ((vx_status)VX_SUCCESS == status)
            {
                for(chId = 0U ; chId < prms->numCh ; chId++)
                {
                    status = tivxQueueCreate(&prms->pendingFrameQ[chId], TIVX_CSITX_MAX_NUM_BUFS, prms->pending_frame_free_q_mem[chId], 0);
    
                    if ((vx_status)VX_SUCCESS != status)
                    {
                        VX_PRINT(VX_ZONE_ERROR, ": Csitx pending queue create failed!!!\r\n");
                        break;
                    }
                }
            }
    
            if ((vx_status)VX_SUCCESS == status)
            {
                tivxSetTargetKernelInstanceContext(kernel, prms, sizeof(tivxCsitxParams));
            }
            else if (NULL != prms)
            {
                for (instIdx = 0U ; instIdx < prms->numOfInstUsed ; instIdx++)
                {
                    instParams = &prms->instParams[instIdx];
                    if (NULL != instParams->drvHandle)
                    {
                        Fvid2_delete(instParams->drvHandle, NULL);
                        instParams->drvHandle = NULL;
                    }
                }
    
                if (NULL != prms->frame_available)
                {
                    tivxEventDelete(&prms->frame_available);
                }
    
                tivxMemFree(prms, sizeof(tivxCsitxParams), (vx_enum)TIVX_MEM_EXTERNAL);
            }
            else
            {
                /* do nothing */
            }
        }
    
        return status;
    }
    
    static void tivxCsitxPrintStatus(tivxCsitxInstParams *prms)
    {
        int32_t fvid2_status;
        uint32_t cnt;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug16: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        if (NULL != prms)
        {
            fvid2_status = Fvid2_control(prms->drvHandle,
                                    IOCTL_CSITX_GET_INST_STATUS,
                                    &prms->csitxStatus,
                                    NULL);
            if (FVID2_SOK == fvid2_status)
            {
                printf(   "==========================================================\r\n");
                printf(
                          " Csitx Status: Instance|%d\r\n", prms->instId);
                printf(
                          "==========================================================\r\n");
                printf(
                          " FIFO Overflow Count: %d\r\n",
                          prms->csitxStatus.overflowCount);
                printf(
                    "  Channel Num | Frame Queue Count |"
                    " Frame De-queue Count | Frame Repeat Count |\n");
                for(cnt = 0U ; cnt < prms->numCh ; cnt ++)
                {
                    printf(
                          "\t\t%d|\t\t%d|\t\t%d|\t\t%d|\n",
                          cnt,
                          prms->csitxStatus.queueCount[cnt],
                          prms->csitxStatus.dequeueCount[cnt],
                          prms->csitxStatus.frmRepeatCount[cnt]);
                }
            }
            else
            {
                VX_PRINT(VX_ZONE_ERROR, " CSITX: ERROR: FVID2 Control failed !!!\n");
            }
        }
    }
    
    
    static vx_status VX_CALLBACK tivxCsitxDelete(
           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;
        int32_t fvid2_status = FVID2_SOK;
        tivxCsitxParams *prms = NULL;
        static Fvid2_FrameList frmList;
        uint32_t size, chId, instIdx;
        tivxCsitxInstParams *instParams;
    
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug6: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        if ( (num_params != TIVX_KERNEL_CSITX_MAX_PARAMS)
            || (NULL == obj_desc[TIVX_KERNEL_CSITX_CONFIGURATION_IDX])
            || (NULL == obj_desc[TIVX_KERNEL_CSITX_INPUT_IDX])
        )
        {
            status = (vx_status)VX_FAILURE;
        }
        else
        {
            status = tivxGetTargetKernelInstanceContext(kernel, (void **)&prms, &size);
    
            if ((vx_status)VX_SUCCESS != status)
            {
                VX_PRINT(VX_ZONE_ERROR, " CSITX: ERROR: Could not obtain kernel instance context !!!\n");
            }
    
            if(NULL == prms)
            {
                VX_PRINT(VX_ZONE_ERROR, "Kernel instance context is NULL!!!\n");
                status = (vx_status)VX_FAILURE;
            }
    
            if ((vx_status)VX_SUCCESS == status)
            {
    
                for (instIdx = 0U ; instIdx < prms->numOfInstUsed ; instIdx++)
                {
                    instParams = &prms->instParams[instIdx];
                    /* Stopping FVID2 Csitx */
                    if ((vx_status)VX_SUCCESS == status)
                    {
                        fvid2_status = Fvid2_stop(instParams->drvHandle, NULL);
    
                        if (FVID2_SOK != fvid2_status)
                        {
                            status = (vx_status)VX_FAILURE;
                            VX_PRINT(VX_ZONE_ERROR, " CSITX: ERROR: FVID2 Csitx not stopped !!!\n");
                        }
                    }
    
                    /* Dequeue all the request from the driver */
                    if ((vx_status)VX_SUCCESS == status)
                    {
                        Fvid2FrameList_init(&frmList);
                        do
                        {
                            fvid2_status = Fvid2_dequeue(
                                instParams->drvHandle,
                                &frmList,
                                0,
                                FVID2_TIMEOUT_NONE);
                        } while (FVID2_SOK == fvid2_status);
    
                        if (FVID2_ENO_MORE_BUFFERS != fvid2_status)
                        {
                            VX_PRINT(VX_ZONE_ERROR, " CSITX: ERROR: FVID2 Csitx Dequeue Failed !!!\n");
                            status = (vx_status)VX_FAILURE;
                        }
                    }
    
                    if ((vx_status)VX_SUCCESS == status)
                    {
                        tivxCsitxPrintStatus(instParams);
                    }
    
                    /* Deleting FVID2 handle */
                    if ((vx_status)VX_SUCCESS == status)
                    {
                        fvid2_status = Fvid2_delete(instParams->drvHandle, NULL);
    
                        if (FVID2_SOK != fvid2_status)
                        {
                            status = (vx_status)VX_FAILURE;
                            VX_PRINT(VX_ZONE_ERROR, " CSITX: ERROR: FVID2 Delete Failed !!!\n");
                        }
                    }
    
                    /* Free-ing kernel instance params */
                    if ( ((vx_status)VX_SUCCESS == status))
                    {
                        instParams->drvHandle = NULL;
    
                        if (sizeof(tivxCsitxParams) == size)
                        {
                            tivxMemFree(prms, sizeof(tivxCsitxParams), (vx_enum)TIVX_MEM_EXTERNAL);
                        }
                    }
                }
            }
    
            /* Deleting FVID2 frame Q */
            if ((vx_status)VX_SUCCESS == status)
            {
                for(chId = 0U; chId < prms->numCh ; chId++)
                {
                    tivxQueueDelete(&prms->freeFvid2FrameQ[chId]);
                }
            }
    
            /* Deleting pending frame Q */
            if ((vx_status)VX_SUCCESS == status)
            {
                for(chId= 0U ; chId < prms->numCh ; chId++)
                {
                    tivxQueueDelete(&prms->pendingFrameQ[chId]);
                }
            }
    
            /* Deleting event */
            if ((vx_status)VX_SUCCESS == status)
            {
                tivxEventDelete(&prms->frame_available);
            }
        }
    
        return status;
    }
    
    static void tivxCsitxCopyStatistics(tivxCsitxParams *prms,
        tivx_csitx_statistics_t *csitx_status_prms)
    {
        uint32_t i, instIdx;
        tivxCsitxInstParams *instParams;
    
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug4: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        for (instIdx = 0U ; instIdx < prms->numOfInstUsed ; instIdx++)
        {
            instParams = &prms->instParams[instIdx];
            for (i = 0U ; i < instParams->numCh ; i++)
            {
                csitx_status_prms->queueCount[instIdx][i]     = instParams->csitxStatus.queueCount[i];
                csitx_status_prms->dequeueCount[instIdx][i]   = instParams->csitxStatus.dequeueCount[i];
                csitx_status_prms->frmRepeatCount[instIdx][i]      = instParams->csitxStatus.frmRepeatCount[i];
            }
            csitx_status_prms->overflowCount[instIdx]         = instParams->csitxStatus.overflowCount;
        }
    }
    
    static vx_status tivxCsitxGetStatistics(tivxCsitxParams *prms,
        tivx_obj_desc_user_data_object_t *usr_data_obj)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        tivx_csitx_statistics_t *csitx_status_prms = NULL;
        void *target_ptr;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug14: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        if (NULL != usr_data_obj)
        {
            target_ptr = tivxMemShared2TargetPtr(&usr_data_obj->mem_ptr);
    
            tivxCheckStatus(&status, tivxMemBufferMap(target_ptr, usr_data_obj->mem_size,
                (vx_enum)VX_MEMORY_TYPE_HOST, (vx_enum)VX_WRITE_ONLY));
    
            if (sizeof(tivx_csitx_statistics_t) ==
                    usr_data_obj->mem_size)
            {
                csitx_status_prms = (tivx_csitx_statistics_t *)target_ptr;
    
                tivxCsitxCopyStatistics(prms, csitx_status_prms);
            }
            else
            {
                VX_PRINT(VX_ZONE_ERROR, "Invalid Size \n");
                status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
            }
    
            tivxCheckStatus(&status, tivxMemBufferUnmap(target_ptr, usr_data_obj->mem_size,
                (vx_enum)VX_MEMORY_TYPE_HOST, (vx_enum)VX_WRITE_ONLY));
        }
        else
        {
            VX_PRINT(VX_ZONE_ERROR, "User Data Object is NULL \n");
            status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
        }
    
        return (status);
    }
    
    static vx_status VX_CALLBACK tivxCsitxControl(
           tivx_target_kernel_instance kernel,
           uint32_t node_cmd_id, tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        int32_t fvid2_status = FVID2_SOK;
        uint32_t             size, instIdx;
        tivxCsitxParams *prms = NULL;
        tivxCsitxInstParams *instParams;
    
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug3: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        status = tivxGetTargetKernelInstanceContext(kernel, (void **)&prms, &size);
    
        if ((vx_status)VX_SUCCESS != status)
        {
            VX_PRINT(VX_ZONE_ERROR, "Failed to Get Target Kernel Instance Context\n");
        }
        else if ((NULL == prms) ||
            (sizeof(tivxCsitxParams) != size))
        {
            VX_PRINT(VX_ZONE_ERROR, "Invalid Object Size\n");
            status = (vx_status)VX_FAILURE;
        }
        else
        {
            /* do nothing */
        }
    
        if ((vx_status)VX_SUCCESS == status)
        {
            switch (node_cmd_id)
            {
                case TIVX_CSITX_PRINT_STATISTICS:
                {
                    for (instIdx = 0U ; instIdx < prms->numOfInstUsed ; instIdx++)
                    {
                        instParams = &prms->instParams[instIdx];
                        tivxCsitxPrintStatus(instParams);
                    }
                    break;
                }
                case TIVX_CSITX_GET_STATISTICS:
                {
                    if (NULL != obj_desc[0])
                    {
                        for (instIdx = 0U ; instIdx < prms->numOfInstUsed ; instIdx++)
                        {
                            instParams = &prms->instParams[instIdx];
                            fvid2_status = Fvid2_control(instParams->drvHandle,
                                                    IOCTL_CSITX_GET_INST_STATUS,
                                                    &instParams->csitxStatus,
                                                    NULL);
                            if (FVID2_SOK != fvid2_status)
                            {
                                VX_PRINT(VX_ZONE_ERROR, "Get status returned failure\n");
                                status = (vx_status)VX_FAILURE;
                                break;
                            }
                        }
                        if (FVID2_SOK == fvid2_status)
                        {
                            status = tivxCsitxGetStatistics(prms,
                                (tivx_obj_desc_user_data_object_t *)obj_desc[0U]);
                            if ((vx_status)VX_SUCCESS != status)
                            {
                                VX_PRINT(VX_ZONE_ERROR, "Get status failed\n");
                                status = (vx_status)VX_FAILURE;
                            }
    
                        }
                    }
                    else
                    {
                        VX_PRINT(VX_ZONE_ERROR, "User data object was NULL\n");
                        status = (vx_status)VX_FAILURE;
                    }
                    break;
                }
                default:
                {
                    VX_PRINT(VX_ZONE_ERROR, "Invalid Command Id\n");
                    status = (vx_status)VX_FAILURE;
                    break;
                }
            }
        }
        return status;
    }
    
    
    void tivxAddTargetKernelCsitx(void)
    {
        char target_name[TIVX_TARGET_MAX_NAME];
        vx_enum self_cpu;
    
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug2: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        self_cpu = tivxGetSelfCpuId();
    
        if (self_cpu == (vx_enum)TIVX_CPU_ID_MCU2_0)
        {
            strncpy(target_name, TIVX_TARGET_CSITX, TIVX_TARGET_MAX_NAME);
    
            vx_csitx_target_kernel = tivxAddTargetKernelByName(
                                TIVX_KERNEL_CSITX_NAME,
                                target_name,
                                tivxCsitxProcess,
                                tivxCsitxCreate,
                                tivxCsitxDelete,
                                tivxCsitxControl,
                                NULL);
        }
    }
    
    void tivxRemoveTargetKernelCsitx(void)
    {
        vx_status status = (vx_status)VX_SUCCESS;
    
        status = tivxRemoveTargetKernel(vx_csitx_target_kernel);
        if ((vx_status)VX_SUCCESS == status)
        {
            vx_csitx_target_kernel = NULL;
        }
    }
    
    static void tivxCsitxGetChannelIndices(tivxCsitxParams *prms,
                                             uint32_t instId,
                                             uint32_t *startChIdx,
                                             uint32_t *endChIdx)
    {
        uint32_t instIdx;
    
        *startChIdx = 0U;
        *endChIdx   = 0U;
        VX_PRINT(VX_ZONE_ERROR, "cyhdebug12: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        for (instIdx = 0U ; instIdx < prms->numOfInstUsed ; instIdx++)
        {
            /* get start channel ID here */
            if (instIdx == instId)
            {
                break;
            }
            else
            {
                *startChIdx += prms->instParams[instIdx].numCh;
            }
        }
        /* Get last channel ID here */
        if (instIdx < prms->numOfInstUsed)
        {
            *endChIdx = *startChIdx + prms->instParams[instIdx].numCh;
        }
    }
    
    static uint32_t tivxCsitxGetNodeChannelNum(tivxCsitxParams *prms,
                                                 uint32_t instId,
                                                 uint32_t chId)
    {
        uint32_t instIdx, chIdx = 0U;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug13: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        /* Get addition of all the channels processed on all previous driver instances */
        for (instIdx = 0U ; instIdx < prms->numOfInstUsed ; instIdx++)
        {
            if (instIdx == instId)
            {
                break;
            }
            else
            {
                chIdx += prms->instParams[instIdx].numCh;
            }
        }
        chIdx += chId;
    
        return (chIdx);
    }
    
    
    

    /*
     *
     * 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 <stdio.h>
    #include "TI/tivx.h"
    #include "VX/vx.h"
    #include "TI/tivx_event.h"
    #include "tivx_hwa_kernels.h"
    #include "tivx_kernel_display_m2m.h"
    #include "TI/tivx_target_kernel.h"
    #include "tivx_kernels_target_utils.h"
    #include "tivx_hwa_display_m2m_priv.h"
    
    #include <TI/tivx_queue.h>
    #include <ti/drv/fvid2/fvid2.h>
    #include <ti/drv/dss/dss.h>
    #include <tivx_obj_desc_priv.h>
    #include <vx_reference.h>
    
    #define DISPLAY_MAX_VALID_PLANES                      2U
    
    #define DISPLAY_M2M_MAX_HANDLES                       (10)
    
    typedef struct
    {
        /*! IDs=> 0: Write-back pipe-line1 */
        uint32_t instId;
        /*! Number of pipe-lines used, should be set to '1' as blending is not supported currently */
        uint32_t numPipe;
        /*! IDs=> 0:VID1, 1:VIDL1, 2:VID2 and 3:VIDL2 */
        uint32_t pipeId[TIVX_DISPLAY_M2M_MAX_PIPE];
        /*! IDs=> 0:Overlay1, 1:Overlay2, 2:Overlay3 and 3:Overlay4 */
        uint32_t overlayId;
        /*! FVID2 display driver handle */
        Fvid2_Handle drvHandle;
        /*! WB pipe create parameters */
        Dss_WbCreateParams createParams;
        /*! WB pipe create status */
        Dss_WbCreateStatus createStatus;
        /*! Callback parameters */
        Fvid2_CbParams cbParams;
        /*! WB pipe status */
        Dss_WbStatus wbStatus;
        /*! WB pipe configuration */
        Dss_WbPipeCfgParams wbCfg;
        /*! WB pipe DMA configuration */
        CSL_DssWbPipeDmaCfg wbDmaCfg;
        /*! WB pipe MFlag configuration */
        Dss_WbPipeMflagParams wbMflagCfg;
        /*! WB pipe CSC configuration */
        CSL_DssCscCoeff wbCscCfg;
        /*! Display pipe configuration */
        Dss_PipeCfgParams pipeCfg[TIVX_DISPLAY_M2M_MAX_PIPE];
        /*! Display pipe MFlag configuration */
        Dss_PipeMflagParams mFlagCfg[TIVX_DISPLAY_M2M_MAX_PIPE];
        /*! Display pipe CSC configuration */
        Dss_PipeCscParams cscCfg[TIVX_DISPLAY_M2M_MAX_PIPE];
        /*! Display Overlay configuration */
        Dss_DctrlOverlayParams ovrCfg;
        /*! Display Layer configuration */
        Dss_DctrlOverlayLayerParams layerCfg;
        /*! Display Global configuration */
        Dss_DctrlGlobalDssParams globalParams;
        /*! Mutex used for waiting for process completion */
        tivx_event waitForProcessCmpl;
        /*! Display M2M Driver Input Frame List, used for providing
         *  an array of input frames */
        Fvid2_FrameList inFrmList;
        /*! Display M2M Driver Output Frame List, used for providing
         *  an array of output frames */
        Fvid2_FrameList outFrmList;
        /*! Display M2M Driver Input Frames */
        Fvid2_Frame inFrm[TIVX_DISPLAY_M2M_MAX_PIPE];
        /*! Display M2M Driver Output Frames */
        Fvid2_Frame outFrm[1U];
    } tivxDisplayM2MDrvObj;
    
    typedef struct
    {
        /*! IDs=> 0: Object free, 1: allocated */
        uint32_t isAlloc;
        /*! Display M2M driver object */
        tivxDisplayM2MDrvObj drvObj;
        /*! Display M2M Node create parameters provided by application */
        tivx_display_m2m_params_t createParams;
    } tivxDisplayM2MParams;
    
    typedef struct
    {
        tivx_mutex      lock;
        tivxDisplayM2MParams  m2mObj[DISPLAY_M2M_MAX_HANDLES];
    } tivxDisplayM2MInstObj;
    
    static tivx_target_kernel vx_display_m2m_target_kernel1 = NULL;
    static tivx_target_kernel vx_display_m2m_target_kernel2 = NULL;
    static tivx_target_kernel vx_display_m2m_target_kernel3 = NULL;
    static tivx_target_kernel vx_display_m2m_target_kernel4 = NULL;
    
    tivxDisplayM2MInstObj gTivxDispM2mInstObj;
    
    static vx_status VX_CALLBACK tivxDisplayM2MProcess(
           tivx_target_kernel_instance kernel,
           tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg);
    static vx_status VX_CALLBACK tivxDisplayM2MCreate(
           tivx_target_kernel_instance kernel,
           tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg);
    static vx_status VX_CALLBACK tivxDisplayM2MDelete(
           tivx_target_kernel_instance kernel,
           tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg);
    static vx_status VX_CALLBACK tivxDisplayM2MControl(
           tivx_target_kernel_instance kernel,
           uint32_t node_cmd_id, tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg);
    
    static vx_status tivxDisplayM2MSetCreateParams(
                               tivxDisplayM2MParams *prms,
                               const tivx_obj_desc_user_data_object_t *obj_desc,
                               const tivx_obj_desc_image_t *obj_desc_imageIn,
                               const tivx_obj_desc_image_t *obj_desc_imageOut);
    
    static vx_status tivxDisplayM2MDrvStructsInit(tivxDisplayM2MDrvObj *drvObj);
    
    static vx_status tivxDisplayM2MDrvCfg(tivxDisplayM2MDrvObj *drvObj);
    
    static int32_t tivxDisplayM2MCallback(Fvid2_Handle handle, void *appData);
    
    static vx_status tivxDisplayExtractFvid2Format(
                                    const tivx_obj_desc_image_t *obj_desc_img,
                                    Fvid2_Format *format);
    
    static tivxDisplayM2MParams *tivxDispM2mAllocObject(tivxDisplayM2MInstObj *instObj);
    static void tivxDispM2mFreeObject(tivxDisplayM2MInstObj *instObj,
        tivxDisplayM2MParams *m2mObj);
    
    
    static vx_status VX_CALLBACK tivxDisplayM2MProcess(
           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;
        tivxDisplayM2MParams *prms = NULL;
        tivxDisplayM2MDrvObj *drvObj;
        tivx_obj_desc_image_t *input_desc;
        tivx_obj_desc_image_t *output_desc;
        void *input_target_ptr, *input_target_ptr2 = NULL;
        void *output_target_ptr, *output_target_ptr2 = NULL;
        Fvid2_Frame *frm;
        int32_t fvid2_status = FVID2_SOK;
        uint32_t pipeIdx;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug11: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__);
        if ( (num_params != TIVX_KERNEL_DISPLAY_M2M_MAX_PARAMS)
            || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_CONFIGURATION_IDX])
            || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_INPUT_IDX])
            || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_OUTPUT_IDX])
        )
        {
            status = (vx_status)VX_FAILURE;
        }
    
        if((vx_status)VX_SUCCESS == status)
        {
            uint32_t size;
            input_desc = (tivx_obj_desc_image_t *)obj_desc[TIVX_KERNEL_DISPLAY_M2M_INPUT_IDX];
            output_desc = (tivx_obj_desc_image_t *)obj_desc[TIVX_KERNEL_DISPLAY_M2M_OUTPUT_IDX];
    
            status = tivxGetTargetKernelInstanceContext(kernel,
                                                        (void **)&prms, &size);
            if (((vx_status)VX_SUCCESS != status) || (NULL == prms) ||
                (sizeof(tivxDisplayM2MParams) != size))
            {
                status = (vx_status)VX_FAILURE;
                VX_PRINT(VX_ZONE_ERROR, "DISPLAY M2M: ERROR: Instance context is NULL!\r\n");
            }
        }
    
        if((vx_status)VX_SUCCESS == status)
        {
            /* Update 'input_desc' to array from only single image input to
               support blending i.e. more than 1 number of pipes. */
            input_target_ptr = tivxMemShared2TargetPtr(&input_desc->mem_ptr[0]);
            if((vx_df_image)VX_DF_IMAGE_NV12 == input_desc->format)
            {
                input_target_ptr2 = tivxMemShared2TargetPtr(&input_desc->mem_ptr[1]);
            }
    
            output_target_ptr = tivxMemShared2TargetPtr(&output_desc->mem_ptr[0]);
    
            if((vx_df_image)VX_DF_IMAGE_NV12 == output_desc->format)
            {
                output_target_ptr2 = tivxMemShared2TargetPtr(&output_desc->mem_ptr[1]);
            }
    
            /* call kernel processing function */
    
            drvObj = &prms->drvObj;
            /* Assign input buffer addresses */
            for (pipeIdx = 0U ; pipeIdx < drvObj->numPipe ; pipeIdx++)
            {
                frm = &drvObj->inFrm[pipeIdx];
                frm->addr[0U] = (uint64_t)input_target_ptr;
                if((vx_df_image)VX_DF_IMAGE_NV12 == input_desc->format)
                {
                    frm->addr[1U] = (uint64_t)input_target_ptr2;
                }
            }
    
            /* Assign output buffer addresses */
            frm = drvObj->outFrm;
            frm->addr[0U] = (uint64_t)output_target_ptr;
            if((vx_df_image)VX_DF_IMAGE_NV12 == output_desc->format)
            {
                frm->addr[1U] = (uint64_t)output_target_ptr2;
            }
    
            /* Submit the request to the driver */
            fvid2_status = Fvid2_processRequest(drvObj->drvHandle,
                                               &drvObj->inFrmList,
                                               &drvObj->outFrmList,
                                               FVID2_TIMEOUT_FOREVER);
            if (FVID2_SOK != fvid2_status)
            {
                VX_PRINT(VX_ZONE_ERROR, "Failed to Submit Request\n");
                status = (vx_status)VX_FAILURE;
            }
            else
            {
                /* Wait for Frame Completion */
                tivxEventWait(drvObj->waitForProcessCmpl, TIVX_EVENT_TIMEOUT_WAIT_FOREVER);
                fvid2_status = Fvid2_getProcessedRequest(drvObj->drvHandle,
                                                        &drvObj->inFrmList,
                                                        &drvObj->outFrmList,
                                                        0);
                if (FVID2_SOK != fvid2_status)
                {
                    VX_PRINT(VX_ZONE_ERROR, "Failed to Get Processed Request\n");
                    status = (vx_status)VX_FAILURE;
                }
            }
    
            /* kernel processing function complete */
        }
    
        return status;
    }
    
    static vx_status VX_CALLBACK tivxDisplayM2MCreate(
           tivx_target_kernel_instance kernel,
           tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg)
    {
    
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug7: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__);
        vx_status status = (vx_status)VX_SUCCESS;
        tivxDisplayM2MParams *prms = NULL;
        tivx_obj_desc_user_data_object_t *configuration_desc;
        tivx_obj_desc_image_t *obj_desc_imageIn, *obj_desc_imageOut;
    
        if ( (num_params != TIVX_KERNEL_DISPLAY_M2M_MAX_PARAMS)
            || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_CONFIGURATION_IDX])
            || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_INPUT_IDX])
            || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_OUTPUT_IDX])
        )
        {
            status = (vx_status)VX_FAILURE;
        }
        else
        {
    
            configuration_desc = (tivx_obj_desc_user_data_object_t *)obj_desc[TIVX_KERNEL_DISPLAY_M2M_CONFIGURATION_IDX];
            obj_desc_imageIn  = (tivx_obj_desc_image_t *)obj_desc[TIVX_KERNEL_DISPLAY_M2M_INPUT_IDX];
            obj_desc_imageOut = (tivx_obj_desc_image_t *)obj_desc[TIVX_KERNEL_DISPLAY_M2M_OUTPUT_IDX];
    
            if (configuration_desc->mem_size != sizeof(tivx_display_m2m_params_t))
            {
                VX_PRINT(VX_ZONE_ERROR, "User data object size on target does not match the size on host, possibly due to misalignment in data structure\n");
                status = (vx_status)VX_FAILURE;
            }
    
            prms = tivxDispM2mAllocObject(&gTivxDispM2mInstObj);
            if (NULL == prms)
            {
                status = (vx_status)VX_ERROR_NO_MEMORY;
                VX_PRINT(VX_ZONE_ERROR, "Unable to allocate local memory\n");
            }
    
            /* Create Node object elements */
            if ((vx_status)VX_SUCCESS == status)
            {
                status = tivxDisplayM2MSetCreateParams(prms,
                                                       configuration_desc,
                                                       obj_desc_imageIn,
                                                       obj_desc_imageOut);
            }
    
            /* Create sync events */
            if (status == (vx_status)VX_SUCCESS)
            {
                status = tivxEventCreate(&prms->drvObj.waitForProcessCmpl);
                if ((vx_status)VX_SUCCESS != status)
                {
                    VX_PRINT(VX_ZONE_ERROR, "Failed to allocate Event\n");
                }
            }
    
            /* DSS M2M Driver create and configuration */
            if (status == (vx_status)VX_SUCCESS)
            {
                status = tivxDisplayM2MDrvCfg(&prms->drvObj);
            }
    
            if ((vx_status)VX_SUCCESS == status)
            {
                tivxSetTargetKernelInstanceContext(kernel, prms, sizeof(tivxDisplayM2MParams));
            }
            else
            {
                status = (vx_status)VX_ERROR_NO_MEMORY;
                VX_PRINT(VX_ZONE_ERROR, "Unable to allocate local memory\n");
            }
        }
    
        return status;
    }
    
    static vx_status VX_CALLBACK tivxDisplayM2MDelete(
           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;
        tivxDisplayM2MParams *prms = NULL;
        uint32_t size;
        int32_t fvid2_status = FVID2_SOK;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug8: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__);
        if ( (num_params != TIVX_KERNEL_DISPLAY_M2M_MAX_PARAMS)
            || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_CONFIGURATION_IDX])
            || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_INPUT_IDX])
            || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_OUTPUT_IDX])
        )
        {
            status = (vx_status)VX_FAILURE;
        }
        else
        {
            status = tivxGetTargetKernelInstanceContext(kernel,
                                                        (void **)&prms,
                                                        &size);
            if ((vx_status)VX_SUCCESS != status)
            {
                VX_PRINT(VX_ZONE_ERROR, " DSS M2M: ERROR: Could not obtain kernel instance context !!!\n");
            }
            if(NULL == prms)
            {
                VX_PRINT(VX_ZONE_ERROR, "Kernel instance context is NULL!!!\n");
                status = (vx_status)VX_FAILURE;
            }
    
            if ((vx_status)VX_SUCCESS == status)
            {
                /* Stop Display M2M Driver */
                fvid2_status = Fvid2_stop(prms->drvObj.drvHandle, NULL);
                if (FVID2_SOK != fvid2_status)
                {
                    status = (vx_status)VX_FAILURE;
                    VX_PRINT(VX_ZONE_ERROR, " DSS M2M: ERROR: FVID2 DSS M2M not stopped !!!\n");
                }
            }
    
    
            if ((vx_status)VX_SUCCESS == status)
            {
                /* Dequeue all the request from the driver */
                while ((vx_status)VX_SUCCESS == status)
                {
                    fvid2_status = Fvid2_getProcessedRequest(prms->drvObj.drvHandle,
                                                            &prms->drvObj.inFrmList,
                                                            &prms->drvObj.outFrmList,
                                                            0);
                    if (FVID2_SOK != fvid2_status)
                    {
                        if (fvid2_status != FVID2_ENO_MORE_BUFFERS)
                        {
                            VX_PRINT(VX_ZONE_ERROR, "Failed to Get Processed Request\n");
                        }
                        status = (vx_status)VX_FAILURE;
                    }
                }
                if (fvid2_status == FVID2_ENO_MORE_BUFFERS)
                {
                    status = (vx_status)VX_SUCCESS;
                }
            }
    
            if ((vx_status)VX_SUCCESS == status)
            {
                /* print status */
                fvid2_status = Fvid2_control(prms->drvObj.drvHandle,
                                             IOCTL_DSS_M2M_GET_CURRENT_STATUS,
                                             &prms->drvObj.wbStatus,
                                             NULL);
                if (FVID2_SOK != fvid2_status)
                {
                    VX_PRINT(VX_ZONE_ERROR, "Get status returned failure\n");
                    status = (vx_status)VX_FAILURE;
                }
                else
                {
                    printf(   "==========================================================\r\n");
                    printf(   " Display M2M Status: Instance|%d\r\n", prms->drvObj.instId);
                    printf(   "==========================================================\r\n");
                    printf(   " Queue Count: %d\r\n", prms->drvObj.wbStatus.queueCount);
                    printf(   " De-queue Count: %d\r\n", prms->drvObj.wbStatus.dequeueCount);
                    printf(   " Write-back Frames Count: %d\r\n", prms->drvObj.wbStatus.wbFrmCount);
                    printf(   " Underflow Count: %d\r\n", prms->drvObj.wbStatus.underflowCount);
                }
            }
    
            if ((vx_status)VX_SUCCESS == status)
            {
                /* Delete FVID2 handle */
                fvid2_status = Fvid2_delete(prms->drvObj.drvHandle, NULL);
                if (FVID2_SOK != fvid2_status)
                {
                    status = (vx_status)VX_FAILURE;
                    VX_PRINT(VX_ZONE_ERROR, " DSS M2M: ERROR: FVID2 Delete Failed !!!\n");
                }
                else
                {
                    prms->drvObj.drvHandle = NULL;
                }
            }
    
            if ((vx_status)VX_SUCCESS == status)
            {
                /* Delete event */
                tivxEventDelete(&prms->drvObj.waitForProcessCmpl);
            }
    
            if ((NULL != prms) &&
                (sizeof(tivxDisplayM2MParams) == size))
            {
                tivxDispM2mFreeObject(&gTivxDispM2mInstObj, prms);
                //tivxMemFree(prms, size, (vx_enum)TIVX_MEM_EXTERNAL);
            }
        }
    
        return status;
    }
    
    static vx_status VX_CALLBACK tivxDisplayM2MControl(
           tivx_target_kernel_instance kernel,
           uint32_t node_cmd_id, tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        int32_t fvid2_status = FVID2_SOK;
        uint32_t size;
        tivxDisplayM2MParams *prms = NULL;
        tivxDisplayM2MDrvObj *drvObj;
        tivx_display_m2m_statistics_t *m2m_status_prms = NULL;
        void *target_ptr;
        tivx_obj_desc_user_data_object_t *usr_data_obj;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug6: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__);
        status = tivxGetTargetKernelInstanceContext(kernel, (void **)&prms, &size);
        if (((vx_status)VX_SUCCESS != status)            ||
            (NULL == prms)                               ||
            (sizeof(tivxDisplayM2MParams) != size))
        {
            status = (vx_status)VX_FAILURE;
        }
    
        if (status == (vx_status)VX_SUCCESS)
        {
            switch (node_cmd_id)
            {
                case TIVX_DISPLAY_M2M_GET_STATISTICS:
                {
                    if (NULL != obj_desc[0])
                    {
                        drvObj = &prms->drvObj;
                        fvid2_status = Fvid2_control(drvObj->drvHandle,
                                                IOCTL_DSS_M2M_GET_CURRENT_STATUS,
                                                &drvObj->wbStatus,
                                                NULL);
                        if (FVID2_SOK != fvid2_status)
                        {
                            VX_PRINT(VX_ZONE_ERROR, "Get status returned failure\n");
                            status = (vx_status)VX_FAILURE;
                        }
                        else
                        {
                            /* Update return status object */
                            usr_data_obj = (tivx_obj_desc_user_data_object_t *)obj_desc[0U];
                            target_ptr = tivxMemShared2TargetPtr(&usr_data_obj->mem_ptr);
                            tivxCheckStatus(&status,
                                            tivxMemBufferMap(target_ptr,
                                            usr_data_obj->mem_size,
                                            (vx_enum)VX_MEMORY_TYPE_HOST,
                                            (vx_enum)VX_WRITE_ONLY));
                            if (sizeof(tivx_display_m2m_statistics_t) ==
                                    usr_data_obj->mem_size)
                            {
                                m2m_status_prms = (tivx_display_m2m_statistics_t *)target_ptr;
                                m2m_status_prms->queueCount     =
                                                    drvObj->wbStatus.queueCount;
                                m2m_status_prms->dequeueCount   =
                                                    drvObj->wbStatus.dequeueCount;
                                m2m_status_prms->wbFrmCount     =
                                                    drvObj->wbStatus.wbFrmCount;
                                m2m_status_prms->underflowCount =
                                                    drvObj->wbStatus.underflowCount;
                            }
                            else
                            {
                                VX_PRINT(VX_ZONE_ERROR, "Invalid Size \n");
                                status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
                            }
    
                            tivxCheckStatus(&status,
                                            tivxMemBufferUnmap(target_ptr,
                                            usr_data_obj->mem_size,
                                            (vx_enum)VX_MEMORY_TYPE_HOST,
                                            (vx_enum)VX_WRITE_ONLY));
                        }
                    }
                    else
                    {
                        VX_PRINT(VX_ZONE_ERROR, "User data object was NULL\n");
                        status = (vx_status)VX_FAILURE;
                    }
                    break;
                }
                default:
                {
                    VX_PRINT(VX_ZONE_ERROR, "Invalid Command Id\n");
                    status = (vx_status)VX_FAILURE;
                    break;
                }
            }
        }
    
        return status;
    }
    
    void tivxAddTargetKernelDisplayM2M(void)
    {
        vx_status status = (vx_status)VX_FAILURE;
        char target_name[TIVX_TARGET_MAX_NAME];
        vx_enum self_cpu;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug1: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__);
        self_cpu = tivxGetSelfCpuId();
    
        if ( self_cpu == (vx_enum)TIVX_CPU_ID_MCU2_0 )
        {
            strncpy(target_name, TIVX_TARGET_DISPLAY_M2M1, TIVX_TARGET_MAX_NAME);
            vx_display_m2m_target_kernel1 = tivxAddTargetKernelByName(
                                TIVX_KERNEL_DISPLAY_M2M_NAME,
                                target_name,
                                tivxDisplayM2MProcess,
                                tivxDisplayM2MCreate,
                                tivxDisplayM2MDelete,
                                tivxDisplayM2MControl,
                                NULL);
            strncpy(target_name, TIVX_TARGET_DISPLAY_M2M2, TIVX_TARGET_MAX_NAME);
            vx_display_m2m_target_kernel2 = tivxAddTargetKernelByName(
                                TIVX_KERNEL_DISPLAY_M2M_NAME,
                                target_name,
                                tivxDisplayM2MProcess,
                                tivxDisplayM2MCreate,
                                tivxDisplayM2MDelete,
                                tivxDisplayM2MControl,
                                NULL);
            strncpy(target_name, TIVX_TARGET_DISPLAY_M2M3, TIVX_TARGET_MAX_NAME);
            vx_display_m2m_target_kernel3 = tivxAddTargetKernelByName(
                                TIVX_KERNEL_DISPLAY_M2M_NAME,
                                target_name,
                                tivxDisplayM2MProcess,
                                tivxDisplayM2MCreate,
                                tivxDisplayM2MDelete,
                                tivxDisplayM2MControl,
                                NULL);
            strncpy(target_name, TIVX_TARGET_DISPLAY_M2M4, TIVX_TARGET_MAX_NAME);
            vx_display_m2m_target_kernel4 = tivxAddTargetKernelByName(
                                TIVX_KERNEL_DISPLAY_M2M_NAME,
                                target_name,
                                tivxDisplayM2MProcess,
                                tivxDisplayM2MCreate,
                                tivxDisplayM2MDelete,
                                tivxDisplayM2MControl,
                                NULL);
    
            status = tivxMutexCreate(&gTivxDispM2mInstObj.lock);
            if ((vx_status)VX_SUCCESS != status)
            {
                VX_PRINT(VX_ZONE_ERROR, "Failed to create Mutex\n");
            }
            else
            {
                memset(&gTivxDispM2mInstObj.m2mObj, 0x0,
                    sizeof(tivxDisplayM2MParams) * DISPLAY_M2M_MAX_HANDLES);
            }
        }
    }
    
    void tivxRemoveTargetKernelDisplayM2M(void)
    {
        vx_status status = (vx_status)VX_SUCCESS;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug13: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__);
        status = tivxRemoveTargetKernel(vx_display_m2m_target_kernel1);
        if (status == (vx_status)VX_SUCCESS)
        {
            vx_display_m2m_target_kernel1 = NULL;
        }
    
        status = tivxRemoveTargetKernel(vx_display_m2m_target_kernel2);
        if (status == (vx_status)VX_SUCCESS)
        {
            vx_display_m2m_target_kernel2 = NULL;
        }
    
        status = tivxRemoveTargetKernel(vx_display_m2m_target_kernel3);
        if (status == (vx_status)VX_SUCCESS)
        {
            vx_display_m2m_target_kernel3 = NULL;
        }
    
        status = tivxRemoveTargetKernel(vx_display_m2m_target_kernel4);
        if (status == (vx_status)VX_SUCCESS)
        {
            vx_display_m2m_target_kernel4 = NULL;
        }
    
        if (NULL != gTivxDispM2mInstObj.lock)
        {
            tivxMutexDelete(&gTivxDispM2mInstObj.lock);
        }
    }
    
    
    static vx_status tivxDisplayM2MSetCreateParams(
                           tivxDisplayM2MParams *prms,
                           const tivx_obj_desc_user_data_object_t *obj_desc,
                           const tivx_obj_desc_image_t *obj_desc_imageIn,
                           const tivx_obj_desc_image_t *obj_desc_imageOut)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        void *cfgPtr;
        tivx_display_m2m_params_t *createParams;
        tivxDisplayM2MDrvObj *drvObj;
        uint32_t pipeIdx, layerIdx;
        Dss_DispParams *dispParams;
        CSL_DssWbPipeCfg *wbPipeCfg;
        Dss_DctrlOverlayParams *ovrParams;
        Dss_DctrlOverlayLayerParams *layerParams;
        Fvid2_Frame *frm;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug12: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__);
        cfgPtr = tivxMemShared2TargetPtr(&obj_desc->mem_ptr);
    
        tivxCheckStatus(&status, tivxMemBufferMap(cfgPtr, obj_desc->mem_size,
            (vx_enum)VX_MEMORY_TYPE_HOST, (vx_enum)VX_READ_ONLY));
    
        if (status == (vx_status)VX_SUCCESS)
        {
            createParams = (tivx_display_m2m_params_t *)cfgPtr;
            memcpy(&prms->createParams, createParams, sizeof(tivx_display_m2m_params_t));
            drvObj = &prms->drvObj;
            /* Set Driver object */
            drvObj->instId    = createParams->instId;
            drvObj->numPipe   = createParams->numPipe;
            drvObj->overlayId = createParams->overlayId;
            memcpy(&drvObj->pipeId[0U],
                   &createParams->pipeId[0U],
                   sizeof(createParams->pipeId));
        }
        /* Initialize driver object */
        if (status == (vx_status)VX_SUCCESS)
        {
            status = tivxDisplayM2MDrvStructsInit(drvObj);
        }
    
        /* set driver object parameters */
        if (status == (vx_status)VX_SUCCESS)
        {
            /* Callback parameters */
            drvObj->cbParams.cbFxn   = (Fvid2_CbFxn) (&tivxDisplayM2MCallback);
            drvObj->cbParams.appData = drvObj;
            drvObj->createParams.numPipe = drvObj->numPipe;
            drvObj->createParams.overlayId = drvObj->overlayId;
            /* Set Display pipeline parameters */
            for (pipeIdx = 0U ; pipeIdx < drvObj->numPipe ; pipeIdx++)
            {
                dispParams = &drvObj->pipeCfg[pipeIdx].cfgParams;
                drvObj->createParams.pipeId[pipeIdx]  = drvObj->pipeId[pipeIdx];
                drvObj->pipeCfg[pipeIdx].pipeId       = drvObj->pipeId[pipeIdx];
                drvObj->mFlagCfg[pipeIdx].pipeId      = drvObj->pipeId[pipeIdx];
                drvObj->cscCfg[pipeIdx].pipeId        = drvObj->pipeId[pipeIdx];
                dispParams->pipeCfg.pipeType          = CSL_DSS_VID_PIPE_TYPE_VID;
                dispParams->layerPos.startX           = 0U;
                dispParams->layerPos.startY           = 0U;
                dispParams->pipeCfg.scEnable          = FALSE;
                dispParams->alphaCfg.globalAlpha      = 0xFFU;
                dispParams->alphaCfg.preMultiplyAlpha = FALSE;
                status = tivxDisplayExtractFvid2Format(
                            obj_desc_imageIn,
                            &dispParams->pipeCfg.inFmt);
                if (status == (vx_status)VX_SUCCESS)
                {
                    /* Set video pipe output frame dimensions same as input as
                       no scaling is done in video pipe-line */
                    dispParams->pipeCfg.outWidth  = dispParams->pipeCfg.inFmt.width;
                    dispParams->pipeCfg.outHeight = dispParams->pipeCfg.inFmt.height;
                }
                else
                {
                    status = (vx_status)VX_FAILURE;
                    VX_PRINT(VX_ZONE_ERROR, "Invalid Input Image\n");
                    break;
                }
            }
    
            /* Set Display WB pipeline parameters */
            if (((vx_status)VX_SUCCESS == status) && (pipeIdx > 0))
            {
                wbPipeCfg               = &drvObj->wbCfg.pipeCfg;
                /* Set WB pipe input frame dimensions same as video pipe input/output frame,
                   no scaling is done in video pipe, it will be done in WB pipe-line */
                wbPipeCfg->inFmt.width  = dispParams->pipeCfg.outWidth;
                wbPipeCfg->inFmt.height = dispParams->pipeCfg.outHeight;
                wbPipeCfg->inPos.startX = 0U;
                wbPipeCfg->inPos.startY = 0U;
                status = tivxDisplayExtractFvid2Format(obj_desc_imageOut,
                                                       &wbPipeCfg->outFmt);
                if (status != (vx_status)VX_SUCCESS)
                {
                    VX_PRINT(VX_ZONE_ERROR, "Invalid Input Image\n");
                    status = (vx_status)VX_FAILURE;
                }
                else
                {
                    if ((wbPipeCfg->inFmt.width != wbPipeCfg->outFmt.width) ||
                        (wbPipeCfg->inFmt.height != wbPipeCfg->outFmt.height))
                    {
                        wbPipeCfg->scEnable = TRUE;
                    }
                }
            }
    
            /* Set Display WB pipeline parameters */
            if ((vx_status)VX_SUCCESS == status)
            {
                ovrParams = &drvObj->ovrCfg;
                ovrParams->overlayId = drvObj->overlayId;
                ovrParams->colorbarEnable = FALSE;
                ovrParams->overlayCfg.colorKeyEnable = FALSE;
                ovrParams->overlayCfg.colorKeySel = CSL_DSS_OVERLAY_TRANS_COLOR_DEST;
                ovrParams->overlayCfg.backGroundColor = 0xc8c800U;
    
                layerParams = &drvObj->layerCfg;
                layerParams->overlayId = drvObj->overlayId;
                /* Set all layer to invalid first and then update only used ones */
                for(layerIdx = 0U ; layerIdx < CSL_DSS_VID_PIPE_ID_MAX ; layerIdx++)
                {
                    layerParams->pipeLayerNum[layerIdx] = CSL_DSS_OVERLAY_LAYER_INVALID;
                }
    
                /* Currently blending is not supported so only one layer is used.
                   This code needs to updated when blending is supported. */
                layerParams->pipeLayerNum[drvObj->createParams.pipeId[0U]] =
                                                    CSL_DSS_OVERLAY_LAYER_NUM_0;
            }
    
            /* Update frame-lists */
            if ((vx_status)VX_SUCCESS == status)
            {
                drvObj->inFrmList.numFrames = drvObj->numPipe;
                for (pipeIdx = 0U ; pipeIdx < drvObj->numPipe ; pipeIdx++)
                {
                    frm = (Fvid2_Frame *) &drvObj->inFrm[pipeIdx];
                    frm->chNum = drvObj->createParams.pipeId[pipeIdx];
                    drvObj->inFrmList.frames[pipeIdx] = frm;
                }
    
                frm = (Fvid2_Frame *) &drvObj->outFrm[0U];
                drvObj->outFrmList.frames[0U] = frm;
                drvObj->outFrmList.numFrames  = 1U;
    
            }
        }
    
        return status;
    }
    
    static vx_status tivxDisplayM2MDrvStructsInit(tivxDisplayM2MDrvObj *drvObj)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        uint32_t loopCnt;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug10: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__);
        /* Initialize driver create parameters */
        Dss_m2mCreateParamsInit(&drvObj->createParams);
        /* Initialize driver call-back parameters */
        Fvid2CbParams_init(&drvObj->cbParams);
        /* Initialize driver pipe configuration parameters */
        for (loopCnt = 0U ; loopCnt < drvObj->numPipe ; loopCnt++)
        {
            Dss_dispParamsInit(&drvObj->pipeCfg[loopCnt].cfgParams);
            Dss_dispPipeMflagParamsInit(&drvObj->mFlagCfg[loopCnt].mFlagCfg);
            CSL_dssCscCoeffInit(&drvObj->cscCfg[loopCnt].csc);
        }
        /* Initialize WB pipeline parameters */
        Dss_m2mPipeCfgParamsInit(&drvObj->wbCfg);
        CSL_dssWbPipeDmaCfgInit(&drvObj->wbDmaCfg);
        Dss_m2mMFlagParamsInit(&drvObj->wbMflagCfg);
        CSL_dssCscCoeffInit(&drvObj->wbCscCfg);
        Dss_m2mStatusInit(&drvObj->wbStatus);
    
        /* Initialize Display overlay parameters */
        Dss_dctrlOverlayParamsInit(&drvObj->ovrCfg);
        Dss_dctrlOverlayLayerParamsInit(&drvObj->layerCfg);
    
        /* Initialize Display global parameters */
        Dss_dctrlGlobalDssParamsInit(&drvObj->globalParams);
    
        /* Initialize input and output frame lists */
        Fvid2FrameList_init(&drvObj->inFrmList);
        Fvid2FrameList_init(&drvObj->outFrmList);
    
        return status;
    }
    
    static vx_status tivxDisplayM2MDrvCfg(tivxDisplayM2MDrvObj *drvObj)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        uint32_t loopCnt;
        int32_t fvid2_status = FVID2_SOK;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug9: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__);
        /* Display M2M Driver create */
        drvObj->drvHandle = Fvid2_create(DSS_M2M_DRV_ID,
                                         drvObj->instId,
                                         &drvObj->createParams,
                                         &drvObj->createStatus,
                                         &drvObj->cbParams);
        if((NULL == drvObj->drvHandle) ||
               (drvObj->createStatus.retVal != FVID2_SOK))
        {
            VX_PRINT(VX_ZONE_ERROR, ": Display M2M Create Failed!!!\r\n");
            status = (vx_status)VX_FAILURE;
        }
    
        /* Display M2M pipe configuration */
        if ((vx_status)VX_SUCCESS == status)
        {
            for (loopCnt = 0U ; loopCnt < drvObj->numPipe ; loopCnt++)
            {
                fvid2_status += Fvid2_control(drvObj->drvHandle,
                                              IOCTL_DSS_M2M_SET_PIPE_PARAMS,
                                              &drvObj->pipeCfg[loopCnt],
                                              NULL);
                fvid2_status += Fvid2_control(drvObj->drvHandle,
                                              IOCTL_DSS_M2M_SET_PIPE_MFLAG_PARAMS,
                                              &drvObj->mFlagCfg[loopCnt],
                                              NULL);
                if (FVID2_SOK != fvid2_status)
                {
                    VX_PRINT(VX_ZONE_ERROR, ": Display M2M DISP IOCTL Failed!!!\r\n");
                    status = (vx_status)VX_FAILURE;
                    break;
                }
            }
        }
    
        /* Display M2M overlay configuration */
        if ((vx_status)VX_SUCCESS == status)
        {
            fvid2_status += Fvid2_control(drvObj->drvHandle,
                                          IOCTL_DSS_DCTRL_SET_OVERLAY_PARAMS,
                                          &drvObj->ovrCfg,
                                          NULL);
            fvid2_status += Fvid2_control(drvObj->drvHandle,
                                          IOCTL_DSS_DCTRL_SET_LAYER_PARAMS,
                                          &drvObj->layerCfg,
                                          NULL);
            if (FVID2_SOK != fvid2_status)
            {
                VX_PRINT(VX_ZONE_ERROR, ": Display M2M Overlay IOCTL Failed!!!\r\n");
                status = (vx_status)VX_FAILURE;
            }
        }
    
        /* Display M2M global configuration */
        if ((vx_status)VX_SUCCESS == status)
        {
            fvid2_status += Fvid2_control(drvObj->drvHandle,
                                          IOCTL_DSS_DCTRL_SET_GLOBAL_DSS_PARAMS,
                                          &drvObj->globalParams,
                                          NULL);
            if (FVID2_SOK != fvid2_status)
            {
                VX_PRINT(VX_ZONE_ERROR, ": Display M2M Global IOCTL Failed!!!\r\n");
                status = (vx_status)VX_FAILURE;
            }
        }
    
        /* Display M2M write-back pipe configuration */
        if ((vx_status)VX_SUCCESS == status)
        {
            fvid2_status += Fvid2_control(drvObj->drvHandle,
                                          IOCTL_DSS_M2M_SET_WB_PIPE_PARAMS,
                                          &drvObj->wbCfg,
                                          NULL);
            fvid2_status += Fvid2_control(drvObj->drvHandle,
                                          IOCTL_DSS_M2M_SET_WB_PIPE_MFLAG_PARAMS,
                                          &drvObj->wbMflagCfg,
                                          NULL);
            fvid2_status += Fvid2_control(drvObj->drvHandle,
                                          IOCTL_DSS_M2M_SET_WB_PIPE_DMA_CFG,
                                          &drvObj->wbDmaCfg,
                                          NULL);
            if (FVID2_SOK != fvid2_status)
            {
                VX_PRINT(VX_ZONE_ERROR, ": Display M2M WB IOCTL Failed!!!\r\n");
                status = (vx_status)VX_FAILURE;
            }
        }
    
        /* Start Display M2M Driver */
        if ((vx_status)VX_SUCCESS == status)
        {
            fvid2_status = Fvid2_start(drvObj->drvHandle, NULL);
            if (FVID2_SOK != fvid2_status)
            {
                VX_PRINT(VX_ZONE_ERROR, ": Display M2M Driver Start Failed!!!\r\n");
                status = (vx_status)VX_FAILURE;
            }
        }
    
        return status;
    }
    
    static int32_t tivxDisplayM2MCallback(Fvid2_Handle handle, void *appData)
    {
        tivxDisplayM2MDrvObj *drvObj = (tivxDisplayM2MDrvObj *)(appData);
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug5: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__);
        if ((NULL != drvObj) && (drvObj->waitForProcessCmpl != NULL))
        {
            tivxEventPost(drvObj->waitForProcessCmpl);
        }
    
        return (vx_status)VX_SUCCESS;
    }
    
    static vx_status tivxDisplayExtractFvid2Format(
                                        const tivx_obj_desc_image_t *obj_desc_img,
                                        Fvid2_Format *format)
    {
        vx_status status = (vx_status)VX_SUCCESS;
    
        Fvid2Format_init(format);
        format->width = obj_desc_img->imagepatch_addr[0].dim_x;
        format->height = obj_desc_img->imagepatch_addr[0].dim_y;
        format->ccsFormat = FVID2_CCSF_BITS8_PACKED;
        format->scanFormat = FVID2_SF_PROGRESSIVE;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug4: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__);
        switch (obj_desc_img->format)
        {
            case (vx_df_image)TIVX_DF_IMAGE_RGB565:
                format->dataFormat = FVID2_DF_BGR16_565;
                format->pitch[FVID2_RGB_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y;
                break;
            case (vx_df_image)VX_DF_IMAGE_RGB:
                format->dataFormat = FVID2_DF_RGB24_888;
                format->pitch[FVID2_RGB_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y;
                break;
            case (vx_df_image)VX_DF_IMAGE_RGBX:
                format->dataFormat = FVID2_DF_RGBX24_8888;
                format->pitch[FVID2_RGB_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y;
                break;
            case (vx_df_image)TIVX_DF_IMAGE_BGRX:
                format->dataFormat = FVID2_DF_BGRX32_8888;
                format->pitch[FVID2_RGB_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y;
                break;
            case (vx_df_image)VX_DF_IMAGE_UYVY:
                format->dataFormat = FVID2_DF_YUV422I_UYVY;
                format->pitch[FVID2_YUV_INT_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y;
                break;
            case (vx_df_image)VX_DF_IMAGE_YUYV:
                format->dataFormat = FVID2_DF_YUV422I_YUYV;
                format->pitch[FVID2_YUV_INT_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y;
                break;
            case (vx_df_image)VX_DF_IMAGE_NV12:
                format->dataFormat = FVID2_DF_YUV420SP_UV;
                format->pitch[FVID2_YUV_SP_Y_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y;
                format->pitch[FVID2_YUV_SP_CBCR_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[1].stride_y;
                break;
            case (vx_df_image)VX_DF_IMAGE_U16:
                format->ccsFormat = FVID2_CCSF_BITS12_UNPACKED16;
                format->dataFormat = FVID2_DF_YUV420SP_UV;
                format->pitch[FVID2_YUV_SP_Y_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y;
                format->pitch[FVID2_YUV_SP_CBCR_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y;
                break;
            case (vx_df_image)VX_DF_IMAGE_U8:
                format->ccsFormat = FVID2_CCSF_BITS8_PACKED;
                format->dataFormat = FVID2_DF_YUV420SP_UV;
                format->pitch[FVID2_YUV_SP_Y_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y;
                format->pitch[FVID2_YUV_SP_CBCR_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y;
                break;
            default:
                status = (vx_status)VX_FAILURE;
                break;
        }
    
        return status;
    }
    
    static tivxDisplayM2MParams *tivxDispM2mAllocObject(tivxDisplayM2MInstObj *instObj)
    {
        uint32_t                cnt;
        tivxDisplayM2MParams *m2mObj = NULL;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug2: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__);
        /* Lock instance mutex */
        tivxMutexLock(instObj->lock);
    
        for (cnt = 0U; cnt < DISPLAY_M2M_MAX_HANDLES; cnt ++)
        {
            if (0U == instObj->m2mObj[cnt].isAlloc)
            {
                m2mObj = &instObj->m2mObj[cnt];
                memset(m2mObj, 0x0, sizeof(tivxDisplayM2MParams));
                instObj->m2mObj[cnt].isAlloc = 1U;
                break;
            }
        }
    
        /* Release instance mutex */
        tivxMutexUnlock(instObj->lock);
    
        return (m2mObj);
    }
    
    static void tivxDispM2mFreeObject(tivxDisplayM2MInstObj *instObj,
        tivxDisplayM2MParams *m2mObj)
    {
        uint32_t cnt;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug3: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__);
        /* Lock instance mutex */
        tivxMutexLock(instObj->lock);
    
        for (cnt = 0U; cnt < DISPLAY_M2M_MAX_HANDLES; cnt ++)
        {
            if (m2mObj == &instObj->m2mObj[cnt])
            {
                m2mObj->isAlloc = 0U;
                break;
            }
        }
    
        /* Release instance mutex */
        tivxMutexUnlock(instObj->lock);
    }
    

    below is log file:

    MobaXterm_COM3ProlificUSB-to-SerialCommPortCOM3_20230316_211455.txt

    I only found two debug print added by me:

    Regards.

  • Hi xie jc,

    ok great, can you also similarly add some prints in the create function and see if they are coming? I want to see where it exactly this is failing in the create API. 

    Regards,

    Brijesh

  • Hi, Brijesh,

    I add some debug in below files:

    /*
     *
     * Copyright (c) 2020 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 <stdio.h>
    #include "TI/tivx.h"
    #include "TI/tivx_event.h"
    #include "VX/vx.h"
    #include "tivx_hwa_kernels.h"
    #include "tivx_kernel_csitx.h"
    #include "TI/tivx_target_kernel.h"
    #include "tivx_kernels_target_utils.h"
    #include "tivx_hwa_csitx_priv.h"
    
    #include <TI/tivx_queue.h>
    #include <ti/drv/fvid2/fvid2.h>
    #include <ti/drv/csitx/csitx.h>
    
    
    #define CSITX_INST_ID_INVALID                         (0xFFFFU)
    
    #define CAPTURE_OUT_CSI_DT_INVALID                    (0xFFFFFFFFU)
    
    typedef struct tivxCsitxParams_t tivxCsitxParams;
    
    typedef struct
    {
        uint32_t instId;
        /**< Csitx Drv Instance ID. */
        uint8_t numCh;
        /**< Number of channels processed on given CSITX DRV instance. */
        uint32_t chVcMap[TIVX_CSITX_MAX_CH];
        /**< Virtual ID for channels for current csitx instance. */
        Fvid2_Handle drvHandle;
        /**< FVID2 csitx driver handle. */
        Csitx_CreateParams createPrms;
        /**< Csitx create time parameters */
        Csitx_CreateStatus createStatus;
        /**< Csitx create time status */
        Fvid2_CbParams drvCbPrms;
        /**< Csitx callback params */
        Csitx_InstStatus csitxStatus;
        /**< CSITX Transmit status. */
        tivxCsitxParams *csitxParams;
        /**< Reference to csitx node parameters. */
    } tivxCsitxInstParams;
    
    struct tivxCsitxParams_t
    {
        tivxCsitxInstParams instParams[TIVX_CSITX_MAX_INST];
        /* Csitx Instance parameters */
        uint32_t numOfInstUsed;
        /**< Number of CSITX DRV instances used in current TIOVX Node. */
        uint8_t numCh;
        /**< Number of channels processed on given csitx node instance. */
        tivx_obj_desc_t *img_obj_desc[TIVX_CSITX_MAX_CH];
        /*  Transmit Images */
        uint8_t steady_state_started;
        /**< Flag indicating whether or not steady state has begun. */
        tivx_event  frame_available;
        /**< Following Queues i.e. freeFvid2FrameQ, pendingFrameQ, fvid2_free_q_mem,
         *   fvid2Frames, and pending_frame_free_q_mem are for given instance of the
         *   Node. If Node instance contains more than 1 instances of the CSITX DRV
         *   instances, then first 'n' channels are for first instance of the driver
         *   then n channels for next driver and so on... */
        /**< Event indicating when a frame is available. */
        tivx_queue freeFvid2FrameQ[TIVX_CSITX_MAX_CH];
        /**< Internal FVID2 queue */
        tivx_queue pendingFrameQ[TIVX_CSITX_MAX_CH];
        /**< Internal pending frame queue */
        uintptr_t fvid2_free_q_mem[TIVX_CSITX_MAX_CH][TIVX_CSITX_MAX_NUM_BUFS];
        /**< FVID2 queue mem */
        Fvid2_Frame fvid2Frames[TIVX_CSITX_MAX_CH][TIVX_CSITX_MAX_NUM_BUFS];
        /**< FVID2 frame structs */
        uintptr_t pending_frame_free_q_mem[TIVX_CSITX_MAX_CH][TIVX_CSITX_MAX_NUM_BUFS];
        /**< pending frame queue mem */
    };
    
    static tivx_target_kernel vx_csitx_target_kernel = NULL;
    
    static vx_status csitxDrvCallback(Fvid2_Handle handle, void *appData, void *reserved);
    static uint32_t tivxCsitxExtractOutCsiDataType(uint32_t format);
    static uint32_t tivxCsitxExtractCcsFormat(uint32_t format);
    static uint32_t tivxCsitxExtractDataFormat(uint32_t format);
    
    static vx_status tivxCsitxEnqueueFrameToDriver(
           tivx_obj_desc_object_array_t *input_desc,
           tivxCsitxParams *prms);
    
    static vx_status tivxCsitxSetCreateParams(
           tivxCsitxParams *prms,
           tivx_obj_desc_user_data_object_t *obj_desc);
    
    static vx_status VX_CALLBACK tivxCsitxProcess(
           tivx_target_kernel_instance kernel,
           tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg);
    static vx_status VX_CALLBACK tivxCsitxCreate(
           tivx_target_kernel_instance kernel,
           tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg);
    static vx_status VX_CALLBACK tivxCsitxDelete(
           tivx_target_kernel_instance kernel,
           tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg);
    static vx_status VX_CALLBACK tivxCsitxControl(
           tivx_target_kernel_instance kernel,
           uint32_t node_cmd_id, tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg);
    
    static vx_status tivxCsitxGetStatistics(tivxCsitxParams *prms,
        tivx_obj_desc_user_data_object_t *usr_data_obj);
    static void tivxCsitxCopyStatistics(tivxCsitxParams *prms,
        tivx_csitx_statistics_t *csitx_status_prms);
    static void tivxCsitxGetChannelIndices(tivxCsitxParams *prms,
                                             uint32_t instId,
                                             uint32_t *startChIdx,
                                             uint32_t *endChIdx);
    static uint32_t tivxCsitxGetNodeChannelNum(tivxCsitxParams *prms,
                                                 uint32_t instId,
                                                 uint32_t chId);
    static uint32_t tivxCsitxMapInstId(uint32_t instId);
    static void tivxCsitxPrintStatus(tivxCsitxInstParams *prms);
    
    /**
     *******************************************************************************
     *
     * \brief Callback function from driver to application
     *
     * Callback function gets called from Driver to application on transmission of
     * a frame
     *
     * \param  handle       [IN] Driver handle for which callback has come.
     * \param  appData      [IN] Application specific data which is registered
     *                           during the callback registration.
     * \param  reserved     [IN] Reserved.
     *
     * \return  SYSTEM_LINK_STATUS_SOK on success
     *
     *******************************************************************************
     */
    static vx_status csitxDrvCallback(Fvid2_Handle handle, void *appData, void *reserved)
    {
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug1: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        tivxCsitxParams *prms = (tivxCsitxParams*)appData;
    
        tivxEventPost(prms->frame_available);
    
        return (vx_status)VX_SUCCESS;
    }
    
    
    static vx_status tivxCsitxEnqueueFrameToDriver(
           tivx_obj_desc_object_array_t *input_desc,
           tivxCsitxParams *prms)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        int32_t fvid2_status = FVID2_SOK;
        void *input_image_target_ptr;
        uint64_t transmit_frame;
        uint32_t chId = 0U;
        static Fvid2_FrameList frmList;
        Fvid2_Frame *fvid2Frame;
        uint32_t startChIdx, endChIdx, instIdx;
        tivxCsitxInstParams *instParams;
    
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug7: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        tivxGetObjDescList(input_desc->obj_desc_id, (tivx_obj_desc_t **)prms->img_obj_desc,
                           prms->numCh);
    
        /* Prepare and queue frame-list for each instance */
        for (instIdx = 0U ; instIdx < prms->numOfInstUsed ; instIdx++)
        {
            instParams = &prms->instParams[instIdx];
            tivxCsitxGetChannelIndices(prms, instIdx, &startChIdx, &endChIdx);
            frmList.numFrames = instParams->numCh;
            for (chId = startChIdx ; chId < endChIdx ; chId++)
            {
                if ((vx_enum)TIVX_OBJ_DESC_RAW_IMAGE == (vx_enum)prms->img_obj_desc[0]->type)
                {
                    tivx_obj_desc_raw_image_t *raw_image;
    
                    raw_image = (tivx_obj_desc_raw_image_t *)prms->img_obj_desc[chId];
    
                    input_image_target_ptr = tivxMemShared2TargetPtr(&raw_image->mem_ptr[0]);
    
    
                    transmit_frame = ((uintptr_t)input_image_target_ptr +
                        (uint64_t)tivxComputePatchOffset(0, 0, &raw_image->imagepatch_addr[0U]));
                }
                else
                {
                    tivx_obj_desc_image_t *image;
                    image = (tivx_obj_desc_image_t *)prms->img_obj_desc[chId];
    
                    input_image_target_ptr = tivxMemShared2TargetPtr(&image->mem_ptr[0]);
    
                    transmit_frame = ((uintptr_t)input_image_target_ptr +
                        (uint64_t)tivxComputePatchOffset(0, 0, &image->imagepatch_addr[0U]));
                }
    
                tivxQueueGet(&prms->freeFvid2FrameQ[chId], (uintptr_t*)&fvid2Frame, TIVX_EVENT_TIMEOUT_NO_WAIT);
    
                if (NULL != fvid2Frame)
                {
                    /* Put into frame list as it is for same driver instance */
                    frmList.frames[(chId - startChIdx)]           = fvid2Frame;
                    frmList.frames[(chId - startChIdx)]->chNum    = (chId - startChIdx);
                    frmList.frames[(chId - startChIdx)]->addr[0U] = transmit_frame;
                    frmList.frames[(chId - startChIdx)]->appData  = input_desc;
                }
                else
                {
                    VX_PRINT(VX_ZONE_ERROR, " CSITX: Could not retrieve buffer from buffer queue!!!\n");
                }
            }
    
            /* All the frames from frame-list */
            fvid2_status = Fvid2_queue(instParams->drvHandle, &frmList, 0);
            if (FVID2_SOK != fvid2_status)
            {
                status = (vx_status)VX_FAILURE;
                VX_PRINT(VX_ZONE_ERROR, " CSITX: ERROR: Frame could not be queued for frame %d !!!\n", chId);
                break;
            }
        }
    
        return status;
    }
    
    
    static uint32_t tivxCsitxExtractOutCsiDataType(uint32_t format)
    {
        uint32_t outCsiDataType;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug10: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        switch (format)
        {
            case (vx_df_image)VX_DF_IMAGE_RGB:
                outCsiDataType = FVID2_CSI2_DF_RGB888;
                break;
            case (vx_df_image)VX_DF_IMAGE_RGBX:
                outCsiDataType = FVID2_CSI2_DF_RGB888;
                break;
            case (vx_df_image)VX_DF_IMAGE_U16:
            case (uint32_t)TIVX_RAW_IMAGE_P12_BIT:
                outCsiDataType = FVID2_CSI2_DF_RAW12;
                break;
            case (vx_df_image)VX_DF_IMAGE_UYVY:
            case (vx_df_image)VX_DF_IMAGE_YUYV:
                outCsiDataType = FVID2_CSI2_DF_YUV422_8B;
                break;
            default:
                outCsiDataType = CAPTURE_OUT_CSI_DT_INVALID;
                break;
        }
    
        return outCsiDataType;
    }
    
    static uint32_t tivxCsitxExtractOutCsiDataTypeFromRawImg(tivx_obj_desc_raw_image_t *raw_img)
    {
        uint32_t inCsiDataType = CAPTURE_OUT_CSI_DT_INVALID;
        tivx_raw_image_create_params_t *params = &raw_img->params;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug11: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        if (TIVX_RAW_IMAGE_16_BIT == params->format[0].pixel_container)
        {
            switch (params->format[0].msb)
            {
                case 9u:
                    inCsiDataType = FVID2_CSI2_DF_RAW10;
                break;
                case 11u:
                    inCsiDataType = FVID2_CSI2_DF_RAW12;
                break;
                case 13u:
                    inCsiDataType = FVID2_CSI2_DF_RAW14;
                break;
                case 15u:
                    inCsiDataType = FVID2_CSI2_DF_RAW16;
                break;
                default:
                    break;
            }
        }
        else if (TIVX_RAW_IMAGE_8_BIT == params->format[0].pixel_container)
        {
            switch (params->format[0].msb)
            {
                case 5u:
                    inCsiDataType = FVID2_CSI2_DF_RAW6;
                break;
                case 6u:
                    inCsiDataType = FVID2_CSI2_DF_RAW7;
                break;
                case 7u:
                    inCsiDataType = FVID2_CSI2_DF_RAW8;
                break;
                default:
                    break;
            }
        }
        else if (TIVX_RAW_IMAGE_P12_BIT == params->format[0].pixel_container)
        {
            if (12u == params->format[0].msb)
            {
                inCsiDataType = FVID2_CSI2_DF_RAW12;
            }
        }
        else
        {
            /* Don Nothing */
        }
    
        return (inCsiDataType);
    }
    
    static uint32_t tivxCsitxExtractCcsFormat(uint32_t format)
    {
        uint32_t ccsFormat = FVID2_CCSF_BITS12_PACKED;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug8: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        switch (format)
        {
            case (uint32_t)TIVX_RAW_IMAGE_P12_BIT:
                ccsFormat = FVID2_CCSF_BITS12_PACKED;
                break;
            case (vx_enum)TIVX_RAW_IMAGE_16_BIT:
            case (vx_df_image)VX_DF_IMAGE_U16:
            case (vx_df_image)VX_DF_IMAGE_UYVY:
            case (vx_df_image)VX_DF_IMAGE_YUYV:
                ccsFormat = FVID2_CCSF_BITS12_UNPACKED16;
                break;
            default:
                ccsFormat = FVID2_CCSF_MAX;
                break;
        }
    
        return ccsFormat;
    }
    
    static uint32_t tivxCsitxMapInstId(uint32_t instId)
    {
        uint32_t drvInstId = CSITX_INST_ID_INVALID;
        VX_PRINT(VX_ZONE_ERROR, "cyhdebug15: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        switch (instId)
        {
            case 0:
                drvInstId = CSITX_INSTANCE_ID_0;
                break;
            default:
                /* do nothing */
                break;
        }
    
        return (drvInstId);
    }
    
    static uint32_t tivxCsitxExtractDataFormat(uint32_t format)
    {
        uint32_t dataFormat = FVID2_DF_BGRX32_8888;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug9: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        switch (format)
        {
            case (vx_df_image)VX_DF_IMAGE_RGBX:
                dataFormat = FVID2_DF_BGRX32_8888;
                break;
            case (vx_df_image)VX_DF_IMAGE_UYVY:
                dataFormat = FVID2_DF_YUV422I_UYVY;
                break;
            case (vx_df_image)VX_DF_IMAGE_YUYV:
                dataFormat = FVID2_DF_YUV422I_YUYV;
                break;
            default:
                /* do nothing */
                break;
        }
    
        return dataFormat;
    }
    
    static vx_status tivxCsitxSetCreateParams(
           tivxCsitxParams *prms,
           tivx_obj_desc_user_data_object_t *obj_desc)
    {
        uint32_t loopCnt = 0U, i, format, width, height, planes, stride[TIVX_IMAGE_MAX_PLANES];
        void *csitx_config_target_ptr;
        tivx_csitx_params_t *params;
        uint32_t chIdx, instId = 0U, instIdx;
        Csitx_CreateParams *createParams;
        tivx_obj_desc_raw_image_t *raw_image = NULL;
        vx_status status = (vx_status)VX_SUCCESS;
    
        csitx_config_target_ptr = tivxMemShared2TargetPtr(&obj_desc->mem_ptr);
    
        tivxCheckStatus(&status, tivxMemBufferMap(csitx_config_target_ptr, obj_desc->mem_size,
            (vx_enum)VX_MEMORY_TYPE_HOST, (vx_enum)VX_READ_ONLY));
    
        params = (tivx_csitx_params_t *)csitx_config_target_ptr;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug18: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        /* Scan through all the channels provided in the Node instance and prepare CSITX DRV instance data/cfg */
        for (chIdx = 0U ; chIdx < params->numCh ; chIdx++)
        {
            instId = params->chInstMap[chIdx];
            prms->instParams[instId].chVcMap[prms->instParams[instId].numCh] = params->chVcNum[chIdx];
            prms->instParams[instId].numCh++;
        }
    
        if ((vx_enum)TIVX_OBJ_DESC_RAW_IMAGE == (vx_enum)prms->img_obj_desc[0]->type)
        {
            raw_image = (tivx_obj_desc_raw_image_t *)prms->img_obj_desc[0];
            format = raw_image->params.format[0].pixel_container; /* TODO: Question: what should be done when this is different per exposure */
            width = raw_image->params.width;
            height = raw_image->params.height + (raw_image->params.meta_height_before + raw_image->params.meta_height_after);
            planes = raw_image->params.num_exposures;
            for (i = 0; i < planes; i++)
            {
                stride[i] = (uint32_t)raw_image->imagepatch_addr[i].stride_y;
            }
        }
        else
        {
            tivx_obj_desc_image_t *image;
            image = (tivx_obj_desc_image_t *)prms->img_obj_desc[0];
            format = image->format;
            width = image->imagepatch_addr[0].dim_x;
            height = image->imagepatch_addr[0].dim_y;
            planes = image->planes;
            for (i = 0; i < planes; i++)
            {
                stride[i] = (uint32_t)image->imagepatch_addr[i].stride_y;
            }
        }
    
        /* Do following for each CSITX DRV instance in the current Node */
        for (instIdx = 0U ; instIdx < params->numInst ; instIdx++)
        {
            prms->instParams[instIdx].csitxParams = prms;
            /* set instance configuration parameters */
            createParams = &prms->instParams[instIdx].createPrms;
            Csitx_createParamsInit(createParams);
            /* Initialize transmit instance status */
            Csitx_instStatusInit(&prms->instParams[instIdx].csitxStatus);
    
            /* set module configuration parameters */
            createParams->instCfg.rxCompEnable = params->instCfg[instIdx].rxCompEnable;
            createParams->instCfg.rxv1p3MapEnable = params->instCfg[instIdx].rxv1p3MapEnable;
            createParams->instCfg.dphyCfg.laneBandSpeed = params->instCfg[instIdx].laneBandSpeed;
            createParams->instCfg.dphyCfg.laneSpeedMbps = params->instCfg[instIdx].laneSpeedMbps;
            createParams->instCfg.numDataLanes = params->instCfg[instIdx].numDataLanes;
            for (loopCnt = 0U ;
                 loopCnt < createParams->instCfg.numDataLanes ;
                 loopCnt++)
            {
                createParams->instCfg.lanePolarityCtrl[loopCnt] = params->instCfg[instIdx].lanePolarityCtrl[loopCnt];
            }
    
            createParams->numCh = prms->instParams[instIdx].numCh;
            for (loopCnt = 0U ; loopCnt < createParams->numCh ; loopCnt++)
            {
                createParams->chCfg[loopCnt].chId = loopCnt;
                createParams->chCfg[loopCnt].chType = CSITX_CH_TYPE_TX;
                createParams->chCfg[loopCnt].vcNum = prms->instParams[instIdx].chVcMap[loopCnt];
    
                if ((vx_enum)TIVX_OBJ_DESC_RAW_IMAGE == (vx_enum)prms->img_obj_desc[0]->type)
                {
                    if (NULL != raw_image)
                    {
                        createParams->chCfg[loopCnt].outCsiDataType =
                            tivxCsitxExtractOutCsiDataTypeFromRawImg(raw_image);
                    }
                }
                else
                {
                    createParams->chCfg[loopCnt].outCsiDataType =
                        tivxCsitxExtractOutCsiDataType(format);
                }
                createParams->chCfg[loopCnt].inFmt.width =
                    width;
                createParams->chCfg[loopCnt].inFmt.height =
                    height;
                for (i = 0; i < planes; i ++)
                {
                    createParams->chCfg[loopCnt].inFmt.pitch[i] =
                        stride[i];
                }
    
                createParams->chCfg[loopCnt].inFmt.dataFormat =
                    tivxCsitxExtractDataFormat(format);
                createParams->chCfg[loopCnt].inFmt.ccsFormat =
                    tivxCsitxExtractCcsFormat(format);
    
                createParams->chCfg[loopCnt].vBlank = params->instCfg[instIdx].vBlank;
                createParams->chCfg[loopCnt].hBlank = params->instCfg[instIdx].hBlank;
                createParams->chCfg[loopCnt].startDelayPeriod = params->instCfg[instIdx].startDelayPeriod;
    
            }
    
            /* set instance to be used for csitx */
            prms->instParams[instIdx].instId = tivxCsitxMapInstId(params->instId[instIdx]);
            prms->numOfInstUsed++;
        }
    
        tivxCheckStatus(&status, tivxMemBufferUnmap(csitx_config_target_ptr,
           obj_desc->mem_size, (vx_enum)VX_MEMORY_TYPE_HOST,
           (vx_enum)VX_READ_ONLY));
    
        return status;
    }
    
    
    static vx_status VX_CALLBACK tivxCsitxProcess(
           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;
        int32_t fvid2_status = FVID2_SOK;
        static Fvid2_FrameList frmList;
        Fvid2_Frame *fvid2Frame;
        tivxCsitxParams *prms = NULL;
        tivxCsitxInstParams *instParams;
        tivx_obj_desc_object_array_t *input_desc;
        tivx_obj_desc_object_array_t *desc;
        vx_uint32 size, frmIdx = 0U, chId = 0U;
        uint32_t instIdx;
        vx_enum state;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug17: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        if ( (num_params != TIVX_KERNEL_CSITX_MAX_PARAMS)
            || (NULL == obj_desc[TIVX_KERNEL_CSITX_CONFIGURATION_IDX])
            || (NULL == obj_desc[TIVX_KERNEL_CSITX_INPUT_IDX])
        )
        {
            status = (vx_status)VX_FAILURE;
        }
    
        if((vx_status)VX_SUCCESS == status)
        {
            input_desc = (tivx_obj_desc_object_array_t *)obj_desc[TIVX_KERNEL_CSITX_INPUT_IDX];
    
            status = tivxGetTargetKernelInstanceContext(kernel,
                (void **)&prms, &size);
    
            if (((vx_status)VX_SUCCESS != status) || (NULL == prms) ||
                (sizeof(tivxCsitxParams) != size))
            {
                status = (vx_status)VX_FAILURE;
            }
            else
            {
                status = tivxGetTargetKernelInstanceState(kernel, &state);
            }
        }
    
        if((vx_status)VX_SUCCESS == status)
        {
    
            /* Steady state: provides a buffer and receives a buffer */
            if ((vx_enum)VX_NODE_STATE_STEADY == state)
            {
                /* Providing buffers to csitx driver */
                status = tivxCsitxEnqueueFrameToDriver(input_desc, prms);
    
                if ((vx_status)VX_SUCCESS != status)
                {
                    status = (vx_status)VX_FAILURE;
                    VX_PRINT(VX_ZONE_ERROR, " CSITX: ERROR: Enqueue Frame to Driver failed !!!\n");
                }
    
                /* Starts FVID2 on initial frame */
                if ((vx_status)VX_SUCCESS == status)
                {
                    if (0U == prms->steady_state_started)
                    {
                        /* start all driver instances in the node */
                        for (instIdx = 0U ; instIdx < prms->numOfInstUsed ; instIdx++)
                        {
                            fvid2_status = Fvid2_start(prms->instParams[instIdx].drvHandle, NULL);
                            if (FVID2_SOK != fvid2_status)
                            {
                                status = (vx_status)VX_FAILURE;
                                VX_PRINT(VX_ZONE_ERROR, " CSITX: ERROR: Could not start FVID2 !!!\n");
                                break;
                            }
                        }
    
                        if((vx_status)VX_SUCCESS == status)
                        {
                            prms->steady_state_started = 1;
                        }
                    }
                }
    
                /* Pends until a frame is available then dequeue frames from csitx driver */
                if ((vx_status)VX_SUCCESS == status)
                {
                    tivx_obj_desc_t *tmp_desc[TIVX_CSITX_MAX_CH] = {NULL};
    
                    uint32_t is_all_ch_frame_available = 0;
    
                    for(chId = 0U ; chId < prms->numCh ; chId++)
                    {
                        tmp_desc[chId] = NULL;
                    }
    
                    while(is_all_ch_frame_available == 0U)
                    {
                        is_all_ch_frame_available = 1;
                        for(chId = 0U ; chId < prms->numCh ; chId++)
                        {
                            tivxQueuePeek(&prms->pendingFrameQ[chId], (uintptr_t*)&tmp_desc[chId]);
                            if(NULL==tmp_desc[chId])
                            {
                                is_all_ch_frame_available = 0;
                            }
                        }
    
                        if(is_all_ch_frame_available == 0U)
                        {
                            tivxEventWait(prms->frame_available, TIVX_EVENT_TIMEOUT_WAIT_FOREVER);
    
                            for (instIdx = 0U ; instIdx < prms->numOfInstUsed ; instIdx++)
                            {
                                instParams = &prms->instParams[instIdx];
                                fvid2_status = Fvid2_dequeue(instParams->drvHandle,
                                                             &frmList,
                                                             0,
                                                             FVID2_TIMEOUT_NONE);
    
                                if(FVID2_SOK == fvid2_status)
                                {
                                    for(frmIdx=0; frmIdx < frmList.numFrames; frmIdx++)
                                    {
                                        fvid2Frame = frmList.frames[frmIdx];
                                        chId = tivxCsitxGetNodeChannelNum(
                                                            prms,
                                                            instIdx,
                                                            fvid2Frame->chNum);
                                        desc = (tivx_obj_desc_object_array_t *)fvid2Frame->appData;
    
                                        tivxQueuePut(&prms->freeFvid2FrameQ[chId], (uintptr_t)fvid2Frame, TIVX_EVENT_TIMEOUT_NO_WAIT);
                                        tivxQueuePut(&prms->pendingFrameQ[chId], (uintptr_t)desc, TIVX_EVENT_TIMEOUT_NO_WAIT);
                                    }
                                }
                                else if (fvid2_status == FVID2_ENO_MORE_BUFFERS)
                                {
                                    /* continue: move onto next driver instance
                                      within node as current driver instance did
                                      not generate this CB */
                                }
                                else
                                {
                                    if (FVID2_EAGAIN != fvid2_status)
                                    {
                                        status = (vx_status)VX_FAILURE;
                                        VX_PRINT(VX_ZONE_ERROR,
                                            " CSITX: ERROR: FVID2 Dequeue failed !!!\n");
                                    }
                                }
                            }
                        }
                    }
    
                    for(chId = 0U ; chId < prms->numCh ; chId++)
                    {
                        tivxQueueGet(&prms->pendingFrameQ[chId], (uintptr_t*)&tmp_desc[chId], TIVX_EVENT_TIMEOUT_NO_WAIT);
                    }
                    /* all values in tmp_desc[] should be same */
                    obj_desc[TIVX_KERNEL_CSITX_INPUT_IDX] = (tivx_obj_desc_t *)tmp_desc[0];
                }
            }
            /* Pipe-up state: only provides a buffer; does not receive a buffer */
            else
            {
                status = tivxCsitxEnqueueFrameToDriver(input_desc, prms);
            }
        }
    
        return status;
    }
    
    static vx_status VX_CALLBACK tivxCsitxCreate(
           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;
        tivx_obj_desc_user_data_object_t *configuration_desc;
        tivx_obj_desc_object_array_t *input_desc;
        tivxCsitxParams *prms = NULL;
        uint32_t chId, bufId, instIdx;
        tivxCsitxInstParams *instParams;
    
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug5: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
    
        if ( (num_params != TIVX_KERNEL_CSITX_MAX_PARAMS)
            || (NULL == obj_desc[TIVX_KERNEL_CSITX_CONFIGURATION_IDX])
            || (NULL == obj_desc[TIVX_KERNEL_CSITX_INPUT_IDX])
        )
        {
            status = (vx_status)VX_FAILURE;
        }
        else
        {
            configuration_desc = (tivx_obj_desc_user_data_object_t *)obj_desc[TIVX_KERNEL_CSITX_CONFIGURATION_IDX];
            input_desc = (tivx_obj_desc_object_array_t *)obj_desc[TIVX_KERNEL_CSITX_INPUT_IDX];
    
            prms = tivxMemAlloc(sizeof(tivxCsitxParams), (vx_enum)TIVX_MEM_EXTERNAL);
    
            if (NULL != prms)
            {
                memset(prms, 0, sizeof(tivxCsitxParams));
            }
            else
            {
                VX_PRINT(VX_ZONE_ERROR, " CSITX: ERROR: Could allocate memory !!!\n");
                status = (vx_status)VX_ERROR_NO_MEMORY;
            }
    
            if ((vx_status)VX_SUCCESS == status)
            {
                /* Initialize steady_state_started to 0 */
                prms->steady_state_started = 0;
    
                /* Set number of channels to number of items in input object array */
                prms->numCh = (uint8_t)input_desc->num_items;
    
                if (prms->numCh > TIVX_CSITX_MAX_CH)
                {
                    status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
                    VX_PRINT(VX_ZONE_ERROR, "Object descriptor number of channels exceeds max value allowed by csitx!!!\r\n");
                }
            }
    
            /* Setting CSITX transmit parameters */
            if ((vx_status)VX_SUCCESS == status)
            {
                tivxGetObjDescList(input_desc->obj_desc_id, (tivx_obj_desc_t **)prms->img_obj_desc,
                               prms->numCh);
    
                tivxCsitxSetCreateParams(prms, configuration_desc);
            }
    
            /* Creating frame available event */
            if ((vx_status)VX_SUCCESS == status)
            {
                status = tivxEventCreate(&prms->frame_available);
    
                if ((vx_status)VX_SUCCESS != status)
                {
                    VX_PRINT(VX_ZONE_ERROR, "Event creation failed in csitx!!!\r\n");
                }
            }
    
            /* Creating FVID2 handle */
            if ((vx_status)VX_SUCCESS == status)
            {
                for (instIdx = 0U ; instIdx < prms->numOfInstUsed ; instIdx++)
                {
                    instParams = &prms->instParams[instIdx];
                    Fvid2CbParams_init(&instParams->drvCbPrms);
    
                    instParams->drvCbPrms.cbFxn   = (Fvid2_CbFxn) &csitxDrvCallback;
                    instParams->drvCbPrms.appData = prms;
    
                    instParams->drvHandle = Fvid2_create(CSITX_TX_DRV_ID,
                                                         instParams->instId,
                                                         &instParams->createPrms,
                                                         &instParams->createStatus,
                                                         &instParams->drvCbPrms);
    
                    if ((NULL == instParams->drvHandle) ||
                        (instParams->createStatus.retVal != FVID2_SOK))
                    {
                        VX_PRINT(VX_ZONE_ERROR, ": Csitx Create Failed!!!\r\n");
                        status = (vx_status)VX_FAILURE;
                    }
                }
            }
    
            /* Creating FVID2 frame Q */
            if ((vx_status)VX_SUCCESS == status)
            {
                for(chId = 0u ; chId < prms->numCh ; chId++)
                {
                    status = tivxQueueCreate(&prms->freeFvid2FrameQ[chId], TIVX_CSITX_MAX_NUM_BUFS, prms->fvid2_free_q_mem[chId], 0);
    
                    if ((vx_status)VX_SUCCESS != status)
                    {
                        VX_PRINT(VX_ZONE_ERROR, ": Csitx free queue create failed!!!\r\n");
                        break;
                    }
    
                    for(bufId = 0u ; bufId < (TIVX_CSITX_MAX_NUM_BUFS) ; bufId++)
                    {
                        tivxQueuePut(&prms->freeFvid2FrameQ[chId], (uintptr_t)&prms->fvid2Frames[chId][bufId], TIVX_EVENT_TIMEOUT_NO_WAIT);
                    }
                }
            }
    
            /* Creating pending frame Q */
            if ((vx_status)VX_SUCCESS == status)
            {
                for(chId = 0U ; chId < prms->numCh ; chId++)
                {
                    status = tivxQueueCreate(&prms->pendingFrameQ[chId], TIVX_CSITX_MAX_NUM_BUFS, prms->pending_frame_free_q_mem[chId], 0);
    
                    if ((vx_status)VX_SUCCESS != status)
                    {
                        VX_PRINT(VX_ZONE_ERROR, ": Csitx pending queue create failed!!!\r\n");
                        break;
                    }
                }
            }
    
            if ((vx_status)VX_SUCCESS == status)
            {
                tivxSetTargetKernelInstanceContext(kernel, prms, sizeof(tivxCsitxParams));
            }
            else if (NULL != prms)
            {
                for (instIdx = 0U ; instIdx < prms->numOfInstUsed ; instIdx++)
                {
                    instParams = &prms->instParams[instIdx];
                    if (NULL != instParams->drvHandle)
                    {
                        Fvid2_delete(instParams->drvHandle, NULL);
                        instParams->drvHandle = NULL;
                    }
                }
    
                if (NULL != prms->frame_available)
                {
                    tivxEventDelete(&prms->frame_available);
                }
    
                tivxMemFree(prms, sizeof(tivxCsitxParams), (vx_enum)TIVX_MEM_EXTERNAL);
            }
            else
            {
                /* do nothing */
            }
        }
    
        return status;
    }
    
    static void tivxCsitxPrintStatus(tivxCsitxInstParams *prms)
    {
        int32_t fvid2_status;
        uint32_t cnt;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug16: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        if (NULL != prms)
        {
            fvid2_status = Fvid2_control(prms->drvHandle,
                                    IOCTL_CSITX_GET_INST_STATUS,
                                    &prms->csitxStatus,
                                    NULL);
            if (FVID2_SOK == fvid2_status)
            {
                printf(   "==========================================================\r\n");
                printf(
                          " Csitx Status: Instance|%d\r\n", prms->instId);
                printf(
                          "==========================================================\r\n");
                printf(
                          " FIFO Overflow Count: %d\r\n",
                          prms->csitxStatus.overflowCount);
                printf(
                    "  Channel Num | Frame Queue Count |"
                    " Frame De-queue Count | Frame Repeat Count |\n");
                for(cnt = 0U ; cnt < prms->numCh ; cnt ++)
                {
                    printf(
                          "\t\t%d|\t\t%d|\t\t%d|\t\t%d|\n",
                          cnt,
                          prms->csitxStatus.queueCount[cnt],
                          prms->csitxStatus.dequeueCount[cnt],
                          prms->csitxStatus.frmRepeatCount[cnt]);
                }
            }
            else
            {
                VX_PRINT(VX_ZONE_ERROR, " CSITX: ERROR: FVID2 Control failed !!!\n");
            }
        }
    }
    
    
    static vx_status VX_CALLBACK tivxCsitxDelete(
           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;
        int32_t fvid2_status = FVID2_SOK;
        tivxCsitxParams *prms = NULL;
        static Fvid2_FrameList frmList;
        uint32_t size, chId, instIdx;
        tivxCsitxInstParams *instParams;
    
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug6: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        if ( (num_params != TIVX_KERNEL_CSITX_MAX_PARAMS)
            || (NULL == obj_desc[TIVX_KERNEL_CSITX_CONFIGURATION_IDX])
            || (NULL == obj_desc[TIVX_KERNEL_CSITX_INPUT_IDX])
        )
        {
            status = (vx_status)VX_FAILURE;
        }
        else
        {
            status = tivxGetTargetKernelInstanceContext(kernel, (void **)&prms, &size);
    
            if ((vx_status)VX_SUCCESS != status)
            {
                VX_PRINT(VX_ZONE_ERROR, " CSITX: ERROR: Could not obtain kernel instance context !!!\n");
            }
    
            if(NULL == prms)
            {
                VX_PRINT(VX_ZONE_ERROR, "Kernel instance context is NULL!!!\n");
                status = (vx_status)VX_FAILURE;
            }
    
            if ((vx_status)VX_SUCCESS == status)
            {
    
                for (instIdx = 0U ; instIdx < prms->numOfInstUsed ; instIdx++)
                {
                    instParams = &prms->instParams[instIdx];
                    /* Stopping FVID2 Csitx */
                    if ((vx_status)VX_SUCCESS == status)
                    {
                        fvid2_status = Fvid2_stop(instParams->drvHandle, NULL);
    
                        if (FVID2_SOK != fvid2_status)
                        {
                            status = (vx_status)VX_FAILURE;
                            VX_PRINT(VX_ZONE_ERROR, " CSITX: ERROR: FVID2 Csitx not stopped !!!\n");
                        }
                    }
    
                    /* Dequeue all the request from the driver */
                    if ((vx_status)VX_SUCCESS == status)
                    {
                        Fvid2FrameList_init(&frmList);
                        do
                        {
                            fvid2_status = Fvid2_dequeue(
                                instParams->drvHandle,
                                &frmList,
                                0,
                                FVID2_TIMEOUT_NONE);
                        } while (FVID2_SOK == fvid2_status);
    
                        if (FVID2_ENO_MORE_BUFFERS != fvid2_status)
                        {
                            VX_PRINT(VX_ZONE_ERROR, " CSITX: ERROR: FVID2 Csitx Dequeue Failed !!!\n");
                            status = (vx_status)VX_FAILURE;
                        }
                    }
    
                    if ((vx_status)VX_SUCCESS == status)
                    {
                        tivxCsitxPrintStatus(instParams);
                    }
    
                    /* Deleting FVID2 handle */
                    if ((vx_status)VX_SUCCESS == status)
                    {
                        fvid2_status = Fvid2_delete(instParams->drvHandle, NULL);
    
                        if (FVID2_SOK != fvid2_status)
                        {
                            status = (vx_status)VX_FAILURE;
                            VX_PRINT(VX_ZONE_ERROR, " CSITX: ERROR: FVID2 Delete Failed !!!\n");
                        }
                    }
    
                    /* Free-ing kernel instance params */
                    if ( ((vx_status)VX_SUCCESS == status))
                    {
                        instParams->drvHandle = NULL;
    
                        if (sizeof(tivxCsitxParams) == size)
                        {
                            tivxMemFree(prms, sizeof(tivxCsitxParams), (vx_enum)TIVX_MEM_EXTERNAL);
                        }
                    }
                }
            }
    
            /* Deleting FVID2 frame Q */
            if ((vx_status)VX_SUCCESS == status)
            {
                for(chId = 0U; chId < prms->numCh ; chId++)
                {
                    tivxQueueDelete(&prms->freeFvid2FrameQ[chId]);
                }
            }
    
            /* Deleting pending frame Q */
            if ((vx_status)VX_SUCCESS == status)
            {
                for(chId= 0U ; chId < prms->numCh ; chId++)
                {
                    tivxQueueDelete(&prms->pendingFrameQ[chId]);
                }
            }
    
            /* Deleting event */
            if ((vx_status)VX_SUCCESS == status)
            {
                tivxEventDelete(&prms->frame_available);
            }
        }
    
        return status;
    }
    
    static void tivxCsitxCopyStatistics(tivxCsitxParams *prms,
        tivx_csitx_statistics_t *csitx_status_prms)
    {
        uint32_t i, instIdx;
        tivxCsitxInstParams *instParams;
    
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug4: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        for (instIdx = 0U ; instIdx < prms->numOfInstUsed ; instIdx++)
        {
            instParams = &prms->instParams[instIdx];
            for (i = 0U ; i < instParams->numCh ; i++)
            {
                csitx_status_prms->queueCount[instIdx][i]     = instParams->csitxStatus.queueCount[i];
                csitx_status_prms->dequeueCount[instIdx][i]   = instParams->csitxStatus.dequeueCount[i];
                csitx_status_prms->frmRepeatCount[instIdx][i]      = instParams->csitxStatus.frmRepeatCount[i];
            }
            csitx_status_prms->overflowCount[instIdx]         = instParams->csitxStatus.overflowCount;
        }
    }
    
    static vx_status tivxCsitxGetStatistics(tivxCsitxParams *prms,
        tivx_obj_desc_user_data_object_t *usr_data_obj)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        tivx_csitx_statistics_t *csitx_status_prms = NULL;
        void *target_ptr;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug14: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        if (NULL != usr_data_obj)
        {
            target_ptr = tivxMemShared2TargetPtr(&usr_data_obj->mem_ptr);
    
            tivxCheckStatus(&status, tivxMemBufferMap(target_ptr, usr_data_obj->mem_size,
                (vx_enum)VX_MEMORY_TYPE_HOST, (vx_enum)VX_WRITE_ONLY));
    
            if (sizeof(tivx_csitx_statistics_t) ==
                    usr_data_obj->mem_size)
            {
                csitx_status_prms = (tivx_csitx_statistics_t *)target_ptr;
    
                tivxCsitxCopyStatistics(prms, csitx_status_prms);
            }
            else
            {
                VX_PRINT(VX_ZONE_ERROR, "Invalid Size \n");
                status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
            }
    
            tivxCheckStatus(&status, tivxMemBufferUnmap(target_ptr, usr_data_obj->mem_size,
                (vx_enum)VX_MEMORY_TYPE_HOST, (vx_enum)VX_WRITE_ONLY));
        }
        else
        {
            VX_PRINT(VX_ZONE_ERROR, "User Data Object is NULL \n");
            status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
        }
    
        return (status);
    }
    
    static vx_status VX_CALLBACK tivxCsitxControl(
           tivx_target_kernel_instance kernel,
           uint32_t node_cmd_id, tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        int32_t fvid2_status = FVID2_SOK;
        uint32_t             size, instIdx;
        tivxCsitxParams *prms = NULL;
        tivxCsitxInstParams *instParams;
    
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug3: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        status = tivxGetTargetKernelInstanceContext(kernel, (void **)&prms, &size);
    
        if ((vx_status)VX_SUCCESS != status)
        {
            VX_PRINT(VX_ZONE_ERROR, "Failed to Get Target Kernel Instance Context\n");
        }
        else if ((NULL == prms) ||
            (sizeof(tivxCsitxParams) != size))
        {
            VX_PRINT(VX_ZONE_ERROR, "Invalid Object Size\n");
            status = (vx_status)VX_FAILURE;
        }
        else
        {
            /* do nothing */
        }
    
        if ((vx_status)VX_SUCCESS == status)
        {
            switch (node_cmd_id)
            {
                case TIVX_CSITX_PRINT_STATISTICS:
                {
                    for (instIdx = 0U ; instIdx < prms->numOfInstUsed ; instIdx++)
                    {
                        instParams = &prms->instParams[instIdx];
                        tivxCsitxPrintStatus(instParams);
                    }
                    break;
                }
                case TIVX_CSITX_GET_STATISTICS:
                {
                    if (NULL != obj_desc[0])
                    {
                        for (instIdx = 0U ; instIdx < prms->numOfInstUsed ; instIdx++)
                        {
                            instParams = &prms->instParams[instIdx];
                            fvid2_status = Fvid2_control(instParams->drvHandle,
                                                    IOCTL_CSITX_GET_INST_STATUS,
                                                    &instParams->csitxStatus,
                                                    NULL);
                            if (FVID2_SOK != fvid2_status)
                            {
                                VX_PRINT(VX_ZONE_ERROR, "Get status returned failure\n");
                                status = (vx_status)VX_FAILURE;
                                break;
                            }
                        }
                        if (FVID2_SOK == fvid2_status)
                        {
                            status = tivxCsitxGetStatistics(prms,
                                (tivx_obj_desc_user_data_object_t *)obj_desc[0U]);
                            if ((vx_status)VX_SUCCESS != status)
                            {
                                VX_PRINT(VX_ZONE_ERROR, "Get status failed\n");
                                status = (vx_status)VX_FAILURE;
                            }
    
                        }
                    }
                    else
                    {
                        VX_PRINT(VX_ZONE_ERROR, "User data object was NULL\n");
                        status = (vx_status)VX_FAILURE;
                    }
                    break;
                }
                default:
                {
                    VX_PRINT(VX_ZONE_ERROR, "Invalid Command Id\n");
                    status = (vx_status)VX_FAILURE;
                    break;
                }
            }
        }
        return status;
    }
    
    
    void tivxAddTargetKernelCsitx(void)
    {
        char target_name[TIVX_TARGET_MAX_NAME];
        vx_enum self_cpu;
    
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug2: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        self_cpu = tivxGetSelfCpuId();
    
        if (self_cpu == (vx_enum)TIVX_CPU_ID_MCU2_0)
        {
            strncpy(target_name, TIVX_TARGET_CSITX, TIVX_TARGET_MAX_NAME);
    
            vx_csitx_target_kernel = tivxAddTargetKernelByName(
                                TIVX_KERNEL_CSITX_NAME,
                                target_name,
                                tivxCsitxProcess,
                                tivxCsitxCreate,
                                tivxCsitxDelete,
                                tivxCsitxControl,
                                NULL);
        }
    }
    
    void tivxRemoveTargetKernelCsitx(void)
    {
        vx_status status = (vx_status)VX_SUCCESS;
    
        status = tivxRemoveTargetKernel(vx_csitx_target_kernel);
        if ((vx_status)VX_SUCCESS == status)
        {
            vx_csitx_target_kernel = NULL;
        }
    }
    
    static void tivxCsitxGetChannelIndices(tivxCsitxParams *prms,
                                             uint32_t instId,
                                             uint32_t *startChIdx,
                                             uint32_t *endChIdx)
    {
        uint32_t instIdx;
    
        *startChIdx = 0U;
        *endChIdx   = 0U;
        VX_PRINT(VX_ZONE_ERROR, "cyhdebug12: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        for (instIdx = 0U ; instIdx < prms->numOfInstUsed ; instIdx++)
        {
            /* get start channel ID here */
            if (instIdx == instId)
            {
                break;
            }
            else
            {
                *startChIdx += prms->instParams[instIdx].numCh;
            }
        }
        /* Get last channel ID here */
        if (instIdx < prms->numOfInstUsed)
        {
            *endChIdx = *startChIdx + prms->instParams[instIdx].numCh;
        }
    }
    
    static uint32_t tivxCsitxGetNodeChannelNum(tivxCsitxParams *prms,
                                                 uint32_t instId,
                                                 uint32_t chId)
    {
        uint32_t instIdx, chIdx = 0U;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug13: CSITX: %s:%d+++++++++++++++++++++++++++++++++++++++++++++++++++++++!!!\n", __func__, __LINE__);
        /* Get addition of all the channels processed on all previous driver instances */
        for (instIdx = 0U ; instIdx < prms->numOfInstUsed ; instIdx++)
        {
            if (instIdx == instId)
            {
                break;
            }
            else
            {
                chIdx += prms->instParams[instIdx].numCh;
            }
        }
        chIdx += chId;
    
        return (chIdx);
    }
    
    
    

    /*
     * Copyright (c) 2012-2016 The Khronos Group Inc.
     *
     * Permission is hereby granted, free of charge, to any person obtaining a
     * copy of this software and/or associated documentation files (the
     * "Materials"), to deal in the Materials without restriction, including
     * without limitation the rights to use, copy, modify, merge, publish,
     * distribute, sublicense, and/or sell copies of the Materials, and to
     * permit persons to whom the Materials are furnished to do so, subject to
     * the following conditions:
     *
     * The above copyright notice and this permission notice shall be included
     * in all copies or substantial portions of the Materials.
     *
     * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
     * KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
     * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
     *    https://www.khronos.org/registry/
     *
     * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
     * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
     */
    
    
    
    #include <vx_internal.h>
    
    static vx_bool ownIsValidBorderMode(vx_enum mode);
    static vx_status ownContextGetUniqueKernels( vx_context context, vx_kernel_info_t *kernel_info, uint32_t max_kernels);
    static vx_status ownContextCreateCmdObj(vx_context context);
    static vx_status ownContextDeleteCmdObj(vx_context context);
    
    
    static const vx_char g_context_implmentation_name[VX_MAX_IMPLEMENTATION_NAME] = "tiovx";
    
    static const vx_char g_context_default_load_module[][TIVX_MODULE_MAX_NAME] = {TIVX_MODULE_NAME_OPENVX_CORE};
    
    static const vx_char g_context_extensions[] = " ";
    
    static vx_context g_context_handle = NULL;
    
    static tivx_context_t g_context_obj;
    
    static vx_bool ownIsValidBorderMode(vx_enum mode)
    {
        vx_bool ret = (vx_bool)vx_true_e;
        switch (mode)
        {
            case (vx_enum)VX_BORDER_UNDEFINED:
            case (vx_enum)VX_BORDER_CONSTANT:
            case (vx_enum)VX_BORDER_REPLICATE:
                break;
            default:
                ret = (vx_bool)vx_false_e;
                break;
        }
        return ret;
    }
    
    /*
     * \brief Fill 'kernel_info' with valid unique kernels info from this context
     *
     *        If more than 'max_kernels' found, the return with error
     */
    static vx_status ownContextGetUniqueKernels( vx_context context, vx_kernel_info_t *kernel_info, uint32_t max_kernels)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        vx_kernel kernel;
        uint32_t num_kernel_info = 0, idx;
    
        if( ownIsValidContext(context) == (vx_bool)vx_false_e)
        {
            VX_PRINT(VX_ZONE_ERROR,"Context is invalid\n");
            status = (vx_status)VX_ERROR_INVALID_REFERENCE;
        }
        else
        {
            ownContextLock(context);
    
            for(idx=0; idx<dimof(context->kerneltable); idx++)
            {
                kernel = context->kerneltable[idx];
                if(ownIsValidSpecificReference(&kernel->base, (vx_enum)VX_TYPE_KERNEL) == (vx_bool)vx_true_e)
                {
                    kernel_info[num_kernel_info].enumeration = kernel->enumeration;
                    strncpy(kernel_info[num_kernel_info].name, kernel->name, VX_MAX_KERNEL_NAME-1U);
                    kernel_info[num_kernel_info].name[VX_MAX_KERNEL_NAME-1U] = '\0';
                    num_kernel_info++;
                }
                if(num_kernel_info > max_kernels)
                {
                    VX_PRINT(VX_ZONE_ERROR,"num kernel info is greater than max kernels\n");
                    status = (vx_status)VX_ERROR_NO_RESOURCES;
                    break;
                }
            }
    
            ownContextUnlock(context);
        }
    
        return status;
    }
    
    static vx_status ownContextCreateCmdObj(vx_context context)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        uint32_t    i;
    
        /* Create the free and pend queues. */
        status = tivxQueueCreate(&context->free_queue,
                                 TIVX_MAX_CTRL_CMD_OBJECTS,
                                 context->free_queue_memory,
                                 0); /* non-blocking */
    
        if (status == (vx_status)VX_SUCCESS)
        {
            status = tivxQueueCreate(&context->pend_queue,
                                     TIVX_MAX_CTRL_CMD_OBJECTS,
                                     context->pend_queue_memory,
                                     0); /* non-blocking */
    
            if (status!=(vx_status)VX_SUCCESS)
            {
                tivxQueueDelete(&context->free_queue);
            }
        }
    
        if (status == (vx_status)VX_SUCCESS)
        {
            /* Allocate {control object, event} pair. */
            for (i = 0; i < TIVX_MAX_CTRL_CMD_OBJECTS; i++)
            {
                context->obj_desc_cmd[i] = NULL;
                context->cmd_ack_event[i] = NULL;
            }
    
            for (i = 0; i < TIVX_MAX_CTRL_CMD_OBJECTS; i++)
            {
                context->obj_desc_cmd[i] = (tivx_obj_desc_cmd_t*)
                    tivxObjDescAlloc((vx_enum)TIVX_OBJ_DESC_CMD, NULL);
    
                if (context->obj_desc_cmd[i] != NULL)
                {
                    status = tivxEventCreate(&context->cmd_ack_event[i]);
    
                    if (status != (vx_status)VX_SUCCESS)
                    {
                        VX_PRINT(VX_ZONE_ERROR,
                                 "context object event [%d] allocation failed\n", i);
                        status = (vx_status)VX_ERROR_NO_RESOURCES;
                        break;
                    }
                }
                else
                {
                    VX_PRINT(VX_ZONE_ERROR,
                             "context object descriptor [%d] allocation failed\n", i);
                    status = (vx_status)VX_ERROR_NO_RESOURCES;
                    break;
                }
            }
    
            if (status != (vx_status)VX_SUCCESS)
            {
                /* Release any allocated resources. */
                for (i = 0; i < TIVX_MAX_CTRL_CMD_OBJECTS; i++)
                {
                    if (context->obj_desc_cmd[i] != NULL)
                    {
                        tivxObjDescFree((tivx_obj_desc_t**)&context->obj_desc_cmd[i]);
                    }
    
                    if (context->cmd_ack_event[i] != NULL)
                    {
                        tivxEventDelete(&context->cmd_ack_event[i]);
                    }
                }
    
                /* Delete the queues. No error checks are being made since we know
                 * that the queues have been created successfully above.
                 */
                tivxQueueDelete(&context->free_queue);
                tivxQueueDelete(&context->pend_queue);
            }
        }
    
        if (status==(vx_status)VX_SUCCESS)
        {
            /* Enqueue all event element index's to free queue */
            for (i = 0; i < TIVX_MAX_CTRL_CMD_OBJECTS; i++)
            {
                /* This call wont fail since number of elements being inserted are equal to
                 * queue depth, hence not doing any error checks
                 */
                tivxQueuePut(&context->free_queue,
                             i,
                             TIVX_EVENT_TIMEOUT_NO_WAIT);
            }
        }
    
        return status;
    }
    
    static vx_status ownContextDeleteCmdObj(vx_context context)
    {
        vx_status status  = (vx_status)VX_SUCCESS;
        vx_status status1 = (vx_status)VX_SUCCESS;
        uint32_t  i;
    
        /* Release any allocated resources. */
        for (i = 0; i < TIVX_MAX_CTRL_CMD_OBJECTS; i++)
        {
            if (context->obj_desc_cmd[i] != NULL)
            {
                status1 = tivxObjDescFree((tivx_obj_desc_t**)&context->obj_desc_cmd[i]);
    
                if (status1 != (vx_status)VX_SUCCESS)
                {
                    VX_PRINT(VX_ZONE_ERROR,
                             "Context control comand memory [%d] free-ing failed\n",
                             i);
                    status = status1;
                }
            }
    
            if (context->cmd_ack_event[i] != NULL)
            {
                status1 = tivxEventDelete(&context->cmd_ack_event[i]);
    
                if (status1 != (vx_status)VX_SUCCESS)
                {
                    VX_PRINT(VX_ZONE_ERROR,
                             "Context control comand event [%d] deletion failed\n",
                             i);
    
                    if (status == (vx_status)VX_SUCCESS)
                    {
                        status = status1;
                    }
                }
            }
        }
    
        status1 = tivxQueueDelete(&context->free_queue);
    
        if (status1 != (vx_status)VX_SUCCESS)
        {
            VX_PRINT(VX_ZONE_ERROR,
                     "Context control command free queue deletion failed\n");
    
            if (status == (vx_status)VX_SUCCESS)
            {
                status = status1;
            }
        }
    
        status1 = tivxQueueDelete(&context->pend_queue);
    
        if (status1 != (vx_status)VX_SUCCESS)
        {
            VX_PRINT(VX_ZONE_ERROR,
                     "Context control command pend queue deletion failed\n");
    
            if (status == (vx_status)VX_SUCCESS)
            {
                status = status1;
            }
        }
    
        return status;
    }
    
    static vx_status ownDeallocateUserKernelId(vx_context context, vx_kernel kernel)
    {
        vx_status status = (vx_status)VX_ERROR_INVALID_REFERENCE;
    
        if ( (ownIsValidContext(context) == (vx_bool)vx_true_e) &&
             (ownIsValidSpecificReference(&kernel->base, (vx_enum)VX_TYPE_KERNEL) == (vx_bool)vx_true_e) )
        {
            status = (vx_status)VX_SUCCESS;
    
            if ( (kernel->enumeration >= (int32_t)VX_KERNEL_BASE(VX_ID_USER, 0U)) &&
                 (kernel->enumeration <  (int32_t)(VX_KERNEL_BASE(VX_ID_USER, 0U) + (int32_t)TIVX_MAX_KERNEL_ID)) )
            {
                uint32_t dynamic_user_kernel_idx = kernel->enumeration - VX_KERNEL_BASE(VX_ID_USER, 0U);
    
                context->is_dynamic_user_kernel_id_used[dynamic_user_kernel_idx] = (vx_bool)vx_false_e;
            }
        }
    
        return status;
    }
    
    vx_status ownContextFlushCmdPendQueue(vx_context context)
    {
        vx_status   status = (vx_status)VX_SUCCESS;
        vx_bool     isEmpty;
    
        isEmpty = tivxQueueIsEmpty(&context->pend_queue);
    
        if (isEmpty == (vx_bool)vx_false_e)
        {
            uintptr_t   obj_id;
    
            while (status == (vx_status)VX_SUCCESS)
            {
                status = tivxQueueGet(&context->pend_queue,
                                      &obj_id,
                                      TIVX_EVENT_TIMEOUT_NO_WAIT);
    
                if (status == (vx_status)VX_SUCCESS)
                {
                    vx_status   status1;
    
                    status1 = tivxQueuePut(&context->free_queue,
                                           obj_id,
                                           TIVX_EVENT_TIMEOUT_NO_WAIT);
    
                    if (status1 != (vx_status)VX_SUCCESS)
                    {
                        VX_PRINT(VX_ZONE_ERROR,
                                 "tivxQueuePut(free_queue) failed\n");
                        status = status1;
                    }
                }
            }
        }
    
        return status;
    }
    
    vx_status ownContextLock(vx_context context)
    {
        return tivxMutexLock(context->lock);
    }
    
    vx_status ownContextUnlock(vx_context context)
    {
        return tivxMutexUnlock(context->lock);
    }
    
    vx_bool ownAddReferenceToContext(vx_context context, vx_reference ref)
    {
        uint32_t ref_idx;
        vx_bool is_success = (vx_bool)vx_false_e;
    
        if (ownIsValidContext(context)==(vx_bool)vx_true_e)
        {
            ownContextLock(context);
    
            for(ref_idx=0; ref_idx < dimof(context->reftable); ref_idx++)
            {
                if(context->reftable[ref_idx]==NULL)
                {
                    char name[VX_MAX_REFERENCE_NAME];
    
                    context->reftable[ref_idx] = ref;
                    context->num_references++;
                    is_success = (vx_bool)vx_true_e;
    
                    tivxLogResourceAlloc("TIVX_CONTEXT_MAX_REFERENCES", 1);
    
                    switch(ref->type)
                    {
                        case (vx_enum)VX_TYPE_DELAY:
                            snprintf(name, VX_MAX_REFERENCE_NAME, "delay_%d", ref_idx);
                            break;
                        case (vx_enum)VX_TYPE_LUT:
                            snprintf(name, VX_MAX_REFERENCE_NAME, "lut_%d", ref_idx);
                            break;
                        case (vx_enum)VX_TYPE_DISTRIBUTION:
                            snprintf(name, VX_MAX_REFERENCE_NAME, "distribution_%d", ref_idx);
                            break;
                        case (vx_enum)VX_TYPE_PYRAMID:
                            snprintf(name, VX_MAX_REFERENCE_NAME, "pyramid_%d", ref_idx);
                            break;
                        case (vx_enum)VX_TYPE_THRESHOLD:
                            snprintf(name, VX_MAX_REFERENCE_NAME, "threshold_%d", ref_idx);
                            break;
                        case (vx_enum)VX_TYPE_MATRIX:
                            snprintf(name, VX_MAX_REFERENCE_NAME, "matrix_%d", ref_idx);
                            break;
                        case (vx_enum)VX_TYPE_CONVOLUTION:
                            snprintf(name, VX_MAX_REFERENCE_NAME, "convolution_%d", ref_idx);
                            break;
                        case (vx_enum)VX_TYPE_SCALAR:
                            snprintf(name, VX_MAX_REFERENCE_NAME, "scalar_%d", ref_idx);
                            break;
                        case (vx_enum)VX_TYPE_ARRAY:
                            snprintf(name, VX_MAX_REFERENCE_NAME, "array_%d", ref_idx);
                            break;
                        case (vx_enum)VX_TYPE_IMAGE:
                            snprintf(name, VX_MAX_REFERENCE_NAME, "image_%d", ref_idx);
                            break;
                        case (vx_enum)VX_TYPE_REMAP:
                            snprintf(name, VX_MAX_REFERENCE_NAME, "remap_%d", ref_idx);
                            break;
                        case (vx_enum)VX_TYPE_OBJECT_ARRAY:
                            snprintf(name, VX_MAX_REFERENCE_NAME, "object_array_%d", ref_idx);
                            break;
                        case (vx_enum)VX_TYPE_NODE:
                            snprintf(name, VX_MAX_REFERENCE_NAME, "node_%d", ref_idx);
                            break;
                        case (vx_enum)VX_TYPE_GRAPH:
                            snprintf(name, VX_MAX_REFERENCE_NAME, "graph_%d", ref_idx);
                            break;
                        case (vx_enum)TIVX_TYPE_DATA_REF_Q:
                            snprintf(name, VX_MAX_REFERENCE_NAME, "data_ref_q_%d", ref_idx);
                            break;
                        case (vx_enum)VX_TYPE_TENSOR:
                            snprintf(name, VX_MAX_REFERENCE_NAME, "tensor_%d", ref_idx);
                            break;
                        case VX_TYPE_USER_DATA_OBJECT:
                            snprintf(name, VX_MAX_REFERENCE_NAME, "user_data_object_%d", ref_idx);
                            break;
                        case TIVX_TYPE_RAW_IMAGE:
                            snprintf(name, VX_MAX_REFERENCE_NAME, "raw_image_%d", ref_idx);
                            break;
                        case TIVX_TYPE_SUPER_NODE:
                            snprintf(name, VX_MAX_REFERENCE_NAME, "super_node_%d", ref_idx);
                            break;
                        default:
                            snprintf(name, VX_MAX_REFERENCE_NAME, "ref_%d", ref_idx);
                            break;
                    }
                    vxSetReferenceName(ref, name);
    
                    break;
                }
            }
    
            if ((vx_bool)vx_false_e == is_success)
            {
                VX_PRINT(VX_ZONE_ERROR, "Max context references exceeded\n");
                VX_PRINT(VX_ZONE_ERROR, "May need to increase the value of TIVX_CONTEXT_MAX_REFERENCES in tiovx/include/TI/tivx_config.h\n");
            }
    
            ownContextUnlock(context);
        }
        return is_success;
    }
    
    vx_bool ownRemoveReferenceFromContext(vx_context context, vx_reference ref)
    {
        uint32_t ref_idx;
        vx_bool is_success = (vx_bool)vx_false_e;
    
        if (ownIsValidContext(context)==(vx_bool)vx_true_e)
        {
            ownContextLock(context);
    
            for(ref_idx=0; ref_idx < dimof(context->reftable); ref_idx++)
            {
                if(context->reftable[ref_idx]==ref)
                {
                    context->reftable[ref_idx] = NULL;
                    context->num_references--;
                    is_success = (vx_bool)vx_true_e;
                    tivxLogResourceFree("TIVX_CONTEXT_MAX_REFERENCES", 1);
                    break;
                }
            }
    
            ownContextUnlock(context);
        }
        return is_success;
    }
    
    vx_bool ownIsValidContext(vx_context context)
    {
        vx_bool ret = (vx_bool)vx_false_e;
        if ((context != NULL) &&
            (context->base.magic == TIVX_MAGIC) &&
            (context->base.type == (vx_enum)VX_TYPE_CONTEXT) &&
            (context->base.context == NULL))
        {
            ret = (vx_bool)vx_true_e; /* this is the top level context */
        }
        return ret;
    }
    
    vx_status ownAddKernelToContext(vx_context context, vx_kernel kernel)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        uint32_t idx;
    
        if(ownIsValidContext(context) == (vx_bool)vx_false_e)
        {
            VX_PRINT(VX_ZONE_ERROR,"Invalid context\n");
            status = (vx_status)VX_ERROR_INVALID_REFERENCE;
        }
        else if (ownIsValidSpecificReference(&kernel->base, (vx_enum)VX_TYPE_KERNEL) == (vx_bool)vx_false_e)
        {
            VX_PRINT(VX_ZONE_ERROR,"Kernel reference is invalid\n");
            status = (vx_status)VX_ERROR_INVALID_REFERENCE;
        }
        else
        {
            ownContextLock(context);
    
            for(idx=0; idx<dimof(context->kerneltable); idx++)
            {
                if ((NULL == context->kerneltable[idx]) && (context->num_unique_kernels < dimof(context->kerneltable)))
                {
                    /* found free entry */
                    context->kerneltable[idx] = kernel;
                    context->num_unique_kernels++;
                    ownIncrementReference(&kernel->base, (vx_enum)VX_INTERNAL);
                    tivxLogResourceAlloc("TIVX_CONTEXT_MAX_KERNELS", 1);
                    break;
                }
            }
            if(idx>=dimof(context->kerneltable))
            {
                /* free entry not found */
                VX_PRINT(VX_ZONE_ERROR,"free entry not found\n");
                VX_PRINT(VX_ZONE_ERROR, "May need to increase the value of TIVX_CONTEXT_MAX_KERNELS in tiovx/include/TI/tivx_config.h\n");
                status = (vx_status)VX_ERROR_NO_RESOURCES;
            }
    
            ownContextUnlock(context);
        }
    
        return status;
    }
    
    vx_status ownRemoveKernelFromContext(vx_context context, vx_kernel kernel)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        uint32_t idx;
    
        if(ownIsValidContext(context) == (vx_bool)vx_false_e)
        {
            VX_PRINT(VX_ZONE_ERROR,"Invalid context\n");
            status = (vx_status)VX_ERROR_INVALID_REFERENCE;
        }
        else if (ownIsValidSpecificReference(&kernel->base, (vx_enum)VX_TYPE_KERNEL) == (vx_bool)vx_false_e)
        {
            VX_PRINT(VX_ZONE_ERROR,"Kernel reference is invalid\n");
            status = (vx_status)VX_ERROR_INVALID_REFERENCE;
        }
        else
        {
            ownContextLock(context);
    
            for(idx=0; idx<dimof(context->kerneltable); idx++)
            {
                if( (context->kerneltable[idx]==kernel) && (context->num_unique_kernels>0U) )
                {
                    /* found kernel entry */
    
                    status = ownDeallocateUserKernelId(context, kernel);
    
                    if ((vx_status)VX_SUCCESS == status)
                    {
                        context->kerneltable[idx] = NULL;
                        context->num_unique_kernels--;
                        tivxLogResourceFree("TIVX_CONTEXT_MAX_KERNELS", 1);
                    }
                    else
                    {
                        VX_PRINT(VX_ZONE_ERROR,"deallocate user kernel id failed\n");
                    }
    
                    break;
                }
            }
            if(idx>=dimof(context->kerneltable))
            {
                /* kernel not found */
                VX_PRINT(VX_ZONE_ERROR,"kernel not found\n");
                status = (vx_status)VX_ERROR_INVALID_REFERENCE;
            }
    
            ownContextUnlock(context);
        }
    
        return status;
    }
    
    vx_status ownIsKernelInContext(vx_context context, vx_enum enumeration, const vx_char string[VX_MAX_KERNEL_NAME], vx_bool *is_found)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        uint32_t idx;
        vx_kernel kernel;
    
        if( (ownIsValidContext(context) == (vx_bool)vx_false_e) || (is_found == NULL) )
        {
            VX_PRINT(VX_ZONE_ERROR,"invalid context\n");
            status = (vx_status)VX_FAILURE;
        }
        else if (NULL == string)
        {
            VX_PRINT(VX_ZONE_ERROR,"provided kernel name was NULL, please provide non-NULL kernel name\n");
            status = (vx_status)VX_FAILURE;
        }
        else
        {
            ownContextLock(context);
    
            *is_found = (vx_bool)vx_false_e;
    
            for(idx=0; idx<dimof(context->kerneltable); idx++)
            {
                kernel = context->kerneltable[idx];
                if((NULL != kernel) &&
                    (ownIsValidSpecificReference( &kernel->base, (vx_enum)VX_TYPE_KERNEL) ==
                        (vx_bool)vx_true_e)
                    &&
                    ( (strncmp(kernel->name, string, VX_MAX_KERNEL_NAME) == 0)
                        ||
                        (kernel->enumeration == enumeration)
                    )
                    )
                {
                    /* found match */
                    *is_found = (vx_bool)vx_true_e;
                    break;
                }
    
            }
    
            ownContextUnlock(context);
        }
    
        return status;
    }
    
    vx_status ownContextSendControlCmd(vx_context context, uint16_t node_obj_desc,
        uint32_t target_id, uint32_t replicated_node_idx, uint32_t node_cmd_id,
        const uint16_t obj_desc_id[], uint32_t num_obj_desc, uint32_t timeout)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        vx_status status1 = (vx_status)VX_SUCCESS;
        uint32_t i;
    
        if((ownIsValidContext(context) == (vx_bool)vx_true_e) &&
           (num_obj_desc < TIVX_CMD_MAX_OBJ_DESCS))
        {
            tivx_obj_desc_cmd_t *obj_desc_cmd;
            tivx_event cmd_ack_event;
            uintptr_t   obj_id;
            uint64_t timestamp = tivxPlatformGetTimeInUsecs()*1000U;
    
            ownContextLock(context);
    
            status = tivxQueueGet(&context->free_queue, &obj_id, TIVX_EVENT_TIMEOUT_NO_WAIT);
    
            if ((status == (vx_status)VX_SUCCESS) && (obj_id < TIVX_MAX_CTRL_CMD_OBJECTS))
            {
                obj_desc_cmd  = context->obj_desc_cmd[obj_id];
                cmd_ack_event = context->cmd_ack_event[obj_id];
    
                tivx_uint64_to_uint32(
                    timestamp,
                    &obj_desc_cmd->timestamp_h,
                    &obj_desc_cmd->timestamp_l
                );
    
                obj_desc_cmd->cmd_id = (vx_enum)TIVX_CMD_NODE_CONTROL;
                obj_desc_cmd->dst_target_id = target_id;
                obj_desc_cmd->src_target_id =
                    (uint32_t)tivxPlatformGetTargetId(TIVX_TARGET_HOST);
                obj_desc_cmd->num_obj_desc = 1u;
                obj_desc_cmd->obj_desc_id[0u] = node_obj_desc;
                obj_desc_cmd->flags = TIVX_CMD_FLAG_SEND_ACK;
                obj_desc_cmd->ack_event_handle = (uint64_t)(uintptr_t)cmd_ack_event;
    
                obj_desc_cmd->replicated_node_idx = (int32_t)replicated_node_idx;
                obj_desc_cmd->node_cmd_id = node_cmd_id;
                obj_desc_cmd->num_cmd_params = num_obj_desc;
    
                for (i = 0; i < num_obj_desc; i ++)
                {
                    obj_desc_cmd->cmd_params_desc_id[i] = obj_desc_id[i];
                }
    
                status = tivxObjDescSend(target_id, obj_desc_cmd->base.obj_desc_id);
    
                if (status == (vx_status)VX_SUCCESS)
                {
                    status = tivxEventWait(cmd_ack_event, timeout);
    
                    if (status == (vx_status)VX_SUCCESS)
                    {
                        if ((vx_status)VX_SUCCESS != (vx_status)obj_desc_cmd->cmd_status)
                        {
                            VX_PRINT(VX_ZONE_ERROR,
                                     "Command ack message returned failure cmd_status: %d\n",
                                     obj_desc_cmd->cmd_status);
                            status = (vx_status)VX_FAILURE;
                        }
    
                        /* Put the object back in the free queue. */
                        status1 = tivxQueuePut(&context->free_queue,
                                               obj_id,
                                               TIVX_EVENT_TIMEOUT_NO_WAIT);
    
                        if (status1 != (vx_status)VX_SUCCESS)
                        {
                            VX_PRINT(VX_ZONE_ERROR,
                                     "Failed to release the object desc id.\n");
                            status = (vx_status)VX_FAILURE;
                        }
                    }
                    else if (status == (vx_status)TIVX_ERROR_EVENT_TIMEOUT)
                    {
                        /* Queue the object into the pend queue for later
                         * action.
                         */
                        status1 = tivxQueuePut(&context->pend_queue,
                                               obj_id,
                                               TIVX_EVENT_TIMEOUT_NO_WAIT);
    
                        if (status1 != (vx_status)VX_SUCCESS)
                        {
                            VX_PRINT(VX_ZONE_ERROR,
                                     "Failed to queue the object desc in pend queue.\n");
                            status = (vx_status)VX_FAILURE;
                        }
                    }
    
                    if (status != (vx_status)VX_SUCCESS)
                    {
                        VX_PRINT(VX_ZONE_ERROR, "tivxEventWait() failed.\n");
                    }
                }
                else
                {
                    if ((vx_status)VX_SUCCESS != (vx_status)obj_desc_cmd->cmd_status)
                    {
                        VX_PRINT(VX_ZONE_ERROR,
                                 "Failed to send object desc\n");
                        status = (vx_status)VX_FAILURE;
                    }
                }
            }
    
            ownContextUnlock(context);
        }
        else
        {
            status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
            if (num_obj_desc >= TIVX_CMD_MAX_OBJ_DESCS)
            {
                VX_PRINT(VX_ZONE_ERROR,
                    "Invalid Number of object desc\n");
            }
            else
            {
                VX_PRINT(VX_ZONE_ERROR,
                    "Invalid Context\n");
            }
        }
    
        return status;
    }
    
    vx_status ownContextSendCmd(vx_context context, uint32_t target_id, uint32_t cmd, uint32_t num_obj_desc, const uint16_t *obj_desc_id, uint32_t timeout)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        vx_status status1 = (vx_status)VX_SUCCESS;
        uint32_t i;
    
        if( (ownIsValidContext(context) == (vx_bool)vx_true_e) && (num_obj_desc < TIVX_CMD_MAX_OBJ_DESCS) )
        {
            tivx_obj_desc_cmd_t *obj_desc_cmd;
            tivx_event cmd_ack_event;
            uintptr_t   obj_id;
            uint64_t timestamp = tivxPlatformGetTimeInUsecs()*1000U;
    
            ownContextLock(context);
    
            status = tivxQueueGet(&context->free_queue, &obj_id, TIVX_EVENT_TIMEOUT_NO_WAIT);
    
            if ((status == (vx_status)VX_SUCCESS) && (obj_id < TIVX_MAX_CTRL_CMD_OBJECTS))
            {
                obj_desc_cmd  = context->obj_desc_cmd[obj_id];
                cmd_ack_event = context->cmd_ack_event[obj_id];
    
                tivx_uint64_to_uint32(
                    timestamp,
                    &obj_desc_cmd->timestamp_h,
                    &obj_desc_cmd->timestamp_l
                );
    
                obj_desc_cmd->cmd_id = cmd;
                obj_desc_cmd->dst_target_id = target_id;
                obj_desc_cmd->src_target_id = (uint32_t)tivxPlatformGetTargetId(TIVX_TARGET_HOST);
                obj_desc_cmd->num_obj_desc = num_obj_desc;
                obj_desc_cmd->flags = TIVX_CMD_FLAG_SEND_ACK;
                obj_desc_cmd->ack_event_handle = (uint64_t)(uintptr_t)cmd_ack_event;
    
                for(i=0; i<num_obj_desc; i++)
                {
                    obj_desc_cmd->obj_desc_id[i] = obj_desc_id[i];
                }
    
                status = tivxObjDescSend(target_id, obj_desc_cmd->base.obj_desc_id);
    			VX_PRINT(VX_ZONE_ERROR,"cyhdebug: run tivxObjDescSend: status: %d---------------------\n", status);
    
                if (status == (vx_status)VX_SUCCESS)
                {
                    status = tivxEventWait(cmd_ack_event, timeout);
    
                    if (status == (vx_status)VX_SUCCESS)
                    {
                        if ((vx_status)VX_SUCCESS != (vx_status)obj_desc_cmd->cmd_status)
                        {
                            VX_PRINT(VX_ZONE_ERROR,
                                     "Command ack message returned failure cmd_status: %d\n",
                                     obj_desc_cmd->cmd_status);
                            status = (vx_status)VX_FAILURE;
                        }
    
                        /* Put the object back in the free queue. */
                        status1 = tivxQueuePut(&context->free_queue,
                                               obj_id,
                                               TIVX_EVENT_TIMEOUT_NO_WAIT);
    
                        if (status1 != (vx_status)VX_SUCCESS)
                        {
                            VX_PRINT(VX_ZONE_ERROR,
                                     "Failed to release the object desc id.\n");
                            status = (vx_status)VX_FAILURE;
                        }
                    }
                    else if (status == (vx_status)TIVX_ERROR_EVENT_TIMEOUT)
                    {
                        /* Queue the object into the pend queue for later
                         * action.
                         */
                        status1 = tivxQueuePut(&context->pend_queue,
                                               obj_id,
                                               TIVX_EVENT_TIMEOUT_NO_WAIT);
    
                        if (status1 != (vx_status)VX_SUCCESS)
                        {
                            VX_PRINT(VX_ZONE_ERROR,
                                     "Failed to queue the object desc in pend queue.\n");
                        }
                    }
    
                    if (status != (vx_status)VX_SUCCESS)
                    {
                        VX_PRINT(VX_ZONE_ERROR, "tivxEventWait() failed.\n");
                    }
                }
                else
                {
                    if ((vx_status)VX_SUCCESS != (vx_status)obj_desc_cmd->cmd_status)
                    {
                        VX_PRINT(VX_ZONE_ERROR,
                                 "Failed to send object desc\n");
                        status = (vx_status)VX_FAILURE;
                    }
                }
            }
    
            ownContextUnlock(context);
        }
        else
        {
            VX_PRINT(VX_ZONE_ERROR,"invalid parameters\n");
            status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
        }
    
        return status;
    }
    
    VX_API_ENTRY vx_context VX_API_CALL vxCreateContext(void)
    {
        vx_context context = NULL;
        vx_status status = (vx_status)VX_SUCCESS;
        uint32_t idx;
    
        tivxPlatformSystemLock((vx_enum)TIVX_PLATFORM_LOCK_CONTEXT);
    
        {
            if (g_context_handle == NULL)
            {
                context = &g_context_obj;
    
                memset(context, 0, sizeof(tivx_context_t));
    
                context->imm_border.mode = (vx_enum)VX_BORDER_UNDEFINED;
                context->imm_border_policy = (vx_enum)VX_BORDER_POLICY_DEFAULT_TO_UNDEFINED;
                context->perf_enabled = (vx_bool)vx_false_e;
                context->imm_target_enum = (vx_enum)VX_TARGET_ANY;
                memset(context->imm_target_string, 0, sizeof(context->imm_target_string));
                context->num_references = 0;
                for(idx=0; idx<dimof(context->reftable); idx++)
                {
                    context->reftable[idx] = NULL;
                }
                for(idx=0; idx<dimof(context->user_structs); idx++)
                {
                    context->user_structs[idx].type = (vx_enum)VX_TYPE_INVALID;
                }
                for(idx=0; idx<dimof(context->kerneltable); idx++)
                {
                    context->kerneltable[idx] = NULL;
                }
                for(idx=0; idx<TIVX_MAX_KERNEL_ID; idx++)
                {
                    context->is_dynamic_user_kernel_id_used[idx] = (vx_bool)vx_false_e;
                }
                for(idx=0; idx<TIVX_MAX_LIBRARY_ID; idx++)
                {
                    context->is_dynamic_user_library_id_used[idx] = (vx_bool)vx_false_e;
                }
                context->num_unique_kernels = 0;
                context->log_enabled = (vx_bool)vx_false_e;
                context->base.release_callback =
                    (tivx_reference_release_callback_f)&vxReleaseContext;
    
                status = tivxMutexCreate(&context->lock);
                if(status==(vx_status)VX_SUCCESS)
                {
                    status = tivxMutexCreate(&context->log_lock);
                }
                if(status==(vx_status)VX_SUCCESS)
                {
                    status = tivxEventQueueCreate(&context->event_queue);
                }
                if(status==(vx_status)VX_SUCCESS)
                {
                    status = ownInitReference(&context->base, NULL, (vx_enum)VX_TYPE_CONTEXT, NULL);
                    if(status==(vx_status)VX_SUCCESS)
                    {
                        status = ownContextCreateCmdObj(context);
                        if(status == (vx_status)VX_SUCCESS)
                        {
                            ownIncrementReference(&context->base, (vx_enum)VX_EXTERNAL);
                            ownCreateConstErrors(context);
                            g_context_handle = context;
                        }
                    }
                    if(status!=(vx_status)VX_SUCCESS)
                    {
                        VX_PRINT(VX_ZONE_ERROR,"context objection creation failed\n");
                        tivxMutexDelete(&context->lock);
                        tivxMutexDelete(&context->log_lock);
                    }
                }
                if(status!=(vx_status)VX_SUCCESS)
                {
                    /* some error context cannot be created */
                    context = NULL;
                }
    
                if(status == (vx_status)VX_SUCCESS)
                {
                    /* set flag to disallow removal of built kernels
                     * via remove kernel API
                     */
                    ownContextSetKernelRemoveLock(context, (vx_bool)vx_true_e);
    
                    for (idx = 0;
                         idx < (sizeof(g_context_default_load_module)/sizeof(g_context_default_load_module[0]));
                         idx ++)
                    {
                        /* this loads default module kernels
                         * Any additional modules should be loaded by the user using
                         * vxLoadKernels()
                         * Error's are not checked here,
                         * User can check kernels that are added using vxQueryContext()
                         */
                        vxLoadKernels(context, g_context_default_load_module[idx]);
                    }
    
                    /* set flag to allow removal additional kernels
                     * installed by user via remove kernel API
                     */
                    ownContextSetKernelRemoveLock(context, (vx_bool)vx_false_e);
                }
            }
            else
            {
                context = g_context_handle;
                ownIncrementReference(&context->base, (vx_enum)VX_EXTERNAL);
            }
        }
        tivxPlatformSystemUnlock((vx_enum)TIVX_PLATFORM_LOCK_CONTEXT);
    
        return context;
    }
    
    VX_API_ENTRY vx_status VX_API_CALL vxReleaseContext(vx_context *c)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        vx_context context;
        vx_uint32 r;
        uint32_t idx;
    
        if(c != NULL)
        {
            context = *c;
        }
        else
        {
            context = 0;
        }
    
        if (c != NULL)
        {
            *c = 0;
        }
        tivxPlatformSystemLock((vx_enum)TIVX_PLATFORM_LOCK_CONTEXT);
        if (ownIsValidContext(context) == (vx_bool)vx_true_e)
        {
            if (ownDecrementReference(&context->base, (vx_enum)VX_EXTERNAL) == 0U)
            {
                ownContextSetKernelRemoveLock(context, (vx_bool)vx_true_e);
    
                for (idx = 0;
                     idx < (sizeof(g_context_default_load_module)/sizeof(g_context_default_load_module[0]));
                     idx ++)
                {
                /* Unload kernels */
                vxUnloadKernels(context, g_context_default_load_module[idx]);
                }
    
                ownContextSetKernelRemoveLock(context, (vx_bool)vx_false_e);
    
                /* Deregister any log callbacks if there is any registered */
                vxRegisterLogCallback(context, NULL, (vx_bool)vx_false_e);
    
                /*! \internal Garbage Collect All References */
                /* Details:
                 *   1. This loop will warn of references which have not been released by the user.
                 *   2. It will close all internally opened error references.
                 *   3. It will close the external references, which in turn will internally
                 *      close any internally dependent references that they reference, assuming the
                 *      reference counting has been done properly in the framework.
                 *   4. This garbage collection must be done before the targets are released since some of
                 *      these external references may have internal references to target kernels.
                 */
                for (r = 0; r < dimof(context->reftable); r++)
                {
                    vx_reference ref = context->reftable[r];
    
                    /* Warnings should only come when users have not released all external references */
                    if ((NULL != ref) && (ref->external_count > 0U) ) {
                        VX_PRINT(VX_ZONE_WARNING,"Found a reference "VX_FMT_REF" of type %08x at external count %u, internal count %u, releasing it\n",
                                 ref, ref->type, ref->external_count, ref->internal_count);
                        VX_PRINT(VX_ZONE_WARNING,"Releasing reference (name=%s) now as a part of garbage collection\n", ref->name);
                    }
    
                    /* These were internally opened during creation, so should internally close ERRORs */
                    if((NULL != ref) && (ref->type == (vx_enum)VX_TYPE_ERROR) ) {
                        ownReleaseReferenceInt(&ref, ref->type, (vx_enum)VX_INTERNAL, NULL);
                    }
    
                    if((NULL != ref) && (ref->type == (vx_enum)VX_TYPE_KERNEL) ) {
                        VX_PRINT(VX_ZONE_WARNING,"A kernel with name %s has not been removed, possibly due to a kernel module not being unloaded.\n", ref->name);
                        VX_PRINT(VX_ZONE_WARNING,"Removing as a part of garbage collection\n");
                        status = vxRemoveKernel((vx_kernel)ref);
                    }
    
                    /* Warning above so user can fix release external objects, but close here anyway */
                    while ((NULL != ref)&& (ref->external_count > 1U) ) {
                        ownDecrementReference(ref, (vx_enum)VX_EXTERNAL);
                    }
                    if ((NULL != ref) && (ref->external_count > 0U) ) {
                        ownReleaseReferenceInt(&ref, ref->type, (vx_enum)VX_EXTERNAL, NULL);
                    }
                }
    
                /* By now, all external and internal references should be removed */
                for (r = 0; r < dimof(context->reftable); r++)
                {
                    if(context->reftable[r] != NULL)
                    {
                            VX_PRINT(VX_ZONE_ERROR,"Reference %d not removed\n", r);
                    }
                }
    
                ownContextDeleteCmdObj(context);
    
                tivxEventQueueDelete(&context->event_queue);
    
                /*! \internal wipe away the context memory first */
                /* Normally destroy sem is part of release reference, but can't for context */
                tivxMutexDelete(&context->base.lock);
    
                tivxMutexDelete(&context->log_lock);
                tivxMutexDelete(&context->lock);
    
                memset(context, 0, sizeof(tivx_context_t));
    
                g_context_handle = NULL;
            }
        }
        else
        {
            VX_PRINT(VX_ZONE_ERROR,"context is invalid\n");
            status = (vx_status)VX_ERROR_INVALID_REFERENCE;
        }
        tivxPlatformSystemUnlock((vx_enum)TIVX_PLATFORM_LOCK_CONTEXT);
    
        return status;
    }
    
    VX_API_ENTRY vx_status VX_API_CALL vxQueryContext(vx_context context, vx_enum attribute, void *ptr, vx_size size)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        if (ownIsValidContext(context) == (vx_bool)vx_false_e)
        {
            VX_PRINT(VX_ZONE_ERROR,"context is invalid\n");
            status = (vx_status)VX_ERROR_INVALID_REFERENCE;
        }
        else
        {
            switch (attribute)
            {
                case (vx_enum)VX_CONTEXT_VENDOR_ID:
                    if (VX_CHECK_PARAM(ptr, size, vx_uint16, 0x1U))
                    {
                        *(vx_uint16 *)ptr = (vx_enum)VX_ID_TI;
                    }
                    else
                    {
                        VX_PRINT(VX_ZONE_ERROR,"query context vendor ID failed\n");
                        status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
                    }
                    break;
                case (vx_enum)VX_CONTEXT_VERSION:
                    if (VX_CHECK_PARAM(ptr, size, vx_uint16, 0x1U))
                    {
                        *(vx_uint16 *)ptr = (vx_uint16)VX_VERSION;
                    }
                    else
                    {
                        VX_PRINT(VX_ZONE_ERROR,"query context version failed\n");
                        status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
                    }
                    break;
                case (vx_enum)VX_CONTEXT_MODULES:
                    if (VX_CHECK_PARAM(ptr, size, vx_uint32, 0x3U))
                    {
                        *(vx_uint32 *)ptr = ownGetModuleCount();
                    }
                    else
                    {
                        VX_PRINT(VX_ZONE_ERROR,"query context modules failed\n");
                        status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
                    }
                    break;
                case (vx_enum)VX_CONTEXT_REFERENCES:
                    if (VX_CHECK_PARAM(ptr, size, vx_uint32, 0x3U))
                    {
                        *(vx_uint32 *)ptr = context->num_references;
                    }
                    else
                    {
                        VX_PRINT(VX_ZONE_ERROR,"query context references failed\n");
                        status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
                    }
                    break;
                case (vx_enum)VX_CONTEXT_IMPLEMENTATION:
                    if (((int32_t)size <= VX_MAX_IMPLEMENTATION_NAME) && (NULL != ptr))
                    {
                        strncpy(ptr, g_context_implmentation_name, VX_MAX_IMPLEMENTATION_NAME);
                    }
                    else
                    {
                        VX_PRINT(VX_ZONE_ERROR,"query context implementation failed\n");
                        status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
                    }
                    break;
                case (vx_enum)VX_CONTEXT_EXTENSIONS_SIZE:
                    if (VX_CHECK_PARAM(ptr, size, vx_size, 0x3U))
                    {
                        *(vx_size *)ptr = sizeof(g_context_extensions);
                    }
                    else
                    {
                        VX_PRINT(VX_ZONE_ERROR,"query context extensions size failed\n");
                        status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
                    }
                    break;
                case (vx_enum)VX_CONTEXT_EXTENSIONS:
                    if ( (size <= sizeof(g_context_extensions) ) && ptr)
                    {
                        uint32_t str_size = sizeof(g_context_extensions);
                        strncpy(ptr, g_context_extensions, str_size);
                    }
                    else
                    {
                        VX_PRINT(VX_ZONE_ERROR,"query context extensions failed\n");
                        status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
                    }
                    break;
                case (vx_enum)VX_CONTEXT_CONVOLUTION_MAX_DIMENSION:
                    if (VX_CHECK_PARAM(ptr, size, vx_size, 0x3U))
                    {
                        *(vx_size *)ptr = TIVX_CONTEXT_MAX_CONVOLUTION_DIM;
                    }
                    else
                    {
                        VX_PRINT(VX_ZONE_ERROR,"query context max convolution dimensions failed\n");
                        status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
                    }
                    break;
                case (vx_enum)VX_CONTEXT_MAX_TENSOR_DIMS:
                    if (VX_CHECK_PARAM(ptr, size, vx_size, 0x3U))
                    {
                        *(vx_size *)ptr = TIVX_CONTEXT_MAX_TENSOR_DIMS;
                    }
                    else
                    {
                        VX_PRINT(VX_ZONE_ERROR,"query context max tensor dimensions failed\n");
                        status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
                    }
                    break;
                case (vx_enum)VX_CONTEXT_NONLINEAR_MAX_DIMENSION:
                    if (VX_CHECK_PARAM(ptr, size, vx_size, 0x3U))
                    {
                        *(vx_size *)ptr = TIVX_CONTEXT_MAX_NONLINEAR_DIM;
                    }
                    else
                    {
                        VX_PRINT(VX_ZONE_ERROR,"query context max nonlinear dimensions failed\n");
                        status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
                    }
                    break;
                case (vx_enum)VX_CONTEXT_OPTICAL_FLOW_MAX_WINDOW_DIMENSION:
                    if (VX_CHECK_PARAM(ptr, size, vx_size, 0x3U))
                    {
                        *(vx_size *)ptr = TIVX_CONTEXT_MAX_OPTICALFLOWPYRLK_DIM;
                    }
                    else
                    {
                        VX_PRINT(VX_ZONE_ERROR,"query context max optical flow window dimensions failed\n");
                        status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
                    }
                    break;
                case (vx_enum)VX_CONTEXT_IMMEDIATE_BORDER:
                    if (VX_CHECK_PARAM(ptr, size, vx_border_t, 0x3U))
                    {
                        *(vx_border_t *)ptr = context->imm_border;
                    }
                    else
                    {
                        VX_PRINT(VX_ZONE_ERROR,"query context immediate border failed\n");
                        status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
                    }
                    break;
                case (vx_enum)VX_CONTEXT_IMMEDIATE_BORDER_POLICY:
                    if (VX_CHECK_PARAM(ptr, size, vx_enum, 0x3U))
                    {
                        *(vx_enum *)ptr = context->imm_border_policy;
                    }
                    else
                    {
                        VX_PRINT(VX_ZONE_ERROR,"query context immediate border policy failed\n");
                        status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
                    }
                    break;
                case (vx_enum)VX_CONTEXT_UNIQUE_KERNELS:
                    if (VX_CHECK_PARAM(ptr, size, vx_uint32, 0x3U))
                    {
                        *(vx_uint32 *)ptr = context->num_unique_kernels;
                    }
                    else
                    {
                        VX_PRINT(VX_ZONE_ERROR,"query context unique kernels failed\n");
                        status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
                    }
                    break;
                case (vx_enum)VX_CONTEXT_UNIQUE_KERNEL_TABLE:
                    if ((size == (context->num_unique_kernels * sizeof(vx_kernel_info_t))) &&
                        (ptr != NULL))
                    {
                        status = ownContextGetUniqueKernels( context, (vx_kernel_info_t*)ptr, context->num_unique_kernels);
                    }
                    else
                    {
                        VX_PRINT(VX_ZONE_ERROR,"query context unique kernel table failed\n");
                        status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
                    }
                    break;
                default:
                    status = (vx_status)VX_ERROR_NOT_SUPPORTED;
                    break;
            }
        }
        return status;
    }
    
    VX_API_ENTRY vx_status VX_API_CALL vxSetContextAttribute(vx_context context, vx_enum attribute, const void *ptr, vx_size size)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        if (ownIsValidContext(context) == (vx_bool)vx_false_e)
        {
            VX_PRINT(VX_ZONE_ERROR,"context is invalid\n");
            status = (vx_status)VX_ERROR_INVALID_REFERENCE;
        }
        else
        {
            switch (attribute) {
                case (vx_enum)VX_CONTEXT_IMMEDIATE_BORDER:
                    if (VX_CHECK_PARAM(ptr, size, vx_border_t, 0x3U))
                    {
                        const vx_border_t *config = (const vx_border_t *)ptr;
                        if (ownIsValidBorderMode(config->mode) == (vx_bool)vx_false_e)
                        {
                            VX_PRINT(VX_ZONE_ERROR,"invalid border mode\n");
                            status = (vx_status)VX_ERROR_INVALID_VALUE;
                        }
                        else
                        {
                            context->imm_border = *config;
                        }
                    }
                    else
                    {
                        VX_PRINT(VX_ZONE_ERROR,"set context immediate border mode failed\n");
                        status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
                    }
                    break;
                default:
                    VX_PRINT(VX_ZONE_ERROR,"unsupported attribute\n");
                    status = (vx_status)VX_ERROR_NOT_SUPPORTED;
                    break;
            }
        }
        return status;
    }
    
    
    VX_API_ENTRY vx_status VX_API_CALL vxDirective(vx_reference reference, vx_enum directive) {
        vx_status status = (vx_status)VX_SUCCESS;
        vx_context context;
        vx_enum ref_type;
    
        status = vxQueryReference(reference, (vx_enum)VX_REFERENCE_TYPE, &ref_type, sizeof(ref_type));
        if (status == (vx_status)VX_SUCCESS)
        {
            if (ref_type == (vx_enum)VX_TYPE_CONTEXT)
            {
                context = (vx_context)reference;
            }
            else
            {
                context = reference->context;
            }
            if (ownIsValidContext(context) == (vx_bool)vx_false_e)
            {
                VX_PRINT(VX_ZONE_ERROR,"context is invalid\n");
                status = (vx_status)VX_ERROR_INVALID_REFERENCE;
            }
            else
            {
                switch (directive)
                {
                    case (vx_enum)VX_DIRECTIVE_DISABLE_LOGGING:
                        context->log_enabled = (vx_bool)vx_false_e;
                        break;
                    case (vx_enum)VX_DIRECTIVE_ENABLE_LOGGING:
                        context->log_enabled = (vx_bool)vx_true_e;
                        break;
                    case (vx_enum)VX_DIRECTIVE_DISABLE_PERFORMANCE:
                        if (ref_type == (vx_enum)VX_TYPE_CONTEXT)
                        {
                            context->perf_enabled = (vx_bool)vx_false_e;
                        }
                        else
                        {
                            VX_PRINT(VX_ZONE_ERROR,"unsupported reference type\n");
                            status = (vx_status)VX_ERROR_NOT_SUPPORTED;
                        }
                        break;
                    case (vx_enum)VX_DIRECTIVE_ENABLE_PERFORMANCE:
                        if (ref_type == (vx_enum)VX_TYPE_CONTEXT)
                        {
                            context->perf_enabled = (vx_bool)vx_true_e;
                        }
                        else
                        {
                            VX_PRINT(VX_ZONE_ERROR,"unsupported reference type\n");
                            status = (vx_status)VX_ERROR_NOT_SUPPORTED;
                        }
                        break;
                    default:
                        VX_PRINT(VX_ZONE_ERROR,"unsupported directive type\n");
                        status = (vx_status)VX_ERROR_NOT_SUPPORTED;
                        break;
                }
            }
        }
        return status;
    }
    
    VX_API_ENTRY vx_enum VX_API_CALL vxRegisterUserStruct(vx_context context, vx_size size)
    {
        vx_enum type = (vx_enum)VX_TYPE_INVALID;
        vx_uint32 i = 0;
    
        if ((ownIsValidContext(context) == (vx_bool)vx_true_e) &&
            (size != 0U))
        {
            (void)ownContextLock(context);
    
            for (i = 0; i < TIVX_CONTEXT_MAX_USER_STRUCTS; ++i)
            {
                if (context->user_structs[i].type == (vx_enum)VX_TYPE_INVALID)
                {
                    context->user_structs[i].type = (vx_enum)VX_TYPE_USER_STRUCT_START + (int32_t)i;
                    context->user_structs[i].size = size;
                    type = context->user_structs[i].type;
                    tivxLogSetResourceUsedValue("TIVX_CONTEXT_MAX_USER_STRUCTS", (uint16_t)i+1U);
                    break;
                }
            }
    
            if (type == (vx_enum)VX_TYPE_INVALID)
            {
                VX_PRINT(VX_ZONE_WARNING, "May need to increase the value of TIVX_CONTEXT_MAX_USER_STRUCTS in tiovx/include/TI/tivx_config.h\n");
            }
    
            (void)ownContextUnlock(context);
        }
        return type;
    }
    
    VX_API_ENTRY vx_status VX_API_CALL vxAllocateUserKernelId(vx_context context, vx_enum * pKernelEnumId)
    {
        vx_status status = (vx_status)VX_ERROR_INVALID_REFERENCE;
        if ((ownIsValidContext(context) == (vx_bool)vx_true_e) && (NULL != pKernelEnumId))
        {
            uint32_t idx;
    
            (void)ownContextLock(context);
    
            status = (vx_status)VX_ERROR_NO_RESOURCES;
            for(idx=0; idx<TIVX_MAX_KERNEL_ID; idx++)
            {
                if (context->is_dynamic_user_kernel_id_used[idx] == (vx_bool)vx_false_e)
                {
                    *pKernelEnumId = VX_KERNEL_BASE(VX_ID_USER, 0U) + (vx_enum)(idx);
                    status = (vx_status)VX_SUCCESS;
                    context->is_dynamic_user_kernel_id_used[idx] = (vx_bool)vx_true_e;
                    break;
                }
            }
    
            (void)ownContextUnlock(context);
        }
        return status;
    }
    
    VX_API_ENTRY vx_status VX_API_CALL vxAllocateUserKernelLibraryId(vx_context context, vx_enum * pLibraryId)
    {
        vx_status status = (vx_status)VX_ERROR_INVALID_REFERENCE;
        if ((ownIsValidContext(context) == (vx_bool)vx_true_e) && (NULL != pLibraryId))
        {
            uint32_t idx;
    
            ownContextLock(context);
    
            for(idx=0; idx<(TIVX_MAX_LIBRARY_ID-1); idx++)
            {
                if (context->is_dynamic_user_library_id_used[idx] == (vx_bool)vx_false_e)
                {
                    *pLibraryId = (int32_t)(idx+1);
                    status = (vx_status)VX_SUCCESS;
                    context->is_dynamic_user_library_id_used[idx+1] = (vx_bool)vx_true_e;
                    break;
                }
            }
    
            ownContextUnlock(context);
        }
        return status;
    }
    
    VX_API_ENTRY vx_status VX_API_CALL vxSetImmediateModeTarget(vx_context context, vx_enum target_enum, const char* target_string)
    {
        vx_status status = (vx_status)VX_ERROR_INVALID_REFERENCE;
        if (ownIsValidContext(context) == (vx_bool)vx_true_e)
        {
            ownContextLock(context);
    
            switch (target_enum)
            {
                case (vx_enum)VX_TARGET_ANY:
                    context->imm_target_enum = (vx_enum)VX_TARGET_ANY;
                    memset(context->imm_target_string, 0, sizeof(context->imm_target_string));
                    status = (vx_status)VX_SUCCESS;
                    break;
    
                case (vx_enum)VX_TARGET_STRING:
                    if (target_string != NULL)
                    {
                        context->imm_target_enum = (vx_enum)VX_TARGET_STRING;
                        strncpy(context->imm_target_string, target_string, sizeof(context->imm_target_string)-1U);
                        context->imm_target_string[sizeof(context->imm_target_string) - 1U] = '\0';
                        status = (vx_status)VX_SUCCESS;
                    }
                    else /* target was not found */
                    {
                        VX_PRINT(VX_ZONE_ERROR,"target was not found\n");
                        status = (vx_status)VX_ERROR_NOT_SUPPORTED;
                    }
                    break;
    
                default:
                    VX_PRINT(VX_ZONE_ERROR,"unsupported target_enum\n");
                    status = (vx_status)VX_ERROR_NOT_SUPPORTED;
                    break;
            }
    
            ownContextUnlock(context);
        }
        return status;
    }
    
    VX_API_ENTRY vx_kernel VX_API_CALL vxGetKernelByName(vx_context context, const vx_char string[VX_MAX_KERNEL_NAME])
    {
        vx_kernel kernel = NULL;
        uint32_t idx;
    
        if( ownIsValidContext(context) == (vx_bool)vx_false_e )
        {
            kernel = NULL;
        }
        else
        {
            ownContextLock(context);
    
            for(idx=0; idx<dimof(context->kerneltable); idx++)
            {
                kernel = context->kerneltable[idx];
                if( (NULL != kernel) && (ownIsValidSpecificReference( &kernel->base, (vx_enum)VX_TYPE_KERNEL) != (vx_bool)vx_false_e)
                    &&
                    ( strncmp(kernel->name, string, VX_MAX_KERNEL_NAME) == 0 )
                    )
                {
                    /* found match */
                    ownIncrementReference(&kernel->base, (vx_enum)VX_EXTERNAL);
                    break;
                }
            }
            if(idx>=dimof(context->kerneltable))
            {
                /* not found */
                kernel = NULL;
            }
    
            ownContextUnlock(context);
        }
    
        return kernel;
    }
    
    VX_API_ENTRY vx_kernel VX_API_CALL vxGetKernelByEnum(vx_context context, vx_enum kernelenum)
    {
        vx_kernel kernel = NULL;
        uint32_t idx;
    
        if( ownIsValidContext(context) == (vx_bool)vx_false_e )
        {
            kernel = NULL;
        }
        else
        {
            ownContextLock(context);
    
            for(idx=0; idx<dimof(context->kerneltable); idx++)
            {
                kernel = context->kerneltable[idx];
                if((NULL != kernel) &&
                   (ownIsValidSpecificReference( &kernel->base, (vx_enum)VX_TYPE_KERNEL) != (vx_bool)vx_false_e)
                    &&
                    ( kernel->enumeration == kernelenum )
                    )
                {
                    /* found match */
                    ownIncrementReference(&kernel->base, (vx_enum)VX_EXTERNAL);
                    break;
                }
            }
            if(idx>=dimof(context->kerneltable))
            {
                /* not found */
                kernel = NULL;
            }
    
            ownContextUnlock(context);
        }
    
        return kernel;
    }
    
    vx_bool ownContextGetKernelRemoveLock(vx_context context)
    {
        return context->remove_kernel_lock;
    }
    
    void ownContextSetKernelRemoveLock(vx_context context, vx_bool do_lock)
    {
        context->remove_kernel_lock = do_lock;
    }
    
    

    /*
     *
     * 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 <stdio.h>
    #include "TI/tivx.h"
    #include "VX/vx.h"
    #include "TI/tivx_event.h"
    #include "tivx_hwa_kernels.h"
    #include "tivx_kernel_display_m2m.h"
    #include "TI/tivx_target_kernel.h"
    #include "tivx_kernels_target_utils.h"
    #include "tivx_hwa_display_m2m_priv.h"
    
    #include <TI/tivx_queue.h>
    #include <ti/drv/fvid2/fvid2.h>
    #include <ti/drv/dss/dss.h>
    #include <tivx_obj_desc_priv.h>
    #include <vx_reference.h>
    
    #define DISPLAY_MAX_VALID_PLANES                      2U
    
    #define DISPLAY_M2M_MAX_HANDLES                       (10)
    
    typedef struct
    {
        /*! IDs=> 0: Write-back pipe-line1 */
        uint32_t instId;
        /*! Number of pipe-lines used, should be set to '1' as blending is not supported currently */
        uint32_t numPipe;
        /*! IDs=> 0:VID1, 1:VIDL1, 2:VID2 and 3:VIDL2 */
        uint32_t pipeId[TIVX_DISPLAY_M2M_MAX_PIPE];
        /*! IDs=> 0:Overlay1, 1:Overlay2, 2:Overlay3 and 3:Overlay4 */
        uint32_t overlayId;
        /*! FVID2 display driver handle */
        Fvid2_Handle drvHandle;
        /*! WB pipe create parameters */
        Dss_WbCreateParams createParams;
        /*! WB pipe create status */
        Dss_WbCreateStatus createStatus;
        /*! Callback parameters */
        Fvid2_CbParams cbParams;
        /*! WB pipe status */
        Dss_WbStatus wbStatus;
        /*! WB pipe configuration */
        Dss_WbPipeCfgParams wbCfg;
        /*! WB pipe DMA configuration */
        CSL_DssWbPipeDmaCfg wbDmaCfg;
        /*! WB pipe MFlag configuration */
        Dss_WbPipeMflagParams wbMflagCfg;
        /*! WB pipe CSC configuration */
        CSL_DssCscCoeff wbCscCfg;
        /*! Display pipe configuration */
        Dss_PipeCfgParams pipeCfg[TIVX_DISPLAY_M2M_MAX_PIPE];
        /*! Display pipe MFlag configuration */
        Dss_PipeMflagParams mFlagCfg[TIVX_DISPLAY_M2M_MAX_PIPE];
        /*! Display pipe CSC configuration */
        Dss_PipeCscParams cscCfg[TIVX_DISPLAY_M2M_MAX_PIPE];
        /*! Display Overlay configuration */
        Dss_DctrlOverlayParams ovrCfg;
        /*! Display Layer configuration */
        Dss_DctrlOverlayLayerParams layerCfg;
        /*! Display Global configuration */
        Dss_DctrlGlobalDssParams globalParams;
        /*! Mutex used for waiting for process completion */
        tivx_event waitForProcessCmpl;
        /*! Display M2M Driver Input Frame List, used for providing
         *  an array of input frames */
        Fvid2_FrameList inFrmList;
        /*! Display M2M Driver Output Frame List, used for providing
         *  an array of output frames */
        Fvid2_FrameList outFrmList;
        /*! Display M2M Driver Input Frames */
        Fvid2_Frame inFrm[TIVX_DISPLAY_M2M_MAX_PIPE];
        /*! Display M2M Driver Output Frames */
        Fvid2_Frame outFrm[1U];
    } tivxDisplayM2MDrvObj;
    
    typedef struct
    {
        /*! IDs=> 0: Object free, 1: allocated */
        uint32_t isAlloc;
        /*! Display M2M driver object */
        tivxDisplayM2MDrvObj drvObj;
        /*! Display M2M Node create parameters provided by application */
        tivx_display_m2m_params_t createParams;
    } tivxDisplayM2MParams;
    
    typedef struct
    {
        tivx_mutex      lock;
        tivxDisplayM2MParams  m2mObj[DISPLAY_M2M_MAX_HANDLES];
    } tivxDisplayM2MInstObj;
    
    static tivx_target_kernel vx_display_m2m_target_kernel1 = NULL;
    static tivx_target_kernel vx_display_m2m_target_kernel2 = NULL;
    static tivx_target_kernel vx_display_m2m_target_kernel3 = NULL;
    static tivx_target_kernel vx_display_m2m_target_kernel4 = NULL;
    
    tivxDisplayM2MInstObj gTivxDispM2mInstObj;
    
    static vx_status VX_CALLBACK tivxDisplayM2MProcess(
           tivx_target_kernel_instance kernel,
           tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg);
    static vx_status VX_CALLBACK tivxDisplayM2MCreate(
           tivx_target_kernel_instance kernel,
           tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg);
    static vx_status VX_CALLBACK tivxDisplayM2MDelete(
           tivx_target_kernel_instance kernel,
           tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg);
    static vx_status VX_CALLBACK tivxDisplayM2MControl(
           tivx_target_kernel_instance kernel,
           uint32_t node_cmd_id, tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg);
    
    static vx_status tivxDisplayM2MSetCreateParams(
                               tivxDisplayM2MParams *prms,
                               const tivx_obj_desc_user_data_object_t *obj_desc,
                               const tivx_obj_desc_image_t *obj_desc_imageIn,
                               const tivx_obj_desc_image_t *obj_desc_imageOut);
    
    static vx_status tivxDisplayM2MDrvStructsInit(tivxDisplayM2MDrvObj *drvObj);
    
    static vx_status tivxDisplayM2MDrvCfg(tivxDisplayM2MDrvObj *drvObj);
    
    static int32_t tivxDisplayM2MCallback(Fvid2_Handle handle, void *appData);
    
    static vx_status tivxDisplayExtractFvid2Format(
                                    const tivx_obj_desc_image_t *obj_desc_img,
                                    Fvid2_Format *format);
    
    static tivxDisplayM2MParams *tivxDispM2mAllocObject(tivxDisplayM2MInstObj *instObj);
    static void tivxDispM2mFreeObject(tivxDisplayM2MInstObj *instObj,
        tivxDisplayM2MParams *m2mObj);
    
    
    static vx_status VX_CALLBACK tivxDisplayM2MProcess(
           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;
        tivxDisplayM2MParams *prms = NULL;
        tivxDisplayM2MDrvObj *drvObj;
        tivx_obj_desc_image_t *input_desc;
        tivx_obj_desc_image_t *output_desc;
        void *input_target_ptr, *input_target_ptr2 = NULL;
        void *output_target_ptr, *output_target_ptr2 = NULL;
        Fvid2_Frame *frm;
        int32_t fvid2_status = FVID2_SOK;
        uint32_t pipeIdx;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug11: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__);
        if ( (num_params != TIVX_KERNEL_DISPLAY_M2M_MAX_PARAMS)
            || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_CONFIGURATION_IDX])
            || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_INPUT_IDX])
            || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_OUTPUT_IDX])
        )
        {
            status = (vx_status)VX_FAILURE;
        }
    
        if((vx_status)VX_SUCCESS == status)
        {
            uint32_t size;
            input_desc = (tivx_obj_desc_image_t *)obj_desc[TIVX_KERNEL_DISPLAY_M2M_INPUT_IDX];
            output_desc = (tivx_obj_desc_image_t *)obj_desc[TIVX_KERNEL_DISPLAY_M2M_OUTPUT_IDX];
    
            status = tivxGetTargetKernelInstanceContext(kernel,
                                                        (void **)&prms, &size);
            if (((vx_status)VX_SUCCESS != status) || (NULL == prms) ||
                (sizeof(tivxDisplayM2MParams) != size))
            {
                status = (vx_status)VX_FAILURE;
                VX_PRINT(VX_ZONE_ERROR, "DISPLAY M2M: ERROR: Instance context is NULL!\r\n");
            }
        }
    
        if((vx_status)VX_SUCCESS == status)
        {
            /* Update 'input_desc' to array from only single image input to
               support blending i.e. more than 1 number of pipes. */
            input_target_ptr = tivxMemShared2TargetPtr(&input_desc->mem_ptr[0]);
            if((vx_df_image)VX_DF_IMAGE_NV12 == input_desc->format)
            {
                input_target_ptr2 = tivxMemShared2TargetPtr(&input_desc->mem_ptr[1]);
            }
    
            output_target_ptr = tivxMemShared2TargetPtr(&output_desc->mem_ptr[0]);
    
            if((vx_df_image)VX_DF_IMAGE_NV12 == output_desc->format)
            {
                output_target_ptr2 = tivxMemShared2TargetPtr(&output_desc->mem_ptr[1]);
            }
    
            /* call kernel processing function */
    
            drvObj = &prms->drvObj;
            /* Assign input buffer addresses */
            for (pipeIdx = 0U ; pipeIdx < drvObj->numPipe ; pipeIdx++)
            {
                frm = &drvObj->inFrm[pipeIdx];
                frm->addr[0U] = (uint64_t)input_target_ptr;
                if((vx_df_image)VX_DF_IMAGE_NV12 == input_desc->format)
                {
                    frm->addr[1U] = (uint64_t)input_target_ptr2;
                }
            }
    
            /* Assign output buffer addresses */
            frm = drvObj->outFrm;
            frm->addr[0U] = (uint64_t)output_target_ptr;
            if((vx_df_image)VX_DF_IMAGE_NV12 == output_desc->format)
            {
                frm->addr[1U] = (uint64_t)output_target_ptr2;
            }
    
            /* Submit the request to the driver */
            fvid2_status = Fvid2_processRequest(drvObj->drvHandle,
                                               &drvObj->inFrmList,
                                               &drvObj->outFrmList,
                                               FVID2_TIMEOUT_FOREVER);
            if (FVID2_SOK != fvid2_status)
            {
                VX_PRINT(VX_ZONE_ERROR, "Failed to Submit Request\n");
                status = (vx_status)VX_FAILURE;
            }
            else
            {
                /* Wait for Frame Completion */
                tivxEventWait(drvObj->waitForProcessCmpl, TIVX_EVENT_TIMEOUT_WAIT_FOREVER);
                fvid2_status = Fvid2_getProcessedRequest(drvObj->drvHandle,
                                                        &drvObj->inFrmList,
                                                        &drvObj->outFrmList,
                                                        0);
                if (FVID2_SOK != fvid2_status)
                {
                    VX_PRINT(VX_ZONE_ERROR, "Failed to Get Processed Request\n");
                    status = (vx_status)VX_FAILURE;
                }
            }
    
            /* kernel processing function complete */
        }
    
        return status;
    }
    
    static vx_status VX_CALLBACK tivxDisplayM2MCreate(
           tivx_target_kernel_instance kernel,
           tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg)
    {
    
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug7: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__);
        vx_status status = (vx_status)VX_SUCCESS;
        tivxDisplayM2MParams *prms = NULL;
        tivx_obj_desc_user_data_object_t *configuration_desc;
        tivx_obj_desc_image_t *obj_desc_imageIn, *obj_desc_imageOut;
    
        if ( (num_params != TIVX_KERNEL_DISPLAY_M2M_MAX_PARAMS)
            || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_CONFIGURATION_IDX])
            || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_INPUT_IDX])
            || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_OUTPUT_IDX])
        )
        {
            status = (vx_status)VX_FAILURE;
        }
        else
        {
    
            configuration_desc = (tivx_obj_desc_user_data_object_t *)obj_desc[TIVX_KERNEL_DISPLAY_M2M_CONFIGURATION_IDX];
            obj_desc_imageIn  = (tivx_obj_desc_image_t *)obj_desc[TIVX_KERNEL_DISPLAY_M2M_INPUT_IDX];
            obj_desc_imageOut = (tivx_obj_desc_image_t *)obj_desc[TIVX_KERNEL_DISPLAY_M2M_OUTPUT_IDX];
    
            if (configuration_desc->mem_size != sizeof(tivx_display_m2m_params_t))
            {
                VX_PRINT(VX_ZONE_ERROR, "User data object size on target does not match the size on host, possibly due to misalignment in data structure\n");
                status = (vx_status)VX_FAILURE;
            }
    
            prms = tivxDispM2mAllocObject(&gTivxDispM2mInstObj);
            if (NULL == prms)
            {
                status = (vx_status)VX_ERROR_NO_MEMORY;
                VX_PRINT(VX_ZONE_ERROR, "Unable to allocate local memory\n");
            }
    
            /* Create Node object elements */
            if ((vx_status)VX_SUCCESS == status)
            {
                status = tivxDisplayM2MSetCreateParams(prms,
                                                       configuration_desc,
                                                       obj_desc_imageIn,
                                                       obj_desc_imageOut);
            }
    
            /* Create sync events */
            if (status == (vx_status)VX_SUCCESS)
            {
                status = tivxEventCreate(&prms->drvObj.waitForProcessCmpl);
                if ((vx_status)VX_SUCCESS != status)
                {
                    VX_PRINT(VX_ZONE_ERROR, "Failed to allocate Event\n");
                }
            }
    
            /* DSS M2M Driver create and configuration */
            if (status == (vx_status)VX_SUCCESS)
            {
                status = tivxDisplayM2MDrvCfg(&prms->drvObj);
            }
    
            if ((vx_status)VX_SUCCESS == status)
            {
                tivxSetTargetKernelInstanceContext(kernel, prms, sizeof(tivxDisplayM2MParams));
            }
            else
            {
                status = (vx_status)VX_ERROR_NO_MEMORY;
                VX_PRINT(VX_ZONE_ERROR, "Unable to allocate local memory\n");
            }
        }
    
        return status;
    }
    
    static vx_status VX_CALLBACK tivxDisplayM2MDelete(
           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;
        tivxDisplayM2MParams *prms = NULL;
        uint32_t size;
        int32_t fvid2_status = FVID2_SOK;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug8: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__);
        if ( (num_params != TIVX_KERNEL_DISPLAY_M2M_MAX_PARAMS)
            || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_CONFIGURATION_IDX])
            || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_INPUT_IDX])
            || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_OUTPUT_IDX])
        )
        {
            status = (vx_status)VX_FAILURE;
        }
        else
        {
            status = tivxGetTargetKernelInstanceContext(kernel,
                                                        (void **)&prms,
                                                        &size);
            if ((vx_status)VX_SUCCESS != status)
            {
                VX_PRINT(VX_ZONE_ERROR, " DSS M2M: ERROR: Could not obtain kernel instance context !!!\n");
            }
            if(NULL == prms)
            {
                VX_PRINT(VX_ZONE_ERROR, "Kernel instance context is NULL!!!\n");
                status = (vx_status)VX_FAILURE;
            }
    
            if ((vx_status)VX_SUCCESS == status)
            {
                /* Stop Display M2M Driver */
                fvid2_status = Fvid2_stop(prms->drvObj.drvHandle, NULL);
                if (FVID2_SOK != fvid2_status)
                {
                    status = (vx_status)VX_FAILURE;
                    VX_PRINT(VX_ZONE_ERROR, " DSS M2M: ERROR: FVID2 DSS M2M not stopped !!!\n");
                }
            }
    
    
            if ((vx_status)VX_SUCCESS == status)
            {
                /* Dequeue all the request from the driver */
                while ((vx_status)VX_SUCCESS == status)
                {
                    fvid2_status = Fvid2_getProcessedRequest(prms->drvObj.drvHandle,
                                                            &prms->drvObj.inFrmList,
                                                            &prms->drvObj.outFrmList,
                                                            0);
                    if (FVID2_SOK != fvid2_status)
                    {
                        if (fvid2_status != FVID2_ENO_MORE_BUFFERS)
                        {
                            VX_PRINT(VX_ZONE_ERROR, "Failed to Get Processed Request\n");
                        }
                        status = (vx_status)VX_FAILURE;
                    }
                }
                if (fvid2_status == FVID2_ENO_MORE_BUFFERS)
                {
                    status = (vx_status)VX_SUCCESS;
                }
            }
    
            if ((vx_status)VX_SUCCESS == status)
            {
                /* print status */
                fvid2_status = Fvid2_control(prms->drvObj.drvHandle,
                                             IOCTL_DSS_M2M_GET_CURRENT_STATUS,
                                             &prms->drvObj.wbStatus,
                                             NULL);
                if (FVID2_SOK != fvid2_status)
                {
                    VX_PRINT(VX_ZONE_ERROR, "Get status returned failure\n");
                    status = (vx_status)VX_FAILURE;
                }
                else
                {
                    printf(   "==========================================================\r\n");
                    printf(   " Display M2M Status: Instance|%d\r\n", prms->drvObj.instId);
                    printf(   "==========================================================\r\n");
                    printf(   " Queue Count: %d\r\n", prms->drvObj.wbStatus.queueCount);
                    printf(   " De-queue Count: %d\r\n", prms->drvObj.wbStatus.dequeueCount);
                    printf(   " Write-back Frames Count: %d\r\n", prms->drvObj.wbStatus.wbFrmCount);
                    printf(   " Underflow Count: %d\r\n", prms->drvObj.wbStatus.underflowCount);
                }
            }
    
            if ((vx_status)VX_SUCCESS == status)
            {
                /* Delete FVID2 handle */
                fvid2_status = Fvid2_delete(prms->drvObj.drvHandle, NULL);
                if (FVID2_SOK != fvid2_status)
                {
                    status = (vx_status)VX_FAILURE;
                    VX_PRINT(VX_ZONE_ERROR, " DSS M2M: ERROR: FVID2 Delete Failed !!!\n");
                }
                else
                {
                    prms->drvObj.drvHandle = NULL;
                }
            }
    
            if ((vx_status)VX_SUCCESS == status)
            {
                /* Delete event */
                tivxEventDelete(&prms->drvObj.waitForProcessCmpl);
            }
    
            if ((NULL != prms) &&
                (sizeof(tivxDisplayM2MParams) == size))
            {
                tivxDispM2mFreeObject(&gTivxDispM2mInstObj, prms);
                //tivxMemFree(prms, size, (vx_enum)TIVX_MEM_EXTERNAL);
            }
        }
    
        return status;
    }
    
    static vx_status VX_CALLBACK tivxDisplayM2MControl(
           tivx_target_kernel_instance kernel,
           uint32_t node_cmd_id, tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        int32_t fvid2_status = FVID2_SOK;
        uint32_t size;
        tivxDisplayM2MParams *prms = NULL;
        tivxDisplayM2MDrvObj *drvObj;
        tivx_display_m2m_statistics_t *m2m_status_prms = NULL;
        void *target_ptr;
        tivx_obj_desc_user_data_object_t *usr_data_obj;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug6: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__);
        status = tivxGetTargetKernelInstanceContext(kernel, (void **)&prms, &size);
        if (((vx_status)VX_SUCCESS != status)            ||
            (NULL == prms)                               ||
            (sizeof(tivxDisplayM2MParams) != size))
        {
            status = (vx_status)VX_FAILURE;
        }
    
        if (status == (vx_status)VX_SUCCESS)
        {
            switch (node_cmd_id)
            {
                case TIVX_DISPLAY_M2M_GET_STATISTICS:
                {
                    if (NULL != obj_desc[0])
                    {
                        drvObj = &prms->drvObj;
                        fvid2_status = Fvid2_control(drvObj->drvHandle,
                                                IOCTL_DSS_M2M_GET_CURRENT_STATUS,
                                                &drvObj->wbStatus,
                                                NULL);
                        if (FVID2_SOK != fvid2_status)
                        {
                            VX_PRINT(VX_ZONE_ERROR, "Get status returned failure\n");
                            status = (vx_status)VX_FAILURE;
                        }
                        else
                        {
                            /* Update return status object */
                            usr_data_obj = (tivx_obj_desc_user_data_object_t *)obj_desc[0U];
                            target_ptr = tivxMemShared2TargetPtr(&usr_data_obj->mem_ptr);
                            tivxCheckStatus(&status,
                                            tivxMemBufferMap(target_ptr,
                                            usr_data_obj->mem_size,
                                            (vx_enum)VX_MEMORY_TYPE_HOST,
                                            (vx_enum)VX_WRITE_ONLY));
                            if (sizeof(tivx_display_m2m_statistics_t) ==
                                    usr_data_obj->mem_size)
                            {
                                m2m_status_prms = (tivx_display_m2m_statistics_t *)target_ptr;
                                m2m_status_prms->queueCount     =
                                                    drvObj->wbStatus.queueCount;
                                m2m_status_prms->dequeueCount   =
                                                    drvObj->wbStatus.dequeueCount;
                                m2m_status_prms->wbFrmCount     =
                                                    drvObj->wbStatus.wbFrmCount;
                                m2m_status_prms->underflowCount =
                                                    drvObj->wbStatus.underflowCount;
                            }
                            else
                            {
                                VX_PRINT(VX_ZONE_ERROR, "Invalid Size \n");
                                status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
                            }
    
                            tivxCheckStatus(&status,
                                            tivxMemBufferUnmap(target_ptr,
                                            usr_data_obj->mem_size,
                                            (vx_enum)VX_MEMORY_TYPE_HOST,
                                            (vx_enum)VX_WRITE_ONLY));
                        }
                    }
                    else
                    {
                        VX_PRINT(VX_ZONE_ERROR, "User data object was NULL\n");
                        status = (vx_status)VX_FAILURE;
                    }
                    break;
                }
                default:
                {
                    VX_PRINT(VX_ZONE_ERROR, "Invalid Command Id\n");
                    status = (vx_status)VX_FAILURE;
                    break;
                }
            }
        }
    
        return status;
    }
    
    void tivxAddTargetKernelDisplayM2M(void)
    {
        vx_status status = (vx_status)VX_FAILURE;
        char target_name[TIVX_TARGET_MAX_NAME];
        vx_enum self_cpu;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug1: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__);
        self_cpu = tivxGetSelfCpuId();
    
        if ( self_cpu == (vx_enum)TIVX_CPU_ID_MCU2_0 )
        {
            strncpy(target_name, TIVX_TARGET_DISPLAY_M2M1, TIVX_TARGET_MAX_NAME);
            vx_display_m2m_target_kernel1 = tivxAddTargetKernelByName(
                                TIVX_KERNEL_DISPLAY_M2M_NAME,
                                target_name,
                                tivxDisplayM2MProcess,
                                tivxDisplayM2MCreate,
                                tivxDisplayM2MDelete,
                                tivxDisplayM2MControl,
                                NULL);
            strncpy(target_name, TIVX_TARGET_DISPLAY_M2M2, TIVX_TARGET_MAX_NAME);
            vx_display_m2m_target_kernel2 = tivxAddTargetKernelByName(
                                TIVX_KERNEL_DISPLAY_M2M_NAME,
                                target_name,
                                tivxDisplayM2MProcess,
                                tivxDisplayM2MCreate,
                                tivxDisplayM2MDelete,
                                tivxDisplayM2MControl,
                                NULL);
            strncpy(target_name, TIVX_TARGET_DISPLAY_M2M3, TIVX_TARGET_MAX_NAME);
            vx_display_m2m_target_kernel3 = tivxAddTargetKernelByName(
                                TIVX_KERNEL_DISPLAY_M2M_NAME,
                                target_name,
                                tivxDisplayM2MProcess,
                                tivxDisplayM2MCreate,
                                tivxDisplayM2MDelete,
                                tivxDisplayM2MControl,
                                NULL);
            strncpy(target_name, TIVX_TARGET_DISPLAY_M2M4, TIVX_TARGET_MAX_NAME);
            vx_display_m2m_target_kernel4 = tivxAddTargetKernelByName(
                                TIVX_KERNEL_DISPLAY_M2M_NAME,
                                target_name,
                                tivxDisplayM2MProcess,
                                tivxDisplayM2MCreate,
                                tivxDisplayM2MDelete,
                                tivxDisplayM2MControl,
                                NULL);
    
            status = tivxMutexCreate(&gTivxDispM2mInstObj.lock);
            if ((vx_status)VX_SUCCESS != status)
            {
                VX_PRINT(VX_ZONE_ERROR, "Failed to create Mutex\n");
            }
            else
            {
                memset(&gTivxDispM2mInstObj.m2mObj, 0x0,
                    sizeof(tivxDisplayM2MParams) * DISPLAY_M2M_MAX_HANDLES);
            }
        }
    }
    
    void tivxRemoveTargetKernelDisplayM2M(void)
    {
        vx_status status = (vx_status)VX_SUCCESS;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug13: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__);
        status = tivxRemoveTargetKernel(vx_display_m2m_target_kernel1);
        if (status == (vx_status)VX_SUCCESS)
        {
            vx_display_m2m_target_kernel1 = NULL;
        }
    
        status = tivxRemoveTargetKernel(vx_display_m2m_target_kernel2);
        if (status == (vx_status)VX_SUCCESS)
        {
            vx_display_m2m_target_kernel2 = NULL;
        }
    
        status = tivxRemoveTargetKernel(vx_display_m2m_target_kernel3);
        if (status == (vx_status)VX_SUCCESS)
        {
            vx_display_m2m_target_kernel3 = NULL;
        }
    
        status = tivxRemoveTargetKernel(vx_display_m2m_target_kernel4);
        if (status == (vx_status)VX_SUCCESS)
        {
            vx_display_m2m_target_kernel4 = NULL;
        }
    
        if (NULL != gTivxDispM2mInstObj.lock)
        {
            tivxMutexDelete(&gTivxDispM2mInstObj.lock);
        }
    }
    
    
    static vx_status tivxDisplayM2MSetCreateParams(
                           tivxDisplayM2MParams *prms,
                           const tivx_obj_desc_user_data_object_t *obj_desc,
                           const tivx_obj_desc_image_t *obj_desc_imageIn,
                           const tivx_obj_desc_image_t *obj_desc_imageOut)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        void *cfgPtr;
        tivx_display_m2m_params_t *createParams;
        tivxDisplayM2MDrvObj *drvObj;
        uint32_t pipeIdx, layerIdx;
        Dss_DispParams *dispParams;
        CSL_DssWbPipeCfg *wbPipeCfg;
        Dss_DctrlOverlayParams *ovrParams;
        Dss_DctrlOverlayLayerParams *layerParams;
        Fvid2_Frame *frm;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug12: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__);
        cfgPtr = tivxMemShared2TargetPtr(&obj_desc->mem_ptr);
    
        tivxCheckStatus(&status, tivxMemBufferMap(cfgPtr, obj_desc->mem_size,
            (vx_enum)VX_MEMORY_TYPE_HOST, (vx_enum)VX_READ_ONLY));
    
        if (status == (vx_status)VX_SUCCESS)
        {
            createParams = (tivx_display_m2m_params_t *)cfgPtr;
            memcpy(&prms->createParams, createParams, sizeof(tivx_display_m2m_params_t));
            drvObj = &prms->drvObj;
            /* Set Driver object */
            drvObj->instId    = createParams->instId;
            drvObj->numPipe   = createParams->numPipe;
            drvObj->overlayId = createParams->overlayId;
            memcpy(&drvObj->pipeId[0U],
                   &createParams->pipeId[0U],
                   sizeof(createParams->pipeId));
        }
        /* Initialize driver object */
        if (status == (vx_status)VX_SUCCESS)
        {
            status = tivxDisplayM2MDrvStructsInit(drvObj);
        }
    
        /* set driver object parameters */
        if (status == (vx_status)VX_SUCCESS)
        {
            /* Callback parameters */
            drvObj->cbParams.cbFxn   = (Fvid2_CbFxn) (&tivxDisplayM2MCallback);
            drvObj->cbParams.appData = drvObj;
            drvObj->createParams.numPipe = drvObj->numPipe;
            drvObj->createParams.overlayId = drvObj->overlayId;
            /* Set Display pipeline parameters */
            for (pipeIdx = 0U ; pipeIdx < drvObj->numPipe ; pipeIdx++)
            {
                dispParams = &drvObj->pipeCfg[pipeIdx].cfgParams;
                drvObj->createParams.pipeId[pipeIdx]  = drvObj->pipeId[pipeIdx];
                drvObj->pipeCfg[pipeIdx].pipeId       = drvObj->pipeId[pipeIdx];
                drvObj->mFlagCfg[pipeIdx].pipeId      = drvObj->pipeId[pipeIdx];
                drvObj->cscCfg[pipeIdx].pipeId        = drvObj->pipeId[pipeIdx];
                dispParams->pipeCfg.pipeType          = CSL_DSS_VID_PIPE_TYPE_VID;
                dispParams->layerPos.startX           = 0U;
                dispParams->layerPos.startY           = 0U;
                dispParams->pipeCfg.scEnable          = FALSE;
                dispParams->alphaCfg.globalAlpha      = 0xFFU;
                dispParams->alphaCfg.preMultiplyAlpha = FALSE;
                status = tivxDisplayExtractFvid2Format(
                            obj_desc_imageIn,
                            &dispParams->pipeCfg.inFmt);
                if (status == (vx_status)VX_SUCCESS)
                {
                    /* Set video pipe output frame dimensions same as input as
                       no scaling is done in video pipe-line */
                    dispParams->pipeCfg.outWidth  = dispParams->pipeCfg.inFmt.width;
                    dispParams->pipeCfg.outHeight = dispParams->pipeCfg.inFmt.height;
                }
                else
                {
                    status = (vx_status)VX_FAILURE;
                    VX_PRINT(VX_ZONE_ERROR, "Invalid Input Image\n");
                    break;
                }
            }
    
            /* Set Display WB pipeline parameters */
            if (((vx_status)VX_SUCCESS == status) && (pipeIdx > 0))
            {
                wbPipeCfg               = &drvObj->wbCfg.pipeCfg;
                /* Set WB pipe input frame dimensions same as video pipe input/output frame,
                   no scaling is done in video pipe, it will be done in WB pipe-line */
                wbPipeCfg->inFmt.width  = dispParams->pipeCfg.outWidth;
                wbPipeCfg->inFmt.height = dispParams->pipeCfg.outHeight;
                wbPipeCfg->inPos.startX = 0U;
                wbPipeCfg->inPos.startY = 0U;
                status = tivxDisplayExtractFvid2Format(obj_desc_imageOut,
                                                       &wbPipeCfg->outFmt);
                if (status != (vx_status)VX_SUCCESS)
                {
                    VX_PRINT(VX_ZONE_ERROR, "Invalid Input Image\n");
                    status = (vx_status)VX_FAILURE;
                }
                else
                {
                    if ((wbPipeCfg->inFmt.width != wbPipeCfg->outFmt.width) ||
                        (wbPipeCfg->inFmt.height != wbPipeCfg->outFmt.height))
                    {
                        wbPipeCfg->scEnable = TRUE;
                    }
                }
            }
    
            /* Set Display WB pipeline parameters */
            if ((vx_status)VX_SUCCESS == status)
            {
                ovrParams = &drvObj->ovrCfg;
                ovrParams->overlayId = drvObj->overlayId;
                ovrParams->colorbarEnable = FALSE;
                ovrParams->overlayCfg.colorKeyEnable = FALSE;
                ovrParams->overlayCfg.colorKeySel = CSL_DSS_OVERLAY_TRANS_COLOR_DEST;
                ovrParams->overlayCfg.backGroundColor = 0xc8c800U;
    
                layerParams = &drvObj->layerCfg;
                layerParams->overlayId = drvObj->overlayId;
                /* Set all layer to invalid first and then update only used ones */
                for(layerIdx = 0U ; layerIdx < CSL_DSS_VID_PIPE_ID_MAX ; layerIdx++)
                {
                    layerParams->pipeLayerNum[layerIdx] = CSL_DSS_OVERLAY_LAYER_INVALID;
                }
    
                /* Currently blending is not supported so only one layer is used.
                   This code needs to updated when blending is supported. */
                layerParams->pipeLayerNum[drvObj->createParams.pipeId[0U]] =
                                                    CSL_DSS_OVERLAY_LAYER_NUM_0;
            }
    
            /* Update frame-lists */
            if ((vx_status)VX_SUCCESS == status)
            {
                drvObj->inFrmList.numFrames = drvObj->numPipe;
                for (pipeIdx = 0U ; pipeIdx < drvObj->numPipe ; pipeIdx++)
                {
                    frm = (Fvid2_Frame *) &drvObj->inFrm[pipeIdx];
                    frm->chNum = drvObj->createParams.pipeId[pipeIdx];
                    drvObj->inFrmList.frames[pipeIdx] = frm;
                }
    
                frm = (Fvid2_Frame *) &drvObj->outFrm[0U];
                drvObj->outFrmList.frames[0U] = frm;
                drvObj->outFrmList.numFrames  = 1U;
    
            }
        }
    
        return status;
    }
    
    static vx_status tivxDisplayM2MDrvStructsInit(tivxDisplayM2MDrvObj *drvObj)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        uint32_t loopCnt;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug10: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__);
        /* Initialize driver create parameters */
        Dss_m2mCreateParamsInit(&drvObj->createParams);
        /* Initialize driver call-back parameters */
        Fvid2CbParams_init(&drvObj->cbParams);
        /* Initialize driver pipe configuration parameters */
        for (loopCnt = 0U ; loopCnt < drvObj->numPipe ; loopCnt++)
        {
            Dss_dispParamsInit(&drvObj->pipeCfg[loopCnt].cfgParams);
            Dss_dispPipeMflagParamsInit(&drvObj->mFlagCfg[loopCnt].mFlagCfg);
            CSL_dssCscCoeffInit(&drvObj->cscCfg[loopCnt].csc);
        }
        /* Initialize WB pipeline parameters */
        Dss_m2mPipeCfgParamsInit(&drvObj->wbCfg);
        CSL_dssWbPipeDmaCfgInit(&drvObj->wbDmaCfg);
        Dss_m2mMFlagParamsInit(&drvObj->wbMflagCfg);
        CSL_dssCscCoeffInit(&drvObj->wbCscCfg);
        Dss_m2mStatusInit(&drvObj->wbStatus);
    
        /* Initialize Display overlay parameters */
        Dss_dctrlOverlayParamsInit(&drvObj->ovrCfg);
        Dss_dctrlOverlayLayerParamsInit(&drvObj->layerCfg);
    
        /* Initialize Display global parameters */
        Dss_dctrlGlobalDssParamsInit(&drvObj->globalParams);
    
        /* Initialize input and output frame lists */
        Fvid2FrameList_init(&drvObj->inFrmList);
        Fvid2FrameList_init(&drvObj->outFrmList);
    
        return status;
    }
    
    static vx_status tivxDisplayM2MDrvCfg(tivxDisplayM2MDrvObj *drvObj)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        uint32_t loopCnt;
        int32_t fvid2_status = FVID2_SOK;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug9: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__);
        /* Display M2M Driver create */
        drvObj->drvHandle = Fvid2_create(DSS_M2M_DRV_ID,
                                         drvObj->instId,
                                         &drvObj->createParams,
                                         &drvObj->createStatus,
                                         &drvObj->cbParams);
        if((NULL == drvObj->drvHandle) ||
               (drvObj->createStatus.retVal != FVID2_SOK))
        {
            VX_PRINT(VX_ZONE_ERROR, ": Display M2M Create Failed!!!\r\n");
            status = (vx_status)VX_FAILURE;
        }
    
        /* Display M2M pipe configuration */
        if ((vx_status)VX_SUCCESS == status)
        {
            for (loopCnt = 0U ; loopCnt < drvObj->numPipe ; loopCnt++)
            {
                fvid2_status += Fvid2_control(drvObj->drvHandle,
                                              IOCTL_DSS_M2M_SET_PIPE_PARAMS,
                                              &drvObj->pipeCfg[loopCnt],
                                              NULL);
                fvid2_status += Fvid2_control(drvObj->drvHandle,
                                              IOCTL_DSS_M2M_SET_PIPE_MFLAG_PARAMS,
                                              &drvObj->mFlagCfg[loopCnt],
                                              NULL);
                if (FVID2_SOK != fvid2_status)
                {
                    VX_PRINT(VX_ZONE_ERROR, ": Display M2M DISP IOCTL Failed!!!\r\n");
                    status = (vx_status)VX_FAILURE;
                    break;
                }
            }
        }
    
        /* Display M2M overlay configuration */
        if ((vx_status)VX_SUCCESS == status)
        {
            fvid2_status += Fvid2_control(drvObj->drvHandle,
                                          IOCTL_DSS_DCTRL_SET_OVERLAY_PARAMS,
                                          &drvObj->ovrCfg,
                                          NULL);
            fvid2_status += Fvid2_control(drvObj->drvHandle,
                                          IOCTL_DSS_DCTRL_SET_LAYER_PARAMS,
                                          &drvObj->layerCfg,
                                          NULL);
            if (FVID2_SOK != fvid2_status)
            {
                VX_PRINT(VX_ZONE_ERROR, ": Display M2M Overlay IOCTL Failed!!!\r\n");
                status = (vx_status)VX_FAILURE;
            }
        }
    
        /* Display M2M global configuration */
        if ((vx_status)VX_SUCCESS == status)
        {
            fvid2_status += Fvid2_control(drvObj->drvHandle,
                                          IOCTL_DSS_DCTRL_SET_GLOBAL_DSS_PARAMS,
                                          &drvObj->globalParams,
                                          NULL);
            if (FVID2_SOK != fvid2_status)
            {
                VX_PRINT(VX_ZONE_ERROR, ": Display M2M Global IOCTL Failed!!!\r\n");
                status = (vx_status)VX_FAILURE;
            }
        }
    
        /* Display M2M write-back pipe configuration */
        if ((vx_status)VX_SUCCESS == status)
        {
            fvid2_status += Fvid2_control(drvObj->drvHandle,
                                          IOCTL_DSS_M2M_SET_WB_PIPE_PARAMS,
                                          &drvObj->wbCfg,
                                          NULL);
            fvid2_status += Fvid2_control(drvObj->drvHandle,
                                          IOCTL_DSS_M2M_SET_WB_PIPE_MFLAG_PARAMS,
                                          &drvObj->wbMflagCfg,
                                          NULL);
            fvid2_status += Fvid2_control(drvObj->drvHandle,
                                          IOCTL_DSS_M2M_SET_WB_PIPE_DMA_CFG,
                                          &drvObj->wbDmaCfg,
                                          NULL);
            if (FVID2_SOK != fvid2_status)
            {
                VX_PRINT(VX_ZONE_ERROR, ": Display M2M WB IOCTL Failed!!!\r\n");
                status = (vx_status)VX_FAILURE;
            }
        }
    
        /* Start Display M2M Driver */
        if ((vx_status)VX_SUCCESS == status)
        {
            fvid2_status = Fvid2_start(drvObj->drvHandle, NULL);
            if (FVID2_SOK != fvid2_status)
            {
                VX_PRINT(VX_ZONE_ERROR, ": Display M2M Driver Start Failed!!!\r\n");
                status = (vx_status)VX_FAILURE;
            }
        }
    
        return status;
    }
    
    static int32_t tivxDisplayM2MCallback(Fvid2_Handle handle, void *appData)
    {
        tivxDisplayM2MDrvObj *drvObj = (tivxDisplayM2MDrvObj *)(appData);
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug5: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__);
        if ((NULL != drvObj) && (drvObj->waitForProcessCmpl != NULL))
        {
            tivxEventPost(drvObj->waitForProcessCmpl);
        }
    
        return (vx_status)VX_SUCCESS;
    }
    
    static vx_status tivxDisplayExtractFvid2Format(
                                        const tivx_obj_desc_image_t *obj_desc_img,
                                        Fvid2_Format *format)
    {
        vx_status status = (vx_status)VX_SUCCESS;
    
        Fvid2Format_init(format);
        format->width = obj_desc_img->imagepatch_addr[0].dim_x;
        format->height = obj_desc_img->imagepatch_addr[0].dim_y;
        format->ccsFormat = FVID2_CCSF_BITS8_PACKED;
        format->scanFormat = FVID2_SF_PROGRESSIVE;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug4: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__);
        switch (obj_desc_img->format)
        {
            case (vx_df_image)TIVX_DF_IMAGE_RGB565:
                format->dataFormat = FVID2_DF_BGR16_565;
                format->pitch[FVID2_RGB_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y;
                break;
            case (vx_df_image)VX_DF_IMAGE_RGB:
                format->dataFormat = FVID2_DF_RGB24_888;
                format->pitch[FVID2_RGB_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y;
                break;
            case (vx_df_image)VX_DF_IMAGE_RGBX:
                format->dataFormat = FVID2_DF_RGBX24_8888;
                format->pitch[FVID2_RGB_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y;
                break;
            case (vx_df_image)TIVX_DF_IMAGE_BGRX:
                format->dataFormat = FVID2_DF_BGRX32_8888;
                format->pitch[FVID2_RGB_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y;
                break;
            case (vx_df_image)VX_DF_IMAGE_UYVY:
                format->dataFormat = FVID2_DF_YUV422I_UYVY;
                format->pitch[FVID2_YUV_INT_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y;
                break;
            case (vx_df_image)VX_DF_IMAGE_YUYV:
                format->dataFormat = FVID2_DF_YUV422I_YUYV;
                format->pitch[FVID2_YUV_INT_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y;
                break;
            case (vx_df_image)VX_DF_IMAGE_NV12:
                format->dataFormat = FVID2_DF_YUV420SP_UV;
                format->pitch[FVID2_YUV_SP_Y_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y;
                format->pitch[FVID2_YUV_SP_CBCR_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[1].stride_y;
                break;
            case (vx_df_image)VX_DF_IMAGE_U16:
                format->ccsFormat = FVID2_CCSF_BITS12_UNPACKED16;
                format->dataFormat = FVID2_DF_YUV420SP_UV;
                format->pitch[FVID2_YUV_SP_Y_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y;
                format->pitch[FVID2_YUV_SP_CBCR_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y;
                break;
            case (vx_df_image)VX_DF_IMAGE_U8:
                format->ccsFormat = FVID2_CCSF_BITS8_PACKED;
                format->dataFormat = FVID2_DF_YUV420SP_UV;
                format->pitch[FVID2_YUV_SP_Y_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y;
                format->pitch[FVID2_YUV_SP_CBCR_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y;
                break;
            default:
                status = (vx_status)VX_FAILURE;
                break;
        }
    
        return status;
    }
    
    static tivxDisplayM2MParams *tivxDispM2mAllocObject(tivxDisplayM2MInstObj *instObj)
    {
        uint32_t                cnt;
        tivxDisplayM2MParams *m2mObj = NULL;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug2: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__);
        /* Lock instance mutex */
        tivxMutexLock(instObj->lock);
    
        for (cnt = 0U; cnt < DISPLAY_M2M_MAX_HANDLES; cnt ++)
        {
            if (0U == instObj->m2mObj[cnt].isAlloc)
            {
                m2mObj = &instObj->m2mObj[cnt];
                memset(m2mObj, 0x0, sizeof(tivxDisplayM2MParams));
                instObj->m2mObj[cnt].isAlloc = 1U;
                break;
            }
        }
    
        /* Release instance mutex */
        tivxMutexUnlock(instObj->lock);
    
        return (m2mObj);
    }
    
    static void tivxDispM2mFreeObject(tivxDisplayM2MInstObj *instObj,
        tivxDisplayM2MParams *m2mObj)
    {
        uint32_t cnt;
    	VX_PRINT(VX_ZONE_ERROR, "cyhdebug3: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__);
        /* Lock instance mutex */
        tivxMutexLock(instObj->lock);
    
        for (cnt = 0U; cnt < DISPLAY_M2M_MAX_HANDLES; cnt ++)
        {
            if (m2mObj == &instObj->m2mObj[cnt])
            {
                m2mObj->isAlloc = 0U;
                break;
            }
        }
    
        /* Release instance mutex */
        tivxMutexUnlock(instObj->lock);
    }
    

    vx_graph_verify.c

    vx_graph_verify.c

    /*
    *
    * Copyright (c) 2017 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 <vx_internal.h>
    
    static tivx_target_t g_target_table[TIVX_TARGET_MAX_TARGETS_IN_CPU];
    
    static tivx_target tivxTargetAllocHandle(vx_enum target_id);
    static void tivxTargetFreeHandle(tivx_target *target_handle);
    static vx_status tivxTargetDequeueObjDesc(tivx_target target, uint16_t *obj_desc_id, uint32_t timeout);
    static tivx_target tivxTargetGetHandle(vx_enum target_id);
    static void tivxTargetNodeDescSendComplete(const tivx_obj_desc_node_t *node_obj_desc);
    static vx_bool tivxTargetNodeDescCanNodeExecute(const tivx_obj_desc_node_t *node_obj_desc);
    static void tivxTargetNodeDescTriggerNextNodes(const tivx_obj_desc_node_t *node_obj_desc);
    static void tivxTargetNodeDescNodeExecuteTargetKernel(tivx_obj_desc_node_t *node_obj_desc, uint16_t prm_obj_desc_id[]);
    static void tivxTargetNodeDescNodeExecuteUserKernel(tivx_obj_desc_node_t *node_obj_desc, uint16_t prm_obj_desc_id[]);
    static void tivxTargetNodeDescNodeExecute(tivx_target target, tivx_obj_desc_node_t *node_obj_desc);
    static vx_status tivxTargetNodeDescNodeCreate(tivx_obj_desc_node_t *node_obj_desc);
    static vx_status tivxTargetNodeDescNodeDelete(const tivx_obj_desc_node_t *node_obj_desc);
    static vx_status tivxTargetNodeDescNodeControl(
        const tivx_obj_desc_cmd_t *cmd_obj_desc,
        const tivx_obj_desc_node_t *node_obj_desc);
    static void tivxTargetCmdDescHandleAck(tivx_obj_desc_cmd_t *cmd_obj_desc);
    static vx_action tivxTargetCmdDescHandleUserCallback(tivx_obj_desc_node_t *node_obj_desc, uint64_t timestamp);
    static void tivxTargetSetGraphStateAbandon(
        const tivx_obj_desc_node_t *node_obj_desc);
    static void tivxTargetCmdDescSendAck(tivx_obj_desc_cmd_t *cmd_obj_desc, vx_status status);
    static void tivxTargetCmdDescHandler(tivx_obj_desc_cmd_t *cmd_obj_desc);
    static void VX_CALLBACK tivxTargetTaskMain(void *app_var);
    static vx_bool tivxTargetNodeDescIsPrevPipeNodeBlocked(tivx_obj_desc_node_t *node_obj_desc);
    static void tivxTargetNodeDescNodeMarkComplete(tivx_obj_desc_node_t *node_obj_desc, uint16_t *blocked_node_id);
    static vx_status tivxTargetNodeSendCommand(const tivx_obj_desc_cmd_t *cmd_obj_desc,
        uint32_t node_id, const tivx_obj_desc_node_t *node_obj_desc);
    
    static tivx_target tivxTargetAllocHandle(vx_enum target_id)
    {
        uint16_t target_inst = TIVX_GET_TARGET_INST(target_id);
        tivx_target tmp_target = NULL, target = NULL;
    
        if(target_inst < TIVX_TARGET_MAX_TARGETS_IN_CPU)
        {
            tmp_target = &g_target_table[target_inst];
    
            if(tmp_target->target_id == target_id)
            {
                /* target id already allocated so return null */
    
                target = NULL;
            }
            else
            {
                /* target ID is not allocated, allocate it */
                tmp_target->target_id = target_id;
    
                target = tmp_target;
                tivxLogResourceAlloc("TIVX_TARGET_MAX_TARGETS_IN_CPU", 1);
            }
        }
        else
        {
            VX_PRINT(VX_ZONE_ERROR, "Exceeded max targets in CPU. Modify TIVX_TARGET_MAX_TARGETS_IN_CPU value in tiovx/include/TI/tivx_config.h\n");
            VX_PRINT(VX_ZONE_ERROR, "May need to increase the value of TIVX_TARGET_MAX_TARGETS_IN_CPU in tiovx/include/TI/tivx_config.h\n");
        }
    
        return target;
    }
    
    static void tivxTargetFreeHandle(tivx_target *target_handle)
    {
        if((NULL != target_handle) && (*target_handle!=NULL))
        {
            /* mark target handle as free */
            (*target_handle)->target_id = (vx_enum)TIVX_TARGET_ID_INVALID;
    
            *target_handle = NULL;
        }
    }
    
    static vx_status tivxTargetDequeueObjDesc(tivx_target target, uint16_t *obj_desc_id, uint32_t timeout)
    {
        vx_status status;
        uintptr_t value = (vx_enum)TIVX_OBJ_DESC_INVALID;
    
        *obj_desc_id = (vx_enum)TIVX_OBJ_DESC_INVALID;
    
        status = tivxQueueGet(&target->job_queue_handle,
                    &value, timeout);
    
        if(status == (vx_status)VX_SUCCESS)
        {
            *obj_desc_id = (uint16_t)value;
        }
    
        return status;
    }
    
    static tivx_target tivxTargetGetHandle(vx_enum target_id)
    {
        uint16_t target_inst = TIVX_GET_TARGET_INST(target_id);
        tivx_target tmp_target = NULL, target = NULL;
    
        if(target_inst < TIVX_TARGET_MAX_TARGETS_IN_CPU)
        {
            tmp_target = &g_target_table[target_inst];
    
            if(tmp_target->target_id == target_id)
            {
                /* target id matches so return it */
    
                target = tmp_target;
            }
            else
            {
                /* target ID does not match so return NULL */
                target = NULL;
            }
        }
    
        return target;
    }
    
    static void tivxTargetNodeDescSendComplete(
        const tivx_obj_desc_node_t *node_obj_desc)
    {
        uint16_t cmd_obj_desc_id;
    
        if( (tivxFlagIsBitSet(node_obj_desc->flags, TIVX_NODE_FLAG_IS_USER_CALLBACK) != (vx_bool)vx_false_e)
                ||
            (node_obj_desc->num_out_nodes == 0U)
            )
        {
            cmd_obj_desc_id = (uint16_t)node_obj_desc->node_complete_cmd_obj_desc_id;
    
            if( (vx_enum)cmd_obj_desc_id != (vx_enum)TIVX_OBJ_DESC_INVALID)
            {
                tivx_obj_desc_cmd_t *cmd_obj_desc = (tivx_obj_desc_cmd_t *)tivxObjDescGet(cmd_obj_desc_id);
    
                if( tivxObjDescIsValidType( (tivx_obj_desc_t*)cmd_obj_desc, TIVX_OBJ_DESC_CMD) != 0)
                {
                    uint64_t timestamp = tivxPlatformGetTimeInUsecs()*1000U;
    
                    tivx_uint64_to_uint32(
                        timestamp,
                        &cmd_obj_desc->timestamp_h,
                        &cmd_obj_desc->timestamp_l
                    );
    
                    /* users wants a notification of node complete or this is leaf node
                     * so send node complete command to host
                     */
                    tivxObjDescSend( cmd_obj_desc->dst_target_id, cmd_obj_desc_id);
                }
            }
        }
    }
    
    static vx_bool tivxTargetNodeDescCanNodeExecute(
        const tivx_obj_desc_node_t *node_obj_desc)
    {
        tivx_obj_desc_node_t *prev_node_obj_desc;
        uint16_t prev_node_obj_desc_id;
        uint16_t i;
        vx_bool can_execute = (vx_bool)vx_true_e;
    
        for(i=0; i<node_obj_desc->num_in_nodes; i++)
        {
            prev_node_obj_desc_id = node_obj_desc->in_node_id[i];
            prev_node_obj_desc = (tivx_obj_desc_node_t*)tivxObjDescGet(prev_node_obj_desc_id);
    
            if( tivxObjDescIsValidType( (tivx_obj_desc_t*)prev_node_obj_desc, TIVX_OBJ_DESC_NODE) != 0)
            {
                if( tivxFlagIsBitSet(prev_node_obj_desc->flags,
                            TIVX_NODE_FLAG_IS_EXECUTED) == (vx_bool)vx_false_e)
                {
                    can_execute = (vx_bool)vx_false_e;
                }
            }
        }
    
        return can_execute;
    }
    
    static void tivxTargetNodeDescTriggerNextNodes(
        const tivx_obj_desc_node_t *node_obj_desc)
    {
        vx_bool can_execute;
        uint16_t i;
        tivx_obj_desc_node_t *next_node_obj_desc;
        uint16_t next_node_obj_desc_id;
    
        /* check and trigger next set of nodes */
        for(i=0; i<node_obj_desc->num_out_nodes; i++)
        {
            next_node_obj_desc_id = node_obj_desc->out_node_id[i];
            next_node_obj_desc = (tivx_obj_desc_node_t*)tivxObjDescGet(next_node_obj_desc_id);
    
            if( tivxObjDescIsValidType( (tivx_obj_desc_t*)next_node_obj_desc, TIVX_OBJ_DESC_NODE) != 0)
            {
                can_execute = tivxTargetNodeDescCanNodeExecute(next_node_obj_desc);
    
                if(can_execute == (vx_bool)vx_true_e)
                {
                    tivxObjDescSend( next_node_obj_desc->target_id, next_node_obj_desc_id);
                }
            }
        }
    }
    
    static void tivxTargetNodeDescNodeExecuteTargetKernel(
        tivx_obj_desc_node_t *node_obj_desc, uint16_t prm_obj_desc_id[])
    {
        tivx_target_kernel_instance target_kernel_instance;
        tivx_obj_desc_t *params[TIVX_KERNEL_MAX_PARAMS] = {NULL};
        uint32_t i, cnt, loop_max = 1;
        uint32_t is_prm_replicated = node_obj_desc->is_prm_replicated;
        uint32_t is_prm_array_element = node_obj_desc->is_prm_array_element;
        uint32_t is_prm_data_ref_q_flag = node_obj_desc->is_prm_data_ref_q;
        tivx_obj_desc_t *parent_obj_desc[TIVX_KERNEL_MAX_PARAMS] = {NULL};
        tivx_obj_desc_t *prm_obj_desc;
    
        if (tivxFlagIsBitSet(node_obj_desc->flags,TIVX_NODE_FLAG_IS_REPLICATED) ==
            (vx_bool)vx_true_e)
        {
            loop_max = node_obj_desc->num_of_replicas;
        }
    
        for (cnt = 0; cnt < loop_max; cnt ++)
        {
            target_kernel_instance = tivxTargetKernelInstanceGet(
                    (uint16_t)node_obj_desc->target_kernel_index[cnt], (vx_enum)node_obj_desc->kernel_id);
    
            for(i=0; i<node_obj_desc->num_params ; i++)
            {
                parent_obj_desc[i] = NULL;
    
                if((is_prm_replicated & ((uint32_t)1U << i)) != 0U)
                {
                    prm_obj_desc = tivxObjDescGet(prm_obj_desc_id[i]);
                    if(prm_obj_desc != NULL)
                    {
                        parent_obj_desc[i] = tivxObjDescGet(
                            prm_obj_desc->scope_obj_desc_id);
    
                        /* if parent is NULL, then prm_obj_desc itself is the parent */
                        if(parent_obj_desc[i]==NULL)
                        {
                            parent_obj_desc[i] = prm_obj_desc;
                        }
                    }
                }
            }
    
            for(i=0; i<node_obj_desc->num_params ; i++)
            {
                params[i] = NULL;
                if((is_prm_replicated & ((uint32_t)1U << i)) != 0U)
                {
                    if(parent_obj_desc[i] != NULL)
                    {
                        if((vx_enum)parent_obj_desc[i]->type==(vx_enum)TIVX_OBJ_DESC_OBJARRAY)
                        {
                            params[i] = tivxObjDescGet(
                                ((tivx_obj_desc_object_array_t*)parent_obj_desc[i])->
                                    obj_desc_id[cnt]);
                        }
                        else
                        if((vx_enum)parent_obj_desc[i]->type==(vx_enum)TIVX_OBJ_DESC_PYRAMID)
                        {
                            params[i] = tivxObjDescGet(
                                ((tivx_obj_desc_pyramid_t*)parent_obj_desc[i])->
                                    obj_desc_id[cnt]);
                        }
                        else
                        {
                            params[i] = NULL;
                        }
                    }
                }
                else if((is_prm_array_element & ((uint32_t)1U << i)) != 0U)
                {
                    if((is_prm_data_ref_q_flag & ((uint32_t)1U << i)) != 0U)
                    {
                        /* this is a case of parameter expected by node being a
                         * element within a object array or pyramid
                         *
                         * Here we index into the object array and pass the element
                         * later return parent back to the framework
                         */
    
                        /* if this parameter is pipelined then it is assumed
                         * that this points to 0th element of object array or pyramid, always
                         */
    
                        parent_obj_desc[i] = tivxObjDescGet(prm_obj_desc_id[i]);
                        if(parent_obj_desc[i] != NULL)
                        {
                            if((vx_enum)parent_obj_desc[i]->type==(vx_enum)TIVX_OBJ_DESC_OBJARRAY)
                            {
                                tivx_obj_desc_t *tmp_node_param;
    
                                tmp_node_param = tivxObjDescGet(node_obj_desc->data_id[i]);
    
                                if (NULL != tmp_node_param)
                                {
                                    params[i] = tivxObjDescGet(
                                        ((tivx_obj_desc_object_array_t*)parent_obj_desc[i])->
                                            obj_desc_id[tmp_node_param->element_idx]);
                                }
                            }
                            else
                            if((vx_enum)parent_obj_desc[i]->type==(vx_enum)TIVX_OBJ_DESC_PYRAMID)
                            {
                                tivx_obj_desc_t *tmp_node_param;
    
                                tmp_node_param = tivxObjDescGet(node_obj_desc->data_id[i]);
    
                                if (NULL != tmp_node_param)
                                {
                                    params[i] = tivxObjDescGet(
                                        ((tivx_obj_desc_pyramid_t*)parent_obj_desc[i])->
                                            obj_desc_id[tmp_node_param->element_idx]);
                                }
                            }
                            else
                            {
                                /* this is not part of a array element,
                                 * pass thru params[] = prm_obj_desc_id[]
                                 * set parent_obj_desc as NULL
                                 * reset bit in is_prm_array_element
                                 * */
                                params[i] = tivxObjDescGet(prm_obj_desc_id[i]);
                                parent_obj_desc[i] = NULL;
                                tivxFlagBitClear(&is_prm_array_element, (uint32_t)1<<i);
                            }
                        }
                    }
                    else
                    {
                        params[i] = tivxObjDescGet(node_obj_desc->data_id[i]);
                    }
                }
                else
                {
                    params[i] = tivxObjDescGet(prm_obj_desc_id[i]);
    
                    /* Note: this check is needed to solve the condition where a replicated object array/pyramid
                     *       is connected to a node that consumes the full object array/pyramid.  The acquire
                     *       parameter function returns the first obj desc id of that array rather than
                     *       the obj desc id of the array/pyramid.  This logic checks if the obj desc id has a
                     *       parent object.  In the case that it does, it checks the type of the parent against
                     *       the type of the node object.  If these match, then the parent object should be returned.
                     *       If they don't, then the element of the parent should be returned.
                     */
                    if((is_prm_data_ref_q_flag & ((uint32_t)1U << i)) != 0U)
                    {
                        parent_obj_desc[i] = tivxObjDescGet(params[i]->scope_obj_desc_id);
    
                        if(NULL != parent_obj_desc[i])
                        {
                            tivx_obj_desc_t *tmp_node_param;
    
                            tmp_node_param = tivxObjDescGet(node_obj_desc->data_id[i]);
    
                            if (NULL != tmp_node_param)
                            {
                                if (parent_obj_desc[i]->type == tmp_node_param->type)
                                {
                                    params[i] = parent_obj_desc[i];
                                }
                            }
                        }
                    }
                }
    
                #if 0
                if(params[i])
                {
                    VX_PRINT(VX_ZONE_INFO," Param %d is %d of type %d (node=%d, pipe=%d)\n",
                            i,
                            params[i]->obj_desc_id,
                            params[i]->type,
                            node_obj_desc->base.obj_desc_id,
                            node_obj_desc->pipeline_id
                    );
                }
                else
                {
                    VX_PRINT(VX_ZONE_INFO," Param %d is NULL (node=%d, pipe=%d)\n",
                            i,
                            node_obj_desc->base.obj_desc_id,
                            node_obj_desc->pipeline_id
                    );
                }
                #endif
            }
    
            {
                if (tivxFlagIsBitSet(node_obj_desc->flags,TIVX_NODE_FLAG_IS_SUPERNODE) ==
                    (vx_bool)vx_true_e)
                {
                    params[0] = (tivx_obj_desc_t *) tivxObjDescGet( node_obj_desc->base.scope_obj_desc_id );
    
                    node_obj_desc->exe_status |= (uint32_t)tivxTargetKernelExecute(target_kernel_instance, params,
                        1);
                }
                else
                {
                    tivxTargetSetTimestamp(node_obj_desc, params);
                    node_obj_desc->exe_status |= (uint32_t)tivxTargetKernelExecute(target_kernel_instance, params,
                        (uint16_t)node_obj_desc->num_params);
                }
            }
        }
    
        /* params[] contain pointer to obj_desc for each parameter,
         * A node could change the obj_desc value of params[i] as part of its execution
         * below logic changes prm_obj_desc_id, based on updated params[i] value.
         * This logic will not take effect for replicated parameters and for non data ref queue parameters
         * i.e it will take effect only for data ref queue parameters and non-replicated parameters
         */
        for(i=0; i<node_obj_desc->num_params ; i++)
        {
            if(    (tivxFlagIsBitSet(is_prm_data_ref_q_flag, ((uint32_t)1<<i)) == (vx_bool)vx_true_e)
                && (tivxFlagIsBitSet(is_prm_replicated, ((uint32_t)1<<i)) == (vx_bool)vx_false_e)
                )
            {
                if(params[i]==NULL)
                {
                    prm_obj_desc_id[i] = (vx_enum)TIVX_OBJ_DESC_INVALID;
                }
                else if(tivxFlagIsBitSet(is_prm_array_element, ((uint32_t)1<<i)) == (vx_bool)vx_true_e)
                {
                    prm_obj_desc_id[i] = (vx_enum)TIVX_OBJ_DESC_INVALID;
    
                    prm_obj_desc = tivxObjDescGet(params[i]->obj_desc_id);
    
                    if (prm_obj_desc != NULL)
                    {
                        parent_obj_desc[i] = tivxObjDescGet(
                            prm_obj_desc->scope_obj_desc_id);
    
                        if(parent_obj_desc[i]!=NULL)
                        {
                            prm_obj_desc_id[i] = parent_obj_desc[i]->obj_desc_id;
                        }
                    }
                }
                else
                {
                    prm_obj_desc_id[i] = params[i]->obj_desc_id;
                }
            }
        }
    
    }
    
    static void tivxTargetNodeDescNodeExecuteUserKernel(tivx_obj_desc_node_t *node_obj_desc, uint16_t prm_obj_desc_id[])
    {
        vx_reference prm_ref[TIVX_KERNEL_MAX_PARAMS];
        uint32_t i;
    
        for(i=0; i<node_obj_desc->num_params; i++)
        {
            prm_ref[i] = ownReferenceGetHandleFromObjDescId(prm_obj_desc_id[i]);
        }
        node_obj_desc->exe_status = (uint32_t)ownNodeUserKernelExecute((vx_node)(uintptr_t)node_obj_desc->base.host_ref, prm_ref);
    }
    
    static vx_bool tivxTargetNodeDescIsPrevPipeNodeBlocked(tivx_obj_desc_node_t *node_obj_desc)
    {
        tivx_obj_desc_node_t *prev_node_obj_desc;
        vx_bool is_prev_node_blocked = (vx_bool)vx_false_e;
    
        prev_node_obj_desc = (tivx_obj_desc_node_t*)tivxObjDescGet(node_obj_desc->prev_pipe_node_id);
        if(prev_node_obj_desc!=NULL)
        {
            if(node_obj_desc->state == TIVX_NODE_OBJ_DESC_STATE_IDLE)
            {
                if(prev_node_obj_desc->state != TIVX_NODE_OBJ_DESC_STATE_IDLE)
                {
                    /* previous node in pipeline is blocked, so block this pipeline node until previous pipeline
                     * completes
                     */
                    node_obj_desc->state = TIVX_NODE_OBJ_DESC_STATE_BLOCKED;
                    prev_node_obj_desc->blocked_node_id = node_obj_desc->base.obj_desc_id;
                    is_prev_node_blocked = (vx_bool)vx_true_e;
                }
            }
            else
            if(node_obj_desc->state == TIVX_NODE_OBJ_DESC_STATE_BLOCKED)
            {
                /* this is trigger from prev node or due to resource being released so proceed with execution */
                node_obj_desc->state = TIVX_NODE_OBJ_DESC_STATE_IDLE;
            }
            else
            {
                /* do nothing */
            }
        }
        return is_prev_node_blocked;
    }
    
    
    static void tivxTargetNodeDescNodeMarkComplete(tivx_obj_desc_node_t *node_obj_desc, uint16_t *blocked_node_id)
    {
        /* check if any node is blocked on this node to get unblocked and complete execution
         * This will be a node from next pipeline instance
         */
        *blocked_node_id = node_obj_desc->blocked_node_id;
        node_obj_desc->blocked_node_id = (vx_enum)TIVX_OBJ_DESC_INVALID;
        node_obj_desc->state = TIVX_NODE_OBJ_DESC_STATE_IDLE;
        tivxFlagBitSet(&node_obj_desc->flags, TIVX_NODE_FLAG_IS_EXECUTED);
    }
    
    static void tivxTargetNodeDescNodeExecute(tivx_target target, tivx_obj_desc_node_t *node_obj_desc)
    {
        uint64_t beg_time, end_time;
        uint16_t blocked_node_id = (vx_enum)TIVX_OBJ_DESC_INVALID;
        uint16_t prm_obj_desc_id[TIVX_KERNEL_MAX_PARAMS];
    
        /* if node is already executed do nothing */
        if( tivxFlagIsBitSet(node_obj_desc->flags,TIVX_NODE_FLAG_IS_EXECUTED) == (vx_bool)vx_false_e )
        {
            /* check if same node in previous pipeline instance is blocked, if yes then
             * dont acquire parameters for this node
             */
            if(tivxTargetNodeDescIsPrevPipeNodeBlocked(node_obj_desc)==(vx_bool)vx_false_e)
            {
                vx_bool is_node_blocked;
                tivx_target_kernel_instance target_kernel_instance;
                vx_enum kernel_instance_state = (vx_enum)VX_NODE_STATE_STEADY;
                uint32_t num_bufs = 1;
    
                is_node_blocked = (vx_bool)vx_false_e;
    
                VX_PRINT(VX_ZONE_INFO,"Node (node=%d, pipe=%d) acquiring parameters on target %08x\n",
                                     node_obj_desc->base.obj_desc_id,
                                     node_obj_desc->pipeline_id,
                                     target->target_id
                               );
    
                /* Note: not taking into account replicated node */
                target_kernel_instance = tivxTargetKernelInstanceGet(
                    (uint16_t)node_obj_desc->target_kernel_index[0], (vx_enum)node_obj_desc->kernel_id);
    
                /* Note: in the case of user kernel, target_kernel instance is NULL */
                if( tivxFlagIsBitSet(node_obj_desc->flags,TIVX_NODE_FLAG_IS_TARGET_KERNEL) != 0)
                {
                    if (NULL != target_kernel_instance)
                    {
                        num_bufs = target_kernel_instance->kernel->num_pipeup_bufs;
    
                        kernel_instance_state = target_kernel_instance->state;
                    }
                }
                else
                {
                    kernel_instance_state = (vx_enum)node_obj_desc->source_state;
    
                    num_bufs = node_obj_desc->num_pipeup_bufs;
                }
    
                if ( ((vx_enum)VX_NODE_STATE_PIPEUP == kernel_instance_state) &&
                     (num_bufs > 1U) )
                {
                    int32_t buf_idx;
    
                    for (buf_idx = 0; buf_idx < ((int32_t)num_bufs - 1); buf_idx++)
                    {
                        tivxTargetNodeDescAcquireAllParametersForPipeup(node_obj_desc, prm_obj_desc_id);
    
                        if( tivxFlagIsBitSet(node_obj_desc->flags,TIVX_NODE_FLAG_IS_TARGET_KERNEL) != 0)
                        {
                            tivxTargetNodeDescNodeExecuteTargetKernel(node_obj_desc, prm_obj_desc_id);
                        }
                        else
                        {
                            tivxTargetNodeDescNodeExecuteUserKernel(node_obj_desc, prm_obj_desc_id);
                        }
                    }
    
                    node_obj_desc->source_state = (vx_enum)VX_NODE_STATE_STEADY;
    
                    if( (tivxFlagIsBitSet(node_obj_desc->flags,TIVX_NODE_FLAG_IS_TARGET_KERNEL) != (vx_bool)vx_false_e) &&
                        (NULL != target_kernel_instance))
                    {
                        target_kernel_instance->state = (vx_enum)VX_NODE_STATE_STEADY;
                    }
                }
    
                tivxTargetNodeDescAcquireAllParameters(node_obj_desc, prm_obj_desc_id, &is_node_blocked);
    
                if(is_node_blocked==(vx_bool)vx_false_e)
                {
                    VX_PRINT(VX_ZONE_INFO,"Node (node=%d, pipe=%d) executing on target %08x\n",
                                     node_obj_desc->base.obj_desc_id,
                                     node_obj_desc->pipeline_id,
                                     target->target_id
                               );
    
                    beg_time = tivxPlatformGetTimeInUsecs();
    
                    tivxLogRtTraceNodeExeStart(beg_time, node_obj_desc);
    
                    if( tivxFlagIsBitSet(node_obj_desc->flags,TIVX_NODE_FLAG_IS_TARGET_KERNEL) != 0)
                    {
                        tivxTargetNodeDescNodeExecuteTargetKernel(node_obj_desc, prm_obj_desc_id);
                    }
                    else
                    {
                        tivxTargetNodeDescNodeExecuteUserKernel(node_obj_desc, prm_obj_desc_id);
                    }
    
                    end_time = tivxPlatformGetTimeInUsecs();
    
                    tivxLogRtTraceNodeExeEnd(end_time, node_obj_desc);
    
                    VX_PRINT(VX_ZONE_INFO,"Node (node=%d, pipe=%d) executing on target %08x ... DONE !!!\n",
                                     node_obj_desc->base.obj_desc_id,
                                     node_obj_desc->pipeline_id,
                                     target->target_id
                               );
    
                    tivx_uint64_to_uint32(
                        beg_time,
                        &node_obj_desc->exe_time_beg_h,
                        &node_obj_desc->exe_time_beg_l
                    );
    
                    tivx_uint64_to_uint32(
                        end_time,
                        &node_obj_desc->exe_time_end_h,
                        &node_obj_desc->exe_time_end_l
                    );
    
                    tivxTargetNodeDescNodeMarkComplete(node_obj_desc, &blocked_node_id);
                    tivxTargetNodeDescReleaseAllParameters(node_obj_desc, prm_obj_desc_id);
                    tivxTargetNodeDescSendComplete(node_obj_desc);
                    tivxTargetNodeDescTriggerNextNodes(node_obj_desc);
    
                    if((vx_enum)blocked_node_id!=(vx_enum)TIVX_OBJ_DESC_INVALID)
                    {
                        /* this will be same node in next pipeline to trigger it last */
                        VX_PRINT(VX_ZONE_INFO,"Re-triggering (node=%d)\n",
                                 blocked_node_id
                        );
                        tivxTargetTriggerNode(blocked_node_id);
                    }
                }
                else
                {
                    VX_PRINT(VX_ZONE_INFO,"Node (node=%d, pipe=%d) ... BLOCKED for resources on target %08x\n",
                                     node_obj_desc->base.obj_desc_id,
                                     node_obj_desc->pipeline_id,
                                     target->target_id
                               );
                }
            }
            else
            {
                VX_PRINT(VX_ZONE_INFO,"Node (node=%d, pipe=%d) ... BLOCKED for previous pipe instance node (node=%d) to complete !!!\n",
                        node_obj_desc->base.obj_desc_id,
                        node_obj_desc->pipeline_id,
                        node_obj_desc->prev_pipe_node_id
                );
            }
        }
    }
    
    static vx_status tivxTargetNodeDescNodeCreate(tivx_obj_desc_node_t *node_obj_desc)
    {
        tivx_target_kernel_instance target_kernel_instance;
        vx_status status = (vx_status)VX_SUCCESS;
        uint16_t i, cnt, loop_max = 1;
        tivx_obj_desc_t *params[TIVX_KERNEL_MAX_PARAMS] = {NULL};
        uint32_t is_prm_replicated = node_obj_desc->is_prm_replicated;
        tivx_obj_desc_t *parent_obj_desc[TIVX_KERNEL_MAX_PARAMS] = {NULL};
        tivx_obj_desc_t *prm_obj_desc;
        tivx_obj_desc_kernel_name_t *kernel_name_obj_desc;
        volatile char *kernel_name = NULL;
    
        if (tivxFlagIsBitSet(node_obj_desc->flags,TIVX_NODE_FLAG_IS_REPLICATED) ==
            (vx_bool)vx_true_e)
        {
            loop_max = (uint16_t)node_obj_desc->num_of_replicas;
        }
    
        kernel_name_obj_desc = (tivx_obj_desc_kernel_name_t*)tivxObjDescGet((uint16_t)node_obj_desc->kernel_name_obj_desc_id);
        if(kernel_name_obj_desc!=NULL)
        {
            kernel_name = kernel_name_obj_desc->kernel_name;
        }
        for (cnt = 0; (cnt < loop_max) && (status == (vx_status)VX_SUCCESS); cnt ++)
        {
            target_kernel_instance = tivxTargetKernelInstanceAlloc(
                (vx_enum)node_obj_desc->kernel_id, kernel_name, (vx_enum)node_obj_desc->target_id);
    
            if(target_kernel_instance == NULL)
            {
                VX_PRINT(VX_ZONE_ERROR, "target_kernel_instance is NULL\n");
                status = (vx_status)VX_ERROR_NO_RESOURCES;
            }
            else
            {
                /* This target_kernel_instance is newly allocated in this create function.  The "kernel"
                 * in this case is a target_kernel which has not had num_pipeup_bufs set either
                 * and thus needs to be set from the node_obj_desc which received this value from
                 * the host side vx_kernel. */
                target_kernel_instance->kernel->num_pipeup_bufs = node_obj_desc->num_pipeup_bufs;
    
                if (target_kernel_instance->kernel->num_pipeup_bufs > 1U)
                {
                    target_kernel_instance->state = (vx_enum)VX_NODE_STATE_PIPEUP;
                }
                else
                {
                    target_kernel_instance->state = (vx_enum)VX_NODE_STATE_STEADY;
                }
    
                /* setting the tile size for each node */
                target_kernel_instance->block_width = node_obj_desc->block_width;
                target_kernel_instance->block_height = node_obj_desc->block_height;
    
                if (tivxFlagIsBitSet(node_obj_desc->flags,TIVX_NODE_FLAG_IS_REPLICATED) ==
                    (vx_bool)vx_true_e)
                {
                    target_kernel_instance->is_kernel_instance_replicated = (vx_bool)vx_true_e;
                }
    
                /* save index key for fast retrival of handle during run-time */
                node_obj_desc->target_kernel_index[cnt] =
                    tivxTargetKernelInstanceGetIndex(target_kernel_instance);
    
                for(i=0; i<node_obj_desc->num_params ; i++)
                {
                    parent_obj_desc[i] = NULL;
    
                    if((is_prm_replicated & ((uint32_t)1U << i)) != 0U)
                    {
                        prm_obj_desc = tivxObjDescGet(node_obj_desc->data_id[i]);
                        if(prm_obj_desc != NULL)
                        {
                            parent_obj_desc[i] = tivxObjDescGet(
                                prm_obj_desc->scope_obj_desc_id);
                        }
                    }
                }
    
                for(i=0; i<node_obj_desc->num_params ; i++)
                {
                    params[i] = NULL;
                    if((is_prm_replicated & ((uint32_t)1U << i)) != 0U)
                    {
                        if(parent_obj_desc[i] != NULL)
                        {
                            if((vx_enum)parent_obj_desc[i]->type==(vx_enum)TIVX_OBJ_DESC_OBJARRAY)
                            {
                                params[i] = tivxObjDescGet(
                                    ((tivx_obj_desc_object_array_t*)parent_obj_desc[i])->
                                        obj_desc_id[cnt]);
                            }
                            else
                            if((vx_enum)parent_obj_desc[i]->type==(vx_enum)TIVX_OBJ_DESC_PYRAMID)
                            {
                                params[i] = tivxObjDescGet(
                                    ((tivx_obj_desc_pyramid_t*)parent_obj_desc[i])->
                                        obj_desc_id[cnt]);
                            }
                            else
                            {
                                params[i] = NULL;
                            }
                        }
                    }
                    else
                    {
                        params[i] = tivxObjDescGet(node_obj_desc->data_id[i]);
                    }
                }
    
                /* Linking the reference to the node object descriptor */
                target_kernel_instance->node_obj_desc = node_obj_desc;
    
                /* copy border mode also in the target_kernel_instance */
                tivx_obj_desc_memcpy(&target_kernel_instance->border_mode, &node_obj_desc->border_mode, (uint32_t)sizeof(vx_border_t));
    
                if (tivxFlagIsBitSet(node_obj_desc->flags,TIVX_NODE_FLAG_IS_SUPERNODE) ==
                    (vx_bool)vx_true_e)
                {
                    params[0] = (tivx_obj_desc_t *) tivxObjDescGet( node_obj_desc->base.scope_obj_desc_id );
    
                    status = tivxTargetKernelCreate(target_kernel_instance,
                        params, 1);
    				VX_PRINT(VX_ZONE_ERROR,"cyhdebug: tivxFlagIsBitSet(TIVX_NODE_FLAG_IS_SUPERNODE) == vx_true_e---------------------status: %d\n", status);
                }
                else
                {
                	
                    status = tivxTargetKernelCreate(target_kernel_instance,
                        params, (uint16_t)node_obj_desc->num_params);
    				VX_PRINT(VX_ZONE_ERROR,"cyhdebug: tivxFlagIsBitSet(TIVX_NODE_FLAG_IS_SUPERNODE) == vx_false_e---------------------status:%d\n", status);
                }
    
                if(status!=(vx_status)VX_SUCCESS)
                {
                    tivxTargetKernelInstanceFree(&target_kernel_instance);
                }
            }
        }
    
        if ((vx_status)VX_SUCCESS != status)
        {
            for (i = 0; i < cnt; i ++)
            {
                target_kernel_instance = tivxTargetKernelInstanceGet(
                    (uint16_t)node_obj_desc->target_kernel_index[i], (vx_enum)node_obj_desc->kernel_id);
    
                if (NULL != target_kernel_instance)
                {
                    tivxTargetKernelInstanceFree(&target_kernel_instance);
                }
            }
        }
    
        return status;
    }
    
    static vx_status tivxTargetNodeDescNodeDelete(const tivx_obj_desc_node_t *node_obj_desc)
    {
        tivx_target_kernel_instance target_kernel_instance;
        vx_status status = (vx_status)VX_SUCCESS;
        uint16_t i, cnt, loop_max = 1;
        tivx_obj_desc_t *params[TIVX_KERNEL_MAX_PARAMS];
    
        if (tivxFlagIsBitSet(node_obj_desc->flags,TIVX_NODE_FLAG_IS_REPLICATED) ==
            (vx_bool)vx_true_e)
        {
            loop_max = (uint16_t)node_obj_desc->num_of_replicas;
        }
    
        for (cnt = 0; cnt < loop_max; cnt ++)
        {
            target_kernel_instance = tivxTargetKernelInstanceGet(
                (uint16_t)node_obj_desc->target_kernel_index[cnt], (vx_enum)node_obj_desc->kernel_id);
    
            if(target_kernel_instance == NULL)
            {
                VX_PRINT(VX_ZONE_ERROR, "target_kernel_instance is NULL\n");
                status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
            }
            else
            {
                {
                    /* NOTE: nothing special for replicated node during
                             create/delete */
                    for(i=0; i<node_obj_desc->num_params ; i++)
                    {
                        params[i] = tivxObjDescGet(node_obj_desc->data_id[i]);
                    }
    
                    if (tivxFlagIsBitSet(node_obj_desc->flags,TIVX_NODE_FLAG_IS_SUPERNODE) ==
                        (vx_bool)vx_true_e)
                    {
                        params[0] = (tivx_obj_desc_t *) tivxObjDescGet( node_obj_desc->base.scope_obj_desc_id );
    
                        tivxCheckStatus(&status, tivxTargetKernelDelete(target_kernel_instance, params, 1));
                    }
                    else
                    {
                        tivxCheckStatus(&status, tivxTargetKernelDelete(target_kernel_instance,
                            params, (uint16_t)node_obj_desc->num_params));
                    }
                }
    
                tivxTargetKernelInstanceFree(&target_kernel_instance);
            }
        }
    
        return status;
    }
    
    static vx_status tivxTargetNodeSendCommand(const tivx_obj_desc_cmd_t *cmd_obj_desc,
        uint32_t node_id, const tivx_obj_desc_node_t *node_obj_desc)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        int16_t i;
        tivx_target_kernel_instance target_kernel_instance;
        tivx_obj_desc_t *params[TIVX_CMD_MAX_OBJ_DESCS];
    
        target_kernel_instance = tivxTargetKernelInstanceGet(
            (uint16_t)node_obj_desc->target_kernel_index[node_id], (vx_enum)node_obj_desc->kernel_id);
    
        if(target_kernel_instance == NULL)
        {
            VX_PRINT(VX_ZONE_ERROR, "target_kernel_instance is NULL\n");
            status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
        }
        else
        {
            for(i=0; i<(int32_t)cmd_obj_desc->num_cmd_params; i++)
            {
                params[i] = tivxObjDescGet(cmd_obj_desc->cmd_params_desc_id[i]);
            }
    
            status = tivxTargetKernelControl(target_kernel_instance,
                cmd_obj_desc->node_cmd_id, params,
                (uint16_t)cmd_obj_desc->num_cmd_params);
        }
    
        return (status);
    }
    
    static vx_status tivxTargetNodeDescNodeControl(
        const tivx_obj_desc_cmd_t *cmd_obj_desc,
        const tivx_obj_desc_node_t *node_obj_desc)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        uint16_t cnt, loop_max = 1;
    
        if (tivxFlagIsBitSet(node_obj_desc->flags,TIVX_NODE_FLAG_IS_REPLICATED) ==
            (vx_bool)vx_true_e)
        {
            loop_max = (uint16_t)node_obj_desc->num_of_replicas;
    
            if ((vx_enum)TIVX_CONTROL_CMD_SEND_TO_ALL_REPLICATED_NODES ==
                cmd_obj_desc->replicated_node_idx)
            {
                for (cnt = 0; cnt < loop_max; cnt ++)
                {
                    status = tivxTargetNodeSendCommand(cmd_obj_desc, cnt,
                        node_obj_desc);
                    if ((vx_status)VX_SUCCESS != status)
                    {
                        VX_PRINT(VX_ZONE_ERROR, "SendCommand Failed\n");
                        break;
                    }
                }
            }
            else
            {
                /* Replicated node idx must be less than total replicated nodes. */
                if (cmd_obj_desc->replicated_node_idx < (int32_t)loop_max)
                {
                    status = tivxTargetNodeSendCommand(cmd_obj_desc,
                        (uint32_t)cmd_obj_desc->replicated_node_idx,
                        node_obj_desc);
                    if ((vx_status)VX_SUCCESS != status)
                    {
                        VX_PRINT(VX_ZONE_ERROR, "SendCommand Failed\n");
                    }
                }
                else
                {
                    VX_PRINT(VX_ZONE_ERROR, "Incorrect node id\n");
                    status = (vx_status)VX_FAILURE;
                }
            }
        }
        else
        {
            /* For non-replicated node, ignore node-id field */
            status = tivxTargetNodeSendCommand(cmd_obj_desc, 0U, node_obj_desc);
            if ((vx_status)VX_SUCCESS != status)
            {
                VX_PRINT(VX_ZONE_ERROR, "SendCommand Failed\n");
            }
        }
    
        return status;
    }
    
    static void tivxTargetCmdDescHandleAck(tivx_obj_desc_cmd_t *cmd_obj_desc)
    {
        if( tivxFlagIsBitSet( cmd_obj_desc->flags, TIVX_CMD_FLAG_IS_ACK) != 0)
        {
            tivxFlagBitClear( &cmd_obj_desc->flags, TIVX_CMD_FLAG_IS_ACK);
    
            tivxEventPost((tivx_event)(uintptr_t)cmd_obj_desc->ack_event_handle);
        }
    }
    
    static vx_action tivxTargetCmdDescHandleUserCallback(tivx_obj_desc_node_t *node_obj_desc, uint64_t timestamp)
    {
        vx_action action;
        vx_node node = (vx_node)(uintptr_t)node_obj_desc->base.host_ref;
        vx_bool is_send_graph_complete_event = (vx_bool)vx_false_e;
    
        /* return action is ignored */
        action = ownNodeExecuteUserCallback(node);
    
        /* if this is leaf node, check if graph is completed */
        if(ownNodeGetNumOutNodes(node)==0U)
        {
            /* check if graph represetned by this node at this pipeline_id
             * is completed and do graph
             * completion handling
             */
            is_send_graph_complete_event = ownCheckGraphCompleted(node->graph, node_obj_desc->pipeline_id);
    
        }
    
        /* first do all booking keeping and then send event q events */
        /* send completion event if enabled */
        ownNodeCheckAndSendCompletionEvent(node_obj_desc, timestamp);
    
        /* if an error occurred within the node, then send an error completion event */
        if ((vx_status)VX_SUCCESS != (vx_status)node_obj_desc->exe_status)
        {
            ownNodeCheckAndSendErrorEvent(node_obj_desc, timestamp, (vx_status)node_obj_desc->exe_status);
        }
    
        /* Clearing node status now that it has been sent as an error event */
        node_obj_desc->exe_status = 0;
    
        /* first we let any node events to go thru before sending graph events */
        if(is_send_graph_complete_event!= 0)
        {
            ownSendGraphCompletedEvent(node->graph);
        }
    
        return (action);
    }
    
    static void tivxTargetSetGraphStateAbandon(
        const tivx_obj_desc_node_t *node_obj_desc)
    {
        vx_node node = (vx_node)(uintptr_t)node_obj_desc->base.host_ref;
    
        ownSetGraphState(node->graph, node_obj_desc->pipeline_id, (vx_enum)VX_GRAPH_STATE_ABANDONED);
    }
    
    static void tivxTargetCmdDescSendAck(tivx_obj_desc_cmd_t *cmd_obj_desc, vx_status status)
    {
        if( tivxFlagIsBitSet( cmd_obj_desc->flags, TIVX_CMD_FLAG_SEND_ACK) != 0)
        {
            tivxFlagBitSet( &cmd_obj_desc->flags, TIVX_CMD_FLAG_IS_ACK);
    
            cmd_obj_desc->cmd_status = (uint32_t)status;
    
            tivxObjDescSend(cmd_obj_desc->src_target_id, cmd_obj_desc->base.obj_desc_id);
        }
    }
    
    static void tivxTargetCmdDescHandler(tivx_obj_desc_cmd_t *cmd_obj_desc)
    {
        uint16_t node_obj_desc_id;
        tivx_obj_desc_node_t *node_obj_desc;
        vx_action action;
        vx_status status = (vx_status)VX_SUCCESS;
    	VX_PRINT(VX_ZONE_ERROR,"cyhdebug: run tivxTargetCmdDescHandler---------------\n");
        switch(cmd_obj_desc->cmd_id)
        {
            case (vx_enum)TIVX_CMD_NODE_CREATE:
            case (vx_enum)TIVX_CMD_NODE_DELETE:
            case (vx_enum)TIVX_CMD_NODE_CONTROL:
    			if (cmd_obj_desc->cmd_id == TIVX_CMD_NODE_CREATE) {
    				VX_PRINT(VX_ZONE_ERROR, "cyhdebug: get cmd_id: %d -> TIVX_CMD_NODE_CREATE\n");
    			}
                if( tivxFlagIsBitSet( cmd_obj_desc->flags, TIVX_CMD_FLAG_IS_ACK) == (vx_bool)vx_false_e )
                {
                	VX_PRINT(VX_ZONE_ERROR,"cyhdebug: tivxFlagIsBitSet(TIVX_CMD_FLAG_IS_ACK)  == vx_false_e---------------------\n");
                    node_obj_desc_id = cmd_obj_desc->obj_desc_id[0];
                    node_obj_desc = (tivx_obj_desc_node_t*)tivxObjDescGet(node_obj_desc_id);
    
                    if( tivxObjDescIsValidType( (tivx_obj_desc_t*)node_obj_desc, TIVX_OBJ_DESC_NODE) != 0)
                    {
                        if( tivxFlagIsBitSet(node_obj_desc->flags,TIVX_NODE_FLAG_IS_TARGET_KERNEL) != 0)
                        {
                        	VX_PRINT(VX_ZONE_ERROR,"cyhdebug: tivxFlagIsBitSet(TIVX_NODE_FLAG_IS_TARGET_KERNEL)  != 0---------------------\n");
                            if((vx_enum)cmd_obj_desc->cmd_id == (vx_enum)TIVX_CMD_NODE_CREATE)
                            {
                            	VX_PRINT(VX_ZONE_ERROR,"cyhdebug: run tivxTargetNodeDescNodeCreate---------------------\n");
                                status = tivxTargetNodeDescNodeCreate(node_obj_desc);
                            }
                            else
                            if((vx_enum)cmd_obj_desc->cmd_id == (vx_enum)TIVX_CMD_NODE_DELETE)
                            {
                            	VX_PRINT(VX_ZONE_ERROR,"cyhdebug: run tivxTargetNodeDescNodeDelete---------------------\n");
                                status = tivxTargetNodeDescNodeDelete(node_obj_desc);
                            }
                            else
                            if((vx_enum)cmd_obj_desc->cmd_id == (vx_enum)TIVX_CMD_NODE_CONTROL)
                            {
                            	VX_PRINT(VX_ZONE_ERROR,"cyhdebug: run tivxTargetNodeDescNodeControl---------------------\n");
                                status = tivxTargetNodeDescNodeControl(cmd_obj_desc, node_obj_desc);
                            }
                            else
                            {
                            	VX_PRINT(VX_ZONE_ERROR,"cyhdebug: do nothing---------------------\n");
                                /* do nothing */
                            }
                        }
                    }
                    else
                    {
                        VX_PRINT(VX_ZONE_ERROR, "object descriptor type is invalid\n");
                        status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
                    }
    				VX_PRINT(VX_ZONE_ERROR,"cyhdebug: run tivxTargetCmdDescSendAck: send status: %d---------------------\n", status);
                    tivxTargetCmdDescSendAck(cmd_obj_desc, status);
                }
                else
                {
                    /* this is ACK for a previously sent command */
    				VX_PRINT(VX_ZONE_ERROR,"cyhdebug: run tivxTargetCmdDescHandleAck: ---------------------\n");
                    tivxTargetCmdDescHandleAck(cmd_obj_desc);
                }
                break;
    
            case (vx_enum)TIVX_CMD_NODE_USER_CALLBACK:
    			VX_PRINT(VX_ZONE_ERROR, "cyhdebug: get cmd_id: %d\n", cmd_obj_desc->cmd_id);
                node_obj_desc_id = cmd_obj_desc->obj_desc_id[0];
                node_obj_desc = (tivx_obj_desc_node_t*)tivxObjDescGet(node_obj_desc_id);
    
                if( tivxObjDescIsValidType( (tivx_obj_desc_t*)node_obj_desc, TIVX_OBJ_DESC_NODE) != 0)
                {
                    uint64_t timestamp;
    
                    tivx_uint32_to_uint64(&timestamp, cmd_obj_desc->timestamp_h, cmd_obj_desc->timestamp_l);
    
                    action = tivxTargetCmdDescHandleUserCallback(node_obj_desc, timestamp);
    
                    if (action == (vx_enum)VX_ACTION_ABANDON)
                    {
                        tivxTargetSetGraphStateAbandon(node_obj_desc);
                    }
                }
                /* No ack for user callback command */
                break;
            case (vx_enum)TIVX_CMD_DATA_REF_CONSUMED:
            {
            	VX_PRINT(VX_ZONE_ERROR, "cyhdebug: get cmd_id: %d\n", cmd_obj_desc->cmd_id);
                tivx_data_ref_queue data_ref_q;
    
                data_ref_q = (tivx_data_ref_queue)ownReferenceGetHandleFromObjDescId(cmd_obj_desc->obj_desc_id[0]);
    
                if( data_ref_q != NULL )
                {
                    uint64_t timestamp;
    
                    tivx_uint32_to_uint64(&timestamp, cmd_obj_desc->timestamp_h, cmd_obj_desc->timestamp_l);
    
                    tivxDataRefQueueSendRefConsumedEvent(data_ref_q, timestamp);
                }
                /* No ack for this command */
            }
                break;
            default:
    
                break;
        }
    
    }
    
    static void VX_CALLBACK tivxTargetTaskMain(void *app_var)
    {
        tivx_target target = (tivx_target)app_var;
        tivx_obj_desc_t *obj_desc;
        uint16_t obj_desc_id;
        vx_status status = (vx_status)VX_SUCCESS;
    
        /* Adding OS-specific task init functions */
        tivxPlatformTaskInit();
    
        while(target->targetExitRequest == (vx_bool)vx_false_e)
        {
            status = tivxTargetDequeueObjDesc(target,
                        &obj_desc_id, TIVX_EVENT_TIMEOUT_WAIT_FOREVER);
    
            if(    (status != (vx_status)VX_SUCCESS)
                || ((vx_enum)obj_desc_id == (vx_enum)TIVX_OBJ_DESC_INVALID) )
            {
                /* in case of error, do nothing,
                 * if target exit was requested, while(...) condition check with
                 * check and exit
                 */
            }
            else
            {
                obj_desc = tivxObjDescGet(obj_desc_id);
                if(obj_desc == NULL)
                {
                    /* in valid obj_desc_id received */
                }
                else
                {
                    tivxLogRtTraceTargetExeStart(target, obj_desc);
    
                    switch(obj_desc->type)
                    {
                        case (vx_enum)TIVX_OBJ_DESC_CMD:
                            if( tivxObjDescIsValidType( obj_desc, TIVX_OBJ_DESC_CMD) != 0)
                            {
                                tivxTargetCmdDescHandler((tivx_obj_desc_cmd_t*)obj_desc);
                            }
                            break;
                        case (vx_enum)TIVX_OBJ_DESC_NODE:
                            if( tivxObjDescIsValidType( obj_desc, TIVX_OBJ_DESC_NODE) != 0)
                            {
                                tivxTargetNodeDescNodeExecute(target, (tivx_obj_desc_node_t*)obj_desc);
                            }
                            break;
                        default:
                            /* unsupported obj_desc received at target */
                            break;
                    }
    
                    tivxLogRtTraceTargetExeEnd(target, obj_desc);
                }
            }
        }
    
        target->targetExitDone = (vx_bool)vx_true_e;
    }
    
    vx_status tivxTargetCreate(vx_enum target_id, const tivx_target_create_params_t *params)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        tivx_target target;
    
        target = tivxTargetAllocHandle(target_id);
    
        if(target == NULL)
        {
            VX_PRINT(VX_ZONE_ERROR, "target is NULL\n");
            status = (vx_status)VX_ERROR_NO_RESOURCES;
        }
        else
        {
            target->target_id = target_id;
    
            tivxTaskSetDefaultCreateParams(&target->task_params);
            target->task_params.stack_ptr = params->task_stack_ptr;
            target->task_params.stack_size = params->task_stack_size;
            target->task_params.core_affinity = params->task_core_affinity;
            target->task_params.priority = params->task_priority;
            target->task_params.task_main = &tivxTargetTaskMain;
            target->task_params.app_var = target;
            strncpy(target->task_params.task_name, params->task_name, TIVX_MAX_TASK_NAME);
            target->task_params.task_name[TIVX_MAX_TASK_NAME-1U] = '\0';
    
            target->targetExitRequest = (vx_bool)vx_false_e;
            target->targetExitDone = (vx_bool)vx_false_e;
    
            /* create job queue */
            status = tivxQueueCreate(&target->job_queue_handle,
                            TIVX_TARGET_MAX_JOB_QUEUE_DEPTH,
                            target->job_queue_memory,
                            TIVX_QUEUE_FLAG_BLOCK_ON_GET);
    
            if(status == (vx_status)VX_SUCCESS)
            {
                /* create and start target task */
                status = tivxTaskCreate(&target->task_handle, &target->task_params);
                if(status != (vx_status)VX_SUCCESS)
                {
                    tivxQueueDelete(&target->job_queue_handle);
                }
            }
    
            if (status != (vx_status)VX_SUCCESS)
            {
                tivxTargetFreeHandle(&target);
            }
        }
        return status;
    }
    
    vx_status tivxTargetDelete(vx_enum target_id)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        tivx_target target;
    
        target = tivxTargetGetHandle(target_id);
    
        /* delete task */
    
        if (NULL != target)
        {
            /* set flag to break target from main loop */
            target->targetExitRequest = (vx_bool)vx_true_e;
    
            /* queue a invalid object descriptor to unblock queue wait */
            tivxTargetQueueObjDesc(target_id, (vx_enum)TIVX_OBJ_DESC_INVALID);
    
            /* wait until target exit is done */
            while(target->targetExitDone==(vx_bool)vx_false_e)
            {
                tivxTaskWaitMsecs(1);
            }
            tivxTaskDelete(&target->task_handle);
    
            /* delete job queue */
            tivxQueueDelete(&target->job_queue_handle);
        }
    
        return status;
    }
    
    void tivxTargetTriggerNode(uint16_t node_obj_desc_id)
    {
        tivx_obj_desc_node_t *node_obj_desc;
    
        node_obj_desc = (tivx_obj_desc_node_t*)tivxObjDescGet(node_obj_desc_id);
    
        if( tivxObjDescIsValidType( (tivx_obj_desc_t*)node_obj_desc, TIVX_OBJ_DESC_NODE) != 0)
        {
            tivxObjDescSend( node_obj_desc->target_id, node_obj_desc_id);
        }
    }
    
    vx_status tivxTargetQueueObjDesc(vx_enum target_id, uint16_t obj_desc_id)
    {
        vx_status status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
        tivx_target target = tivxTargetGetHandle(target_id);
    
        if(target!=NULL)
        {
            status = tivxQueuePut(&target->job_queue_handle,
                    (uintptr_t)obj_desc_id, TIVX_EVENT_TIMEOUT_NO_WAIT);
    
            if((vx_status)VX_SUCCESS != status)
            {
                VX_PRINT(VX_ZONE_ERROR,"***************************************************************************************************\n");
                VX_PRINT(VX_ZONE_ERROR,"FATAL ERROR: tivxQueuePut failed\n");
                VX_PRINT(VX_ZONE_ERROR,"May need to increase the value of TIVX_TARGET_MAX_JOB_QUEUE_DEPTH in tiovx/include/TI/tivx_config.h\n");
                VX_PRINT(VX_ZONE_ERROR,"***************************************************************************************************\n");
            }
        }
        else
        {
            VX_PRINT(VX_ZONE_ERROR, "target is NULL\n");
        }
    
        return status;
    }
    
    void tivxTargetSetDefaultCreateParams(tivx_target_create_params_t *params)
    {
        params->task_stack_ptr = NULL;
        params->task_stack_size = 0;
        params->task_core_affinity = 0;
        params->task_priority = TIVX_TASK_PRI_LOWEST;
        strncpy(params->task_name, "TIVX_TARGET", TIVX_MAX_TASK_NAME);
        params->task_name[TIVX_MAX_TASK_NAME-1U] = '\0';
    }
    
    vx_enum tivxTargetGetCpuId(vx_enum target_id)
    {
        vx_uint32 returnVal = TIVX_GET_CPU_ID(target_id);
        return ((vx_enum)returnVal);
    }
    
    void tivxTargetInit(void)
    {
        uint16_t i;
    
        for(i=0; i<dimof(g_target_table); i++)
        {
            g_target_table[i].target_id = (vx_enum)TIVX_TARGET_ID_INVALID;
        }
    
        tivxTargetKernelInit();
        tivxTargetKernelInstanceInit();
    }
    
    void tivxTargetDeInit(void)
    {
        tivxTargetKernelInstanceDeInit();
        tivxTargetKernelDeInit();
    
    }
    
    void tivxTargetSetTimestamp(
        const tivx_obj_desc_node_t *node_obj_desc, tivx_obj_desc_t *obj_desc[])
    {
        uint16_t prm_id;
        uint64_t timestamp = 0, obj_timestamp = 0;
        uint32_t is_prm_input_flag;
        tivx_obj_desc_t *parent_obj_desc;
    
        is_prm_input_flag = node_obj_desc->is_prm_input;
    
        /* Reading all input timestamps, taking the most recent of the timestamps to pass along */
        for (prm_id = 0U; prm_id < node_obj_desc->num_params; prm_id++)
        {
            if (NULL != obj_desc[prm_id])
            {
                if (tivxFlagIsBitSet(is_prm_input_flag, ((uint32_t)1U<<prm_id)))
                {
                    obj_timestamp = obj_desc[prm_id]->timestamp;
    
                    if (obj_timestamp > timestamp)
                    {
                        timestamp = obj_timestamp;
                    }
                }
            }
        }
    
        /* Setting all outputs to use most recent of the timestamps */
        for (prm_id = 0U; prm_id < node_obj_desc->num_params; prm_id++)
        {
            if (NULL != obj_desc[prm_id])
            {
                if (!tivxFlagIsBitSet(is_prm_input_flag, ((uint32_t)1U<<prm_id)))
                {
                    obj_desc[prm_id]->timestamp = timestamp;
    
                    /* Handle case of parent objects */
                    parent_obj_desc = tivxObjDescGet(
                            obj_desc[prm_id]->scope_obj_desc_id);
    
                    if(parent_obj_desc!=NULL)
                    {
                        parent_obj_desc->timestamp = timestamp;
                    }
                }
            }
        }
    }
    
    

    /*
    *
    * Copyright (c) 2017 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 <vx_internal.h>
    
    static tivx_target_kernel VX_API_CALL tivxAddTargetKernelInternal(
                                 vx_enum kernel_id,
                                 const char *kernel_name,
                                 const char *target_name,
                                 tivx_target_kernel_f process_func,
                                 tivx_target_kernel_f create_func,
                                 tivx_target_kernel_f delete_func,
                                 tivx_target_kernel_control_f control_func,
                                 void *priv_arg);
    
    static tivx_target_kernel_t g_target_kernel_table[TIVX_TARGET_KERNEL_MAX];
    static tivx_mutex g_target_kernel_lock;
    
    vx_status tivxTargetKernelInit(void)
    {
        uint32_t i;
        vx_status status;
    
        for(i=0; i<dimof(g_target_kernel_table); i++)
        {
            g_target_kernel_table[i].kernel_id = (vx_int32)TIVX_TARGET_KERNEL_ID_INVALID;
            g_target_kernel_table[i].target_id = (vx_int32)TIVX_TARGET_KERNEL_ID_INVALID;
        }
    
        status = tivxMutexCreate(&g_target_kernel_lock);
    
        return status;
    }
    
    void tivxTargetKernelDeInit(void)
    {
        tivxMutexDelete(&g_target_kernel_lock);
    }
    
    static tivx_target_kernel VX_API_CALL tivxAddTargetKernelInternal(
                                 vx_enum kernel_id,
                                 const char *kernel_name,
                                 const char *target_name,
                                 tivx_target_kernel_f process_func,
                                 tivx_target_kernel_f create_func,
                                 tivx_target_kernel_f delete_func,
                                 tivx_target_kernel_control_f control_func,
                                 void *priv_arg)
    {
        uint32_t i;
        tivx_target_kernel knl = NULL;
        vx_status status;
        vx_bool resource_added = (vx_bool)vx_false_e;
    
        if ((NULL != target_name) &&
            (process_func != NULL) && (create_func != NULL))
        {
            status = tivxMutexLock(g_target_kernel_lock);
    
            if ((vx_status)VX_SUCCESS == status)
            {
                for(i=0; i<dimof(g_target_kernel_table); i++)
                {
                    if ((vx_int32)TIVX_TARGET_KERNEL_ID_INVALID ==
                        g_target_kernel_table[i].kernel_id)
                    {
                        g_target_kernel_table[i].kernel_id = kernel_id;
                        g_target_kernel_table[i].kernel_name[0] = '\0';
                        if(kernel_name!=NULL)
                        {
                            strncpy(g_target_kernel_table[i].kernel_name, kernel_name, VX_MAX_KERNEL_NAME-1U);
                            g_target_kernel_table[i].kernel_name[VX_MAX_KERNEL_NAME-1U] = '\0';
                            VX_PRINT(VX_ZONE_INFO, "registered kernel %s on target %s\n", kernel_name, target_name);
                        }
                        g_target_kernel_table[i].target_id =
                            tivxPlatformGetTargetId(target_name);
                        g_target_kernel_table[i].process_func = process_func;
                        g_target_kernel_table[i].create_func = create_func;
                        g_target_kernel_table[i].delete_func = delete_func;
                        g_target_kernel_table[i].control_func = control_func;
                        g_target_kernel_table[i].caller_priv_arg = priv_arg;
                        g_target_kernel_table[i].num_pipeup_bufs = 1;
    
                        knl = &g_target_kernel_table[i];
    
                        tivxLogResourceAlloc("TIVX_TARGET_KERNEL_MAX", 1);
                        resource_added = (vx_bool)vx_true_e;
    
                        break;
                    }
                }
    
                if ((vx_bool)vx_false_e == resource_added)
                {
                    VX_PRINT(VX_ZONE_WARNING, "May need to increase the value of TIVX_TARGET_KERNEL_MAX in tiovx/include/TI/tivx_config.h\n");
                }
    
                tivxMutexUnlock(g_target_kernel_lock);
            }
        }
        else
        {
            VX_PRINT(VX_ZONE_ERROR, "Invalid parameters given to function\n");
        }
    
        return (knl);
    }
    
    VX_API_ENTRY tivx_target_kernel VX_API_CALL tivxAddTargetKernelByName(
                                 const char *kernel_name,
                                 const char *target_name,
                                 tivx_target_kernel_f process_func,
                                 tivx_target_kernel_f create_func,
                                 tivx_target_kernel_f delete_func,
                                 tivx_target_kernel_control_f control_func,
                                 void *priv_arg)
    {
        return tivxAddTargetKernelInternal(
                    (vx_int32)TIVX_TARGET_KERNEL_ID_NOT_USED,
                    kernel_name, target_name, process_func, create_func, delete_func, control_func, priv_arg);
    }
    
    VX_API_ENTRY tivx_target_kernel VX_API_CALL tivxAddTargetKernel(
                                 vx_enum kernel_id,
                                 const char *target_name,
                                 tivx_target_kernel_f process_func,
                                 tivx_target_kernel_f create_func,
                                 tivx_target_kernel_f delete_func,
                                 tivx_target_kernel_control_f control_func,
                                 void *priv_arg)
    {
        return tivxAddTargetKernelInternal(
                    kernel_id,
                    NULL, target_name, process_func, create_func, delete_func, control_func, priv_arg);
    }
    
    VX_API_ENTRY vx_status VX_API_CALL tivxRemoveTargetKernel(
        tivx_target_kernel target_kernel)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        uint32_t i;
    
        if (NULL != target_kernel)
        {
            status = tivxMutexLock(g_target_kernel_lock);
            if ((vx_status)VX_SUCCESS == status)
            {
                for(i=0; i<dimof(g_target_kernel_table); i++)
                {
                    if (target_kernel ==
                        &g_target_kernel_table[i])
                    {
                        g_target_kernel_table[i].kernel_id =
                            (vx_int32)TIVX_TARGET_KERNEL_ID_INVALID;
                        g_target_kernel_table[i].target_id =
                            (vx_int32)TIVX_TARGET_KERNEL_ID_INVALID;
                        g_target_kernel_table[i].process_func = NULL;
                        g_target_kernel_table[i].create_func = NULL;
                        g_target_kernel_table[i].delete_func = NULL;
                        g_target_kernel_table[i].control_func = NULL;
    
                        tivxLogResourceFree("TIVX_TARGET_KERNEL_MAX", 1);
    
                        break;
                    }
                }
    
                tivxMutexUnlock(g_target_kernel_lock);
            }
        }
    
        return (status);
    }
    
    tivx_target_kernel tivxTargetKernelGet(vx_enum kernel_id, volatile char *kernel_name, vx_enum target_id)
    {
        uint32_t i;
        tivx_target_kernel knl = NULL;
        vx_status status;
    
        status = tivxMutexLock(g_target_kernel_lock);
    
        if ((vx_status)VX_SUCCESS == status)
        {
            tivx_target_kernel tmp_knl = NULL;
    
            for(i=0; i<dimof(g_target_kernel_table); i++)
            {
                tmp_knl = &g_target_kernel_table[i];
                if(tmp_knl->kernel_name[0]==(char)0)
                {
                    /* kernel is registered using kernel_id only */
                    if ((kernel_id == tmp_knl->kernel_id) &&
                        (target_id == tmp_knl->target_id))
                    {
                        knl = tmp_knl;
                    }
                }
                else
                if(kernel_name!=NULL)
                {
                    /* kernel registered using name, compare using kernel_name string */
                    if( (tivx_obj_desc_strncmp_delim(kernel_name, tmp_knl->kernel_name, VX_MAX_KERNEL_NAME, ':')==0)
                        && (target_id == tmp_knl->target_id)
                        )
                    {
                        /* copy kernel_id into tmp_knl->kernel_id since it will used
                         * later during tivxTargetKernelInstanceGet as a additional check
                         * to make the correct target kernel instance is being referenced
                         */
                        tmp_knl->kernel_id = kernel_id;
                        knl = tmp_knl;
                    }
                }
                else
                {
                    /* do nothing */
                }
                if(knl!=NULL)
                {
                    /* kernel found */
                    break;
                }
            }
    
            tivxMutexUnlock(g_target_kernel_lock);
        }
    
        return (knl);
    }
    
    vx_status tivxTargetKernelCreate(
        tivx_target_kernel_instance target_kernel_instance,
        tivx_obj_desc_t *obj_desc[], uint16_t num_params)
    {
        vx_status status = (vx_status)VX_FAILURE;
        tivx_target_kernel knl = NULL;
    
        if ((NULL != target_kernel_instance) && (NULL != obj_desc))
        {
            /* Check if the kernel is valid */
            knl = tivxTargetKernelInstanceGetKernel(target_kernel_instance);
    
            if ((NULL != knl) && (NULL != knl->create_func))
            {
                VX_PRINT(VX_ZONE_ERROR, "Executing create callback for kernel [%s]\n", knl->kernel_name);
    
                status = knl->create_func(
                    target_kernel_instance, obj_desc, num_params,
                    knl->caller_priv_arg);
    
                VX_PRINT(VX_ZONE_ERROR, "Done executing create callback for kernel [%s]---status: %d\n", knl->kernel_name, status);
            }
            else
            {
                VX_PRINT(VX_ZONE_ERROR, "Kernel create function is NULL\n");
                status = (vx_status)VX_FAILURE;
            }
        }
    
        return (status);
    }
    
    vx_status tivxTargetKernelDelete(
        tivx_target_kernel_instance target_kernel_instance,
        tivx_obj_desc_t *obj_desc[], uint16_t num_params)
    {
        vx_status status = (vx_status)VX_FAILURE;
        tivx_target_kernel knl = NULL;
    
        if ((NULL != target_kernel_instance) && (NULL != obj_desc))
        {
            /* Check if the kernel is valid */
            knl = tivxTargetKernelInstanceGetKernel(target_kernel_instance);
    
            if ((NULL != knl) && (NULL != knl->delete_func))
            {
                VX_PRINT(VX_ZONE_INFO, "Executing delete callback for kernel [%s]\n", knl->kernel_name);
    
                status = knl->delete_func(
                    target_kernel_instance, obj_desc, num_params,
                    knl->caller_priv_arg);
    
                VX_PRINT(VX_ZONE_INFO, "Done executing delete callback for kernel [%s]\n", knl->kernel_name);
            }
            else
            {
                VX_PRINT(VX_ZONE_ERROR, "Kernel delete function is NULL\n");
                status = (vx_status)VX_FAILURE;
            }
        }
    
        return (status);
    }
    
    vx_status tivxTargetKernelExecute(
        tivx_target_kernel_instance target_kernel_instance,
        tivx_obj_desc_t *obj_desc[], uint16_t num_params)
    {
        vx_status status = (vx_status)VX_FAILURE;
        tivx_target_kernel knl = NULL;
    
        if ((NULL != target_kernel_instance) && (NULL != obj_desc))
        {
            /* Check if the kernel is valid */
            knl = tivxTargetKernelInstanceGetKernel(target_kernel_instance);
    
            if ((NULL != knl) && (NULL != knl->process_func))
            {
                VX_PRINT(VX_ZONE_INFO, "Executing process callback for kernel [%s]\n", knl->kernel_name);
    
                tivxPlatformActivate();
                status = knl->process_func(
                    target_kernel_instance, obj_desc, num_params,
                    knl->caller_priv_arg);
                tivxPlatformDeactivate();
    
                VX_PRINT(VX_ZONE_INFO, "Done executing process callback for kernel [%s]\n", knl->kernel_name);
    
                if((vx_status)VX_SUCCESS != status)
                {
                    /* making info since on a valid kernel process error, it will continously print errors  */
                    VX_PRINT(VX_ZONE_INFO, "Kernel process function for [%s] returned error code: %d\n", knl->kernel_name, status);
                }
            }
            else
            {
                VX_PRINT(VX_ZONE_ERROR, "Kernel process function is NULL\n");
                status = (vx_status)VX_FAILURE;
            }
        }
    
        return (status);
    }
    
    vx_status tivxTargetKernelControl(
        tivx_target_kernel_instance target_kernel_instance,
        uint32_t node_cmd_id, tivx_obj_desc_t *obj_desc[], uint16_t num_params)
    {
        vx_status status = (vx_status)VX_FAILURE;
        tivx_target_kernel knl = NULL;
    
        if ((NULL != target_kernel_instance) && (NULL != obj_desc))
        {
            /* Check if the kernel is valid */
            knl = tivxTargetKernelInstanceGetKernel(target_kernel_instance);
    
            if ((NULL != knl) && (NULL != knl->control_func))
            {
                VX_PRINT(VX_ZONE_INFO, "Executing control callback for kernel [%s]\n", knl->kernel_name);
    
                status = knl->control_func(
                    target_kernel_instance, node_cmd_id, obj_desc, num_params,
                    knl->caller_priv_arg);
    
                VX_PRINT(VX_ZONE_INFO, "Done executing control callback for kernel [%s]\n", knl->kernel_name);
            }
            else
            {
                VX_PRINT(VX_ZONE_ERROR, "Kernel control function is NULL\n");
                status = (vx_status)VX_FAILURE;
            }
        }
    
        return (status);
    }
    
    #if defined(BUILD_BAM)
    
    VX_API_ENTRY vx_status VX_API_CALL tivxEnableKernelForSuperNode(
                                 tivx_target_kernel target_kernel,
                                 tivx_target_kernel_create_in_bam_graph_f   create_in_bam_func,
                                 tivx_target_kernel_get_node_port_f         get_node_port_func,
                                 tivx_target_kernel_append_internal_edges_f append_internal_edges_func,
                                 tivx_target_kernel_pre_post_process_f      preprocess_func,
                                 tivx_target_kernel_pre_post_process_f      postprocess_func,
                                 int32_t                                    kernel_params_size,
                                 void *priv_arg)
    {
        uint32_t i;
        vx_status status;
    
        if ((NULL != target_kernel) &&
            (create_in_bam_func != NULL) && (get_node_port_func != NULL))
        {
            status = tivxMutexLock(g_target_kernel_lock);
    
            if ((vx_status)VX_SUCCESS == status)
            {
                for(i=0; i<dimof(g_target_kernel_table); i++)
                {
                    if (target_kernel ==
                        &g_target_kernel_table[i])
                    {
                        g_target_kernel_table[i].create_in_bam_func = create_in_bam_func;
                        g_target_kernel_table[i].get_node_port_func = get_node_port_func;
                        g_target_kernel_table[i].append_internal_edges_func = append_internal_edges_func;
                        g_target_kernel_table[i].preprocess_func = preprocess_func;
                        g_target_kernel_table[i].postprocess_func = postprocess_func;
                        g_target_kernel_table[i].kernel_params_size = kernel_params_size;
                        break;
                    }
                }
    
                tivxMutexUnlock(g_target_kernel_lock);
            }
        }
        else
        {
            status = (vx_status)VX_ERROR_INVALID_PARAMETERS;
            VX_PRINT(VX_ZONE_ERROR, "Invalid parameters given to function\n");
        }
    
        return status;
    }
    
    #endif
    

    the log file:

    MobaXterm_COM3ProlificUSB-to-SerialCommPortCOM3_20230317_144640.txt

    it seems that   tivxFlagIsBitSet( cmd_obj_desc->flags, TIVX_CMD_FLAG_IS_ACK) is not equal to  (vx_bool)vx_false_e

    Regards.

  • add node.c 

    vx_node.c

  • hi xie jc,

    I meant to put some prints in tivxDisplayM2MCreate API in file display_m2m/vx_display_m2m_target.c. This should get called since this kernel is already registered and then lets see where in this API, it is failing.. 

    Regards,

    Brijesh

  • Hi, Brijesh, 

    I already add prints in tivxDisplayM2MCreate before,  you can see the file "vx_display_m2m_target.c" i uploaded before, 

    it seems that the api tivxDisplayM2MCreate was not get called because the condition  " if tivxFlagIsBitSet( cmd_obj_desc->flags, TIVX_CMD_FLAG_IS_ACK) is== (vx_bool)vx_false_e "  in vx_target.c is not met.  can you check this code again? 

    Regards.

  • Hi xie jc,

    but this is ack for previously sent command, which means Create command was sent to mcu2_0 and it received ack with the an error..  is M2M Node correctly registered on the mcu2_0? How many DSS M2M node are you trying to open? What exactly is your application data flow? 

    Regards,

    Brijesh

  • is M2M Node correctly registered on the mcu2_0?

    I am not  sure. but i check code for several times, but can not find where have mistakes.

    How many DSS M2M node are you trying to open?

    I am trying to open one M2M node(M2M1)

    What exactly is your application data flow? 

    data flow: read uyvy picture  ->  M2M node(convert uyvy to rgba888) -> csitx 

    Regards.

  • Hi xie jc,

    On mcu2_0, there is a continuous print "EnetPhy_enableState: PHY 0: no supported caps found". Can you please see why this is coming? If possible, can you please disable ethernet firmware on mcu2_0 for the time being and see if the create of DSS M2M is getting called? 

    Regards,

    Brijesh

  • Hi, Brijesh,

    I disable the ethfw, and  the new log was show belown:

    MobaXterm_COM3ProlificUSB-to-SerialCommPortCOM3_20230320_145208.txt

    Regards.

  • Hi xie jc,

    ok, atleast we now know why dss m2m is not working. There is an error reported by the driver.

    [MCU2_0] 44.186013 s: src/drv/m2m/dss_m2mApi.c @ Line 1426:
    [MCU2_0] 44.186058 s: Given destination Fvid2_format not supported!!

    What exactly output format that you are using for the DSS M2M output images? Can you please share the exact OpenVX format? 

    Also which exactly SDK release are you using? We might just require to add this format support in the DSS M2M driver. 

    Regards,

    Brijesh

  • Hi, Brijesh,

    What exactly output format that you are using for the DSS M2M output images?

    VX_DF_IMAGE_RGBX

    Also which exactly SDK release are you using?

    sdk version we are using:

    rtos: 08_04_00_06

    linux: 08_04_00_11

    Regards.

  • Hi,

    ok since you are connecting DSS M2M output to CSITX, i will request you to make a small change in the node and then use TIVX_DF_IMAGE_BGRX as output format in the application? 

    In the file ti-processor-sdk-rtos-j721e-evm-08_04_00_02\tiovx\kernels_j7\hwa\display_m2m\vx_display_m2m_target.c, in the API tivxDisplayExtractFvid2Format, can you please make below change in the format->dataFormat?

            case (vx_df_image)TIVX_DF_IMAGE_BGRX:
                format->dataFormat = FVID2_DF_BGRX24_8888;
                format->pitch[FVID2_RGB_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y;
                break;
    

    After this change, please rebuild tiovx and sdk and check the output from CSITX. 

    Regards,

    Brijesh

  • Hi, Brijesh,

    I did below changes:

    log file:  MobaXterm_COM3ProlificUSB-to-SerialCommPortCOM3_20230320_173247.txt

    Regards.

  • sorry, can you also please add this format in host side? 

    In the file ti-processor-sdk-rtos-j721e-evm-08_04_00_02\tiovx\kernels_j7\hwa\host\vx_display_m2m_host.c, in the api tivxAddKernelDisplayM2MValidate, please change

    if( ((vx_df_image)VX_DF_IMAGE_RGB != output_fmt) &&
    ((vx_df_image)VX_DF_IMAGE_RGBX != output_fmt) &&
    ((vx_df_image)VX_DF_IMAGE_UYVY != output_fmt) &&
    ((vx_df_image)VX_DF_IMAGE_YUYV != output_fmt) &&
    ((vx_df_image)VX_DF_IMAGE_NV12 != output_fmt) &&

    ((vx_df_image)TIVX_DF_IMAGE_BGRX != output_fmt))

    Rgds,

    Brijesh

  • Hi, Brijesh, 

    okok. the M2M node can run now. 

    the log is : MobaXterm_COM3ProlificUSB-to-SerialCommPortCOM3_20230320_190137.txt

    i post one uyvy picture like:

      

    but i the screen display is:

    Regards.

  • Hi, Brijesh,

    I save the output of M2M node, the output format of M2M node is BGRA8888 now. but what the csitx node display was not match.

    Regards.

  • Hi xie jc,

    Are you continuously running graph? Because unlike DSS, CSITX will stop outputting data if the graph is stopped. We need to keep pushing new frames to the CSITX to get some frame on receiver.

    Also what is the receiver connected at the CSITX? Is it detecting correct frames? 

    Regards,

    Brijesh

  • Hi, Brijesh,

    after I pointed the M2M's output to the csitx's input,  an error occured: 

    log file: MobaXterm_COM3ProlificUSB-to-SerialCommPortCOM3_20230320_205147.txt

    Regards.

  • ok, it looks like there are multiple dependencies.. 

    Can you please use output format as VX_DF_IMAGE_RGBX in the application and please change below case statement in the dss m2m node, ie in ti-processor-sdk-rtos-j784s4-evm-08_05_00_11\tiovx\kernels_j7\hwa\display_m2m\vx_display_m2m_target.c file?

    case (vx_df_image)VX_DF_IMAGE_RGBX:
    format->dataFormat = FVID2_DF_BGRX24_8888;
    format->pitch[FVID2_RGB_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y;
    break;

    Regards,

    Brijesh

  • Hi, Brijesh,

    Oh, yeah. it works fine now:

    Thank you for support!!!

    Regards.

  • Cool, closing this ticket.