TDA4AL-Q1: [multi-cam] How can multi_cam continue outputting images after losing one camera?

Part Number: TDA4AL-Q1

Tool/software:

Hi TI,

I am using multi_cam to receive images from 4 cameras on CSI0.

When I remove one camera and use "s" in multi_cam, I cannot access the images.

It seems to get stuck at the vxQueryImage API.

When I reconnect the camera, multi_cam returns to its normal state.

Is there any way to improve this behavior?

  • Hi,

    Are you using the multi-cam demo in the SDK?

    If yes, Are there any modifications done to the same?

    Is the error frame registered for the capture node (i.e. in case the sensor stops streaming, this would stream a blank data so that other sensors are not affected)

    Regards,

    Nikhil

  • Hi Nikhil,

    Yes, I am using SDK 8.6 with multi_cam.

    The multi_cam architecture has not been modified; I only added a few small features. I am providing the source code for your reference.

     I tried disabling enable_error_detection, but the issue still occurs, as shown in the image below.

    /*
     *
     * 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 <utils/draw2d/include/draw2d.h>
    #include <utils/perf_stats/include/app_perf_stats.h>
    #include <utils/console_io/include/app_get.h>
    #include <utils/grpx/include/app_grpx.h>
    #include <utils/hwa/include/app_hwa_api.h>
    #include <VX/vx_khr_pipelining.h>
    
    #include <pthread.h>
    #include "app_common.h"
    #include "app_sensor_module.h"
    #include "app_capture_module.h"
    #include "app_obj_arr_split_module.h"
    #include "app_viss_module.h"
    #include "app_aewb_module.h"
    #include "app_ldc_module.h"
    #include "app_img_mosaic_module.h"
    #include "app_display_module.h"
    #include "app_test.h"
    
    #define CAPTURE_BUFFER_Q_DEPTH  (4)
    #define APP_BUFFER_Q_DEPTH      (4)
    #define APP_PIPELINE_DEPTH      (7)
    #define NUM_CHANNELS  (1)
    
    //#define USE_CSITX
    //#define DSS_M2M
    
    typedef struct {
    
        SensorObj     sensorObj;
        CaptureObj    captureObj;
        ObjArrSplitObj  objArrSplitObj;
        VISSObj       vissObj;
        AEWBObj       aewbObj;
        LDCObj        ldcObj;
        VISSObj       vissObj1;
        AEWBObj       aewbObj1;
        LDCObj        ldcObj1;
        ImgMosaicObj  imgMosaicObj;
        DisplayObj    displayObj;
    
    #ifdef USE_CSITX
        tivx_display_m2m_params_t display_m2m_params;
        vx_node displaym2mNode;
        vx_user_data_object display_m2m_param_obj;
        vx_image display_m2m_output_image;
        vx_node csitx_node;
        vx_user_data_object csitx_config;
        vx_object_array csitx_image_arr;
        vx_int32 is_csitx;
    #endif
        vx_char output_file_path[APP_MAX_FILE_PATH];
    
        /* OpenVX references */
        vx_context context;
        vx_graph   graph;
    
        vx_int32 en_out_img_write;
        vx_int32 test_mode;
    
        vx_uint32 is_interactive;
    
        vx_uint32 num_frames_to_run;
    
        vx_uint32 num_frames_to_write;
        vx_uint32 num_frames_to_skip;
    
        tivx_task task;
        vx_uint32 stop_task;
        vx_uint32 stop_task_done;
    
        app_perf_point_t total_perf;
        app_perf_point_t fileio_perf;
        app_perf_point_t draw_perf;
    
        uint32_t open_debug_menu;
        uint32_t save_images_time;
    
        int32_t enable_ldc;
        int32_t enable_viss;
        int32_t enable_split_graph;
        int32_t enable_aewb;
        int32_t enable_mosaic;
    
        int32_t pipeline;
    
        int32_t enqueueCnt;
        int32_t dequeueCnt;
    
        int32_t write_file;
    
        vx_uint32 enable_configure_hwa_freq;
        vx_uint32 hwa_freq_config;
        vx_uint32 bypass_split_graph;
    
    } AppObj;
    
    AppObj gAppObj;
    
    vx_object_array tx_frame = 0;
    //static tivx_raw_image raw_image_exemplar;
    /* static tivx_raw_image raw_image_exemplar; */
    /* static vx_rectangle_t rect; */
    
    static void app_parse_cmd_line_args(AppObj *obj, vx_int32 argc, vx_char *argv[]);
    static vx_status app_init(AppObj *obj);
    static void app_deinit(AppObj *obj);
    static vx_status app_create_graph(AppObj *obj);
    static vx_status app_verify_graph(AppObj *obj);
    static vx_status app_run_graph(AppObj *obj);
    static vx_status app_run_graph_interactive(AppObj *obj);
    static vx_status app_run_graph_FXN(AppObj *obj);
    static vx_status read_camera_FXN(AppObj *obj);
    static void app_delete_graph(AppObj *obj);
    static void app_default_param_set(AppObj *obj);
    static void app_update_param_set(AppObj *obj);
    static void app_pipeline_params_defaults(AppObj *obj);
    static void add_graph_parameter_by_node_index(vx_graph graph, vx_node node, vx_uint32 node_parameter_index);
    static vx_int32 calc_grid_size(vx_uint32 ch);
    static void set_img_mosaic_params(ImgMosaicObj *imgMosaicObj, vx_uint32 in_width, vx_uint32 in_height, vx_int32 numCh, ObjArrSplitObj *objArrSplitObj, int32_t enable_split_graph);
    static void app_draw_graphics(Draw2D_Handle *handle, Draw2D_BufInfo *draw2dBufInfo, uint32_t update_type);
    
    static void app_show_usage(vx_int32 argc, vx_char* argv[])
    {
        printf("\n");
        printf(" Camera Demo - (c) Texas Instruments 2020\n");
        printf(" ========================================================\n");
        printf("\n");
        printf(" Usage,\n");
        printf("  %s --cfg <config file>\n", argv[0]);
        printf("\n");
    }
    
    static char menu[] = {
        "\n"
        "\n ========================="
        "\n Demo : Camera Demo"
        "\n ========================="
        "\n"
        "\n s: Save CSIx, VISS and LDC outputs"
        "\n"
        "\n S: Save Raw image"
        "\n"
        "\n p: Print performance statistics"
        "\n"
        "\n r: read des register"
        "\n w: write des register"
        "\n x: Exit"
        "\n"
        "\n Enter Choice: "
    };
    
    static int save_debug_images(AppObj *obj);
    
    static void app_run_task(void *app_var)
    {
        AppObj *obj = (AppObj *)app_var;
        vx_status status = VX_SUCCESS;
        while((!obj->stop_task) && (status == VX_SUCCESS))
        {
            status = app_run_graph(obj);
        }
        obj->stop_task_done = 1;
    }
    
    static int32_t app_run_task_create(AppObj *obj)
    {
        tivx_task_create_params_t params;
        vx_status status;
    
        tivxTaskSetDefaultCreateParams(&params);
        params.task_main = app_run_task;
        params.app_var = obj;
    
        obj->stop_task_done = 0;
        obj->stop_task = 0;
    
        status = tivxTaskCreate(&obj->task, &params);
    
        return status;
    }
    
    static void app_run_task_delete(AppObj *obj)
    {
        while(obj->stop_task_done==0)
        {
            tivxTaskWaitMsecs(100);
        }
    
        tivxTaskDelete(&obj->task);
    }
    static vx_status read_camera_FXN(AppObj *obj)
    {
        static uint32_t done = 1;
        static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
        double around_regvalue;
        uint32_t channel_id;
        uint32_t regaddr;
        uint32_t regaddrs[] = {0xE700, 0xE708, 0xE710, 0xE718, 0xE720, 0xE728, 0xE730, 0xE738};
        uint32_t channel_ids[] = {0, 1, 2, 3};
        vx_status status = VX_SUCCESS;
        
        pthread_mutex_lock(&lock);
        if(done == 1){
            tivxTaskWaitMsecs(100);
            for (int i = 0; i < sizeof(regaddrs)/sizeof(regaddrs[0]); i++) {
                for (int j = 0; j < sizeof(channel_ids)/sizeof(channel_ids[0]); j++) {
                     regaddr = regaddrs[i];
                     channel_id = channel_ids[j];
                     getaroundSensor(regaddr, channel_id, 2, &around_regvalue);
                     printf("regAddr = 0x%x, channelId = %d, regValue = %f\n", regaddr, channel_id, around_regvalue);
                }
            }
        done = 0;
        }
        pthread_mutex_unlock(&lock);
        return status;
    }
    
    static vx_status app_run_graph_FXN(AppObj *obj)
    {
        vx_status status;
        uint32_t done = 0;
        status = app_run_task_create(obj);
        if(status == VX_FAILURE)
        {
            printf("app_tidl: ERROR: Unable to create task\n");
        }
        else
        {
            appPerfStatsResetAll();
            status = read_camera_FXN(obj);
            while(!done)
            {
                appDebugImageSensor("OX08B-MAX96717", 0x01);
                tivxTaskWaitMsecs(10000);
            }
        }
        app_run_task_delete(obj);
        return status;
    }
    
    static vx_status app_run_graph_interactive(AppObj *obj)
    {
        vx_status status;
        uint32_t done = 0;
    
        char ch;
        FILE *fp;
        app_perf_point_t *perf_arr[1];
    
        uint32_t regaddr;
        uint8_t regWrite;
        uint32_t regvalue;
        uint32_t channel_id;
    
        char input[20];
        int c;
    
    
        status = app_run_task_create(obj);
        if(status == VX_FAILURE)
        {
            printf("app_tidl: ERROR: Unable to create task\n");
        }
        else
        {
            appPerfStatsResetAll();
            status = read_camera_FXN(obj);
            while(!done)
            {
                printf(menu);
                ch = getchar();
                printf("\n");
    
                switch(ch)
                {
                    case 'p':
                        appPerfStatsPrintAll();
                        status = tivx_utils_graph_perf_print(obj->graph);
                        appPerfPointPrint(&obj->fileio_perf);
                        appPerfPointPrint(&obj->total_perf);
                        printf("\n");
                        appPerfPointPrintFPS(&obj->total_perf);
                        appPerfPointReset(&obj->total_perf);
                        printf("\n");
    
                        vx_reference refs[1];
                        refs[0] = (vx_reference)obj->captureObj.raw_image_arr[0];
                        if (status == VX_SUCCESS)
                        {
                            status = tivxNodeSendCommand(obj->captureObj.node, 0u,
                                        TIVX_CAPTURE_PRINT_STATISTICS,
                                        refs, 1u);
                        }
                        break;
                    case 'e':
                        perf_arr[0] = &obj->total_perf;
                        fp = appPerfStatsExportOpenFile(".", "basic_demos_app_multi_cam");
                        if (NULL != fp)
                        {
                            appPerfStatsExportAll(fp, perf_arr, 1);
                            if (status == VX_SUCCESS)
                            {
                                status = tivx_utils_graph_perf_export(fp, obj->graph);
                            }
                            appPerfStatsExportCloseFile(fp);
                            appPerfStatsResetAll();
                        }
                        else
                        {
                            printf("fp is null\n");
                        }
                        break;
                    case 's':
                        obj->write_file = 1;
                        save_debug_images(obj);
                        break;
                    case 'S':
                        save_debug_images(obj);
                        break;
                    case 'd':
                        /* appDebugImageSensor("OX03C-MAX9295E", 0x01); */
                        appDebugImageSensor("OX08BA-MAX96701", 0x01);
    
                        break;
                    case 'w':
                        memset(&regvalue, 0, sizeof(regvalue));
                        //printf("pleace input readdr: 0x");
                        //scanf("%d",&regaddr);
                        /* char input[20]; */
                        printf("Please input regaddr in hexadecimal: 0x");
                        /* int c; */
                        while ((c = getchar()) != '\n' && c != EOF);
                        if (fgets(input, sizeof(input), stdin) != NULL)
                        {
                            input[strcspn(input, "\n")] = '\0';
                            if (strlen(input) >= 3 && strncmp(input, "0x", 2) == 0)
                            {
                                if (sscanf(input + 2, "%x", &regaddr) != 1)
                                {
                                    printf("Invalid input for regaddr\n");
                                    return 1;
                                }
                            } else {
                                if (sscanf(input, "%x", &regaddr) != 1)
                                {
                                    printf("Invalid input for regaddr\n");
                                    return 1;
                                }
                            }
                        }
                        else
                        {
                            printf("Error reading input\n");
                            return 1;
                        }
    
                        printf("Please input value: ");
                        if (fgets(input, sizeof(input), stdin) != NULL)
                        {
                            input[strcspn(input, "\n")] = '\0';
                            if (sscanf(input, "%hhx", &regWrite) != 1)
                            {
                                printf("Invalid input for reg value\n");
                                return 1;
                            }
                        }
                        else
                        {
                            printf("Error reading input\n");
                            return 1;
                        }
    
                        printf("Please input channel_id: ");
                        if (fgets(input, sizeof(input), stdin) != NULL)
                        {
                            input[strcspn(input, "\n")] = '\0';
                            if (sscanf(input, "%u", &channel_id) != 1)
                            {
                                printf("Invalid input for channel_id\n");
                                return 1;
                            }
                        }
                        else
                        {
                            printf("Error reading input\n");
                            return 1;
                        }
                        //printf("pleace input byte_num: ");
                        //scanf("%hhd",&byte_num);
                        //printf("pleace input channel_id: ");
                        //scanf("%d",&channel_id);
                        /* getSensorOtpFromSensor(regaddr, channel_id, byte_num, &regvalue); */
                        printf("AccessDesRegister called with:\n");
                        printf("regaddr = 0x%04X\n", regaddr);
                        printf("channel_id = 0x%d\n", channel_id);
                        printf("regWrite = 0x%04X\n", regWrite);
    
                        AccessDesRegister(regaddr, channel_id, regWrite,1);
                        printf("regValue = 0x%x\n",regvalue);
                        break;
                    case 'r':
                        memset(&regvalue, 0, sizeof(regvalue));
                        //printf("pleace input readdr: 0x");
                        //scanf("%d",&regaddr);
                        /* char input[20]; */
                        printf("Please input regaddr in hexadecimal: 0x");
                        /* int c; */
                        while ((c = getchar()) != '\n' && c != EOF);
                        if (fgets(input, sizeof(input), stdin) != NULL)
                        {
                            input[strcspn(input, "\n")] = '\0';
                            if (strlen(input) >= 3 && strncmp(input, "0x", 2) == 0)
                            {
                                if (sscanf(input + 2, "%x", &regaddr) != 1)
                                {
                                    printf("Invalid input for regaddr\n");
                                    return 1;
                                }
                            } else {
                                if (sscanf(input, "%x", &regaddr) != 1)
                                {
                                    printf("Invalid input for regaddr\n");
                                    return 1;
                                }
                            }
                        }
                        else
                        {
                            printf("Error reading input\n");
                            return 1;
                        }
    /*
                        printf("Please input value: ");
                        if (fgets(input, sizeof(input), stdin) != NULL)
                        {   
                            input[strcspn(input, "\n")] = '\0';
                            if (sscanf(input, "%hhd", &regWrite) != 1)
                            {   
                                printf("Invalid input for reg value\n");
                                return 1;
                            }
                        }
                        else
                        {   
                            printf("Error reading input\n");
                            return 1;
                        }
    */
                        printf("Please input channel_id: ");
                        if (fgets(input, sizeof(input), stdin) != NULL)
                        {
                            input[strcspn(input, "\n")] = '\0';
                            if (sscanf(input, "%u", &channel_id) != 1)
                            {
                                printf("Invalid input for channel_id\n");
                                return 1;
                            }
                        }
                        else
                        {
                            printf("Error reading input\n");
                            return 1;
                        }
                        //printf("pleace input byte_num: ");
                        //scanf("%hhd",&byte_num);
                        //printf("pleace input channel_id: ");
                        //scanf("%d",&channel_id);
                        /* getSensorOtpFromSensor(regaddr, channel_id, byte_num, &regvalue); */
                        getSensorOtpFromSensor(regaddr, channel_id, 4, &regvalue);
                        //AccessDesRegister(regaddr, channel_id, regWrite,0);
                        printf("regValue = 0x%x\n",regvalue);
                        break;
                     case 'x':
                         obj->stop_task = 1;
                         done = 1;
                         break;
                }
            }
            app_run_task_delete(obj);
        }
        return status;
    }
    
    static void app_set_cfg_default(AppObj *obj)
    {
        snprintf(obj->captureObj.output_file_path,APP_MAX_FILE_PATH, ".");
        snprintf(obj->vissObj.output_file_path,APP_MAX_FILE_PATH, ".");
        snprintf(obj->vissObj1.output_file_path,APP_MAX_FILE_PATH, ".");
        snprintf(obj->ldcObj.output_file_path,APP_MAX_FILE_PATH, ".");
    
        obj->captureObj.en_out_capture_write = 0;
        obj->vissObj.en_out_viss_write = 0;
        obj->vissObj1.en_out_viss_write = 0;
        obj->ldcObj.en_out_ldc_write = 0;
        obj->ldcObj1.en_out_ldc_write = 0;
    
        obj->num_frames_to_write = 0;
        obj->num_frames_to_skip = 0;
    
        obj->objArrSplitObj.num_outputs = 2;
        obj->objArrSplitObj.output0_num_elements = 0;
        obj->objArrSplitObj.output1_num_elements = 0;
        obj->objArrSplitObj.output2_num_elements = 0;
        obj->objArrSplitObj.output3_num_elements = 0;
    }
    
    static void app_parse_cfg_file(AppObj *obj, vx_char *cfg_file_name)
    {
        FILE *fp = fopen(cfg_file_name, "r");
        vx_char line_str[1024];
        vx_char *token;
    
        if(fp==NULL)
        {
            printf("# ERROR: Unable to open config file [%s]\n", cfg_file_name);
            exit(0);
        }
    
        while(fgets(line_str, sizeof(line_str), fp)!=NULL)
        {
            vx_char s[]=" \t";
    
            if (strchr(line_str, '#'))
            {
                continue;
            }
    
            /* get the first token */
            token = strtok(line_str, s);
            if(token != NULL)
            {
                if(strcmp(token, "sensor_index")==0)
                {
                    token = strtok(NULL, s);
                    if(token != NULL)
                    {
                        obj->sensorObj.sensor_index = atoi(token);
                    }
                }
                else
                if(strcmp(token, "num_frames_to_run")==0)
                {
                    token = strtok(NULL, s);
                    if(token != NULL)
                    {
                        obj->num_frames_to_run = atoi(token);
                    }
                }
                else
                if(strcmp(token, "enable_error_detection")==0)
                {
                    token = strtok(NULL, s);
                    if(token != NULL)
                    {
                        obj->captureObj.enable_error_detection = atoi(token);
                    }
                }
                else
                if(strcmp(token, "enable_configure_hwa_freq")==0)
                {
                    token = strtok(NULL, s);
                    if(token != NULL)
                    {
                        obj->enable_configure_hwa_freq = atoi(token);
                    }
                }
                else
                if(strcmp(token, "hwa_freq_config")==0)
                {
                    token = strtok(NULL, s);
                    if(token != NULL)
                    {
                        obj->hwa_freq_config = atoi(token);
                    }
                }
                else
                if(strcmp(token, "enable_ldc")==0)
                {
                    token = strtok(NULL, s);
                    if(token != NULL)
                    {
                        obj->sensorObj.enable_ldc = atoi(token);
                        if(obj->sensorObj.enable_ldc > 1)
                            obj->sensorObj.enable_ldc = 1;
                    }
                }
                else
                if(strcmp(token, "en_out_img_write")==0)
                {
                    token = strtok(NULL, s);
                    if(token != NULL)
                    {
                        obj->en_out_img_write = atoi(token);
                        if(obj->en_out_img_write > 1)
                            obj->en_out_img_write = 1;
                    }
                }
                else
                if(strcmp(token, "en_out_capture_write")==0)
                {
                    token = strtok(NULL, s);
                    if(token != NULL)
                    {
                        obj->captureObj.en_out_capture_write = atoi(token);
                        if(obj->captureObj.en_out_capture_write > 1)
                            obj->captureObj.en_out_capture_write = 1;
                    }
                }
                else
                if(strcmp(token, "en_out_viss_write")==0)
                {
                    token = strtok(NULL, s);
                    if(token != NULL)
                    {
                        obj->vissObj.en_out_viss_write = atoi(token);
                        if(obj->vissObj.en_out_viss_write > 1)
                            obj->vissObj.en_out_viss_write = 1;
                    }
                }
                else
                if(strcmp(token, "en_out_ldc_write")==0)
                {
                    token = strtok(NULL, s);
                    if(token != NULL)
                    {
                        obj->ldcObj.en_out_ldc_write = atoi(token);
                        if(obj->ldcObj.en_out_ldc_write > 1)
                            obj->ldcObj.en_out_ldc_write = 1;
                    }
                }
                else
                if(strcmp(token, "output_file_path")==0)
                {
                    token = strtok(NULL, s);
                    if(token != NULL)
                    {
                        token[strlen(token)-1]=0;
                        strcpy(obj->captureObj.output_file_path, token);
                        strcpy(obj->vissObj.output_file_path, token);
                        strcpy(obj->vissObj1.output_file_path, token);
                        strcpy(obj->ldcObj.output_file_path, token);
                        strcpy(obj->ldcObj1.output_file_path, token);
                        strcpy(obj->output_file_path, token);
                    }
                }
                else
                if(strcmp(token, "display_option")==0)
                {
                    token = strtok(NULL, s);
                    if(token != NULL)
                    {
                        obj->displayObj.display_option = atoi(token);
                        if(obj->displayObj.display_option > 1)
                            obj->displayObj.display_option = 1;
                    }
                }
                else
                if (strcmp(token, "save_images_time") == 0)
                {
                    token = strtok(NULL, s);
                    if (token != NULL)
                    {
                        token[strlen(token) - 1] = 0;
                        obj->save_images_time = atoi(token);
                        printf("Set save_images_time = [%d]\n", obj->save_images_time);
                    }
                }
                else
                if (strcmp(token, "open_debug_menu") == 0)
                {
                    token = strtok(NULL, s);
                    if (token != NULL)
                    {
                        token[strlen(token) - 1] = 0;
                        obj->open_debug_menu = atoi(token);
                        if (obj->open_debug_menu == 1)
                        {
                            printf("open_debug_menu [open] \n");
                        }
                        else
                        {
                            printf("open_debug_menu [close] \n");
                        }
                    }
                }
                else
                if(strcmp(token, "is_interactive")==0)
                {
                    token = strtok(NULL, s);
                    if(token != NULL)
                    {
                        token[strlen(token)-1]=0;
                        obj->is_interactive = atoi(token);
                        if(obj->is_interactive > 1)
                        {
                            obj->is_interactive = 1;
                        }
                    }
                    obj->sensorObj.is_interactive = obj->is_interactive;
                }
    #ifdef USE_CSITX
                else
                if(strcmp(token, "is_csitx")==0)
                {
                    token = strtok(NULL, s);
                    if(token != NULL)
                    {
                        token[strlen(token)-1]=0;
                        obj->is_csitx = atoi(token);
                        if(obj->is_csitx > 1)
                        {
                            obj->is_csitx = 1;
                        }
                    }
                }
    #endif
                else
                if(strcmp(token, "bypass_split_graph")==0)
                {
                    token = strtok(NULL, s);
                    if(token != NULL)
                    {
                        token[strlen(token)-1]=0;
                        obj->bypass_split_graph = atoi(token);
                        if(obj->bypass_split_graph > 1)
                        {
                            obj->bypass_split_graph = 1;
                        }
                    }
                }
                else
    
                /*
                    num_cameras_enabled from cfg file is ignored
                    Instead channel_mask is read. num_cameras_enabled = number of 1 bits in mask
                    For e.g. channel_mask = 15 (0x0F) indicates that first 4 cameras are enabled
                */
                if(strcmp(token, "channel_mask")==0)
                {
                    token = strtok(NULL, s);
                    if(token != NULL)
                    {
                        token[strlen(token)-1]=0;
                        obj->sensorObj.ch_mask = atoi(token);
                    }
                }
                else
                if(strcmp(token, "usecase_option")==0)
                {
                    token = strtok(NULL, s);
                    if(token != NULL)
                    {
                        token[strlen(token)-1]=0;
                        obj->sensorObj.usecase_option = atoi(token);
                    }
                }
                else
                if(strcmp(token, "num_frames_to_write")==0)
                {
                    token = strtok(NULL, s);
                    if(token != NULL)
                    {
                        token[strlen(token)-1]=0;
                        obj->num_frames_to_write = atoi(token);
                    }
                }
                else
                if(strcmp(token, "num_frames_to_skip")==0)
                {
                    token = strtok(NULL, s);
                    if(token != NULL)
                    {
                        token[strlen(token)-1]=0;
                        obj->num_frames_to_skip = atoi(token);
                    }
                }
                else
                if(strcmp(token, "test_mode")==0)
                {
                    token = strtok(NULL, s);
                    if(token != NULL)
                    {
                        obj->test_mode = atoi(token);
                        obj->captureObj.test_mode = atoi(token);
                    }
                }
            }
        }
    
        fclose(fp);
    
    }
    
    static void app_parse_cmd_line_args(AppObj *obj, vx_int32 argc, vx_char *argv[])
    {
        vx_int32 i;
        vx_int16 num_test_cams = 0xFF, sensor_override = 0xFF;
        vx_bool set_test_mode = vx_false_e;
    
        app_set_cfg_default(obj);
    
        if(argc==1)
        {
            app_show_usage(argc, argv);
            exit(0);
        }
    
        for(i=0; i<argc; i++)
        {
            if(strcmp(argv[i], "--cfg")==0)
            {
                i++;
                if(i>=argc)
                {
                    app_show_usage(argc, argv);
                }
                app_parse_cfg_file(obj, argv[i]);
            }
            else
            if(strcmp(argv[i], "--help")==0)
            {
                app_show_usage(argc, argv);
                exit(0);
            }
            else
            if(strcmp(argv[i], "--test")==0)
            {
                set_test_mode = vx_true_e;
                // check to see if there is another argument following --test
                if (argc > i+1)
                {
                    num_test_cams = atoi(argv[i+1]);
                    // increment i again to avoid this arg
                    i++;
                }
            }
            else
            if(strcmp(argv[i], "--sensor")==0)
            {
                // check to see if there is another argument following --sensor
                if (argc > i+1)
                {
                    sensor_override = atoi(argv[i+1]);
                    // increment i again to avoid this arg
                    i++;
                }
            }
        }
    
        if (set_test_mode == vx_true_e)
        {
            obj->test_mode = 1;
            obj->captureObj.test_mode = 1;
            obj->is_interactive = 0;
            obj->bypass_split_graph = 0;
            obj->enable_configure_hwa_freq = 0;
            obj->hwa_freq_config = 0;
            obj->sensorObj.is_interactive = 0;
            // set the number of test cams from cmd line
            if (num_test_cams != 0xFF)
            {
                obj->sensorObj.num_cameras_enabled = num_test_cams;
            }
            if (sensor_override != 0xFF)
            {
                obj->sensorObj.sensor_index = sensor_override;
            }
        }
    
        return;
    }
    #ifdef USE_CSITX
    static vx_status readRAWinput(tivx_raw_image raw_image, char *raw_image_fname)
    {
        vx_status  vxStatus = (vx_status)VX_SUCCESS;
        /* Taking the test data from the app_single_cam demo to save space in the repo */
        FILE * fp;
        vx_uint32 width, height, i;
        vx_imagepatch_addressing_t image_addr;
        vx_rectangle_t rect;
        vx_map_id map_id;
        void *data_ptr;
        vx_uint32 num_bytes_per_pixel = 2; /*Supports only RAW 12b Unpacked format*/
        vx_uint32 num_bytes_read_from_file;
        //tivx_raw_image raw_image = NULL;
        tivx_raw_image_format_t format;
        vx_uint32 imgaddr_width, imgaddr_height, imgaddr_stride;
    
    
        /* Nothing is being populated here - just an empty frame */
    
        APP_PRINTF("Reading test RAW image %s \n", raw_image_fname);
        fp = fopen(raw_image_fname, "rb");
        if(!fp)
        {
            printf("read_test_image_raw : Unable to open file %s\n", raw_image_fname);
            return VX_FAILURE;
        }
        tivxQueryRawImage(raw_image, TIVX_RAW_IMAGE_WIDTH, &width, sizeof(vx_uint32));
        tivxQueryRawImage(raw_image, TIVX_RAW_IMAGE_HEIGHT, &height, sizeof(vx_uint32));
        tivxQueryRawImage(raw_image, TIVX_RAW_IMAGE_FORMAT, &format, sizeof(format));
    
        /* width=1920; */
        /* height=1080; */
    
        printf("raw12:img_width = %d \timg_height = %d\n", width, height);
        rect.start_x = 0;
        rect.start_y = 0;
        rect.end_x = width;
        rect.end_y = height;
    
        image_addr.dim_x = 1920;//480;
        image_addr.dim_y = 1080;//360;
        image_addr.stride_x = 2;//TIVX_RAW_IMAGE_16_BIT aka RAW12
        image_addr.stride_y = 1920*image_addr.stride_x;
        image_addr.scale_x = VX_SCALE_UNITY;
        image_addr.scale_y = VX_SCALE_UNITY;
        image_addr.step_x = 1;
        image_addr.step_y = 1;
    
        vxStatus = tivxMapRawImagePatch(raw_image,
                                        &rect,
                                        0,
                                        &map_id,
                                        &image_addr,
                                        &data_ptr,
                                        VX_READ_AND_WRITE,
                                        VX_MEMORY_TYPE_HOST,
                                        TIVX_RAW_IMAGE_PIXEL_BUFFER
            );
    
        if(!data_ptr)
        {
            APP_PRINTF("data_ptr is NULL \n");
            fclose(fp);
            return VX_FAILURE;
        }
        num_bytes_read_from_file = 0;
    
        imgaddr_width  = image_addr.dim_x;
        imgaddr_height = image_addr.dim_y;
        imgaddr_stride = image_addr.stride_y;
    
        printf("raw12:imgaddr_width = %d \timgaddr_height = %d \timgaddr_stride = %d\n", imgaddr_width, imgaddr_height, imgaddr_stride);
    
        for(i=0;i<imgaddr_height;i++)
        {
            num_bytes_read_from_file += fread(data_ptr, 1, imgaddr_width*num_bytes_per_pixel, fp);
            data_ptr += imgaddr_stride;
        }
    
        tivxUnmapRawImagePatch(raw_image, map_id);
    
        fclose(fp);
        APP_PRINTF("%d bytes read from %s\n", num_bytes_read_from_file, raw_image_fname);
        return vxStatus;
    }
    #endif
    
    vx_int32 app_multi_cam_main(vx_int32 argc, vx_char* argv[])
    {
        vx_status status = VX_SUCCESS;
    
        AppObj *obj = &gAppObj;
    
        /*Optional parameter setting*/
        app_default_param_set(obj);
    
        /*Config parameter reading*/
        app_parse_cmd_line_args(obj, argc, argv);
    
        /* Querry sensor parameters */
        status = app_querry_sensor(&obj->sensorObj);
        if(1 == obj->sensorObj.sensor_out_format)
        {
            printf("YUV Input selected. VISS, AEWB and Mosaic nodes will be bypassed. \n");
            obj->enable_viss = 0;
            obj->enable_split_graph = 0;
            obj->enable_aewb = 0;
            obj->enable_mosaic = 0;
            #ifdef DSS_M2M
            //obj->enable_mosaic = 1;
            #endif
        }
        else
        {
            obj->enable_viss = 1;//1;
            obj->enable_split_graph = 1;
            obj->enable_aewb = 0;//0;//Brandon for Heap Alloc Crash
            obj->enable_mosaic = 1;
        }
        printf("TDCU Vision App Version (a72) %s %s!!!\n",TDCU_VISION_APP_VERSION, __TIMESTAMP__);
        /*Update of parameters are config file read*/
        app_update_param_set(obj);
    
        if (status == VX_SUCCESS)
        {
            status = app_init(obj);
        }
        if(status == VX_SUCCESS)
        {
            APP_PRINTF("App Init Done! \n");
    
            status = app_create_graph(obj);
    
            if(status == VX_SUCCESS)
            {
                APP_PRINTF("App Create Graph Done! \n");
    
                status = app_verify_graph(obj);
    
                if(status == VX_SUCCESS)
                {
                    APP_PRINTF("App Verify Graph Done! \n");
    
                    if (status == VX_SUCCESS)
                    {
                        APP_PRINTF("App Send Error Frame Done! \n");
                        if(obj->is_interactive)
                        {
                            status = app_run_graph_interactive(obj);
                        }
                        else
                        {
                            if (obj->open_debug_menu == 1)
                            {
                                status = app_run_graph_interactive(obj);
                            }
                            else
                            {
                                status = app_run_graph_FXN(obj);
                            }
                        }
    
                        tivx_set_debug_zone(VX_ZONE_INFO);//Brandon
    
                    }
                }
            }
    
            APP_PRINTF("App Run Graph Done! \n");
        }
    
        app_delete_graph(obj);
    
        APP_PRINTF("App Delete Graph Done! \n");
    
        app_deinit(obj);
    
        APP_PRINTF("App De-init Done! \n");
    
        if(obj->test_mode == 1)
        {
            if((vx_false_e == test_result) || (status != VX_SUCCESS))
            {
                printf("\n\nTEST FAILED\n\n");
                print_new_checksum_structs();
                status = (status == VX_SUCCESS) ? VX_FAILURE : status;
            }
            else
            {
                printf("\n\nTEST PASSED\n\n");
            }
        }
        return status;
    }
    
    static vx_status app_init(AppObj *obj)
    {
        vx_status status = VX_SUCCESS;
        app_grpx_init_prms_t grpx_prms;
    
        if (1U == obj->enable_configure_hwa_freq)
        {
            APP_PRINTF("Configuring VPAC frequency!\n");
            if (0U == obj->hwa_freq_config)
            {
                APP_PRINTF("Configuring VPAC frequency to 650 MHz and DMPAC to 520 MHz!\n");
                status = appVhwaConfigureFreq(APP_HWA_CONFIGURE_FREQ_VPAC_650_DMPAC_520);
                APP_PRINTF("Configuring VPAC frequency done!\n");
            }
            else if (1U == obj->hwa_freq_config)
            {
                APP_PRINTF("Configuring VPAC frequency to 720 MHz and DMPAC to 480 MHz!\n");
                status = appVhwaConfigureFreq(APP_HWA_CONFIGURE_FREQ_VPAC_720_DMPAC_480);
                APP_PRINTF("Configuring VPAC frequency done!\n");
            }
            else
            {
                APP_PRINTF("Invalid option for VPAC frequency configuration!\n");
            }
        }
    
        if (status == VX_SUCCESS)
        {
            /* Create OpenVx Context */
            obj->context = vxCreateContext();
            status = vxGetStatus((vx_reference)obj->context);
            APP_PRINTF("Creating context done!\n");
        }
    
        if (status == VX_SUCCESS)
        {
            tivxHwaLoadKernels(obj->context);
            tivxImagingLoadKernels(obj->context);
            tivxFileIOLoadKernels(obj->context);
            APP_PRINTF("Kernel loading done!\n");
        }
    
        /* Initialize modules */
        if (status == VX_SUCCESS)
        {
            app_init_sensor(&obj->sensorObj, "sensor_obj");
        }
    
        if (status == VX_SUCCESS)
        {
            APP_PRINTF("Sensor init done!\n");
            status = app_init_capture(obj->context, &obj->captureObj, &obj->sensorObj, "capture_obj", CAPTURE_BUFFER_Q_DEPTH);
        }
    
        if( (1 == obj->enable_split_graph) && (status == VX_SUCCESS) )
        {
            obj->objArrSplitObj.input_arr = obj->captureObj.raw_image_arr[0];
            APP_PRINTF("Obj arr splitter init done!\n");
            status = app_init_obj_arr_split(obj->context, &obj->objArrSplitObj, "objArrSplit_obj");
        }
    
        if((1 == obj->enable_viss) && (status == VX_SUCCESS))
        {
            status = app_init_viss(obj->context, &obj->vissObj, &obj->sensorObj, "viss_obj", obj->objArrSplitObj.output0_num_elements);
            APP_PRINTF("VISS init done!\n");
        }
    
        if((1 == obj->enable_aewb) && (status == VX_SUCCESS))
        {
            status = app_init_aewb(obj->context, &obj->aewbObj, &obj->sensorObj, "aewb_obj", 0, obj->objArrSplitObj.output0_num_elements);
            APP_PRINTF("AEWB init done!\n");
        }
    
        if((obj->sensorObj.enable_ldc == 1) && (status == VX_SUCCESS))
        {
            status = app_init_ldc(obj->context, &obj->ldcObj, &obj->sensorObj, "ldc_obj", obj->objArrSplitObj.output0_num_elements);
            APP_PRINTF("LDC init done!\n");
        }
    
        if((1 == obj->enable_split_graph) && (status == VX_SUCCESS))
        {
            status = app_init_viss(obj->context, &obj->vissObj1, &obj->sensorObj, "viss_obj1", obj->objArrSplitObj.output1_num_elements);
            APP_PRINTF("VISS init done!\n");
            if((1 == obj->enable_aewb) && (status == VX_SUCCESS))
            {
                status = app_init_aewb(obj->context, &obj->aewbObj1, &obj->sensorObj, "aewb_obj", obj->objArrSplitObj.output0_num_elements, obj->objArrSplitObj.output1_num_elements);
                APP_PRINTF("AEWB init done!\n");
            }
            if((obj->sensorObj.enable_ldc == 1) && (status == VX_SUCCESS))
            {
                status = app_init_ldc(obj->context, &obj->ldcObj1, &obj->sensorObj, "ldc_obj",obj->objArrSplitObj.output1_num_elements);
                APP_PRINTF("LDC init done!\n");
            }
        }
    
        if((obj->enable_mosaic == 1) && (status == VX_SUCCESS))
        {
            status = app_init_img_mosaic(obj->context, &obj->imgMosaicObj, "img_mosaic_obj", APP_BUFFER_Q_DEPTH);
            APP_PRINTF("Img Mosaic init done!\n");
        }
    //#if 0
    #ifndef USE_CSITX
        if (status == VX_SUCCESS)
        {
            status = app_init_display(obj->context, &obj->displayObj, "display_obj");
            APP_PRINTF("Display init done!\n");
        }
    #else
        if(obj->is_csitx)
        {
            /* CSI-TX initialization */
            tivx_csitx_params_t local_csitx_config;
            uint32_t loopCnt;
            /* CSITX Config initialization */
            tivx_csitx_params_init(&local_csitx_config);
            local_csitx_config.numInst                          = 1U;
            local_csitx_config.numCh                            = NUM_CHANNELS;
            local_csitx_config.instId[0U]                       = 0;
            local_csitx_config.instCfg[0U].rxCompEnable         = (uint32_t)vx_true_e;
            local_csitx_config.instCfg[0U].rxv1p3MapEnable      = (uint32_t)vx_true_e;
            local_csitx_config.instCfg[0U].laneBandSpeed        = (TIVX_CAPTURE_LANE_BAND_SPEED_880_TO_1040_MBPS);//(TIVX_CAPTURE_LANE_BAND_SPEED_720_TO_800_MBPS);//(TIVX_CAPTURE_LANE_BAND_SPEED_1750_TO_2000_MBPS);//(TIVX_CAPTURE_LANE_BAND_SPEED_720_TO_800_MBPS);
            local_csitx_config.instCfg[0U].laneSpeedMbps        = 1000U;//2000U;//800U;//TIVX_CSITX_LANE_SPEED_MBPS_RESERVED;
            local_csitx_config.instCfg[0U].numDataLanes         = 4U;
            for (loopCnt = 0U ;
                 loopCnt < local_csitx_config.instCfg[0U].numDataLanes ;
                 loopCnt++)
            {
                local_csitx_config.instCfg[0U].lanePolarityCtrl[loopCnt] = 0u;
            }
            for (loopCnt = 0U; loopCnt < NUM_CHANNELS; loopCnt++)
            {
                local_csitx_config.chVcNum[loopCnt]   = loopCnt;
                local_csitx_config.chInstMap[loopCnt] = 0;
            }
            obj->csitx_config = vxCreateUserDataObject(obj->context, "tivx_csitx_params_t", sizeof(tivx_csitx_params_t), &local_csitx_config);
        }
    #ifdef DSS_M2M
        /* DSS M2M initialization */
        tivx_display_m2m_params_init(&obj->display_m2m_params);
        obj->display_m2m_params.instId     = 0;
        obj->display_m2m_params.numPipe    = 1;
        obj->display_m2m_params.pipeId[0U] = 3;
        obj->display_m2m_params.overlayId  = 3;
    #endif
    #endif
        appGrpxInitParamsInit(&grpx_prms, obj->context);
        grpx_prms.draw_callback = app_draw_graphics;
        appGrpxInit(&grpx_prms);
    
        appPerfPointSetName(&obj->total_perf , "TOTAL");
        appPerfPointSetName(&obj->fileio_perf, "FILEIO");
        return status;
    }
    
    static void app_deinit(AppObj *obj)
    {
        app_deinit_sensor(&obj->sensorObj);
        APP_PRINTF("Sensor deinit done!\n");
    
        app_deinit_capture(&obj->captureObj, CAPTURE_BUFFER_Q_DEPTH);
        APP_PRINTF("Capture deinit done!\n");
    
        if(1 == obj->enable_split_graph)
        {
            app_deinit_obj_arr_split(&obj->objArrSplitObj);
            APP_PRINTF("Object array splitter deinit done!\n");
        }
    
        if(1 == obj->enable_viss)
        {
            app_deinit_viss(&obj->vissObj);
            APP_PRINTF("VISS deinit done!\n");
        }
    
        if(1 == obj->enable_aewb)
        {
            app_deinit_aewb(&obj->aewbObj);
            APP_PRINTF("AEWB deinit done!\n");
        }
    
        if(obj->sensorObj.enable_ldc == 1)
        {
            app_deinit_ldc(&obj->ldcObj);
            APP_PRINTF("LDC deinit done!\n");
        }
    
        if(1 == obj->enable_split_graph)
        {
            app_deinit_viss(&obj->vissObj1);
            APP_PRINTF("VISS deinit done!\n");
            if(1 == obj->enable_aewb)
            {
                app_deinit_aewb(&obj->aewbObj1);
                APP_PRINTF("AEWB deinit done!\n");
            }
            if(obj->sensorObj.enable_ldc == 1)
            {
                app_deinit_ldc(&obj->ldcObj1);
                APP_PRINTF("LDC deinit done!\n");
            }
        }
    
        if(obj->enable_mosaic == 1)
        {
            app_deinit_img_mosaic(&obj->imgMosaicObj, APP_BUFFER_Q_DEPTH);
            APP_PRINTF("Img Mosaic deinit done!\n");
        }
    #ifndef USE_CSITX
        app_deinit_display(&obj->displayObj);
        APP_PRINTF("Display deinit done!\n");
    #else
        if(NULL != obj->csitx_config)
        {
            APP_PRINTF("releasing csi-tx Data Object\n");
            vxReleaseUserDataObject(&obj->csitx_config);
        }
        if(NULL != obj->csitx_image_arr)
        {
            APP_PRINTF("releasing csitx Image \n");
            vxReleaseObjectArray(&obj->csitx_image_arr);
        }
        if(NULL != obj->display_m2m_param_obj)
        {
            APP_PRINTF("releasing Display Param Data Object\n");
            vxReleaseUserDataObject(&obj->display_m2m_param_obj);
        }
        if(NULL != obj->display_m2m_output_image)
        {
            APP_PRINTF("releasing Display Param Data Object\n");
            vxReleaseImage(&obj->display_m2m_output_image);
        }
        if(NULL != raw_image_exemplar)
        {
            APP_PRINTF("releasing raw_image_exemplar\n");
            tivxReleaseRawImage(&raw_image_exemplar);
        }
    #endif
    
    
        appGrpxDeInit();
    
        tivxHwaUnLoadKernels(obj->context);
        tivxImagingUnLoadKernels(obj->context);
        tivxFileIOUnLoadKernels(obj->context);
        APP_PRINTF("Kernels unload done!\n");
    
        vxReleaseContext(&obj->context);
        APP_PRINTF("Release context done!\n");
    }
    
    static void app_delete_graph(AppObj *obj)
    {
        app_delete_capture(&obj->captureObj);
        APP_PRINTF("Capture delete done!\n");
    
        if(1 == obj->enable_split_graph)
        {
            app_delete_obj_arr_split(&obj->objArrSplitObj);
            APP_PRINTF("Object array splitter delete done!\n");
        }
    
        app_delete_viss(&obj->vissObj);
        APP_PRINTF("VISS delete done!\n");
    
        app_delete_aewb(&obj->aewbObj);
        APP_PRINTF("AEWB delete done!\n");
    
        if(1 == obj->enable_split_graph)
        {
            app_delete_viss(&obj->vissObj1);
            APP_PRINTF("VISS delete done!\n");
    
            app_delete_aewb(&obj->aewbObj1);
            APP_PRINTF("AEWB delete done!\n");
        }
    
        if(obj->sensorObj.enable_ldc == 1)
        {
            app_delete_ldc(&obj->ldcObj);
            APP_PRINTF("LDC delete done!\n");
            if(1 == obj->enable_split_graph)
            {
                app_delete_ldc(&obj->ldcObj1);
                APP_PRINTF("LDC delete done!\n");
            }
        }
    
        app_delete_img_mosaic(&obj->imgMosaicObj);
        APP_PRINTF("Img Mosaic delete done!\n");
    #ifndef USE_CSITX
        app_delete_display(&obj->displayObj);
        APP_PRINTF("Display delete done!\n");
    #else
        if(NULL != obj->csitx_node)
        {
            APP_PRINTF("releasing csitx_node\n");
            vxReleaseNode(&obj->csitx_node);
        }
        if(NULL != obj->displaym2mNode)
        {
            APP_PRINTF("releasing displaym2mNode\n");
            vxReleaseNode(&obj->displaym2mNode);
        }
    #endif
    
        vxReleaseGraph(&obj->graph);
        APP_PRINTF("Graph delete done!\n");
    }
    
    static vx_status app_create_graph(AppObj *obj)
    {
        vx_status status = VX_SUCCESS;
        vx_graph_parameter_queue_params_t graph_parameters_queue_params_list[2];
        vx_int32 graph_parameter_index;
    
        obj->graph = vxCreateGraph(obj->context);
        status = vxGetStatus((vx_reference)obj->graph);
        if (status == VX_SUCCESS)
        {
            status = vxSetReferenceName((vx_reference)obj->graph, "app_multi_cam_graph");
            APP_PRINTF("Graph create done!\n");
        }
    
        if(status == VX_SUCCESS)
        {
            status = app_create_graph_capture(obj->graph, &obj->captureObj);
            APP_PRINTF("Capture graph done!\n");
        }
    
        if( (1 == obj->enable_split_graph) && (status == VX_SUCCESS) )
        {
            status = app_create_graph_obj_arr_split(obj->graph, &obj->objArrSplitObj);
            APP_PRINTF("Object array splitter graph done!\n");
        }
    
        if(1 == obj->enable_viss)
        {
            if(status == VX_SUCCESS)
            {
                if(1 == obj->enable_split_graph)
                {
                    status = app_create_graph_viss(obj->graph, &obj->vissObj, obj->objArrSplitObj.output0_arr, TIVX_TARGET_VPAC_VISS1);
                }
                else
                {
                    status = app_create_graph_viss(obj->graph, &obj->vissObj, obj->captureObj.raw_image_arr[0], TIVX_TARGET_VPAC_VISS1);
                }
                APP_PRINTF("VISS graph done!\n");
            }
        }
    
        if(1 == obj->enable_aewb)
        {
            if(status == VX_SUCCESS)
            {
                status = app_create_graph_aewb(obj->graph, &obj->aewbObj, obj->vissObj.h3a_stats_arr);
    
                APP_PRINTF("AEWB graph done!\n");
            }
        }
    
        vx_int32 idx = 0;
        if(obj->sensorObj.enable_ldc == 1)
        {
            vx_object_array ldc_in_arr;
            if(1 == obj->enable_viss)
            {
                ldc_in_arr = obj->vissObj.output_arr;
            }
            else
            {
                ldc_in_arr = obj->objArrSplitObj.output0_arr;
            }
            if (status == VX_SUCCESS)
            {
                status = app_create_graph_ldc(obj->graph, &obj->ldcObj, ldc_in_arr, TIVX_TARGET_VPAC_LDC1);
                APP_PRINTF("LDC graph done!\n");
            }
            obj->imgMosaicObj.input_arr[idx++] = obj->ldcObj.output_arr;
            APP_PRINTF("IDX = %i!\n",idx);
        }
        else
        {
            vx_object_array mosaic_in_arr;
            if(1 == obj->enable_viss)
            {
                mosaic_in_arr = obj->vissObj.output_arr;
            }
            else
            {
                mosaic_in_arr = obj->objArrSplitObj.output0_arr;
            }
    
            obj->imgMosaicObj.input_arr[idx++] = mosaic_in_arr;
        }
    
        if(1 == obj->enable_split_graph)
        {
            if(status == VX_SUCCESS)
            {
                #if defined(SOC_J784S4)
                status = app_create_graph_viss(obj->graph, &obj->vissObj1, obj->objArrSplitObj.output1_arr, TIVX_TARGET_VPAC2_VISS1);
                #else
                status = app_create_graph_viss(obj->graph, &obj->vissObj1, obj->objArrSplitObj.output1_arr, TIVX_TARGET_VPAC_VISS1);
                #endif
                APP_PRINTF("VISS graph done!\n");
            }
            if(1 == obj->enable_aewb)
            {
                if(status == VX_SUCCESS)
                {
                    status = app_create_graph_aewb(obj->graph, &obj->aewbObj1, obj->vissObj1.h3a_stats_arr);
    
                    APP_PRINTF("AEWB graph done!\n");
                }
            }
            if(obj->sensorObj.enable_ldc == 1)
            {
                vx_object_array ldc_in_arr;
                if(1 == obj->enable_split_graph)
                {
                    ldc_in_arr = obj->vissObj1.output_arr;
                }
                else
                {
                    ldc_in_arr = obj->objArrSplitObj.output1_arr;
                }
                if (status == VX_SUCCESS)
                {
                    #if defined(SOC_J784S4)
                    status = app_create_graph_ldc(obj->graph, &obj->ldcObj1, ldc_in_arr, TIVX_TARGET_VPAC2_LDC1);
                    #else
                    status = app_create_graph_ldc(obj->graph, &obj->ldcObj1, ldc_in_arr, TIVX_TARGET_VPAC_LDC1);
                    #endif
                    APP_PRINTF("LDC graph done!\n");
                }
                obj->imgMosaicObj.input_arr[idx++] = obj->ldcObj1.output_arr;
                APP_PRINTF("IDX = %i!\n",idx);
            }
            else
            {
                vx_object_array mosaic_in_arr;
                if(1 == obj->enable_split_graph)
                {
                    mosaic_in_arr = obj->vissObj1.output_arr;
                }
                else
                {
                    mosaic_in_arr = obj->objArrSplitObj.output1_arr;
                }
    
                obj->imgMosaicObj.input_arr[idx++] = mosaic_in_arr;
            }
        }
    //#ifdef DSS_M2M
    //#ifndef USE_CSITX
    
    
        /* tivx_raw_image tx_frame_array_item=0; */
        vx_image display_in_image=0;
        if(obj->enable_mosaic == 1)
        {
    #if 1
            obj->imgMosaicObj.num_inputs = idx;
    
            if(status == VX_SUCCESS)
            {
                status = app_create_graph_img_mosaic(obj->graph, &obj->imgMosaicObj, NULL);
                APP_PRINTF("Img Mosaic graph done!\n");
            }
            display_in_image = obj->imgMosaicObj.output_image[0];
    #endif
        }
        else
        {
            display_in_image = (vx_image)vxGetObjectArrayItem(obj->captureObj.raw_image_arr[0], 0);
        }
    
    //#endif
        if(status == VX_SUCCESS)
        {
    #ifndef USE_CSITX
            status = app_create_graph_display(obj->graph, &obj->displayObj, display_in_image);
            APP_PRINTF("Display graph done!\n");
    #else
    #ifdef DSS_M2M
            if(obj->is_csitx)
            {
                printf ("Enabling DSS_M2M \n");
                obj->display_m2m_output_image = vxCreateImage(obj->context, obj->imgMosaicObj.out_width, obj->imgMosaicObj.out_height,  VX_DF_IMAGE_UYVY );
                obj->display_m2m_param_obj = vxCreateUserDataObject(obj->context, "tivx_display_m2m_params_t", sizeof(tivx_display_m2m_params_t), &obj->display_m2m_params);
                obj->displaym2mNode = tivxDisplayM2MNode(obj->graph, obj->display_m2m_param_obj, display_in_image, obj->display_m2m_output_image);
                if(status == VX_SUCCESS)
                {
                    status = vxSetNodeTarget(obj->displaym2mNode, VX_TARGET_STRING, TIVX_TARGET_DISPLAY_M2M1);
                }
    
                if(status == VX_SUCCESS)
                {
                    status = tivxSetNodeParameterNumBufByIndex(obj->displaym2mNode, 2u, APP_BUFFER_Q_DEPTH);
                }
    
                // CSI-TX
                {
                    obj->csitx_image_arr = vxCreateObjectArray(obj->context, (vx_reference)obj->display_m2m_output_image, 1);
                    obj->csitx_node = tivxCsitxNode(obj->graph, obj->csitx_config, obj->csitx_image_arr);
                    vxSetNodeTarget(obj->csitx_node, VX_TARGET_STRING, TIVX_TARGET_CSITX);
                }
            }
    #else
            // CSI-TX
            if(obj->is_csitx)
            {
    
                #if 0
                /* vxSetNodeTarget(obj->csitx_node, VX_TARGET_STRING, TIVX_TARGET_CSITX); */
                #else
    
                status = app_create_graph_display(obj->graph, &obj->displayObj, display_in_image);
                APP_PRINTF("Display graph done!\n");
    
                uint16_t frmIdx;
                tivx_raw_image tx_frame_array_item=0;
                tivx_raw_image_create_params_t params;
                params.width = 1920;
                params.height = 1080;
                params.num_exposures = 1;
                params.line_interleaved = vx_false_e;//vx_true_e;
                params.format[0].pixel_container = TIVX_RAW_IMAGE_16_BIT;
                params.format[0].msb = 11;//13;
                params.meta_height_before = 0;
                params.meta_height_after = 0;
                raw_image_exemplar = tivxCreateRawImage(obj->context, &params);
                tx_frame = vxCreateObjectArray(obj->context, (vx_reference)raw_image_exemplar, NUM_CHANNELS);
                /* tx_frame = vxCreateObjectArray(obj->context, (vx_reference)obj->captureObj.raw_image_arr[0], 4); */
                printf("Initializing Transmit Buffers...\n");
    
                for (frmIdx = 0U; frmIdx < NUM_CHANNELS; frmIdx++)
                {
                    tx_frame_array_item = (tivx_raw_image)vxGetObjectArrayItem(tx_frame , frmIdx);
                    if (tx_frame_array_item == NULL)
                    {
                        printf("%s[%d]vx_frame_array_item create failed\n", __FUNCTION__, __LINE__);
                    }
                    else
                    {
                        printf("vxGetObjectArrayItem success\n");
                    }
    
                    status = readRAWinput(tx_frame_array_item, "./csitx.raw");
                    if (status != VX_SUCCESS)
                    {
                        printf("%s[%d] load rawfile failed\n", __FUNCTION__, __LINE__);
                    }
                    status = tivxReleaseRawImage(&tx_frame_array_item);
                    if (status != VX_SUCCESS)
                    {
                        printf("%s[%d] tx_frame_array_item Release failed\n", __FUNCTION__, __LINE__);
                    }
    
                }
                printf("Initializing Transmit Buffers Done.\n");
                obj->csitx_node = tivxCsitxNode(obj->graph, obj->csitx_config, tx_frame);
                vxSetNodeTarget(obj->csitx_node, VX_TARGET_STRING, TIVX_TARGET_CSITX);
                printf("Csitx graph done!\n");
    #endif
            }
    #endif
    #endif
        }
    
        if(status == VX_SUCCESS)
        {
            graph_parameter_index = 0;
            add_graph_parameter_by_node_index(obj->graph, obj->captureObj.node, 1);
            obj->captureObj.graph_parameter_index = graph_parameter_index;
            graph_parameters_queue_params_list[graph_parameter_index].graph_parameter_index = graph_parameter_index;
            graph_parameters_queue_params_list[graph_parameter_index].refs_list_size = CAPTURE_BUFFER_Q_DEPTH;
            graph_parameters_queue_params_list[graph_parameter_index].refs_list = (vx_reference*)&obj->captureObj.raw_image_arr[0];
            graph_parameter_index++;
    
            if((obj->en_out_img_write == 1) || (obj->test_mode == 1))
            {
                add_graph_parameter_by_node_index(obj->graph, obj->imgMosaicObj.node, 1);
                obj->imgMosaicObj.graph_parameter_index = graph_parameter_index;
                graph_parameters_queue_params_list[graph_parameter_index].graph_parameter_index = graph_parameter_index;
                graph_parameters_queue_params_list[graph_parameter_index].refs_list_size = CAPTURE_BUFFER_Q_DEPTH;
                graph_parameters_queue_params_list[graph_parameter_index].refs_list = (vx_reference*)&obj->imgMosaicObj.output_image[0];
                graph_parameter_index++;
            }
    
            status = vxSetGraphScheduleConfig(obj->graph,
                    VX_GRAPH_SCHEDULE_MODE_QUEUE_AUTO,
                    graph_parameter_index,
                    graph_parameters_queue_params_list);
    
            if (status == VX_SUCCESS)
            {
                status = tivxSetGraphPipelineDepth(obj->graph, APP_PIPELINE_DEPTH);
            }
            if((obj->enable_viss == 1) && (status == VX_SUCCESS))
            {
                status = tivxSetNodeParameterNumBufByIndex(obj->vissObj.node, 6, APP_BUFFER_Q_DEPTH);
    
                if (status == VX_SUCCESS)
                {
                    status = tivxSetNodeParameterNumBufByIndex(obj->vissObj.node, 9, APP_BUFFER_Q_DEPTH);
                }
            }
            if((obj->enable_aewb == 1) && (status == VX_SUCCESS))
            {
                if (status == VX_SUCCESS)
                {
                    status = tivxSetNodeParameterNumBufByIndex(obj->aewbObj.node, 4, APP_BUFFER_Q_DEPTH);
                }
            }
            if((obj->sensorObj.enable_ldc == 1) && (status == VX_SUCCESS))
            {
                status = tivxSetNodeParameterNumBufByIndex(obj->ldcObj.node, 7, APP_BUFFER_Q_DEPTH);
            }
            if((obj->enable_split_graph == 1) && (status == VX_SUCCESS))
            {
                status = tivxSetNodeParameterNumBufByIndex(obj->vissObj1.node, 6, APP_BUFFER_Q_DEPTH);
    
                if (status == VX_SUCCESS)
                {
                    status = tivxSetNodeParameterNumBufByIndex(obj->vissObj1.node, 9, APP_BUFFER_Q_DEPTH);
                }
                if((obj->enable_aewb == 1) && (status == VX_SUCCESS))
                {
                    if (status == VX_SUCCESS)
                    {
                        status = tivxSetNodeParameterNumBufByIndex(obj->aewbObj1.node, 4, APP_BUFFER_Q_DEPTH);
                    }
                }
                if((obj->sensorObj.enable_ldc == 1) && (status == VX_SUCCESS))
                {
                    status = tivxSetNodeParameterNumBufByIndex(obj->ldcObj1.node, 7, APP_BUFFER_Q_DEPTH);
                }
            }
    
            if((obj->enable_mosaic == 1) && (status == VX_SUCCESS))
            {
                if(!((obj->en_out_img_write == 1) || (obj->test_mode == 1)))
                {
                    status = tivxSetNodeParameterNumBufByIndex(obj->imgMosaicObj.node, 1, CAPTURE_BUFFER_Q_DEPTH);
                    APP_PRINTF("Pipeline params setup done!\n");
                }
            }
        }
    
        return status;
    }
    
    static vx_status app_verify_graph(AppObj *obj)
    {
        vx_status status = VX_SUCCESS;
    
        status = vxVerifyGraph(obj->graph);
    
        if(status == VX_SUCCESS)
        {
            APP_PRINTF("Graph verify done!\n");
        }
    
        #if 1
        if(VX_SUCCESS == status)
        {
          status = tivxExportGraphToDot(obj->graph,".", "vx_app_multi_cam_ahp");
        }
        #endif
    
        if (((obj->captureObj.enable_error_detection) || (obj->test_mode)) && (status == VX_SUCCESS))
        {
            status = app_send_error_frame(&obj->captureObj);
        }
    
        /* wait a while for prints to flush */
        tivxTaskWaitMsecs(100);
    
        return status;
    }
    
    static vx_status app_run_graph_for_one_frame_pipeline(AppObj *obj, vx_int32 frame_id)
    {
        vx_status status = VX_SUCCESS;
    
        APP_PRINTF("app_run_graph_for_one_pipeline: frame %d beginning\n", frame_id);
        appPerfPointBegin(&obj->total_perf);
    
        ImgMosaicObj *imgMosaicObj = &obj->imgMosaicObj;
        CaptureObj *captureObj = &obj->captureObj;
    
        /* checksum_actual is the checksum determined by the realtime test
            checksum_expected is the checksum that is expected to be the pipeline output */
        uint32_t checksum_actual = 0;
    
        /* This is the number of frames required for the pipeline AWB and AE algorithms to stabilize
            (note that 15 is only required for the 6-8 camera use cases - others converge quicker) */
        uint8_t stability_frame = 15;
    
        if(obj->pipeline < 0)
        {
            /* Enqueue outpus */
            if ((obj->en_out_img_write == 1) || (obj->test_mode == 1))
            {
                status = vxGraphParameterEnqueueReadyRef(obj->graph, imgMosaicObj->graph_parameter_index, (vx_reference*)&imgMosaicObj->output_image[obj->enqueueCnt], 1);
            }
    
            /* Enqueue inputs during pipeup dont execute */
            if (status == VX_SUCCESS)
            {
                status = vxGraphParameterEnqueueReadyRef(obj->graph, captureObj->graph_parameter_index, (vx_reference*)&obj->captureObj.raw_image_arr[obj->enqueueCnt], 1);
            }
            obj->enqueueCnt++;
            obj->enqueueCnt   = (obj->enqueueCnt  >= CAPTURE_BUFFER_Q_DEPTH)? 0 : obj->enqueueCnt;
            obj->pipeline++;
        }
    
        if((obj->pipeline == 0) && (status == VX_SUCCESS))
        {
            if((obj->en_out_img_write == 1) || (obj->test_mode == 1))
            {
                status = vxGraphParameterEnqueueReadyRef(obj->graph, imgMosaicObj->graph_parameter_index, (vx_reference*)&imgMosaicObj->output_image[obj->enqueueCnt], 1);
            }
    
            /* Execute 1st frame */
            if(status == VX_SUCCESS)
            {
                status = vxGraphParameterEnqueueReadyRef(obj->graph, captureObj->graph_parameter_index, (vx_reference*)&obj->captureObj.raw_image_arr[obj->enqueueCnt], 1);
            }
            obj->enqueueCnt++;
            obj->enqueueCnt   = (obj->enqueueCnt  >= CAPTURE_BUFFER_Q_DEPTH)? 0 : obj->enqueueCnt;
            obj->pipeline++;
        }
    
        if((obj->pipeline > 0) && (status == VX_SUCCESS))
        {
            vx_object_array capture_input_arr;
            vx_image mosaic_output_image;
            uint32_t num_refs;
    
            /* Dequeue input */
            status = vxGraphParameterDequeueDoneRef(obj->graph, captureObj->graph_parameter_index, (vx_reference*)&capture_input_arr, 1, &num_refs);
            if((obj->en_out_img_write == 1) || (obj->test_mode == 1))
            {
                vx_char output_file_name[APP_MAX_FILE_PATH];
    
                /* Dequeue output */
                if (status == VX_SUCCESS)
                {
                    status = vxGraphParameterDequeueDoneRef(obj->graph, imgMosaicObj->graph_parameter_index, (vx_reference*)&mosaic_output_image, 1, &num_refs);
                }
                if ((status == VX_SUCCESS) && (obj->test_mode == 1) && (frame_id > TEST_BUFFER))
                {
                    /* calculate the checksum of the mosaic output */
    
                    if ((app_test_check_image(mosaic_output_image, checksums_expected[obj->sensorObj.sensor_index][obj->sensorObj.num_cameras_enabled-1],
                                            &checksum_actual) != vx_true_e) && (frame_id > stability_frame))
                    {
                        test_result = vx_false_e;
                        /* in case test fails and needs to change */
                        populate_gatherer(obj->sensorObj.sensor_index, obj->sensorObj.num_cameras_enabled-1, checksum_actual);
                    }
                }
    
                if (obj->en_out_img_write == 1) {
                    appPerfPointBegin(&obj->fileio_perf);
                    snprintf(output_file_name, APP_MAX_FILE_PATH, "%s/mosaic_output_%010d_%dx%d.yuv", obj->output_file_path, (frame_id - CAPTURE_BUFFER_Q_DEPTH), imgMosaicObj->out_width, imgMosaicObj->out_height);
                    if (status == VX_SUCCESS)
                    {
                        status = writeMosaicOutput(output_file_name, mosaic_output_image);
                    }
                    appPerfPointEnd(&obj->fileio_perf);
                }
                /* Enqueue output */
                if (status == VX_SUCCESS)
                {
                    status = vxGraphParameterEnqueueReadyRef(obj->graph, imgMosaicObj->graph_parameter_index, (vx_reference*)&mosaic_output_image, 1);
                }
            }
    
            /* Enqueue input - start execution */
            if (status == VX_SUCCESS)
            {
                status = vxGraphParameterEnqueueReadyRef(obj->graph, captureObj->graph_parameter_index, (vx_reference*)&capture_input_arr, 1);
            }
            obj->enqueueCnt++;
            obj->dequeueCnt++;
    
            obj->enqueueCnt = (obj->enqueueCnt >= CAPTURE_BUFFER_Q_DEPTH)? 0 : obj->enqueueCnt;
            obj->dequeueCnt = (obj->dequeueCnt >= CAPTURE_BUFFER_Q_DEPTH)? 0 : obj->dequeueCnt;
        }
    
        appPerfPointEnd(&obj->total_perf);
        return status;
    }
    
    static vx_status app_run_graph(AppObj *obj)
    {
        vx_status status = VX_SUCCESS;
        SensorObj *sensorObj = &obj->sensorObj;
        vx_int32 frame_id;
        int32_t ch_mask = obj->sensorObj.ch_mask;
    
        app_pipeline_params_defaults(obj);
        APP_PRINTF("app_pipeline_params_defaults returned\n");
    
        if(NULL == sensorObj->sensor_name)
        {
            printf("sensor name is NULL \n");
            return VX_FAILURE;
        }
    
        // if test_mode is enabled, don't fail the program if the sensor init fails
        if( (obj->test_mode) || (obj->captureObj.enable_error_detection) )
        {
            appStartImageSensor(sensorObj->sensor_name, ch_mask);
        }
        else
        {
            status = appStartImageSensor(sensorObj->sensor_name, ch_mask);
            APP_PRINTF("appStartImageSensor returned with status: %d\n", status);
        }
    
        if(0 == obj->enable_viss)
        {
            obj->vissObj.en_out_viss_write = 0;
        }
        if(0 == obj->enable_split_graph)
        {
            obj->vissObj1.en_out_viss_write = 0;
        }
    
        if (obj->test_mode == 1) {
            // The buffer allows AWB/AE algos to converge before checksums are calculated
            obj->num_frames_to_run = TEST_BUFFER + 30;
        }
    
        for(frame_id = 0; frame_id < obj->num_frames_to_run; frame_id++)
        {
            if(obj->write_file == 1)
            {
                if((obj->captureObj.en_out_capture_write == 1) && (status == VX_SUCCESS))
                {
                    status = app_send_cmd_capture_write_node(&obj->captureObj, frame_id, obj->num_frames_to_write, obj->num_frames_to_skip);
                }
                if((obj->vissObj.en_out_viss_write == 1) && (status == VX_SUCCESS))
                {
                    status = app_send_cmd_viss_write_node(&obj->vissObj, frame_id, obj->num_frames_to_write, obj->num_frames_to_skip);
                }
                if((obj->vissObj1.en_out_viss_write == 1) && (status == VX_SUCCESS))
                {
                    status = app_send_cmd_viss_write_node(&obj->vissObj1, frame_id, obj->num_frames_to_write, obj->num_frames_to_skip);
                }
                if((obj->ldcObj.en_out_ldc_write == 1) && (status == VX_SUCCESS))
                {
                    status = app_send_cmd_ldc_write_node(&obj->ldcObj, frame_id, obj->num_frames_to_write, obj->num_frames_to_skip);
                }
                if((obj->ldcObj1.en_out_ldc_write == 1) && (status == VX_SUCCESS))
                {
                    status = app_send_cmd_ldc_write_node(&obj->ldcObj1, frame_id, obj->num_frames_to_write, obj->num_frames_to_skip);
                }
                obj->write_file = 0;
            }
    
            if (status == VX_SUCCESS)
            {
                status = app_run_graph_for_one_frame_pipeline(obj, frame_id);
                if((frame_id % obj->save_images_time)==0)
                {
                    save_debug_images(obj);
                    frame_id = 0;
                }
    
            }
            /* user asked to:stop processing */
            if(obj->stop_task)
              break;
        }
    
        if (status == VX_SUCCESS)
        {
            status = vxWaitGraph(obj->graph);
        }
        obj->stop_task = 1;
    
        if (status == VX_SUCCESS)
        {
            status = appStopImageSensor(obj->sensorObj.sensor_name, ch_mask);
        }
    
        return status;
    }
    
    static void set_display_defaults(DisplayObj *displayObj)
    {
        displayObj->display_option = 1;
    }
    
    static void app_pipeline_params_defaults(AppObj *obj)
    {
        obj->pipeline       = -CAPTURE_BUFFER_Q_DEPTH + 1;
        obj->enqueueCnt     = 0;
        obj->dequeueCnt     = 0;
    }
    
    static void set_sensor_defaults(SensorObj *sensorObj)
    {
        strcpy(sensorObj->sensor_name, SENSOR_SONY_IMX390_UB953_D3);
    
        sensorObj->num_sensors_found = 0;
        sensorObj->sensor_features_enabled = 0;
        sensorObj->sensor_features_supported = 0;
        sensorObj->sensor_dcc_enabled = 0;
        sensorObj->sensor_wdr_enabled = 0;
        sensorObj->sensor_exp_control_enabled = 0;
        sensorObj->sensor_gain_control_enabled = 0;
    }
    
    static void app_default_param_set(AppObj *obj)
    {
        set_sensor_defaults(&obj->sensorObj);
    
        set_display_defaults(&obj->displayObj);
    
        app_pipeline_params_defaults(obj);
    
        obj->is_interactive = 1;
    #ifdef USE_CSITX
        obj->is_csitx = 1;
    #endif
        obj->test_mode = 0;
        obj->write_file = 0;
        obj->bypass_split_graph = 0;
    
        obj->sensorObj.enable_ldc = 0;
        obj->sensorObj.num_cameras_enabled = 1;
        obj->sensorObj.ch_mask = 0x1;
        obj->sensorObj.usecase_option = APP_SENSOR_FEATURE_CFG_UC0;
    }
    
    static vx_int32 calc_grid_size(vx_uint32 ch)
    {
        if(0==ch)
        {
            return -1;
        }
        else if(1==ch)
        {
            return 1;
        }
        else if(4>=ch)
        {
            return 2;
        }
        else if(9>=ch)
        {
            return 3;
        }
        else if(16>=ch)
        {
            return 4;
        }else
        {
            return -1;
        }
    }
    
    static void set_img_mosaic_params(ImgMosaicObj *imgMosaicObj, vx_uint32 in_width, vx_uint32 in_height, vx_int32 numCh, ObjArrSplitObj *objArrSplitObj, int32_t enable_split_graph)
    {
        vx_int32 idx, ch;
        vx_int32 grid_size = calc_grid_size(numCh);
    
        imgMosaicObj->out_width    = DISPLAY_WIDTH;
        imgMosaicObj->out_height   = DISPLAY_HEIGHT;
    
        if (1 == enable_split_graph)
        {
            imgMosaicObj->num_inputs   = 2;
        }
        else
        {
            imgMosaicObj->num_inputs   = 1;
        }
    
        idx = 0;
    
        tivxImgMosaicParamsSetDefaults(&imgMosaicObj->params);
    
        for(ch = 0; ch < numCh; ch++)
        {
            vx_int32 winX = ch%grid_size;
            vx_int32 winY = ch/grid_size;
    
            imgMosaicObj->params.windows[idx].startX  = (winX * (in_width/grid_size));
            imgMosaicObj->params.windows[idx].startY  = (winY * (in_height/grid_size));
            imgMosaicObj->params.windows[idx].width   = in_width/grid_size;
            imgMosaicObj->params.windows[idx].height  = in_height/grid_size;
            imgMosaicObj->params.windows[idx].input_select   = 0;
            if (1 == enable_split_graph)
            {
                if(ch >= objArrSplitObj->output0_num_elements)
                {
                    imgMosaicObj->params.windows[idx].input_select   = 1;
                }
                imgMosaicObj->params.windows[idx].channel_select = ch%objArrSplitObj->output0_num_elements;
            }
            else
            {
                imgMosaicObj->params.windows[idx].channel_select = ch;
            }
            idx++;
        }
    
        imgMosaicObj->params.num_windows  = idx;
    
        /* Number of time to clear the output buffer before it gets reused */
        imgMosaicObj->params.clear_count  = CAPTURE_BUFFER_Q_DEPTH;
    }
    
    static void app_update_param_set(AppObj *obj)
    {
        vx_uint16 resized_width, resized_height;
        appIssGetResizeParams(obj->sensorObj.image_width, obj->sensorObj.image_height, DISPLAY_WIDTH, DISPLAY_HEIGHT, &resized_width, &resized_height);
    
        if ( (obj->sensorObj.num_cameras_enabled == 1))
        {
            obj->objArrSplitObj.output0_num_elements = 1;
            obj->objArrSplitObj.output1_num_elements = 0;
            obj->enable_split_graph = 0;
        }
        else if (1 == obj->bypass_split_graph)
        {
            obj->objArrSplitObj.output0_num_elements = obj->sensorObj.num_cameras_enabled;
            obj->objArrSplitObj.output1_num_elements = 0;
            obj->enable_split_graph = 0;
        }
        else
        {
            obj->objArrSplitObj.output0_num_elements = (obj->sensorObj.num_cameras_enabled + 1) / 2;
            obj->objArrSplitObj.output1_num_elements = obj->sensorObj.num_cameras_enabled - obj->objArrSplitObj.output0_num_elements;
        }
        set_img_mosaic_params(&obj->imgMosaicObj, resized_width, resized_height, obj->sensorObj.num_cameras_enabled, &obj->objArrSplitObj, obj->enable_split_graph);
    }
    
    /*
     * Utility API used to add a graph parameter from a node, node parameter index
     */
    static void add_graph_parameter_by_node_index(vx_graph graph, vx_node node, vx_uint32 node_parameter_index)
    {
        vx_parameter parameter = vxGetParameterByIndex(node, node_parameter_index);
    
        vxAddParameterToGraph(graph, parameter);
        vxReleaseParameter(&parameter);
    }
    
    static void app_draw_graphics(Draw2D_Handle *handle, Draw2D_BufInfo *draw2dBufInfo, uint32_t update_type)
    {
        appGrpxDrawDefault(handle, draw2dBufInfo, update_type);
    
        if(update_type == 0)
        {
            Draw2D_FontPrm sHeading;
    
            sHeading.fontIdx = 4;
            Draw2D_drawString(handle, 700, 5, "Multi Cam Demo", &sHeading);
        }
    
      return;
    }
    //Brandon@0914
    vx_int32 write_output_image_fp(FILE * fp, vx_image out_image)
    {
        vx_uint32 width, height;
        vx_df_image df;
        vx_imagepatch_addressing_t image_addr;
        vx_rectangle_t rect;
        vx_map_id map_id1, map_id2;
        void *data_ptr1, *data_ptr2;
        vx_uint32 num_bytes_per_4pixels;
        vx_uint32 num_luma_bytes_written_to_file=0;
        vx_uint32 num_chroma_bytes_written_to_file=0;
        vx_uint32 num_bytes_written_to_file=0;
        vx_uint32 imgaddr_width, imgaddr_height, imgaddr_stride;
        int i;
    
        vxQueryImage(out_image, VX_IMAGE_WIDTH, &width, sizeof(vx_uint32));
        vxQueryImage(out_image, VX_IMAGE_HEIGHT, &height, sizeof(vx_uint32));
        vxQueryImage(out_image, VX_IMAGE_FORMAT, &df, sizeof(vx_df_image));
    
    
        if(VX_DF_IMAGE_NV12 == df)
        {
            num_bytes_per_4pixels = 4;
        }
        else if(TIVX_DF_IMAGE_NV12_P12 == df)
        {
            num_bytes_per_4pixels = 6;
        }
        else
        {
            num_bytes_per_4pixels = 8;
        }
    
        rect.start_x = 0;
        rect.start_y = 0;
        rect.end_x = width;
        rect.end_y = height;
    
        vxMapImagePatch(out_image,
                        &rect,
                        0,
                        &map_id1,
                        &image_addr,
                        &data_ptr1,
                        VX_WRITE_ONLY,
                        VX_MEMORY_TYPE_HOST,
                        VX_NOGAP_X
            );
    
        if(!data_ptr1)
        {
            printf("data_ptr1 is NULL \n");
            return -1;
        }
    
        imgaddr_width  = image_addr.dim_x;
        imgaddr_height = image_addr.dim_y;
        imgaddr_stride = image_addr.stride_y;
        printf("imgaddr_width = %d \n", imgaddr_width);
        printf("imgaddr_height = %d \n", imgaddr_height);
        printf("imgaddr_stride = %d \n", imgaddr_stride);
        printf("width = %d \n", width);
        printf("height = %d \n", height);
    
        num_luma_bytes_written_to_file = 0;
    
        for(i=0;i<height;i++)
        {
            num_luma_bytes_written_to_file  += fwrite(data_ptr1, 1, width*num_bytes_per_4pixels/4, fp);
            data_ptr1 += imgaddr_stride;
        }
        vxUnmapImagePatch(out_image, map_id1);
    
        fflush(fp);
    
    
        if(VX_DF_IMAGE_NV12 == df || TIVX_DF_IMAGE_NV12_P12 == df)
        {
            vxMapImagePatch(out_image,
                            &rect,
                            1,
                            &map_id2,
                            &image_addr,
                            &data_ptr2,
                            VX_WRITE_ONLY,
                            VX_MEMORY_TYPE_HOST,
                            VX_NOGAP_X
                );
    
            if(!data_ptr2)
            {
                printf("data_ptr2 is NULL \n");
                return -1;
            }
    
            imgaddr_width  = image_addr.dim_x;
            imgaddr_height = image_addr.dim_y;
            imgaddr_stride = image_addr.stride_y;
    
            num_chroma_bytes_written_to_file = 0;
            for(i=0;i<imgaddr_height/2;i++)
            {
                num_chroma_bytes_written_to_file  += fwrite(data_ptr2, 1, imgaddr_width*num_bytes_per_4pixels/4, fp);
                data_ptr2 += imgaddr_stride;
            }
    
            fflush(fp);
    
            vxUnmapImagePatch(out_image, map_id2);
        }
    
        num_bytes_written_to_file = num_luma_bytes_written_to_file + num_chroma_bytes_written_to_file;
        printf("Written %d bytes \n", num_bytes_written_to_file);
    
        return num_bytes_written_to_file;
    }
    vx_int32 write_output_image_yuv422_8bit(char * file_name, vx_image out_yuv)
    {
        FILE * fp = fopen(file_name, "wb");
        if(!fp)
        {
            APP_PRINTF("Unable to open file %s\n", file_name);
            return -1;
        }
        vx_uint32 len1 = write_output_image_fp(fp, out_yuv);
        fclose(fp);
        APP_PRINTF("%d bytes written to %s\n", len1, file_name);
        return len1;
    }
    
    
    vx_int32 write_output_image_nv12_8bit(char * file_name, vx_image out_nv12)
    {
        FILE * fp = fopen(file_name, "wb");
        if(!fp)
        {
            APP_PRINTF("Unable to open file %s\n", file_name);
            return -1;
        }
        vx_uint32 len1 = write_output_image_fp(fp, out_nv12);
        fclose(fp);
        APP_PRINTF("%d bytes written to %s\n", len1, file_name);
        return len1;
    }
    
    static int save_debug_images(AppObj *obj)
    {
        int num_bytes_io = 0;
        static int file_index = 0;
        char raw_image_fname[256];
        char failsafe_test_data_path[12] = "./test_data";
        char * test_data_path = getenv("VX_TEST_DATA_PATH");//app_get_test_file_path();
        struct stat s;
        int i;
    
        if(NULL == test_data_path)
        {
            printf("Test data path is NULL. Defaulting to current folder \n");
            test_data_path = failsafe_test_data_path;
        }
    
        if (stat(test_data_path, &s))
        {
            printf("Test data path %s does not exist. Defaulting to current folder \n", test_data_path);
            test_data_path = failsafe_test_data_path;
        }
    
        if(1 != obj->sensorObj.sensor_out_format)
        {
            for(i=0;i<1;i++){
    
                vx_image cap_image;
                snprintf(raw_image_fname, 256, "%s/%s_%04d_0_%d.yuv", test_data_path, "img", file_index, i);
                printf("RAW file name %s \n", raw_image_fname);//N12 fromat Brandon@0913
                cap_image = (vx_image)obj->imgMosaicObj.output_image[i];
                num_bytes_io = write_output_image_nv12_8bit(raw_image_fname, cap_image);
    
                if(num_bytes_io < 0)
                {
                    printf("Error writing to RAW file \n");
                    return VX_FAILURE;
                }
            }
        }
        else
        {
            vx_image cap_yuv;
            int i=0;
            for(i=0;i<4;i++)
            {
                snprintf(raw_image_fname, 256, "%s/%s_ch%d_%04d.yuv", test_data_path,"cap",i ,file_index);
                printf("YUV file name %s \n", raw_image_fname);
                cap_yuv = (vx_image)vxGetObjectArrayItem(obj->captureObj.raw_image_arr[0], i);
                num_bytes_io = write_output_image_yuv422_8bit(raw_image_fname, cap_yuv);
                if(num_bytes_io < 0)
                {
                    printf("Error writing to YUV file \n");
                    return VX_FAILURE;
                }
            }
    
        }
        file_index++;
        if (file_index ==5)
            file_index = 0;
        return (file_index-1);
    }
    

  • ok,

    Please keep the enable_error_detection as 1 itself. Then when you run the application and remove the camera, please press "p" and check if the frame count is increasing in other cameras or if it has stopped?

    Then we can ensure that the issue could be only with the saving part.

    Regards,

    Nikhil

  • Hi Nikhil,

    When the camera is not removed, the frame count increases normally.

    However, after removing one camera, the program gets stuck at the part displaying the FPS log. Pressing "Enter" has no effect.

    The frame count log is only output again after reconnecting the camera, indicating that the program seems to have frozen.

     =========================
     Demo : Camera Demo
     =========================
    
     s: Save CSIx, VISS and LDC outputs
    
     S: Save Raw image
    
     p: Print performance statistics
    
     r: read des register
     w: write des register
     x: Exit
    
     Enter Choice: p
    
    
    Summary of CPU load,
    ====================
    
    CPU: mpu1_0: TOTAL LOAD =   2.30 % ( HWI =   0.10 %, SWI =   0. 4 % )
    CPU: mcu2_0: TOTAL LOAD =   8. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
    CPU: mcu2_1: TOTAL LOAD =   7. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
    CPU:  c7x_1: TOTAL LOAD =   0. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
    CPU:  c7x_2: TOTAL LOAD =   0. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
    
    
    HWA performance statistics,
    ===========================
    
    
    
    DDR performance statistics,
    ===========================
    
    DDR: READ  BW: AVG =     29 MB/s, PEAK =   3830 MB/s
    DDR: WRITE BW: AVG =    221 MB/s, PEAK =   2397 MB/s
    DDR: TOTAL BW: AVG =    250 MB/s, PEAK =   6227 MB/s
    
    
    Detailed CPU performance/memory statistics,
    ===========================================
    
    DDR_SHARED_MEM: Alloc's: 17 alloc's of 32768216 bytes 
    DDR_SHARED_MEM: Free's : 0 free's  of 0 bytes 
    DDR_SHARED_MEM: Open's : 17 allocs  of 32768216 bytes 
    DDR_SHARED_MEM: Total size: 536870912 bytes 
    
    CPU: mcu2_0: TASK:           IPC_RX:   0. 1 %
    CPU: mcu2_0: TASK:       REMOTE_SRV:   0.31 %
    CPU: mcu2_0: TASK:        LOAD_TEST:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CPU_0:   0. 0 %
    CPU: mcu2_0: TASK:        TIVX_V1NF:   0. 0 %
    CPU: mcu2_0: TASK:      TIVX_V1LDC1:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_V1SC1:   0. 0 %
    CPU: mcu2_0: TASK:      TIVX_V1MSC2:   0. 0 %
    CPU: mcu2_0: TASK:       TIVXVVISS1:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CAPT1:   0.37 %
    CPU: mcu2_0: TASK:       TIVX_CAPT2:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_DISP1:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_DISP2:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CSITX:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CAPT3:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CAPT4:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CAPT5:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CAPT6:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CAPT7:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CAPT8:   0. 0 %
    CPU: mcu2_0: TASK:      TIVX_DPM2M1:   0. 0 %
    CPU: mcu2_0: TASK:      TIVX_DPM2M2:   0. 0 %
    CPU: mcu2_0: TASK:      TIVX_DPM2M3:   0. 0 %
    CPU: mcu2_0: TASK:      TIVX_DPM2M4:   0. 0 %
    
    CPU: mcu2_0: HEAP:    DDR_LOCAL_MEM: size =   16777216 B, free =   16713472 B ( 99 % unused)
    CPU: mcu2_0: HEAP:           L3_MEM: size =     524288 B, free =     524032 B ( 99 % unused)
    
    CPU: mcu2_1: TASK:           IPC_RX:   0. 0 %
    CPU: mcu2_1: TASK:       REMOTE_SRV:   0. 0 %
    CPU: mcu2_1: TASK:        LOAD_TEST:   0. 0 %
    CPU: mcu2_1: TASK:       TIVX_CPU_1:   0. 0 %
    CPU: mcu2_1: TASK:         TIVX_SDE:   0. 0 %
    CPU: mcu2_1: TASK:         TIVX_DOF:   0. 0 %
    CPU: mcu2_1: TASK:      IPC_TEST_RX:   0. 0 %
    CPU: mcu2_1: TASK:      IPC_TEST_TX:   0. 0 %
    CPU: mcu2_1: TASK:      IPC_TEST_TX:   0. 0 %
    CPU: mcu2_1: TASK:      IPC_TEST_TX:   0. 0 %
    CPU: mcu2_1: TASK:      IPC_TEST_TX:   0. 0 %
    
    CPU: mcu2_1: HEAP:    DDR_LOCAL_MEM: size =   16777216 B, free =   16773120 B ( 99 % unused)
    CPU: mcu2_1: HEAP:           L3_MEM: size =     524288 B, free =     524288 B (100 % unused)
    
    CPU:  c7x_1: TASK:           IPC_RX:   0. 0 %
    CPU:  c7x_1: TASK:       REMOTE_SRV:   0. 0 %
    CPU:  c7x_1: TASK:        LOAD_TEST:   0. 0 %
    CPU:  c7x_1: TASK:      TIVX_C71_P1:   0. 0 %
    CPU:  c7x_1: TASK:      TIVX_C71_P2:   0. 0 %
    CPU:  c7x_1: TASK:      TIVX_C71_P3:   0. 0 %
    CPU:  c7x_1: TASK:      TIVX_C71_P4:   0. 0 %
    CPU:  c7x_1: TASK:      TIVX_C71_P5:   0. 0 %
    CPU:  c7x_1: TASK:      TIVX_C71_P6:   0. 0 %
    CPU:  c7x_1: TASK:      TIVX_C71_P7:   0. 0 %
    CPU:  c7x_1: TASK:      TIVX_C71_P8:   0. 0 %
    CPU:  c7x_1: TASK:      IPC_TEST_RX:   0. 0 %
    CPU:  c7x_1: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c7x_1: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c7x_1: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c7x_1: TASK:      IPC_TEST_TX:   0. 0 %
    
    CPU:  c7x_1: HEAP:    DDR_LOCAL_MEM: size =  268435456 B, free =  268435200 B ( 99 % unused)
    CPU:  c7x_1: HEAP:           L3_MEM: size =    3964928 B, free =    3964928 B (100 % unused)
    CPU:  c7x_1: HEAP:           L2_MEM: size =     458752 B, free =     458752 B (100 % unused)
    CPU:  c7x_1: HEAP:           L1_MEM: size =      16384 B, free =      16384 B (100 % unused)
    CPU:  c7x_1: HEAP:  DDR_SCRATCH_MEM: size =  385875968 B, free =  385875968 B (100 % unused)
    
    CPU:  c7x_2: TASK:           IPC_RX:   0. 0 %
    CPU:  c7x_2: TASK:       REMOTE_SRV:   0. 0 %
    CPU:  c7x_2: TASK:        LOAD_TEST:   0. 0 %
    CPU:  c7x_2: TASK:         TIVX_CPU:   0. 0 %
    CPU:  c7x_2: TASK:      IPC_TEST_RX:   0. 0 %
    CPU:  c7x_2: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c7x_2: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c7x_2: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c7x_2: TASK:      IPC_TEST_TX:   0. 0 %
    
    CPU:  c7x_2: HEAP:    DDR_LOCAL_MEM: size =   16777216 B, free =   16772608 B ( 99 % unused)
    CPU:  c7x_2: HEAP:           L2_MEM: size =     458752 B, free =     458752 B (100 % unused)
    CPU:  c7x_2: HEAP:           L1_MEM: size =      16384 B, free =      16384 B (100 % unused)
    CPU:  c7x_2: HEAP:  DDR_SCRATCH_MEM: size =   67108864 B, free =   67108864 B (100 % unused)
    
    
    GRAPH: app_multi_cam_graph (#nodes =   1, #executions =   1072)
     NODE:       CAPTURE1:             capture_node: avg =  39970 usecs, min/max =  39909 /  61686 usecs, #executions =       1072
    
     PERF:           FILEIO: avg =      0 usecs, min/max = 4294967295 /      0 usecs, #executions =          0
     PERF:            TOTAL: avg =  49784 usecs, min/max =     18 /  77731 usecs, #executions =       1074
    
     PERF:            TOTAL:   20. 8 FPS
    
    [MCU2_0]    129.866537 s: ==========================================================
    [MCU2_0]    129.866617 s:  Capture Status: Instance|1
    [MCU2_0]    129.866645 s: ==========================================================
    [MCU2_0]    129.866683 s:  overflowCount: 0
    [MCU2_0]    129.866713 s:  spuriousUdmaIntrCount: 0
    [MCU2_0]    129.866744 s:  frontFIFOOvflCount: 0
    [MCU2_0]    129.866772 s:  crcCount: 0
    
    
     =========================
     Demo : Camera Demo
     =========================
    
     s: Save CSIx, VISS and LDC outputs
    
     S: Save Raw image
    
     p: Print performance statistics
    
     r: read des register
     w: write des register
     x: Exit
    
    [MCU2_0]    129.866799 s:  eccCount: 0
     Enter Choice: 
    
    
     =========================
     Demo : Camera Demo
     =========================
    
     s: Save CSIx, VISS and LDC outputs
    
     S: Save Raw image
    
     p: Print performance statistics
    
     r: read des register
     w: write des register
     x: Exit
    
     Enter Choice: [MCU2_0]    129.866826 s:  correctedEccCount: 0
    [MCU2_0]    129.866856 s:  dataIdErrorCount: 0
    [MCU2_0]    129.866887 s:  invalidAccessCount: 0
    [MCU2_0]    129.866923 s:  invalidSpCount: 0
    [MCU2_0]    129.866957 s:  strmFIFOOvflCount[0]: 0
    [MCU2_0]    129.866992 s:  strmFIFOOvflCount[1]: 0
    [MCU2_0]    129.867018 s:  Channel Num | Frame Queue Count | Frame De-queue Count | Frame Drop Count | Error Frame Count |
    [MCU2_0]    129.867085 s:            0 |              1076 |                 1074 |                0 |                 0 |
    [MCU2_0]    129.867153 s:            1 |              1076 |                 1074 |                0 |                 0 |
    [MCU2_0]    129.867220 s:            2 |              1076 |                 1074 |                0 |                 0 |
    [MCU2_0]    129.867287 s:            3 |              1076 |                 1074 |                0 |                 0 |
    
    
    
    
     =========================
     Demo : Camera Demo
     =========================
    
     s: Save CSIx, VISS and LDC outputs
    
     S: Save Raw image
    
     p: Print performance statistics
    
     r: read des register
     w: write des register
     x: Exit
    
     Enter Choice: p
    
    
    Summary of CPU load,
    ====================
    
    CPU: mpu1_0: TOTAL LOAD =   0.27 % ( HWI =   0. 0 %, SWI =   0. 0 % )
    CPU: mcu2_0: TOTAL LOAD =   1. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
    CPU: mcu2_1: TOTAL LOAD =   1. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
    CPU:  c7x_1: TOTAL LOAD =   0. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
    CPU:  c7x_2: TOTAL LOAD =   0. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
    
    
    HWA performance statistics,
    ===========================
    
    
    
    DDR performance statistics,
    ===========================
    
    DDR: READ  BW: AVG =      2 MB/s, PEAK =    656 MB/s
    DDR: WRITE BW: AVG =    205 MB/s, PEAK =   1448 MB/s
    DDR: TOTAL BW: AVG =    207 MB/s, PEAK =   2104 MB/s
    
    
    Detailed CPU performance/memory statistics,
    ===========================================
    
    DDR_SHARED_MEM: Alloc's: 17 alloc's of 32768216 bytes 
    DDR_SHARED_MEM: Free's : 0 free's  of 0 bytes 
    DDR_SHARED_MEM: Open's : 17 allocs  of 32768216 bytes 
    DDR_SHARED_MEM: Total size: 536870912 bytes 
    
    CPU: mcu2_0: TASK:           IPC_RX:   0. 2 %
    CPU: mcu2_0: TASK:       REMOTE_SRV:   0. 1 %
    CPU: mcu2_0: TASK:        LOAD_TEST:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CPU_0:   0. 0 %
    CPU: mcu2_0: TASK:        TIVX_V1NF:   0. 0 %
    CPU: mcu2_0: TASK:      TIVX_V1LDC1:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_V1SC1:   0. 0 %
    CPU: mcu2_0: TASK:      TIVX_V1MSC2:   0. 0 %
    CPU: mcu2_0: TASK:       TIVXVVISS1:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CAPT1:   0.53 %
    CPU: mcu2_0: TASK:       TIVX_CAPT2:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_DISP1:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_DISP2:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CSITX:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CAPT3:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CAPT4:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CAPT5:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CAPT6:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CAPT7:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CAPT8:   0. 0 %
    CPU: mcu2_0: TASK:      TIVX_DPM2M1:   0. 0 %
    CPU: mcu2_0: TASK:      TIVX_DPM2M2:   0. 0 %
    CPU: mcu2_0: TASK:      TIVX_DPM2M3:   0. 0 %
    CPU: mcu2_0: TASK:      TIVX_DPM2M4:   0. 0 %
    
    CPU: mcu2_0: HEAP:    DDR_LOCAL_MEM: size =   16777216 B, free =   16713472 B ( 99 % unused)
    CPU: mcu2_0: HEAP:           L3_MEM: size =     524288 B, free =     524032 B ( 99 % unused)
    
    CPU: mcu2_1: TASK:           IPC_RX:   0. 0 %
    CPU: mcu2_1: TASK:       REMOTE_SRV:   0. 1 %
    CPU: mcu2_1: TASK:        LOAD_TEST:   0. 0 %
    CPU: mcu2_1: TASK:       TIVX_CPU_1:   0. 0 %
    CPU: mcu2_1: TASK:         TIVX_SDE:   0. 0 %
    CPU: mcu2_1: TASK:         TIVX_DOF:   0. 0 %
    CPU: mcu2_1: TASK:      IPC_TEST_RX:   0. 0 %
    CPU: mcu2_1: TASK:      IPC_TEST_TX:   0. 0 %
    CPU: mcu2_1: TASK:      IPC_TEST_TX:   0. 0 %
    CPU: mcu2_1: TASK:      IPC_TEST_TX:   0. 0 %
    CPU: mcu2_1: TASK:      IPC_TEST_TX:   0. 0 %
    
    CPU: mcu2_1: HEAP:    DDR_LOCAL_MEM: size =   16777216 B, free =   16773120 B ( 99 % unused)
    CPU: mcu2_1: HEAP:           L3_MEM: size =     524288 B, free =     524288 B (100 % unused)
    
    CPU:  c7x_1: TASK:           IPC_RX:   0. 0 %
    CPU:  c7x_1: TASK:       REMOTE_SRV:   0. 0 %
    CPU:  c7x_1: TASK:        LOAD_TEST:   0. 0 %
    CPU:  c7x_1: TASK:      TIVX_C71_P1:   0. 0 %
    CPU:  c7x_1: TASK:      TIVX_C71_P2:   0. 0 %
    CPU:  c7x_1: TASK:      TIVX_C71_P3:   0. 0 %
    CPU:  c7x_1: TASK:      TIVX_C71_P4:   0. 0 %
    CPU:  c7x_1: TASK:      TIVX_C71_P5:   0. 0 %
    CPU:  c7x_1: TASK:      TIVX_C71_P6:   0. 0 %
    CPU:  c7x_1: TASK:      TIVX_C71_P7:   0. 0 %
    CPU:  c7x_1: TASK:      TIVX_C71_P8:   0. 0 %
    CPU:  c7x_1: TASK:      IPC_TEST_RX:   0. 0 %
    CPU:  c7x_1: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c7x_1: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c7x_1: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c7x_1: TASK:      IPC_TEST_TX:   0. 0 %
    
    CPU:  c7x_1: HEAP:    DDR_LOCAL_MEM: size =  268435456 B, free =  268435200 B ( 99 % unused)
    CPU:  c7x_1: HEAP:           L3_MEM: size =    3964928 B, free =    3964928 B (100 % unused)
    CPU:  c7x_1: HEAP:           L2_MEM: size =     458752 B, free =     458752 B (100 % unused)
    CPU:  c7x_1: HEAP:           L1_MEM: size =      16384 B, free =      16384 B (100 % unused)
    CPU:  c7x_1: HEAP:  DDR_SCRATCH_MEM: size =  385875968 B, free =  385875968 B (100 % unused)
    
    CPU:  c7x_2: TASK:           IPC_RX:   0. 0 %
    CPU:  c7x_2: TASK:       REMOTE_SRV:   0. 0 %
    CPU:  c7x_2: TASK:        LOAD_TEST:   0. 0 %
    CPU:  c7x_2: TASK:         TIVX_CPU:   0. 0 %
    CPU:  c7x_2: TASK:      IPC_TEST_RX:   0. 0 %
    CPU:  c7x_2: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c7x_2: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c7x_2: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c7x_2: TASK:      IPC_TEST_TX:   0. 0 %
    
    CPU:  c7x_2: HEAP:    DDR_LOCAL_MEM: size =   16777216 B, free =   16772608 B ( 99 % unused)
    CPU:  c7x_2: HEAP:           L2_MEM: size =     458752 B, free =     458752 B (100 % unused)
    CPU:  c7x_2: HEAP:           L1_MEM: size =      16384 B, free =      16384 B (100 % unused)
    CPU:  c7x_2: HEAP:  DDR_SCRATCH_MEM: size =   67108864 B, free =   67108864 B (100 % unused)
    
    
    GRAPH: app_multi_cam_graph (#nodes =   1, #executions =   1146)
     NODE:       CAPTURE1:             capture_node: avg =  39968 usecs, min/max =  39128 /  61686 usecs, #executions =       1146
    
     PERF:           FILEIO: avg =      0 usecs, min/max = 4294967295 /      0 usecs, #executions =          0
     PERF:            TOTAL: avg =  50000 usecs, min/max =  49969 /  50056 usecs, #executions =         74
    
     PERF:            TOTAL:   20. 0 FPS
    
    
    
     =========================
     Demo : Camera Demo
     =========================
    
     s: Save CSIx, VISS and LDC outputs
    
     S: Save Raw image
    
     p: Print performance statistics
    
     r: read des register
     w: write des register
     x: Exit
    
     Enter Choice: 
    
    
     =========================
     Demo : Camera Demo
     =========================
    
     s: Save CSIx, VISS and LDC outputs
    
     S: Save Raw image
    
     p: Print performance statistics
    
     r: read des register
     w: write des register
     x: Exit
    
     Enter Choice: [MCU2_0]    132.826662 s: ==========================================================
    [MCU2_0]    132.826741 s:  Capture Status: Instance|1
    [MCU2_0]    132.826769 s: ==========================================================
    [MCU2_0]    132.826807 s:  overflowCount: 0
    [MCU2_0]    132.826837 s:  spuriousUdmaIntrCount: 0
    [MCU2_0]    132.826868 s:  frontFIFOOvflCount: 0
    [MCU2_0]    132.826901 s:  crcCount: 0
    [MCU2_0]    132.826928 s:  eccCount: 0
    [MCU2_0]    132.826956 s:  correctedEccCount: 0
    [MCU2_0]    132.826986 s:  dataIdErrorCount: 0
    [MCU2_0]    132.827016 s:  invalidAccessCount: 0
    [MCU2_0]    132.827046 s:  invalidSpCount: 0
    [MCU2_0]    132.827080 s:  strmFIFOOvflCount[0]: 0
    [MCU2_0]    132.827116 s:  strmFIFOOvflCount[1]: 0
    [MCU2_0]    132.827141 s:  Channel Num | Frame Queue Count | Frame De-queue Count | Frame Drop Count | Error Frame Count |
    [MCU2_0]    132.827208 s:            0 |              1150 |                 1148 |                0 |                 0 |
    [MCU2_0]    132.827275 s:            1 |              1150 |                 1148 |                0 |                 0 |
    [MCU2_0]    132.827342 s:            2 |              1150 |                 1148 |                0 |                 0 |
    [MCU2_0]    132.827409 s:            3 |              1150 |                 1148 |                0 |                 0 |
    Test data path is NULL. Defaulting to current folder 
    YUV file name ./test_data/cap_ch0_0000.yuv 
    imgaddr_width = 1280 
    imgaddr_height = 800 
    imgaddr_stride = 2560 
    width = 1280 
    height = 800 
    Written 2048000 bytes 
    YUV file name ./test_data/cap_ch1_0000.yuv 
    imgaddr_width = 1280 
    imgaddr_height = 800 
    imgaddr_stride = 2560 
    width = 1280 
    height = 800 
    Written 2048000 bytes 
    YUV file name ./test_data/cap_ch2_0000.yuv 
    imgaddr_width = 1280 
    imgaddr_height = 800 
    imgaddr_stride = 2560 
    width = 1280 
    height = 800 
    Written 2048000 bytes 
    YUV file name ./test_data/cap_ch3_0000.yuv 
    imgaddr_width = 1280 
    imgaddr_height = 800 
    imgaddr_stride = 2560 
    width = 1280 
    height = 800 
    Written 2048000 bytes 
    p
    
    
    Summary of CPU load,
    ====================
    
    CPU: mpu1_0: TOTAL LOAD =   0.30 % ( HWI =   0. 3 %, SWI =   0. 0 % )
    CPU: mcu2_0: TOTAL LOAD =   2. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
    CPU: mcu2_1: TOTAL LOAD =   1. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
    CPU:  c7x_1: TOTAL LOAD =   0. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
    CPU:  c7x_2: TOTAL LOAD =   1. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
    
    
    HWA performance statistics,
    ===========================
    
    
    
    DDR performance statistics,
    ===========================
    
    DDR: READ  BW: AVG =      4 MB/s, PEAK =    915 MB/s
    DDR: WRITE BW: AVG =    193 MB/s, PEAK =   1379 MB/s
    DDR: TOTAL BW: AVG =    197 MB/s, PEAK =   2294 MB/s
    
    
    Detailed CPU performance/memory statistics,
    ===========================================
    
    DDR_SHARED_MEM: Alloc's: 17 alloc's of 32768216 bytes 
    DDR_SHARED_MEM: Free's : 0 free's  of 0 bytes 
    DDR_SHARED_MEM: Open's : 17 allocs  of 32768216 bytes 
    DDR_SHARED_MEM: Total size: 536870912 bytes 
    
    CPU: mcu2_0: TASK:           IPC_RX:   0. 8 %
    CPU: mcu2_0: TASK:       REMOTE_SRV:   0. 1 %
    CPU: mcu2_0: TASK:        LOAD_TEST:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CPU_0:   0. 0 %
    CPU: mcu2_0: TASK:        TIVX_V1NF:   0. 0 %
    CPU: mcu2_0: TASK:      TIVX_V1LDC1:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_V1SC1:   0. 0 %
    CPU: mcu2_0: TASK:      TIVX_V1MSC2:   0. 0 %
    CPU: mcu2_0: TASK:       TIVXVVISS1:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CAPT1:   1.32 %
    CPU: mcu2_0: TASK:       TIVX_CAPT2:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_DISP1:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_DISP2:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CSITX:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CAPT3:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CAPT4:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CAPT5:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CAPT6:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CAPT7:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_CAPT8:   0. 0 %
    CPU: mcu2_0: TASK:      TIVX_DPM2M1:   0. 0 %
    CPU: mcu2_0: TASK:      TIVX_DPM2M2:   0. 0 %
    CPU: mcu2_0: TASK:      TIVX_DPM2M3:   0. 0 %
    CPU: mcu2_0: TASK:      TIVX_DPM2M4:   0. 0 %
    
    CPU: mcu2_0: HEAP:    DDR_LOCAL_MEM: size =   16777216 B, free =   16713472 B ( 99 % unused)
    CPU: mcu2_0: HEAP:           L3_MEM: size =     524288 B, free =     524032 B ( 99 % unused)
    
    CPU: mcu2_1: TASK:           IPC_RX:   0. 0 %
    CPU: mcu2_1: TASK:       REMOTE_SRV:   0. 1 %
    CPU: mcu2_1: TASK:        LOAD_TEST:   0. 0 %
    CPU: mcu2_1: TASK:       TIVX_CPU_1:   0. 0 %
    CPU: mcu2_1: TASK:         TIVX_SDE:   0. 0 %
    CPU: mcu2_1: TASK:         TIVX_DOF:   0. 0 %
    CPU: mcu2_1: TASK:      IPC_TEST_RX:   0. 0 %
    CPU: mcu2_1: TASK:      IPC_TEST_TX:   0. 0 %
    CPU: mcu2_1: TASK:      IPC_TEST_TX:   0. 0 %
    CPU: mcu2_1: TASK:      IPC_TEST_TX:   0. 0 %
    CPU: mcu2_1: TASK:      IPC_TEST_TX:   0. 0 %
    
    CPU: mcu2_1: HEAP:    DDR_LOCAL_MEM: size =   16777216 B, free =   16773120 B ( 99 % unused)
    CPU: mcu2_1: HEAP:           L3_MEM: size =     524288 B, free =     524288 B (100 % unused)
    
    CPU:  c7x_1: TASK:           IPC_RX:   0. 0 %
    CPU:  c7x_1: TASK:       REMOTE_SRV:   0. 0 %
    CPU:  c7x_1: TASK:        LOAD_TEST:   0. 0 %
    CPU:  c7x_1: TASK:      TIVX_C71_P1:   0. 0 %
    CPU:  c7x_1: TASK:      TIVX_C71_P2:   0. 0 %
    CPU:  c7x_1: TASK:      TIVX_C71_P3:   0. 0 %
    CPU:  c7x_1: TASK:      TIVX_C71_P4:   0. 0 %
    CPU:  c7x_1: TASK:      TIVX_C71_P5:   0. 0 %
    CPU:  c7x_1: TASK:      TIVX_C71_P6:   0. 0 %
    CPU:  c7x_1: TASK:      TIVX_C71_P7:   0. 0 %
    CPU:  c7x_1: TASK:      TIVX_C71_P8:   0. 0 %
    CPU:  c7x_1: TASK:      IPC_TEST_RX:   0. 0 %
    CPU:  c7x_1: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c7x_1: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c7x_1: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c7x_1: TASK:      IPC_TEST_TX:   0. 0 %
    
    CPU:  c7x_1: HEAP:    DDR_LOCAL_MEM: size =  268435456 B, free =  268435200 B ( 99 % unused)
    CPU:  c7x_1: HEAP:           L3_MEM: size =    3964928 B, free =    3964928 B (100 % unused)
    CPU:  c7x_1: HEAP:           L2_MEM: size =     458752 B, free =     458752 B (100 % unused)
    CPU:  c7x_1: HEAP:           L1_MEM: size =      16384 B, free =      16384 B (100 % unused)
    CPU:  c7x_1: HEAP:  DDR_SCRATCH_MEM: size =  385875968 B, free =  385875968 B (100 % unused)
    
    CPU:  c7x_2: TASK:           IPC_RX:   0. 0 %
    CPU:  c7x_2: TASK:       REMOTE_SRV:   0. 0 %
    CPU:  c7x_2: TASK:        LOAD_TEST:   0. 0 %
    CPU:  c7x_2: TASK:         TIVX_CPU:   0. 0 %
    CPU:  c7x_2: TASK:      IPC_TEST_RX:   0. 0 %
    CPU:  c7x_2: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c7x_2: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c7x_2: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c7x_2: TASK:      IPC_TEST_TX:   0. 0 %
    
    CPU:  c7x_2: HEAP:    DDR_LOCAL_MEM: size =   16777216 B, free =   16772608 B ( 99 % unused)
    CPU:  c7x_2: HEAP:           L2_MEM: size =     458752 B, free =     458752 B (100 % unused)
    CPU:  c7x_2: HEAP:           L1_MEM: size =      16384 B, free =      16384 B (100 % unused)
    CPU:  c7x_2: HEAP:  DDR_SCRATCH_MEM: size =   67108864 B, free =   67108864 B (100 % unused)
    
    
    GRAPH: app_multi_cam_graph (#nodes =   1, #executions =   1337)
     NODE:       CAPTURE1:             capture_node: avg =  39965 usecs, min/max =  39128 /  61686 usecs, #executions =       1337
    
     PERF:           FILEIO: avg =      0 usecs, min/max = 4294967295 /      0 usecs, #executions =          0
     PERF:            TOTAL: avg =  49770 usecs, min/max =   6091 /  50129 usecs, #executions =        191
    
     PERF:            TOTAL:   20. 9 FPS
    
    
    
    
    
    
    
    *********At this point, when I press "Enter," no log is displayed.******************
    
    
    
    
    
    
    
     =========================
     Demo : Camera Demo
     =========================
    
     s: Save CSIx, VISS and LDC outputs
    
     S: Save Raw image
    
     p: Print performance statistics
    
     r: read des register
     w: write des register
     x: Exit
    
     Enter Choice: 
    
    
     =========================
     Demo : Camera Demo
     =========================
    
     s: Save CSIx, VISS and LDC outputs
    
     S: Save Raw image
    
     p: Print performance statistics
    
     r: read des register
     w: write des register
     x: Exit
    
     Enter Choice: 
    
    
     =========================
     Demo : Camera Demo
     =========================
    
     s: Save CSIx, VISS and LDC outputs
    
     S: Save Raw image
    
     p: Print performance statistics
    
     r: read des register
     w: write des register
     x: Exit
    
     Enter Choice: 
    
    
     =========================
     Demo : Camera Demo
     =========================
    
     s: Save CSIx, VISS and LDC outputs
    
     S: Save Raw image
    
     p: Print performance statistics
    
     r: read des register
     w: write des register
     x: Exit
    
     Enter Choice: 
    
    
     =========================
     Demo : Camera Demo
     =========================
    
     s: Save CSIx, VISS and LDC outputs
    
     S: Save Raw image
    
     p: Print performance statistics
    
     r: read des register
     w: write des register
     x: Exit
    
     Enter Choice: 
    
    
     =========================
     Demo : Camera Demo
     =========================
    
     s: Save CSIx, VISS and LDC outputs
    
     S: Save Raw image
    
     p: Print performance statistics
    
     r: read des register
     w: write des register
     x: Exit
    
     Enter Choice: 
    
    
     =========================
     Demo : Camera Demo
     =========================
    
     s: Save CSIx, VISS and LDC outputs
    
     S: Save Raw image
    
     p: Print performance statistics
    
     r: read des register
     w: write des register
     x: Exit
    
     Enter Choice: 
    
    
     =========================
     Demo : Camera Demo
     =========================
    
     s: Save CSIx, VISS and LDC outputs
    
     S: Save Raw image
    
     p: Print performance statistics
    
     r: read des register
     w: write des register
     x: Exit
    
     Enter Choice: 
    
    
     =========================
     Demo : Camera Demo
     =========================
    
     s: Save CSIx, VISS and LDC outputs
    
     S: Save Raw image
    
     p: Print performance statistics
    
     r: read des register
     w: write des register
     x: Exit
    
     Enter Choice: 
    
    
     =========================
     Demo : Camera Demo
     =========================
    
     s: Save CSIx, VISS and LDC outputs
    
     S: Save Raw image
    
     p: Print performance statistics
    
     r: read des register
     w: write des register
     x: Exit
    
     Enter Choice: 
    
    
     =========================
     Demo : Camera Demo
     =========================
    
     s: Save CSIx, VISS and LDC outputs
    
     S: Save Raw image
    
     p: Print performance statistics
    
     r: read des register
     w: write des register
     x: Exit
    
     Enter Choice: 
    
    
     =========================
     Demo : Camera Demo
     =========================
    
     s: Save CSIx, VISS and LDC outputs
    
     S: Save Raw image
    
     p: Print performance statistics
    
     r: read des register
     w: write des register
     x: Exit
    
     Enter Choice: [MCU2_0]    152.529814 s: ==========================================================
    [MCU2_0]    152.529897 s:  Capture Status: Instance|1
    [MCU2_0]    152.529924 s: ==========================================================
    [MCU2_0]    152.529962 s:  overflowCount: 0
    [MCU2_0]    152.529992 s:  spuriousUdmaIntrCount: 0
    [MCU2_0]    152.530023 s:  frontFIFOOvflCount: 0
    [MCU2_0]    152.530051 s:  crcCount: 0
    [MCU2_0]    152.530078 s:  eccCount: 0
    [MCU2_0]    152.530106 s:  correctedEccCount: 0
    [MCU2_0]    152.530135 s:  dataIdErrorCount: 0
    [MCU2_0]    152.530165 s:  invalidAccessCount: 0
    [MCU2_0]    152.530195 s:  invalidSpCount: 0
    [MCU2_0]    152.530229 s:  strmFIFOOvflCount[0]: 0
    [MCU2_0]    152.530265 s:  strmFIFOOvflCount[1]: 0
    [MCU2_0]    152.530290 s:  Channel Num | Frame Queue Count | Frame De-queue Count | Frame Drop Count | Error Frame Count |
    [MCU2_0]    152.530358 s:            0 |              1341 |                 1339 |                0 |                 0 |
    [MCU2_0]    152.530426 s:            1 |              1341 |                 1340 |              301 |                 0 |
    [MCU2_0]    152.530493 s:            2 |              1341 |                 1340 |              301 |                 0 |
    [MCU2_0]    152.530560 s:            3 |              1341 |                 1340 |              301 |                 0 |