Tool/software:
Hello everybody,
i am facing a stucked graph execution and i need some support to solve that problem.
First of all to the circumstances:
PSDK RTOS Version: 09_01_00_06
PSDK Linux Version: 09_01_00_06
I was able to exctract the problem from a complex project, so i have written a small quick and dirty program which executes a small graph.
Following graph gets stuck while executing:
The graph is pretty simple. I have a CSI Node, an user node histogram equalization and a display node. Currently no image sensor is connected, so i register an error frame which is send after the CSI timeout is expired. Normaly the graph should run after the error frame is send to the CSI node. Unfortunatly the graph runs only the first time after the initial timeout is expired and get stuck while running the second iteration. The histogram equalization node is not executed and the main programm is waiting for the graph to finish execution (endless waiting). The code is shown bellow.
I tried to modify the graph so i can enclose the problem to a specific node. I created following two graphs by commenting out the histogram equalization node or the display node, resulting in this two graphs:
Without a display node, the resulting histogram image is saved in a bmp file. The resulting output images from the histogram node are correct.
Without the histogram node, the error frame is directly transfered to the display node, which shows the error frame correctly.
Both graphs are executed normaly and the program finished successfull. All iterations are executed.
I was not able to discover the problem which leads to the stucked graph and i can not explain myself why the other two graphes are executed normaly. There is no error in my user defined histogram kernel, otherwise the graph without the display node would not run successfully.
Please let me know if you need more informations (more code, callstack, etc.)
Source Code:
#include "own_tracking.h" #include <TI/hwa_kernels.h> #include <TI/soc/tivx_soc_j784s4.h> #include <TI/tivx.h> #include <TI/video_io_capture.h> #include <TI/video_io_display.h> #include <TI/video_io_kernels.h> #include <VX/vx.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <tivx_utils.h> #include <tivx_utils_file_rd_wr.h> #include <unistd.h> #include <utils/mem/include/app_mem.h> #define IMG_HEIGHT 480 #define IMG_WIDTH 640 #define DISPLAY_WIDTH 1920 #define DISPLAY_HEIGHT 1080 #define CSI_LANES 4 #define CSI_TIMEOUT_MS 500 #define CSI_TIMEOUT_INIT_MS 10000 #define CLIP_LIMIT_PROZENT 40 #define NUM_GRAPH_EXECUTIONS 100 extern int32_t appCommonInit(); extern int32_t appCommonDeInit(); void error_check(vx_reference reference); void init_csi_params(tivx_capture_params_t *params); void init_display_params(tivx_display_params_t *params); void set_reference_names(); void run_graph(); void release(); void deinit(); void init(); vx_image create_error_frame(); vx_context context; vx_graph graph; vx_node node_csi, node_hist, node_display; vx_user_data_object usr_data_csi, usr_data_display; vx_object_array array_csi_image; vx_image img_exemplar, img_csi, img_hist, img_error_frame; vx_scalar scalar_clip; int main(int argc, char **argv) { vx_status status; tivx_display_params_t params_display; tivx_capture_params_t params_csi; vx_uint8 clip_limit; clip_limit = CLIP_LIMIT_PROZENT; init(); context = vxCreateContext(); error_check((vx_reference) context); graph = vxCreateGraph(context); error_check((vx_reference) graph); ownTrackingLoadKernels(context, true); ownRegisterTrackingA72Kernels(); #ifndef x86_64 tivxVideoIOLoadKernels(context); #endif init_csi_params(¶ms_csi); usr_data_csi = vxCreateUserDataObject(context, "tivx_capture_params_t", sizeof(tivx_capture_params_t), ¶ms_csi); error_check((vx_reference) usr_data_csi); img_exemplar = vxCreateImage(context, IMG_WIDTH, IMG_HEIGHT, VX_DF_IMAGE_U16); error_check((vx_reference) img_exemplar); array_csi_image = vxCreateObjectArray(context, (vx_reference) img_exemplar, 1); error_check((vx_reference) array_csi_image); node_csi = tivxCaptureNode(graph, usr_data_csi, array_csi_image); error_check((vx_reference) node_csi); vxSetNodeTarget(node_csi, VX_TARGET_STRING, TIVX_TARGET_CAPTURE1); img_csi = (vx_image) vxGetObjectArrayItem(array_csi_image, 0); error_check((vx_reference) img_csi); img_hist = vxCreateImage(context, IMG_WIDTH, IMG_HEIGHT, VX_DF_IMAGE_U8); error_check((vx_reference) img_hist); scalar_clip = vxCreateScalar(context, VX_TYPE_UINT8, &clip_limit); error_check((vx_reference) scalar_clip); // comment out next two lines for graph without histogram node node_hist = ownHistogramEqualNode(graph, img_csi, img_hist, scalar_clip); error_check((vx_reference) node_hist); init_display_params(¶ms_display); usr_data_display = vxCreateUserDataObject(context, "tivx_display_params_t", sizeof(params_display), (void *) ¶ms_display); error_check((vx_reference) usr_data_display); // comment out next line for graph without display node node_display = tivxDisplayNode(graph, usr_data_display, img_hist); // uncomment the next line for graph without histogram node // node_display = tivxDisplayNode(graph, usr_data_display, img_csi); error_check((vx_reference) node_display); status = vxVerifyGraph(graph); if (status != VX_SUCCESS) error_check(NULL); img_error_frame = create_error_frame(); error_check((vx_reference) img_error_frame); tivxCaptureRegisterErrorFrame(node_csi, (vx_reference) img_error_frame); set_reference_names(); tivxExportGraphToDot(graph, "/home/root/xcorr_app/graph_out", "test_graphs"); run_graph(); printf("Successfully executed csi graph ! \n"); release(); deinit(); return EXIT_SUCCESS; } void error_check(vx_reference reference) { vx_status status; status = vxGetStatus(reference); if (status != VX_SUCCESS) { release(); deinit(); exit(EXIT_FAILURE); } } void init_csi_params(tivx_capture_params_t *params) { tivx_capture_params_init(params); params->timeout = CSI_TIMEOUT_MS; params->timeoutInitial = CSI_TIMEOUT_INIT_MS; params->numInst = 1U; params->numCh = 1U; { vx_uint8 ch, id, lane, q; for (id = 0; id < params->numInst; id++) { params->instId[id] = id; params->instCfg[id].enableCsiv2p0Support = (uint32_t) vx_true_e; params->instCfg[id].numDataLanes = CSI_LANES; params->instCfg[id].laneBandSpeed = TIVX_CAPTURE_LANE_BAND_SPEED_2000_TO_2250_MBPS; for (lane = 0; lane < params->instCfg[id].numDataLanes; lane++) { params->instCfg[id].dataLanesMap[lane] = lane + 1; } for (q = 0; q < 4; q++) { ch = (4 - 1) * id + q; params->chVcNum[ch] = q; params->chInstMap[ch] = id; } } } } void init_display_params(tivx_display_params_t *params) { memset(params, 0, sizeof(tivx_display_params_t)); if (tivxIsTargetEnabled(TIVX_TARGET_DISPLAY1) == vx_true_e) { params->opMode = TIVX_KERNEL_DISPLAY_ZERO_BUFFER_COPY_MODE; params->pipeId = 0; params->outWidth = IMG_WIDTH; params->outHeight = IMG_HEIGHT; params->posX = (DISPLAY_WIDTH - IMG_WIDTH) / 2; params->posY = (DISPLAY_HEIGHT - IMG_HEIGHT) / 2; } } void set_reference_names() { vxSetReferenceName((vx_reference) img_csi, "CSI OUTPUT IMAGE"); vxSetReferenceName((vx_reference) img_error_frame, "ERROR FRAME IMAGE"); vxSetReferenceName((vx_reference) img_hist, "HISTOGRAM EQUALIZATION IMAGE"); vxSetReferenceName((vx_reference) array_csi_image, "CSI OUTPUT 'ARRAY"); vxSetReferenceName((vx_reference) usr_data_display, "DISPLAY USER DATA"); vxSetReferenceName((vx_reference) usr_data_csi, "CSI USER DATA"); vxSetReferenceName((vx_reference) scalar_clip, "CLIP LIMIT SCALAR"); vxSetReferenceName((vx_reference) node_csi, "CSI NODE"); vxSetReferenceName((vx_reference) node_display, "DISPLAY NODE"); vxSetReferenceName((vx_reference) node_hist, "HISTOGRAM EQUALIZATION NODE"); vxSetReferenceName((vx_reference) graph, "CSI TEST GRAPH"); } void run_graph() { vx_status status; for (int i = 0; i < NUM_GRAPH_EXECUTIONS; ++i) { char outfilename[200]; printf("Run %d. iteration !\n", i); status = vxScheduleGraph(graph); if (status != VX_SUCCESS) error_check(NULL); status = vxWaitGraph(graph); if (status != VX_SUCCESS) error_check(NULL); sprintf(outfilename, "/home/root/xcorr_app/test_images/images/%s_%04d.bmp", "out", i); tivx_utils_save_vximage_to_bmpfile(outfilename, img_hist); } } void release() { if (img_csi != NULL) vxReleaseImage(&img_csi); if (img_hist != NULL) vxReleaseImage(&img_hist); if (img_error_frame != NULL) vxReleaseImage(&img_error_frame); if (img_exemplar != NULL) vxReleaseImage(&img_exemplar); if (usr_data_csi != NULL) vxReleaseUserDataObject(&usr_data_csi); if (usr_data_display != NULL) vxReleaseUserDataObject(&usr_data_display); if (array_csi_image != NULL) vxReleaseObjectArray(&array_csi_image); if (scalar_clip != NULL) vxReleaseScalar(&scalar_clip); if (node_csi != NULL) vxReleaseNode(&node_csi); if (node_display != NULL) vxReleaseNode(&node_display); if (node_hist != NULL) vxReleaseNode(&node_hist); ownTrackingUnLoadKernels(context); #ifndef x86_64 tivxVideoIOUnLoadKernels(context); #endif if (graph != NULL) vxReleaseGraph(&graph); if (context != NULL) vxReleaseContext(&context); } void deinit() { tivxHostDeInit(); tivxDeInit(); appCommonDeInit(); if (appMemDeInit() != 0) { printf("Failed to deinit memory !\n"); } } void init() { appMemInit(NULL); appCommonInit(); tivxInit(); tivxHostInit(); } vx_image create_error_frame() { vx_status status; vx_image error_frame, error_image; vx_size size; vx_rectangle_t rect = { 0 }; vx_imagepatch_addressing_t addr = { 0 }; void *buffer; uint16_t *data; size = IMG_WIDTH * IMG_HEIGHT * sizeof(vx_uint16); buffer = malloc(size); rect.end_x = IMG_WIDTH; rect.end_y = IMG_HEIGHT; addr.dim_x = IMG_WIDTH; addr.dim_y = IMG_HEIGHT; addr.stride_x = 2; addr.stride_y = addr.stride_x * IMG_WIDTH; error_frame = vxCreateImage(context, IMG_WIDTH, IMG_HEIGHT, VX_DF_IMAGE_U16); error_image = tivx_utils_create_vximage_from_bmpfile( context, "/home/root/xcorr_app/test_images/images/error_image.bmp", vx_true_e); status = vxGetStatus((vx_reference) error_frame); if (status != VX_SUCCESS) exit(EXIT_FAILURE); status = vxGetStatus((vx_reference) error_image); if (status != VX_SUCCESS) exit(EXIT_FAILURE); vxCopyImagePatch(error_image, &rect, 0, &addr, buffer, VX_READ_ONLY, VX_MEMORY_TYPE_HOST); data = (uint16_t *) buffer; for (int i = 0; i < (IMG_WIDTH * IMG_HEIGHT); ++i) { data[i] = data[i] << 6; } vxCopyImagePatch(error_frame, &rect, 0, &addr, buffer, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST); vxReleaseImage(&error_image); free(buffer); return error_frame; }
Thank you for your help !