This thread has been locked.

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

TDA4VM: capture FPS

Part Number: TDA4VM


Hi Brijesh,

My software version is:
  PDK-RTOS :processor-sdk-rtos-j721e-evm-08_06_00_12
  PDK-LINUX:processor-sdk-linux-08_06_00

data_flow:

1920x1536 YUV422_8 * 2  ---> max96792A - - ->   CSI1 

1.We added 2 cameras and when I ran run_app_multi_cam.sh, it worked at 60FPS as 'P' below:

 frame_id:1506 
p frame_id:1507 
 frame_id:1508 
 frame_id:1509 
 frame_id:1510 
 frame_id:1511 
 frame_id:1512 
 frame_id:1513 
 frame_id:1514 
 frame_id:1515 
 frame_id:1516 
 frame_id:1517 
 frame_id:1518 
 frame_id:1519 



Summary of CPU load,
====================

CPU: mpu1_0: TOTAL LOAD =   0.41 % ( HWI =   0. 8 %, SWI =   0. 0 % )
CPU: mcu2_0: TOTAL LOAD =   6. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
CPU: mcu2_1: TOTAL LOAD =   1. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
CPU:  c6x_1: TOTAL LOAD =   0. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
CPU:  c6x_2: TOTAL LOAD =   0. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
CPU:  c7x_1: TOTAL LOAD =   1. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )


HWA performance statistics,
===========================



DDR performance statistics,
===========================

DDR: READ  BW: AVG =    366 MB/s, PEAK =   1544 MB/s
DDR: WRITE BW: AVG =    709 MB/s, PEAK =   2134 MB/s
DDR: TOTAL BW: AVG =   1075 MB/s, PEAK =   3678 MB/s


Detailed CPU performance/memory statistics,
===========================================

DDR_SHARED_MEM: Alloc's: 10 alloc's of 47186180 bytes 
DDR_SHARED_MEM: Free's : 0 free's  of 0 bytes 
DDR_SHARED_MEM: Open's : 10 allocs  of 47186180 bytes 
DDR_SHARED_MEM: Total size: 536870912 bytes 

CPU: mcu2_0: TASK:           IPC_RX:   0.31 %
CPU: mcu2_0: TASK:       REMOTE_SRV:   0. 2 %
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:   2.83 %
CPU: mcu2_0: TASK:       TIVX_CAPT2:   0. 0 %
CPU: mcu2_0: TASK:       TIVX_DISP1:   2.13 %
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 %

 frame_id:1520 
CPU: mcu2_0: HEAP:    DDR_LOCAL_MEM: size =   16777216 B, free =   16688896 B ( 99 % unused)
CPU: mcu2_0: HEAP:           L3_MEM: size =     262144 B, free =     261888 B ( 99 % unused)

CPU: mcu2_1: TASK:           IPC_RX:   0. 0 %
CPU: mcu2_1: TASK:       REMOTE_SRV:   0. 2 %
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: TASK:      IPC_TEST_TX:   0. 0 %

CPU: mcu2_1: HEAP:    DDR_LOCAL_MEM: size =   16777216 B, free =   16773376 B ( 99 % unused)
CPU: mcu2_1: HEAP:           L3_MEM: size =     262144 B, free =     262144 B (100 % unused)

CPU:  c6x_1: TASK:           IPC_RX:   0. 0 %
CPU:  c6x_1: TASK:       REMOTE_SRV:   0. 0 %
CPU:  c6x_1: TASK:        LOAD_TEST:   0. 0 %
CPU:  c6x_1: TASK:         TIVX_CPU:   0. 0 %
CPU:  c6x_1: TASK:      IPC_TEST_RX:   0. 0 %
CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %

CPU:  c6x_1: HEAP:    DDR_LOCAL_MEM: size =   16777216 B, free =   16773376 B ( 99 % unused)
CPU:  c6x_1: HEAP:           L2_MEM: size =     229376 B, free =     229376 B (100 % unused)
CPU:  c6x_1: HEAP:  DDR_SCRATCH_MEM: size =   50331648 B, free =   50331648 B (100 % unused)

CPU:  c6x_2: TASK:           IPC_RX:   0. 0 %
CPU:  c6x_2: TASK:       REMOTE_SRV:   0. 0 %
CPU:  c6x_2: TASK:        LOAD_TEST:   0. 0 %
CPU:  c6x_2: TASK:         TIVX_CPU:   0. 0 %
CPU:  c6x_2: TASK:      IPC_TEST_RX:   0. 0 %
CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %

 frame_id:1521 
CPU:  c6x_2: HEAP:    DDR_LOCAL_MEM: size =   16777216 B, free =   16773376 B ( 99 % unused)
CPU:  c6x_2: HEAP:           L2_MEM: size =     229376 B, free =     229376 B (100 % unused)
 frame_id:1522 
CPU:  c6x_2: HEAP:  DDR_SCRATCH_MEM: size =   50331648 B, free =   50331648 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: 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 =    8159232 B, free =    8159232 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)


GRAPH: app_multi_cam_graph (#nodes =   2, #executions =   1522)
 NODE:       CAPTURE1:             capture_node: avg =  14141 usecs, min/max =     95 /  30771 usecs, #executions =   2
 NODE:       DISPLAY1:              DisplayNode: avg =   2262 usecs, min/max =     67 /  18608 usecs, #executions =   2

 PERF:           FILEIO: avg =      0 usecs, min/max = 4294967295 /      0 usecs, #executions =          0
 PERF:            TOTAL: avg =  16550 usecs, min/max =     32 /  33326 usecs, #executions =        330

 PERF:            TOTAL:   60.42 FPS



 =========================
 Demo : Camera Demo
 =========================

 s: Save CSIx, VISS and LDC outputs

 p: Print performance statistics

 x: Exit

 Enter Choice: 


 =========================
 Demo : Camera Demo
 =========================

 s: Save CSIx, VISS and LDC outputs

 p: Print performance statistics

 x: Exit

 Enter Choice:  frame_id:1523 
[MCU2_0]    153.940105 s: ==========================================================
[MCU2_0]    153.940206 s:  Capture Status: Instance|0
[MCU2_0]    153.940240 s: ==========================================================
[MCU2_0]    153.940289 s:  overflowCount: 0
[MCU2_0]    153.940324 s:  spuriousUdmaIntrCount: 0
[MCU2_0]    153.940359 s:  frontFIFOOvflCount: 0
[MCU2_0]    153.940393 s:  crcCount: 0
[MCU2_0]    153.940423 s:  eccCount: 0
[MCU2_0]    153.940455 s:  correctedEccCount: 0
[MCU2_0]    153.940488 s:  dataIdErrorCount: 0
[MCU2_0]    153.940523 s:  invalidAccessCount: 0
[MCU2_0]    153.940557 s:  invalidSpCount: 0
[MCU2_0]    153.940596 s:  strmFIFOOvflCount[0]: 0
[MCU2_0]    153.940636 s:  strmFIFOOvflCount[1]: 0
[MCU2_0]    153.940666 s:  Channel Num | Frame Queue Count | Frame De-queue Count | Frame Drop Count | Error Frame Cou|
[MCU2_0]    153.940725 s: ==========================================================
[MCU2_0]    153.940775 s:  Capture Status: Instance|1
 frame_id:1524 
[MCU2_0]    153.940804 s: ==========================================================
 frame_id:1525 
[MCU2_0]    153.940860 s:  overflowCount: 0
[MCU2_0]    153.940895 s:  spuriousUdmaIntrCount: 0
[MCU2_0]    153.940931 s:  frontFIFOOvflCount: 0
[MCU2_0]    153.940964 s:  crcCount: 0
[MCU2_0]    153.940994 s:  eccCount: 0
[MCU2_0]    153.941025 s:  correctedEccCount: 0
[MCU2_0]    153.941059 s:  dataIdErrorCount: 0
[MCU2_0]    153.941094 s:  invalidAccessCount: 0
[MCU2_0]    153.941127 s:  invalidSpCount: 0
[MCU2_0]    153.941165 s:  strmFIFOOvflCount[0]: 0
[MCU2_0]    153.941204 s:  strmFIFOOvflCount[1]: 0
[MCU2_0]    153.941233 s:  Channel Num | Frame Queue Count | Frame De-queue Count | Frame Drop Count | Error Frame Cou|
[MCU2_0]    153.941311 s:            0 |              1525 |                 1524 |              128 |                |
[MCU2_0]    153.941388 s:            1 |              1525 |                 1524 |              127 |                |
 frame_id:1526 
 frame_id:1527 
 frame_id:1528 
 frame_id:1529 
 frame_id:1530 
 frame_id:1531 
 frame_id:1532 
 frame_id:1533 
 frame_id:1534 
 frame_id:1535 
 frame_id:1536 

2.But after I add the patch:  e2e.ti.com/.../faq-processor-sdk-j721e-how-to-enable-multiple-displays-by-sending-bigger-size-frames-from-dss

the frame rate will only be 30FPS. What is the reason? How should we solve this problem?

Camera frame_id:1124 
pCamera frame_id:1125 
Camera frame_id:1126 
Camera frame_id:1127 
Camera frame_id:1128 
Camera frame_id:1129 
Camera frame_id:1130 
Camera frame_id:1131 



Summary of CPU load,
====================

CPU: mpu1_0: TOTAL LOAD =   0.17 % ( HWI =   0.17 %, SWI =   0. 0 % )
CPU: mcu2_0: TOTAL LOAD =   3. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
CPU: mcu2_1: TOTAL LOAD =   1. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
CPU:  c6x_1: TOTAL LOAD =   0. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
CPU:  c6x_2: TOTAL LOAD =   0. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
CPU:  c7x_1: TOTAL LOAD =   1. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )


HWA performance statistics,
===========================



DDR performance statistics,
===========================

DDR: READ  BW: AVG =    714 MB/s, PEAK =   2802 MB/s
DDR: WRITE BW: AVG =    708 MB/s, PEAK =   1436 MB/s
DDR: TOTAL BW: AVG =   1422 MB/s, PEAK =   4238 MB/s


Detailed CPU performance/memory statistics,
===========================================

DDR_SHARED_MEM: Alloc's: 12 alloc's of 47186228 bytes 
DDR_SHARED_MEM: Free's : 0 free's  of 0 bytes 
DDR_SHARED_MEM: Open's : 12 allocs  of 47186228 bytes 
DDR_SHARED_MEM: Total size: 536870912 bytes 

CPU: mcu2_0: TASK:           IPC_RX:   0.17 %
CPU: mcu2_0: TASK:       REMOTE_SRV:   0. 6 %
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.86 %
CPU: mcu2_0: TASK:       TIVX_CAPT2:   0. 0 %
CPU: mcu2_0: TASK:       TIVX_DISP1:   1.87 %
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 =   16680704 B ( 99 % unused)
CPU: mcu2_0: HEAP:           L3_MEM: size =     262144 B, free =     261888 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: TASK:      IPC_TEST_TX:   0. 0 %

CPU: mcu2_1: HEAP:    DDR_LOCAL_MEM: size =   16777216 B, free =   16773376 B ( 99 % unused)
CPU: mcu2_1: HEAP:           L3_MEM: size =     262144 B, free =     262144 B (100 % unused)

CPU:  c6x_1: TASK:           IPC_RX:   0. 0 %
CPU:  c6x_1: TASK:       REMOTE_SRV:   0. 0 %
CPU:  c6x_1: TASK:        LOAD_TEST:   0. 0 %
CPU:  c6x_1: TASK:         TIVX_CPU:   0. 0 %
CPU:  c6x_1: TASK:      IPC_TEST_RX:   0. 0 %
CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %

CPU:  c6x_1: HEAP:    DDR_LOCAL_MEM: size =   16777216 B, free =   16773376 B ( 99 % unused)
CPU:  c6x_1: HEAP:           L2_MEM: size =     229376 B, free =     229376 B (100 % unused)
CPU:  c6x_1: HEAP:  DDR_SCRATCH_MEM: size =   50331648 B, free =   50331648 B (100 % unused)

CPU:  c6x_2: TASK:           IPC_RX:   0. 0 %
CPU:  c6x_2: TASK:       REMOTE_SRV:   0. 0 %
CPU:  c6x_2: TASK:        LOAD_TEST:   0. 0 %
CPU:  c6x_2: TASK:         TIVX_CPU:   0. 0 %
CPU:  c6x_2: TASK:      IPC_TEST_RX:   0. 0 %
CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %

Camera frame_id:1132 
Camera frame_id:1133 
CPU:  c6x_2: HEAP:    DDR_LOCAL_MEM: size =   16777216 B, free =   16773376 B ( 99 % unused)
CPU:  c6x_2: HEAP:           L2_MEM: size =     229376 B, free =     229376 B (100 % unused)
CPU:  c6x_2: HEAP:  DDR_SCRATCH_MEM: size =   50331648 B, free =   50331648 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: 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 =    8159232 B, free =    8159232 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)


GRAPH: app_multi_cam_graph (#nodes =   3, #executions =   1133)
 NODE:       CAPTURE1:             capture_node: avg =    162 usecs, min/max =     89 /  29023 usecs, #executions =   3
 NODE:       DISPLAY1:              DisplayNode: avg =  16585 usecs, min/max =  10551 /  16610 usecs, #executions =   3
 NODE:       DISPLAY1:              DisplayNode: avg =  16220 usecs, min/max =     76 /  27460 usecs, #executions =   3

 PERF:           FILEIO: avg =      0 usecs, min/max = 4294967295 /      0 usecs, #executions =          0
 PERF:            TOTAL: avg =  32130 usecs, min/max =     15 /  33350 usecs, #executions =         71

 PERF:            TOTAL:   31.12 FPS



 =========================
 Demo : Camera Demo
 =========================

 s: Save CSIx, VISS and LDC outputs

 p: Print performance statistics

 x: Exit

 Enter Choice: 


 =========================
 Demo : Camera Demo
 =========================

 s: Save CSIx, VISS and LDC outputs

 p: Print performance statistics

 x: Exit

 Enter Choice: [MCU2_0]    106.099955 s: ==========================================================
[MCU2_0]    106.100049 s:  Capture Status: Instance|0
[MCU2_0]    106.100084 s: ==========================================================
[MCU2_0]    106.100132 s:  overflowCount: 0
[MCU2_0]    106.100167 s:  spuriousUdmaIntrCount: 0
[MCU2_0]    106.100202 s:  frontFIFOOvflCount: 0
[MCU2_0]    106.100236 s:  crcCount: 0
[MCU2_0]    106.100265 s:  eccCount: 0
[MCU2_0]    106.100297 s:  correctedEccCount: 0
[MCU2_0]    106.100331 s:  dataIdErrorCount: 0
[MCU2_0]    106.100366 s:  invalidAccessCount: 0
[MCU2_0]    106.100401 s:  invalidSpCount: 0
[MCU2_0]    106.100439 s:  strmFIFOOvflCount[0]: 0
[MCU2_0]    106.100480 s:  strmFIFOOvflCount[1]: 0
[MCU2_0]    106.100510 s:  Channel Num | Frame Queue Count | Frame De-queue Count | Frame Drop Count | Error Frame Cou|
[MCU2_0]    106.100568 s: ==========================================================
[MCU2_0]    106.100617 s:  Capture Status: Instance|1
Camera frame_id:1134 
[MCU2_0]    106.100646 s: ==========================================================
Camera frame_id:1135 
[MCU2_0]    106.100689 s:  overflowCount: 0
[MCU2_0]    106.100722 s:  spuriousUdmaIntrCount: 0
[MCU2_0]    106.100757 s:  frontFIFOOvflCount: 0
[MCU2_0]    106.100804 s:  crcCount: 0
[MCU2_0]    106.100835 s:  eccCount: 0
[MCU2_0]    106.100866 s:  correctedEccCount: 0
[MCU2_0]    106.100899 s:  dataIdErrorCount: 0
[MCU2_0]    106.100933 s:  invalidAccessCount: 0
[MCU2_0]    106.100966 s:  invalidSpCount: 0
[MCU2_0]    106.101004 s:  strmFIFOOvflCount[0]: 0
[MCU2_0]    106.101043 s:  strmFIFOOvflCount[1]: 0
[MCU2_0]    106.101072 s:  Channel Num | Frame Queue Count | Frame De-queue Count | Frame Drop Count | Error Frame Cou|
[MCU2_0]    106.101148 s:            0 |              1136 |                 1135 |             1280 |                |
[MCU2_0]    106.101224 s:            1 |              1136 |                 1135 |             1281 |                |
Camera frame_id:1136 
Camera frame_id:1137 
Camera frame_id:1138 
Camera frame_id:1139 
Camera frame_id:1140 
Camera frame_id:1141 
Camera frame_id:1142 
Camera frame_id:1143 
Camera frame_id:1144 
Camera frame_id:1145 

Our goal is to have two display pipelines placed side by side to create super frames and send them to DSS, and the camera needs to run at 60FPS.How should we modify to solve this problem?

Very much looking forward to your reply.

Regards,

Barry

  • Hi Barry,

    Are both of the displays connected to the same output? 

    This is strange that that all the nodes are running in real time, but still graph is not. Have you tried increasing the number of buffers at the capture node's output? Due to asynch capture and display and also display holding one of the buffer, if there are insufficient buffers, it can drop the frames. So can you please first try increasing the number of buffers in capture output? 

    Regards,

    Brijesh

  • Hi Brijesh,

    thank you for your reply.

    1.We added this patch to MulticamDemo:  e2e.ti.com/.../faq-processor-sdk-j721e-how-to-enable-multiple-displays-by-sending-bigger-size-frames-from-dss

    The purpose is to create a side-by-side superframe in MulticamDemo.(The DSS output mode is set to DSI. DSI will be output to the LCD through serdes.)

    But after adding the patch, the frame rate dropped to 30. What is the reason for this?Can you share a patch for us that solves this problem?

    2.

    I tried to increase the values ​​of CAPTURE_BUFFER_Q_DEPTH and APP_BUFFER_Q_DEPTH at the same time, but there was no effective improvement.

    Below is the value I only increased CAPTURE_BUFFER_Q_DEPTH:

    #define CAPTURE_BUFFER_Q_DEPTH (8)
    #define APP_BUFFER_Q_DEPTH (4)
    #define APP_PIPELINE_DEPTH (7)

    Camera frame_id:19595 
    Camera frame_id:19596 
    pCamera frame_id:19597 
    Camera frame_id:19598 
    Camera frame_id:19599 
    Camera frame_id:19600 
    Camera frame_id:19601 
    Camera frame_id:19602 
    Camera frame_id:19603 
    Camera frame_id:19604 
    Camera frame_id:19605 
    Camera frame_id:19606 
    
    
    
    Summary of CPU load,
    ====================
    
    CPU: mpu1_0: TOTAL LOAD =   0.38 % ( HWI =   0. 7 %, SWI =   0. 0 % )
    CPU: mcu2_0: TOTAL LOAD =   4. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
    CPU: mcu2_1: TOTAL LOAD =   1. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
    CPU:  c6x_1: TOTAL LOAD =   0. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
    CPU:  c6x_2: TOTAL LOAD =   1. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
    CPU:  c7x_1: TOTAL LOAD =   1. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
    
    
    HWA performance statistics,
    ===========================
    
    
    
    DDR performance statistics,
    ===========================
    
    DDR: READ  BW: AVG =    717 MB/s, PEAK =   3130 MB/s
    DDR: WRITE BW: AVG =    709 MB/s, PEAK =   2416 MB/s
    DDR: TOTAL BW: AVG =   1426 MB/s, PEAK =   5546 MB/s
    
    
    Detailed CPU performance/memory statistics,
    ===========================================
    
    DDR_SHARED_MEM: Alloc's: 20 alloc's of 94372148 bytes 
    DDR_SHARED_MEM: Free's : 0 free's  of 0 bytes 
    DDR_SHARED_MEM: Open's : 20 allocs  of 94372148 bytes 
    DDR_SHARED_MEM: Total size: 536870912 bytes 
    
    CPU: mcu2_0: TASK:           IPC_RX:   0.18 %
    CPU: mcu2_0: TASK:       REMOTE_SRV:   0. 2 %
    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.93 %
    CPU: mcu2_0: TASK:       TIVX_CAPT2:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_DISP1:   2.27 %
    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 =   16680704 B ( 99 % unused)
    CPU: mcu2_0: HEAP:           L3_MEM: size =     262144 B, free =     261888 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: TASK:      IPC_TEST_TX:   0. 0 %
    
    CPU: mcu2_1: HEAP:    DDR_LOCAL_MEM: size =   16777216 B, free =   16773376 B ( 99 % unused)
    CPU: mcu2_1: HEAP:           L3_MEM: size =     262144 B, free =     262144 B (100 % unused)
    
    CPU:  c6x_1: TASK:           IPC_RX:   0. 0 %
    CPU:  c6x_1: TASK:       REMOTE_SRV:   0. 0 %
    CPU:  c6x_1: TASK:        LOAD_TEST:   0. 0 %
    CPU:  c6x_1: TASK:         TIVX_CPU:   0. 0 %
    CPU:  c6x_1: TASK:      IPC_TEST_RX:   0. 0 %
    CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %
    
    CPU:  c6x_1: HEAP:    DDR_LOCAL_MEM: size =   16777216 B, free =   16773376 B ( 99 % unused)
    CPU:  c6x_1: HEAP:           L2_MEM: size =     229376 B, free =     229376 B (100 % unused)
    CPU:  c6x_1: HEAP:  DDR_SCRATCH_MEM: size =   50331648 B, free =   50331648 B (100 % unused)
    
    CPU:  c6x_2: TASK:           IPC_RX:   0. 0 %
    CPU:  c6x_2: TASK:       REMOTE_SRV:   0. 0 %
    CPU:  c6x_2: TASK:        LOAD_TEST:   0. 0 %
    CPU:  c6x_2: TASK:         TIVX_CPU:   0. 0 %
    CPU:  c6x_2: TASK:      IPC_TEST_RX:   0. 0 %
    CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %
    
    Camera frame_id:19607 
    Camera frame_id:19608 
    Camera frame_id:19609 
    CPU:  c6x_2: HEAP:    DDR_LOCAL_MEM: size =   16777216 B, free =   16773376 B ( 99 % unused)
    CPU:  c6x_2: HEAP:           L2_MEM: size =     229376 B, free =     229376 B (100 % unused)
    CPU:  c6x_2: HEAP:  DDR_SCRATCH_MEM: size =   50331648 B, free =   50331648 B (100 % unused)
    Camera frame_id:19610 
    
    Camera frame_id:19611 
    Camera frame_id:19612 
    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: 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 =    8159232 B, free =    8159232 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)
    
    
    GRAPH: app_multi_cam_graph (#nodes =   3, #executions =  19608)
     NODE:       CAPTURE1:             capture_node: avg =    154 usecs, min/max =     81 /  48846 usecs, #executions =      19608
     NODE:       DISPLAY1:              DisplayNode: avg =  16588 usecs, min/max =  12704 /  16619 usecs, #executions =      19608
     NODE:       DISPLAY1:              DisplayNode: avg =  16572 usecs, min/max =     64 /  29523 usecs, #executions =      19608
    
     PERF:           FILEIO: avg =      0 usecs, min/max = 4294967295 /      0 usecs, #executions =          0
     PERF:            TOTAL: avg =  31386 usecs, min/max =     12 /  33414 usecs, #executions =        185
    
     PERF:            TOTAL:   31.86 FPS
    
    Camera frame_id:19613 
    Camera frame_id:19614 
    
    
     =========================
     Demo : Camera Demo
     =========================
    
     s: Save CSIx, VISS and LDC outputs
    
     p: Print performance statistics
    
     x: Exit
    
     Enter Choice: 
    
    
     =========================
     Demo : Camera Demo
     =========================
    
     s: Save CSIx, VISS and LDC outputs
    
     p: Print performance statistics
    
     x: Exit
    
     Enter Choice: [MCU2_0]    753.449766 s: ==========================================================
    [MCU2_0]    753.449861 s:  Capture Status: Instance|0
    [MCU2_0]    753.449901 s: ==========================================================
    [MCU2_0]    753.449952 s:  overflowCount: 0
    [MCU2_0]    753.449988 s:  spuriousUdmaIntrCount: 0
    [MCU2_0]    753.450023 s:  frontFIFOOvflCount: 0
    [MCU2_0]    753.450057 s:  crcCount: 0
    [MCU2_0]    753.450088 s:  eccCount: 0
    [MCU2_0]    753.450121 s:  correctedEccCount: 0
    [MCU2_0]    753.450154 s:  dataIdErrorCount: 0
    [MCU2_0]    753.450188 s:  invalidAccessCount: 0
    [MCU2_0]    753.450222 s:  invalidSpCount: 0
    [MCU2_0]    753.450260 s:  strmFIFOOvflCount[0]: 0
    [MCU2_0]    753.450299 s:  strmFIFOOvflCount[1]: 0
    [MCU2_0]    753.450329 s:  Channel Num | Frame Queue Count | Frame De-queue Count | Frame Drop Count | Error Frame Count |
    [MCU2_0]    753.450386 s: ==========================================================
    [MCU2_0]    753.450435 s:  Capture Status: Instance|1
    [MCU2_0]    753.450464 s: ==========================================================
    [MCU2_0]    753.450507 s:  overflowCount: 0
    [MCU2_0]    753.450540 s:  spuriousUdmaIntrCount: 0
    [MCU2_0]    753.450574 s:  frontFIFOOvflCount: 0
    [MCU2_0]    753.450607 s:  crcCount: 0
    [MCU2_0]    753.450637 s:  eccCount: 0
    [MCU2_0]    753.450668 s:  correctedEccCount: 0
    [MCU2_0]    753.450711 s:  dataIdErrorCount: 0
    [MCU2_0]    753.450745 s:  invalidAccessCount: 0
    [MCU2_0]    753.450779 s:  invalidSpCount: 0
    [MCU2_0]    753.450817 s:  strmFIFOOvflCount[0]: 0
    [MCU2_0]    753.450856 s:  strmFIFOOvflCount[1]: 0
    [MCU2_0]    753.450885 s:  Channel Num | Frame Queue Count | Frame De-queue Count | Frame Drop Count | Error Frame Count |
    [MCU2_0]    753.450962 s:            0 |             19615 |                19613 |            19653 |                 0 |
    Camera frame_id:19615 
    [MCU2_0]    753.451039 s:            1 |             19615 |                19613 |            19653 |                 0 |
    Camera frame_id:19616 
    Camera frame_id:19617 
    Camera frame_id:19618 
    Camera frame_id:19619 
    Camera frame_id:19620 
    Camera frame_id:19621 
    Camera frame_id:19622 
    Camera frame_id:19623 
    Camera frame_id:19624 
    Camera frame_id:19625 

    Looking forward to your sharing.

    Regards,

    Barry

  • Video link:

    1920x1536 *2 ->csi1 ->MultiCamDemo ->

    ->2560x800 Superframe(1280x800 side-by-side 1280x800) ->DSI ->serdes ->lcd

    Looking forward to the expert's reply.

    Regards,

    Barry

  • Hi Brijesh,

    Why will the camera frame rate change from 60 to 30FPS after adding the patch?

    We must create two cameras as a superframe input to DSS for DSI output so that splitter display can be performed in DSI->serdes.

    How should we modify this patch now so as not to affect the 60FPS frame rate?

    Can you help us send the relevant patch? Thanks.

    Your support is important to us

    Camera frame_id:257508 
    pCamera frame_id:257509 
    Camera frame_id:257510 
    Camera frame_id:257511 
    Camera frame_id:257512 
    Camera frame_id:257513 
    Camera frame_id:257514 
    Camera frame_id:257515 
    
    
    
    Summary of CPU load,
    ====================
    
    CPU: mpu1_0: TOTAL LOAD =   0.21 % ( HWI =   0. 7 %, SWI =   0. 0 % )
    CPU: mcu2_0: TOTAL LOAD =   4. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
    CPU: mcu2_1: TOTAL LOAD =   1. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
    CPU:  c6x_1: TOTAL LOAD =   0. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
    CPU:  c6x_2: TOTAL LOAD =   0. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
    CPU:  c7x_1: TOTAL LOAD =   0. 0 % ( HWI =   0. 0 %, SWI =   0. 0 % )
    
    
    HWA performance statistics,
    ===========================
    
    
    
    DDR performance statistics,
    ===========================
    
    DDR: READ  BW: AVG =    717 MB/s, PEAK =   3092 MB/s
    DDR: WRITE BW: AVG =    709 MB/s, PEAK =   1396 MB/s
    DDR: TOTAL BW: AVG =   1426 MB/s, PEAK =   4488 MB/s
    
    
    Detailed CPU performance/memory statistics,
    ===========================================
    
    DDR_SHARED_MEM: Alloc's: 16 alloc's of 70779188 bytes 
    DDR_SHARED_MEM: Free's : 0 free's  of 0 bytes 
    DDR_SHARED_MEM: Open's : 16 allocs  of 70779188 bytes 
    DDR_SHARED_MEM: Total size: 536870912 bytes 
    
    CPU: mcu2_0: TASK:           IPC_RX:   0.15 %
    CPU: mcu2_0: TASK:       REMOTE_SRV:   0. 2 %
    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.92 %
    CPU: mcu2_0: TASK:       TIVX_CAPT2:   0. 0 %
    CPU: mcu2_0: TASK:       TIVX_DISP1:   2.20 %
    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 =   16680704 B ( 99 % unused)
    CPU: mcu2_0: HEAP:           L3_MEM: size =     262144 B, free =     261888 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: TASK:      IPC_TEST_TX:   0. 0 %
    
    CPU: mcu2_1: HEAP:    DDR_LOCAL_MEM: size =   16777216 B, free =   16773376 B ( 99 % unused)
    CPU: mcu2_1: HEAP:           L3_MEM: size =     262144 B, free =     262144 B (100 % unused)
    
    CPU:  c6x_1: TASK:           IPC_RX:   0. 0 %
    CPU:  c6x_1: TASK:       REMOTE_SRV:   0. 0 %
    CPU:  c6x_1: TASK:        LOAD_TEST:   0. 0 %
    CPU:  c6x_1: TASK:         TIVX_CPU:   0. 0 %
    CPU:  c6x_1: TASK:      IPC_TEST_RX:   0. 0 %
    CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %
    
    CPU:  c6x_1: HEAP:    DDR_LOCAL_MEM: size =   16777216 B, free =   16773376 B ( 99 % unused)
    CPU:  c6x_1: HEAP:           L2_MEM: size =     229376 B, free =     229376 B (100 % unused)
    CPU:  c6x_1: HEAP:  DDR_SCRATCH_MEM: size =   50331648 B, free =   50331648 B (100 % unused)
    
    CPU:  c6x_2: TASK:           IPC_RX:   0. 0 %
    CPU:  c6x_2: TASK:       REMOTE_SRV:   0. 0 %
    CPU:  c6x_2: TASK:        LOAD_TEST:   0. 0 %
    CPU:  c6x_2: TASK:         TIVX_CPU:   0. 0 %
    CPU:  c6x_2: TASK:      IPC_TEST_RX:   0. 0 %
    CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %
    CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %
    
    Camera frame_id:257516 
    Camera frame_id:257517 
    Camera frame_id:257518 
    Camera frame_id:257519 
    CPU:  c6x_2: HEAP:    DDR_LOCAL_MEM: size =   16777216 B, free =   16773376 B ( 99 % unused)
    CPU:  c6x_2: HEAP:           L2_MEM: size =     229376 B, free =     229376 B (100 % unused)
    CPU:  c6x_2: HEAP:  DDR_SCRATCH_MEM: size =   50331648 B, free =   50331648 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: 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 =    8159232 B, free =    8159232 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)
    
    
    GRAPH: app_multi_cam_graph (#nodes =   3, #executions = 257517)
     NODE:       CAPTURE1:             capture_node: avg =    129 usecs, min/max =     76 /  49116 usecs, #executions =     257517
     NODE:       DISPLAY1:              DisplayNode: avg =  16588 usecs, min/max =   3849 /  16732 usecs, #executions =     257517
     NODE:       DISPLAY1:              DisplayNode: avg =  16574 usecs, min/max =     64 /  20674 usecs, #executions =     257517
    
     PERF:           FILEIO: avg =      0 usecs, min/max = 4294967295 /      0 usecs, #executions =          0
     PERF:            TOTAL: avg =  32309 usecs, min/max =     14 /  33365 usecs, #executions =        198
    
     PERF:            TOTAL:   30.95 FPS
    
    Camera frame_id:257520 
    
    
     =========================
     Demo : Camera Demo
     =========================
    
     s: Save CSIx, VISS and LDC outputs
    
     p: Print performance statistics
    
     x: Exit
    
     Enter Choice: 
    
    
     =========================
     Demo : Camera Demo
     =========================
    
     s: Save CSIx, VISS and LDC outputs
    
     p: Print performance statistics
    
     x: Exit
    
     Enter Choice: [MCU2_0]   8972.073554 s: ==========================================================
    [MCU2_0]   8972.073655 s:  Capture Status: Instance|0
    [MCU2_0]   8972.073692 s: ==========================================================
    [MCU2_0]   8972.073739 s:  overflowCount: 0
    [MCU2_0]   8972.073774 s:  spuriousUdmaIntrCount: 0
    [MCU2_0]   8972.073811 s:  frontFIFOOvflCount: 0
    [MCU2_0]   8972.073845 s:  crcCount: 0
    [MCU2_0]   8972.073875 s:  eccCount: 0
    [MCU2_0]   8972.073907 s:  correctedEccCount: 0
    [MCU2_0]   8972.073942 s:  dataIdErrorCount: 0
    [MCU2_0]   8972.073977 s:  invalidAccessCount: 0
    [MCU2_0]   8972.074026 s:  invalidSpCount: 0
    [MCU2_0]   8972.074066 s:  strmFIFOOvflCount[0]: 0
    [MCU2_0]   8972.074106 s:  strmFIFOOvflCount[1]: 0
    [MCU2_0]   8972.074136 s:  Channel Num | Frame Queue Count | Frame De-queue Count | Frame Drop Count | Error Frame Count |
    [MCU2_0]   8972.074194 s: ==========================================================
    [MCU2_0]   8972.074243 s:  Capture Status: Instance|1
    [MCU2_0]   8972.074272 s: ==========================================================
    [MCU2_0]   8972.074315 s:  overflowCount: 0
    [MCU2_0]   8972.074348 s:  spuriousUdmaIntrCount: 0
    [MCU2_0]   8972.074384 s:  frontFIFOOvflCount: 0
    [MCU2_0]   8972.074417 s:  crcCount: 0
    [MCU2_0]   8972.074446 s:  eccCount: 0
    [MCU2_0]   8972.074478 s:  correctedEccCount: 0
    [MCU2_0]   8972.074512 s:  dataIdErrorCount: 0
    Camera frame_id:257521 
    [MCU2_0]   8972.074546 s:  invalidAccessCount: 0
    [MCU2_0]   8972.074580 s:  invalidSpCount: 0
    [MCU2_0]   8972.074619 s:  strmFIFOOvflCount[0]: 0
    Camera frame_id:257522 
    [MCU2_0]   8972.074659 s:  strmFIFOOvflCount[1]: 0
    Camera frame_id:257523 
    [MCU2_0]   8972.074688 s:  Channel Num | Frame Queue Count | Frame De-queue Count | Frame Drop Count | Error Frame Count |
    Camera frame_id:257524 
    [MCU2_0]   8972.074765 s:            0 |            257522 |               257520 |           257988 |                 0 |
    [MCU2_0]   8972.074844 s:            1 |            257522 |               257520 |           257987 |                 0 |
    Camera frame_id:257525 
    Camera frame_id:257526 
    Camera frame_id:257527 
    Camera frame_id:257528 
    Camera frame_id:257529 
    Camera frame_id:257530 
    Camera frame_id:257531 
    Camera frame_id:257532 
    

    Regards,

    Barry

  • Hi Barry,

    This is strange, i dont see any error in capture, capture and display both are running in realtime, but still graph performance is dropping to 30fps. 

    Do you have any graph parameter in the application? and after Dequeueing graph parameter, are you doing any processing in the application, which potentially is delaying graph performance? 

    Which SDK release are you using? Have you tried changing numPIxels parameter in the CSIRX to 1? 

    Regards,

    Brijesh

  • Hi Brijesh,

    Thanks Reply.

    SDK version:

    PDK-RTOS :processor-sdk-rtos-j721e-evm-08_06_00_12
    PDK-LINUX:processor-sdk-linux-08_06_00

    The application uses app_multi_cam, In apps/basic_demos/app_multi_cam/main.c, Apart from adding this patch: there are no other changes.

    https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1107628/faq-processor-sdk-j721e-how-to-enable-multiple-displays-by-sending-bigger-size-frames-from-dss

    apps/basic_demos/app_multi_cam/main.c
    
    diff --git a/PDK0806_RTOS/vision_apps/apps/basic_demos/app_multi_cam/main.c b/PDK0806_RTOS/vision_apps/apps/basic_demos/app_multi_cam/main.c
    index b4c8b1350..d3260784e 100755
    --- a/PDK0806_RTOS/vision_apps/apps/basic_demos/app_multi_cam/main.c
    +++ b/PDK0806_RTOS/vision_apps/apps/basic_demos/app_multi_cam/main.c
    @@ -94,7 +94,8 @@ typedef struct {
         AEWBObj       aewbObj1;
         LDCObj        ldcObj1;
         ImgMosaicObj  imgMosaicObj;
    -    DisplayObj    displayObj;
    +    DisplayObj    displayObj1;
    +    DisplayObj    displayObj2;
     
         vx_char output_file_path[APP_MAX_FILE_PATH];
     
    @@ -137,6 +138,10 @@ typedef struct {
         vx_uint32 hwa_freq_config;
         vx_uint32 bypass_split_graph;
     
    +    /* Dual Display references */
    +    tivx_display_select_channel_params_t channel_prms;
    +    vx_user_data_object switch_ch_obj;
    +
     } AppObj;
     
     AppObj gAppObj;
    @@ -155,7 +160,7 @@ 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_draw_graphics(Draw2D_Handle *handle, Draw2D_BufInfo *draw2dBufInfo, uint32_t update_type);
     
     static void app_show_usage(vx_int32 argc, vx_char* argv[])
     {
    @@ -222,6 +227,32 @@ static void app_run_task_delete(AppObj *obj)
         tivxTaskDelete(&obj->task);
     }
     
    +static void app_activate_dual_channel(AppObj *obj)
    +{
    +    vx_reference dualRefs1st[1];
    +    vx_reference dualRefs2nd[1];
    +
    +    /* 2nd Camera Channel Activation */
    +    obj->channel_prms.active_channel_id = 0;
    +    vxCopyUserDataObject(obj->switch_ch_obj, 0,
    +                         sizeof(tivx_display_select_channel_params_t),
    +                         &obj->channel_prms, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST);
    +    dualRefs1st[0] = (vx_reference)obj->switch_ch_obj;
    +    tivxNodeSendCommand(obj->displayObj1.disp_node, 0,
    +                        TIVX_DISPLAY_SELECT_CHANNEL, dualRefs1st, 1u);
    +
    +
    +    /* 1st Camera Channel Activation -- Default Channel */
    +    obj->channel_prms.active_channel_id = 1;
    +    vxCopyUserDataObject(obj->switch_ch_obj, 0,
    +                         sizeof(tivx_display_select_channel_params_t),
    +                         &obj->channel_prms, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST);
    +    dualRefs2nd[0] = (vx_reference)obj->switch_ch_obj;
    +    tivxNodeSendCommand(obj->displayObj2.disp_node, 0,
    +                        TIVX_DISPLAY_SELECT_CHANNEL, dualRefs2nd, 1u);
    +
    +}
    +
     static vx_status app_run_graph_interactive(AppObj *obj)
     {
         vx_status status;
    @@ -461,17 +492,17 @@ static void app_parse_cfg_file(AppObj *obj, vx_char *cfg_file_name)
                     }
                 }
                 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, "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, "is_interactive")==0)
                 {
                     token = strtok(NULL, s);
    @@ -507,6 +538,7 @@ static void app_parse_cfg_file(AppObj *obj, vx_char *cfg_file_name)
                     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);
    @@ -650,10 +682,12 @@ vx_int32 app_multi_cam_main(vx_int32 argc, vx_char* argv[])
     
         /*Optional parameter setting*/
         app_default_param_set(obj);
    -
    +    
         /*Config parameter reading*/
         app_parse_cmd_line_args(obj, argc, argv);
     
    +    obj->sensorObj.ch_mask = 0x30;  //
    +
         /* Querry sensor parameters */
         status = app_querry_sensor(&obj->sensorObj);
         if(1 == obj->sensorObj.sensor_out_format)
    @@ -740,7 +774,7 @@ vx_int32 app_multi_cam_main(vx_int32 argc, vx_char* argv[])
     static vx_status app_init(AppObj *obj)
     {
         vx_status status = VX_SUCCESS;
    -    app_grpx_init_prms_t grpx_prms;
    +    // app_grpx_init_prms_t grpx_prms;
     
         if (1U == obj->enable_configure_hwa_freq)
         {
    @@ -840,13 +874,19 @@ static vx_status app_init(AppObj *obj)
     
         if (status == VX_SUCCESS)
         {
    -        status = app_init_display(obj->context, &obj->displayObj, "display_obj");
    -        APP_PRINTF("Display init done!\n");
    +        status = app_init_display(obj->context, &obj->displayObj1, "display_obj1");
    +        APP_PRINTF("Display1 init done!\n");
         }
     
    -    appGrpxInitParamsInit(&grpx_prms, obj->context);
    -    grpx_prms.draw_callback = app_draw_graphics;
    -    appGrpxInit(&grpx_prms);
    +    if (status == VX_SUCCESS)
    +    {
    +        status = app_init_display(obj->context, &obj->displayObj2, "display_obj2");
    +        APP_PRINTF("Display2 init done!\n");
    +    }
    +
    +    // 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");
    @@ -907,10 +947,14 @@ static void app_deinit(AppObj *obj)
             APP_PRINTF("Img Mosaic deinit done!\n");
         }
     
    -    app_deinit_display(&obj->displayObj);
    -    APP_PRINTF("Display deinit done!\n");
    +    app_deinit_display(&obj->displayObj1);
    +    APP_PRINTF("Display1 deinit done!\n");
    +
    +    app_deinit_display(&obj->displayObj2);
    +    APP_PRINTF("Display2 deinit done!\n");
    +    // appGrpxDeInit();
     
    -    appGrpxDeInit();
    +    vxReleaseUserDataObject(&obj->switch_ch_obj);
     
         tivxHwaUnLoadKernels(obj->context);
         tivxImagingUnLoadKernels(obj->context);
    @@ -961,7 +1005,10 @@ static void app_delete_graph(AppObj *obj)
         app_delete_img_mosaic(&obj->imgMosaicObj);
         APP_PRINTF("Img Mosaic delete done!\n");
     
    -    app_delete_display(&obj->displayObj);
    +    app_delete_display(&obj->displayObj1);
    +    APP_PRINTF("Display delete done!\n");
    +
    +    app_delete_display(&obj->displayObj2);
         APP_PRINTF("Display delete done!\n");
     
         vxReleaseGraph(&obj->graph);
    @@ -973,6 +1020,7 @@ 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;
    +    vx_image display_in_image;
     
         obj->graph = vxCreateGraph(obj->context);
         status = vxGetStatus((vx_reference)obj->graph);
    @@ -1114,7 +1162,9 @@ static vx_status app_create_graph(AppObj *obj)
             }
         }
     
    -    vx_image display_in_image;
    +    // display_in_image = (vx_image)vxGetObjectArrayItem(obj->vissObj.output_arr, 0);
    +    // vx_image display_in_image;
    +
         if(obj->enable_mosaic == 1)
         {
             obj->imgMosaicObj.num_inputs = idx;
    @@ -1133,10 +1183,40 @@ static vx_status app_create_graph(AppObj *obj)
     
         if(status == VX_SUCCESS)
         {
    -        status = app_create_graph_display(obj->graph, &obj->displayObj, display_in_image);
    -        APP_PRINTF("Display graph done!\n");
    +        status = app_create_graph_display(obj->graph, &obj->displayObj1, display_in_image);
    +        APP_PRINTF("Display1 graph done!\n");
    +    }
    +
    +    if(status == VX_SUCCESS)
    +    {
    +        status = app_create_graph_display(obj->graph, &obj->displayObj2, display_in_image);
    +        APP_PRINTF("Display2 graph done!\n");
    +    }
    +
    +    if(status == VX_SUCCESS)
    +    {
    +        obj->channel_prms.active_channel_id = 0;
    +        obj->switch_ch_obj = vxCreateUserDataObject(
    +            obj->context, "tivx_display_select_channel_params_t",
    +            sizeof(tivx_display_select_channel_params_t), &obj->channel_prms);
    +        if (vxGetStatus((vx_reference)obj->switch_ch_obj) != VX_SUCCESS)
    +        {
    +            APP_PRINTF("switch_ch_obj create failed\n");
    +        }
         }
     
    +    // if(status == VX_SUCCESS)
    +    // {
    +    //     obj->channel_prms.active_channel_id = 1;
    +    //     obj->switch_ch_obj = vxCreateUserDataObject(
    +    //         obj->context, "tivx_display_select_channel_params_t",
    +    //         sizeof(tivx_display_select_channel_params_t), &obj->channel_prms);
    +    //     if (vxGetStatus((vx_reference)obj->switch_ch_obj) != VX_SUCCESS)
    +    //     {
    +    //         APP_PRINTF("switch_ch_obj create failed\n");
    +    //     }
    +    // }
    +
         if(status == VX_SUCCESS)
         {
             graph_parameter_index = 0;
    @@ -1243,6 +1323,12 @@ static vx_status app_verify_graph(AppObj *obj)
             status = app_send_error_frame(&obj->captureObj);
         }
     
    +    if (VX_SUCCESS == status)
    +    {
    +        /* Activate dual channels */
    +        app_activate_dual_channel(obj);
    +    }
    +
         /* wait a while for prints to flush */
         tivxTaskWaitMsecs(100);
     
    @@ -1253,7 +1339,7 @@ static vx_status app_run_graph_for_one_frame_pipeline(AppObj *obj, vx_int32 fram
     {
         vx_status status = VX_SUCCESS;
     
    -    APP_PRINTF("app_run_graph_for_one_pipeline: frame %d beginning\n", frame_id);
    +    APP_PRINTF("app_run_graph_for_one_pipeline: frame %d beginning, pipeline:%d,line:%d \n", frame_id,obj->pipeline,__LINE__);
         appPerfPointBegin(&obj->total_perf);
     
         ImgMosaicObj *imgMosaicObj = &obj->imgMosaicObj;
    @@ -1392,6 +1478,8 @@ static vx_status app_run_graph(AppObj *obj)
             APP_PRINTF("appStartImageSensor returned with status: %d\n", status);
         }
     
    +    tivxTaskWaitMsecs(20000);
    +
         if(0 == obj->enable_viss)
         {
             obj->vissObj.en_out_viss_write = 0;
    @@ -1438,6 +1526,7 @@ static vx_status app_run_graph(AppObj *obj)
                 status = app_run_graph_for_one_frame_pipeline(obj, frame_id);
             }
     
    +        printf("Camera frame_id:%d \n", frame_id);
             /* user asked to stop processing */
             if(obj->stop_task)
               break;
    @@ -1486,7 +1575,8 @@ static void app_default_param_set(AppObj *obj)
     {
         set_sensor_defaults(&obj->sensorObj);
     
    -    set_display_defaults(&obj->displayObj);
    +    set_display_defaults(&obj->displayObj1);
    +    set_display_defaults(&obj->displayObj2);
     
         app_pipeline_params_defaults(obj);
     
    @@ -1496,9 +1586,9 @@ static void app_default_param_set(AppObj *obj)
         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;
    +    obj->sensorObj.num_cameras_enabled = 2;
    +    obj->sensorObj.ch_mask = 0x30;
    +    obj->sensorObj.usecase_option = APP_SENSOR_FEATURE_CFG_UC1;         //?
     }
     
     static vx_int32 calc_grid_size(vx_uint32 ch)
    @@ -1585,7 +1675,7 @@ 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))
    +    if ((obj->sensorObj.num_cameras_enabled == 1))
         {
             obj->objArrSplitObj.output0_num_elements = 1;
             obj->objArrSplitObj.output1_num_elements = 0;
    @@ -1616,17 +1706,17 @@ static void add_graph_parameter_by_node_index(vx_graph graph, vx_node node, vx_u
         vxReleaseParameter(&parameter);
     }
     
    -static void app_draw_graphics(Draw2D_Handle *handle, Draw2D_BufInfo *draw2dBufInfo, uint32_t update_type)
    -{
    -    appGrpxDrawDefault(handle, draw2dBufInfo, update_type);
    +// 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;
    +//     if(update_type == 0)
    +//     {
    +//         Draw2D_FontPrm sHeading;
     
    -        sHeading.fontIdx = 4;
    -        Draw2D_drawString(handle, 700, 5, "Multi Cam Demo", &sHeading);
    -    }
    +//         sHeading.fontIdx = 4;
    +//         Draw2D_drawString(handle, 700, 5, "Multi Cam Demo", &sHeading);
    +//     }
     
    -  return;
    -}
    +//   return;
    +// }
    \ No newline at end of file

    After adding the patch, the frame rate dropped from 60 to 30. It is obvious that this phenomenon is caused by the addition of this patch;

    The obvious thing is: after adding the patch, a DISPLAY1 node will be added. How should we modify the patch to solve this problem?

    The result of numPIxels value 0/1 is 30FPS, which does not change the problem.

    Looking forward to expert support on this issue.

    Regards,

    Barry

  • Hi Barry,

    The obvious thing is: after adding the patch, a DISPLAY1 node will be added. How should we modify the patch to solve this problem?

    Sorry, did not get above. 

    One change that i noted in the above patch is, it is using app_init_display, which internally uses same display id. Can you try using different display id for both of these displays? Lets say, can you try using dispId as 0 for the first object and 2 for the second display in displayObj->disp_params.pipeId variable? 

    Regards,

    Brijesh 

  • Hi Brijesh,

    Thanks Reply.

    This change has been modified a long time ago.

    modules/src/app_display_module.c
    
    diff --git a/PDK0806_RTOS/vision_apps/modules/src/app_display_module.c b/PDK0806_RTOS/vision_apps/modules/src/app_display_module.c
    old mode 100644
    new mode 100755
    index 9b59e4c97..39264f52f
    --- a/PDK0806_RTOS/vision_apps/modules/src/app_display_module.c
    +++ b/PDK0806_RTOS/vision_apps/modules/src/app_display_module.c
    @@ -64,6 +64,7 @@
     vx_status app_init_display(vx_context context, DisplayObj *displayObj, char *objName)
     {
         vx_status status = VX_SUCCESS;
    +    static int32_t dispId = 0;
     
         if (displayObj->display_option == 1)
         {
    @@ -81,11 +82,23 @@ vx_status app_init_display(vx_context context, DisplayObj *displayObj, char *obj
                 memset(&displayObj->disp_params, 0, sizeof(tivx_display_params_t));
     
                 displayObj->disp_params.opMode = TIVX_KERNEL_DISPLAY_ZERO_BUFFER_COPY_MODE;//TIVX_KERNEL_DISPLAY_BUFFER_COPY_MODE;
    -            displayObj->disp_params.pipeId = 0; /* pipe ID = 2 */
    -            displayObj->disp_params.outWidth = DISPLAY_WIDTH;
    -            displayObj->disp_params.outHeight = DISPLAY_HEIGHT;
    -            displayObj->disp_params.posX = (1920-DISPLAY_WIDTH)/2;
    -            displayObj->disp_params.posY = (1080-DISPLAY_HEIGHT)/2;
    +
    +            if (dispId == 0)
    +            {
    +                displayObj->disp_params.pipeId = 0; /* pipe ID = 0 */
    +                displayObj->disp_params.outWidth = 1280;
    +                displayObj->disp_params.outHeight = 800;
    +                displayObj->disp_params.posX = 0;
    +                displayObj->disp_params.posY = 0;
    +            }
    +            else
    +            {
    +                displayObj->disp_params.pipeId = 2; /* pipe ID = 2 */
    +                displayObj->disp_params.outWidth = 1280;
    +                displayObj->disp_params.outHeight = 800;
    +                displayObj->disp_params.posX = 1280;
    +                displayObj->disp_params.posY = 0;
    +            }
     
                 displayObj->disp_params_obj = vxCreateUserDataObject(context, "tivx_display_params_t", sizeof(tivx_display_params_t), &displayObj->disp_params);
                 status = vxGetStatus((vx_reference)displayObj->disp_params_obj);
    @@ -94,6 +107,8 @@ vx_status app_init_display(vx_context context, DisplayObj *displayObj, char *obj
                 {
                     vxSetReferenceName((vx_reference)displayObj->disp_params_obj, "display_node_disp_params_obj");
                 }
    +
    +            dispId++;
             }
         }
     

    Looking to the experts.

    Regards,

    Barry

  • Why will the camera frame rate change from 60 to 30FPS after adding the patch?

    One question, is the graph running fine without this patch? Lets say if there is no display in the graph, does it capture at 60fps? 

    Also i see you are using two CSIRX instances, are both the instances managed by single instance of CSIRX capture node? 

    Regards,

    Brijesh

  • Hi Brijesh,

    Thanks Reply.

    As I mentioned repeatedly upstairs, without adding this patch, the frame rate can reach 60.

    Our CSI0 is not connected to the camera, but CSI1 is connected to two 60FPS cameras.

    Regards,

    Barry

  • Hi Barry,

    Strange, this patch just enables a second pipeline to display second camera input and most likely both the display pipelines are connected to the same display, so there should not be any delay in display. This should not be due to display. This is why i was asking to check if it works without this patch? Even if this is due to display, increasing number of buffers should have helps, because then there is enough margin for the delay due to display. 

    I feel the issue is due to something else. 

    Can you try increasing numPIxels to 1 in the capture node? You might require changes that i suggested in below link.

    https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1260910/tda4vh-q1-can-csi-rx-module-handle-two-4k-cameras-at-yuv422-8bit-30-fps

    Regards,

    Brijesh

  • Hi Brijesh,

    Thanks for reply.

    I reviewed the SDK8.6 I am currently using, and it is the same as the patch code you mentioned.

    Try to modify The result of numPIxels value 0/1 are both 30FPS, which does not change the problem.

    This is app_multi_cam/main.c after we added the patch:

    packages/ti/drv/csirx/src/csirx_drvUdma.c:
    
    /* ========================================================================== */
    /*                          Function Definitions                              */
    /* ========================================================================== */
    int32_t CsirxDrv_getDMACfgParams(CsirxDrv_ChObj *chObj)
    {
        int32_t retVal = FVID2_SOK;
        Csirx_CreateParams *createParams;
        uint32_t chType;
    
        createParams = &chObj->instObj->createParams;
    
        /* Assign UDMA Rx channel params from channel configurations */
        chObj->rxChParams = &chObj->chCfg->rxChParams;
        /* Init UDMA channel parameters */
        chType = UDMA_CH_TYPE_RX;
        UdmaChPrms_init(&chObj->chParams, chType);
        chObj->trpdMem = &gCsirxUdmaTprdMem[chObj->instObj->drvInstId][chObj->psilThreadId][0U][0U];
        chObj->rxFqRingMem = &gCsirxRingMem[chObj->instObj->drvInstId][chObj->psilThreadId][0U];
    #if defined (SOC_J721E)
        chObj->rxCqRingMem = &gCsirxCompRingMem[chObj->instObj->drvInstId][chObj->psilThreadId][0U];
        chObj->rxTdCqRingMem = &gCsirxTdCompRingMem[chObj->instObj->drvInstId][chObj->psilThreadId][0U];
    #endif
        chObj->chParams.peerChNum            = (chObj->instObj->psilThreadIdStart +
                                                chObj->psilThreadId);
        chObj->chParams.fqRingPrms.ringMem   = chObj->rxFqRingMem;
        chObj->chParams.fqRingPrms.orderId   = chObj->chCfg->ringOrderId;
        chObj->chParams.fqRingPrms.elemCnt   = CSIRX_CAPT_QUEUE_DEPTH_PER_CH;
    #if defined (SOC_J721E)
        chObj->chParams.cqRingPrms.ringMem   = chObj->rxCqRingMem;
        chObj->chParams.tdCqRingPrms.ringMem = chObj->rxTdCqRingMem;
        /* Initialize ring order ID */
        chObj->chParams.cqRingPrms.orderId   = chObj->chCfg->ringOrderId;
        chObj->chParams.tdCqRingPrms.orderId = chObj->chCfg->ringOrderId;
        chObj->chParams.cqRingPrms.elemCnt   = CSIRX_CAPT_QUEUE_DEPTH_PER_CH;
        chObj->chParams.tdCqRingPrms.elemCnt = CSIRX_CAPT_QUEUE_DEPTH_PER_CH;
    #endif
    
        /* Get the PSI-L Threads/DMA channel configuration parameters */
        chObj->dmaCfgParams.chNum = chObj->psilThreadId;
        chObj->dmaCfgParams.virtCh = chObj->chCfg->vcNum;
        chObj->dmaCfgParams.dataType = chObj->chCfg->inCsiDataType;
        chObj->dmaCfgParams.dstTag = CSIRX_DRV_PSI_DEST_TAG;
        chObj->dmaCfgParams.srcTag = CSIRX_DRV_PSI_SRC_TAG;
        chObj->dmaCfgParams.psFlags = 0U;
        chObj->dmaCfgParams.pktType = 0U;
    
        chObj->dmaCfgParams.dualPkgEnable = 0U;
        /* Storage mode for YUV422 data format */
        if (chObj->chCfg->outFmt.dataFormat == FVID2_DF_YUV422I_UYVY)
        {
            chObj->dmaCfgParams.yuv422Mode = (uint32_t)CSL_CSIRX_YUV422_MODE_YVYU;
        }
        else if (chObj->chCfg->outFmt.dataFormat == FVID2_DF_YUV422I_YUYV)
        {
            chObj->dmaCfgParams.yuv422Mode = (uint32_t)CSL_CSIRX_YUV422_MODE_VYUY;
        }
        else if (chObj->chCfg->outFmt.dataFormat == FVID2_DF_YUV422I_YVYU)
        {
            chObj->dmaCfgParams.yuv422Mode = (uint32_t)CSL_CSIRX_YUV422_MODE_UYVY;
        }
        else if (chObj->chCfg->outFmt.dataFormat == FVID2_DF_YUV422I_VYUY)
        {
            chObj->dmaCfgParams.yuv422Mode = (uint32_t)CSL_CSIRX_YUV422_MODE_YUYV;
        }
        else
        {
            /* If input format is not YUV422, this parameter values is not used */
            chObj->dmaCfgParams.yuv422Mode = (uint32_t)CSL_CSIRX_YUV422_MODE_UYVY;
        }
        chObj->dmaCfgParams.pck12CfgEnable = 0U;
        /* Change 12 bit packed mode only if DT(inCsiDataType) is
           FVID2_CSI2_DF_RAW12 */
        if (chObj->chCfg->inCsiDataType == FVID2_CSI2_DF_RAW12)
        {
            if (chObj->chCfg->outFmt.ccsFormat == FVID2_CCSF_BITS12_PACKED)
            {
                chObj->dmaCfgParams.pck12CfgEnable = 1U;
            }
            else if (chObj->chCfg->outFmt.ccsFormat == FVID2_CCSF_BITS12_UNPACKED16)
            {
                chObj->dmaCfgParams.pck12CfgEnable = 0U;
            }
            else
            {
                /* If input format is not RAW12, this parameter values is not used */
                chObj->dmaCfgParams.pck12CfgEnable = 0U;
            }
        }
        if ((chObj->chCfg->inCsiDataType == FVID2_CSI2_DF_YUV422_8B) && 
            (createParams->instCfg.numPixelsStrm0 == 1U))
        {
            chObj->dmaCfgParams.dualPkgEnable = 1U;
        }
        if (chObj->chCfg->inCsiDataType == FVID2_CSI2_DF_RAW20)
        {
            chObj->dmaCfgParams.dataSizeShift =
                                (uint32_t)CSL_CSIRX_DMA_DATA_SIZE_SHIFT_32BITS;
        }
        else if (chObj->chCfg->outFmt.ccsFormat == FVID2_CCSF_BITS12_PACKED)
        {
            chObj->dmaCfgParams.dataSizeShift =
                                    (uint32_t)CSL_CSIRX_DMA_DATA_SIZE_SHIFT_8BITS;
        }
        else if ((chObj->chCfg->inCsiDataType == FVID2_CSI2_DF_YUV420_10B) ||
                 (chObj->chCfg->inCsiDataType == FVID2_CSI2_DF_YUV422_10B) ||
                 (chObj->chCfg->inCsiDataType == FVID2_CSI2_DF_RAW10) ||
                 (chObj->chCfg->inCsiDataType == FVID2_CSI2_DF_RAW12) ||
                 (chObj->chCfg->inCsiDataType == FVID2_CSI2_DF_RAW14) ||
                 (chObj->chCfg->inCsiDataType == FVID2_CSI2_DF_RAW16) ||
                 (chObj->chCfg->inCsiDataType == FVID2_CSI2_DF_YUV422_8B))
        {
            if (chObj->chCfg->inCsiDataType == FVID2_CSI2_DF_YUV422_8B)
            {
                chObj->dmaCfgParams.dataSizeShift =
                                    (uint32_t)CSL_CSIRX_DMA_DATA_SIZE_SHIFT_8BITS;          /*for yuv422_8 green*/
            }
            else if (createParams->instCfg.numPixelsStrm0 == 0U)
            {
                chObj->dmaCfgParams.dataSizeShift =
                                    (uint32_t)CSL_CSIRX_DMA_DATA_SIZE_SHIFT_16BITS;
            }
            else if(createParams->instCfg.numPixelsStrm0 == 1U)
            {
                chObj->dmaCfgParams.dataSizeShift =
                                    (uint32_t)CSL_CSIRX_DMA_DATA_SIZE_SHIFT_32BITS;
            }
            else
            {
                /* Do nothing as above two conditions should be hit
                   and check has done before entering this function */
            }
        }
        else if (chObj->chCfg->inCsiDataType == FVID2_CSI2_DF_RAW8)
        {
    
            if (createParams->instCfg.numPixelsStrm0 == 0U)
            {
                chObj->dmaCfgParams.dataSizeShift =
                                    (uint32_t)CSL_CSIRX_DMA_DATA_SIZE_SHIFT_8BITS;
            }
            else if(createParams->instCfg.numPixelsStrm0 == 1U)
            {
                chObj->dmaCfgParams.dataSizeShift =
                                    (uint32_t)CSL_CSIRX_DMA_DATA_SIZE_SHIFT_16BITS;
            }
            else if(createParams->instCfg.numPixelsStrm0 == 2U)
            {
                chObj->dmaCfgParams.dataSizeShift =
                                    (uint32_t)CSL_CSIRX_DMA_DATA_SIZE_SHIFT_32BITS;
            }
            else
            {
                /* Do nothing as above two conditions should be hit
                   and check has done before entering this function */
            }
        }
        else
        {
            chObj->dmaCfgParams.dataSizeShift =
                                (uint32_t)CSL_CSIRX_DMA_DATA_SIZE_SHIFT_8BITS;
        }
    
        return retVal;
    }
    
    
    apps/basic_demos/app_multi_cam/main.c:
    
    
    /*
     *
     * 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 "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)
    
    typedef struct {
    
        SensorObj     sensorObj;
        CaptureObj    captureObj;
        ObjArrSplitObj  objArrSplitObj;
        VISSObj       vissObj;
        AEWBObj       aewbObj;
        LDCObj        ldcObj;
        VISSObj       vissObj1;
        AEWBObj       aewbObj1;
        LDCObj        ldcObj1;
        ImgMosaicObj  imgMosaicObj;
        DisplayObj    displayObj1;
        DisplayObj    displayObj2;
    
        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;
    
        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;
    
        /* Dual Display references */
        tivx_display_select_channel_params_t channel_prms;
        vx_user_data_object switch_ch_obj;
    
    } AppObj;
    
    AppObj gAppObj;
    
    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 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 p: Print performance statistics"
        "\n"
        "\n x: Exit"
        "\n"
        "\n Enter Choice: "
    };
    
    
    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 void app_activate_dual_channel(AppObj *obj)
    {
        vx_reference dualRefs1st[1];
        vx_reference dualRefs2nd[1];
    
        /* 2nd Camera Channel Activation */
        obj->channel_prms.active_channel_id = 0;
        vxCopyUserDataObject(obj->switch_ch_obj, 0,
                             sizeof(tivx_display_select_channel_params_t),
                             &obj->channel_prms, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST);
        dualRefs1st[0] = (vx_reference)obj->switch_ch_obj;
        tivxNodeSendCommand(obj->displayObj1.disp_node, 0,
                            TIVX_DISPLAY_SELECT_CHANNEL, dualRefs1st, 1u);
    
    
        /* 1st Camera Channel Activation -- Default Channel */
        obj->channel_prms.active_channel_id = 1;
        vxCopyUserDataObject(obj->switch_ch_obj, 0,
                             sizeof(tivx_display_select_channel_params_t),
                             &obj->channel_prms, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST);
        dualRefs2nd[0] = (vx_reference)obj->switch_ch_obj;
        tivxNodeSendCommand(obj->displayObj2.disp_node, 0,
                            TIVX_DISPLAY_SELECT_CHANNEL, dualRefs2nd, 1u);
    
    }
    
    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];
    
        status = app_run_task_create(obj);
        if(status == VX_FAILURE)
        {
            printf("app_tidl: ERROR: Unable to create task\n");
        }
        else
        {
            appPerfStatsResetAll();
            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;
                        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, "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;
                }
                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;
    }
    
    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);
    
        obj->sensorObj.ch_mask = 0x30;  //
    
        /* 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;
        }
        else
        {
            obj->enable_viss = 1;
            obj->enable_split_graph = 1;
            obj->enable_aewb = 1;
            obj->enable_mosaic = 1;
        }
    
        /*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
                        {
                            status = app_run_graph(obj);
                        }
                    }
                }
            }
    
            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 (status == VX_SUCCESS)
        {
            status = app_init_display(obj->context, &obj->displayObj1, "display_obj1");
            APP_PRINTF("Display1 init done!\n");
        }
    
        if (status == VX_SUCCESS)
        {
            status = app_init_display(obj->context, &obj->displayObj2, "display_obj2");
            APP_PRINTF("Display2 init done!\n");
        }
    
        // 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");
        }
    
        app_deinit_display(&obj->displayObj1);
        APP_PRINTF("Display1 deinit done!\n");
    
        app_deinit_display(&obj->displayObj2);
        APP_PRINTF("Display2 deinit done!\n");
        // appGrpxDeInit();
    
        vxReleaseUserDataObject(&obj->switch_ch_obj);
    
        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");
    
        app_delete_display(&obj->displayObj1);
        APP_PRINTF("Display delete done!\n");
    
        app_delete_display(&obj->displayObj2);
        APP_PRINTF("Display delete done!\n");
    
        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;
        vx_image display_in_image;
    
        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;
            }
        }
    
        // display_in_image = (vx_image)vxGetObjectArrayItem(obj->vissObj.output_arr, 0);
        // vx_image display_in_image;
    
        if(obj->enable_mosaic == 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];
        }
        else
        {
            display_in_image = (vx_image)vxGetObjectArrayItem(obj->captureObj.raw_image_arr[0], 0);
        }
    
        if(status == VX_SUCCESS)
        {
            status = app_create_graph_display(obj->graph, &obj->displayObj1, display_in_image);
            APP_PRINTF("Display1 graph done!\n");
        }
    
        if(status == VX_SUCCESS)
        {
            status = app_create_graph_display(obj->graph, &obj->displayObj2, display_in_image);
            APP_PRINTF("Display2 graph done!\n");
        }
    
        if(status == VX_SUCCESS)
        {
            obj->channel_prms.active_channel_id = 0;
            obj->switch_ch_obj = vxCreateUserDataObject(
                obj->context, "tivx_display_select_channel_params_t",
                sizeof(tivx_display_select_channel_params_t), &obj->channel_prms);
            if (vxGetStatus((vx_reference)obj->switch_ch_obj) != VX_SUCCESS)
            {
                APP_PRINTF("switch_ch_obj create failed\n");
            }
        }
    
        // if(status == VX_SUCCESS)
        // {
        //     obj->channel_prms.active_channel_id = 1;
        //     obj->switch_ch_obj = vxCreateUserDataObject(
        //         obj->context, "tivx_display_select_channel_params_t",
        //         sizeof(tivx_display_select_channel_params_t), &obj->channel_prms);
        //     if (vxGetStatus((vx_reference)obj->switch_ch_obj) != VX_SUCCESS)
        //     {
        //         APP_PRINTF("switch_ch_obj create failed\n");
        //     }
        // }
    
        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);
        }
    
        if (VX_SUCCESS == status)
        {
            /* Activate dual channels */
            app_activate_dual_channel(obj);
        }
    
        /* 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, pipeline:%d,line:%d \n", frame_id,obj->pipeline,__LINE__);
        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);
        }
    
        // tivxTaskWaitMsecs(20000);
    
        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);
            }
    
            printf("Camera frame_id:%d \n", frame_id);
            /* 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->displayObj1);
        set_display_defaults(&obj->displayObj2);
    
        app_pipeline_params_defaults(obj);
    
        obj->is_interactive = 1;
        obj->test_mode = 0;
        obj->write_file = 0;
        obj->bypass_split_graph = 0;
    
        obj->sensorObj.enable_ldc = 0;
        obj->sensorObj.num_cameras_enabled = 2;
        obj->sensorObj.ch_mask = 0x30;
        obj->sensorObj.usecase_option = APP_SENSOR_FEATURE_CFG_UC1;         //?
    }
    
    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;
    // }

    Looking forward to expert reply, thank you.

    Regards,

    Barry

  • Hi Barry,

    Let me think again and see if anything else is missing. 

    Regards,

    Brijesh

  • Hi Barry,

    Can you try one experiment and see if it helps? 

    In the API ownTargetNodeDescReleaseParameter in the file source/framework/vx_target_acquire_parameters.c, can you please make highlighted change, rebuild sdk and then try it out?

    {
    parent_obj_desc = ownObjDescGet(obj_desc->scope_obj_desc_id);

    if(parent_obj_desc!=NULL)
    {
    num_in_nodes = obj_desc->in_node_done_cnt + parent_obj_desc->in_node_done_cnt;
    }
    else
    {
    num_in_nodes = obj_desc->in_node_done_cnt;
    }
    }

    //if(num_in_nodes==data_ref_q_obj_desc->num_in_nodes)

    if (do_release_ref == (vx_bool)vx_true_e)
    {
    do_release_ref_to_queue = (vx_bool)vx_true_e;
    /* Note: This is needed because the delay obj_desc does not get re-acquired for each slot.
    * Therefore, each in_node_done_cnt must be reset for each delay slot. */
    obj_desc->in_node_done_cnt = 0;
    }

    Regards,

    Brijesh

  • Hi Brijesh,

    thank you for your reply .

    But this experiment cannot solve the problem.

    Frame Drop Count is still cumulatively greater than Frame De-queue Count.

    Regards,

    Barry

  • Hi Barry,

    ok, this seems some framework issue, so i will need to check with our team. 

    Is there a way to reproduce this issue on EVM to support this debug?

    Also do you also see this issue with 30fps input? Lets says if input sensor is outputting at 30fps, then do you see correct output fps? or it still reduces to 15fps? 

    For which project do you require this feature? Can you please provide some more information? If not on e2e, can you please provide this information to our local TI FAE? 

    Regards,

    Brijesh

  • Hi Brijesh,

    Sorry, we don’t have an EVM camera, and the output method we verified is DSI, so we can’t verify it on the EVM board.

    DSI-SERDES-LCD

    Our final goal is to use serdes to split the superframe into two 1280*800 images that can be displayed independently.

    We set the DSI output timing to 2560*800 on the customer board, so we add this patch to make it output a superframe:https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1107628/faq-processor-sdk-j721e-how-to-enable-multiple-displays-by-sending-bigger-size-frames-from-dss

    As mentioned repeatedly above, the fps dropped from 60 to 30 after adding the patch.

    In addition, if you switch to two 30 cameras, the output will still reach 30 after adding the patch, and it will not drop to 15.

    Regards,

    Barry

  • Hi Barry,

    I have raised to our team, but due to release SDK9.2, it could be checked only after SDK9.2 release. 

    https://jira.itg.ti.com/browse/TIOVX-1590

    Regards,

    Brijesh

  • Hi Barry,

    Can you please attached patch on tiovx folder and see if it helps?

    /cfs-file/__key/communityserver-discussions-components-files/791/TIOVX_2D00_ADASVISION_2D00_5758.patch

    Regards,

    Brijesh