Hi experts,
I'm trying to display 4 RGB images using multi-display or mosaic.
The data flow is image->cv::mat->vx_image_RGB->display.
However, for multi-display, there are only 2 display to use (TIVX_TARGET_DISPLAY1 & TIVX_TARGET_DISPLAY2).
I try to use M2M display, but there is not much example code that I can refer to.
For mosaic, I can't display RGB images either.
Is there a way to display 4 RGB images succesfully?
I will show my code (.cpp) here.
mosaic:
#include <iostream> #include <stdexcept> //OpenVX includes #include <VX/vx.h> extern "C" { #include <utils/app_init/include/app_init.h> #include <utils/grpx/include/app_grpx.h> #include "display_common.h" #include "app_img_mosaic_module.h" #include <TI/video_io_display.h> #include <TI/video_io_display_m2m.h> #include <TI/hwa_kernels.h> #include <TI/video_io_kernels.h> #include <TI/tivx.h> #include <TI/tivx_task.h> } #include "test_vximage_mosaic.h" //OpenCV includes #include "opencv2/core.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #define CAPTURE_BUFFER_Q_DEPTH (4) #define APP_BUFFER_Q_DEPTH (4) #define APP_PIPELINE_DEPTH (7) #define INPUT_DISPLAY_WIDTH 1920 #define INPUT_DISPLAY_HEIGHT 720 #define INPUT_DISPLAY_WIDTH_DISPLAY 1920 #define INPUT_DISPLAY_HEIGHT_DISPLAY 720 vx_status app_init_display1(vx_context context, DisplayObj *displayObj, char *objName); void app_deinit_display1(DisplayObj *displayObj); void app_delete_display1(DisplayObj *displayObj); vx_status app_create_graph_display1(vx_graph graph, DisplayObj *displayObj, vx_image disp_image); vx_status app_run_graph(AppObj *obj); void app_draw_graphics(Draw2D_Handle *handle, Draw2D_BufInfo *draw2dBufInfo, uint32_t update_type); static vx_status app_create_graph(AppObj *obj); inline vx_image vxCvMatToVxImage(const vx_context context, const cv::Mat &cv_image); static void set_img_mosaic_params(ImgMosaicObj *imgMosaicObj) { imgMosaicObj->out_width = INPUT_DISPLAY_WIDTH; imgMosaicObj->out_height = INPUT_DISPLAY_HEIGHT; imgMosaicObj->num_inputs = 4; tivxImgMosaicParamsSetDefaults(&imgMosaicObj->params); imgMosaicObj->params.windows[0].startX = 0; imgMosaicObj->params.windows[0].startY = 0; imgMosaicObj->params.windows[0].width = INPUT_DISPLAY_WIDTH/2; imgMosaicObj->params.windows[0].height = INPUT_DISPLAY_HEIGHT/2; imgMosaicObj->params.windows[0].input_select = 0; imgMosaicObj->params.windows[0].channel_select = 0; imgMosaicObj->params.windows[1].startX = 1920-INPUT_DISPLAY_WIDTH/2; imgMosaicObj->params.windows[1].startY = 0; imgMosaicObj->params.windows[1].width = INPUT_DISPLAY_WIDTH/2; imgMosaicObj->params.windows[1].height = INPUT_DISPLAY_HEIGHT/2; imgMosaicObj->params.windows[1].input_select = 1; imgMosaicObj->params.windows[1].channel_select = 0; imgMosaicObj->params.windows[2].startX = 0; imgMosaicObj->params.windows[2].startY = INPUT_DISPLAY_HEIGHT/2; imgMosaicObj->params.windows[2].width = INPUT_DISPLAY_WIDTH/2; imgMosaicObj->params.windows[2].height = INPUT_DISPLAY_HEIGHT/2; imgMosaicObj->params.windows[2].input_select = 2; imgMosaicObj->params.windows[2].channel_select = 0; imgMosaicObj->params.windows[3].startX = 1920-INPUT_DISPLAY_WIDTH/2; imgMosaicObj->params.windows[3].startY = INPUT_DISPLAY_HEIGHT/2; imgMosaicObj->params.windows[3].width = INPUT_DISPLAY_WIDTH/2; imgMosaicObj->params.windows[3].height = INPUT_DISPLAY_HEIGHT/2; imgMosaicObj->params.windows[3].input_select = 3; imgMosaicObj->params.windows[3].channel_select = 0; imgMosaicObj->params.num_windows = 4; // imgMosaicObj->params.clear_count = 1; } void app_draw_graphics(Draw2D_Handle *handle, Draw2D_BufInfo *draw2dBufInfo, uint32_t update_type) { AppObj *obj = &gAppObj; appGrpxDrawDefault(handle, draw2dBufInfo, update_type); if(update_type == 0) { Draw2D_FontPrm sHeading; Draw2D_FontPrm sAlgo1; Draw2D_FontPrm sAlgo2; Draw2D_FontPrm sAlgo3; Draw2D_FontPrm sAlgo4; Draw2D_FontPrm sAlgo5; Draw2D_FontPrm sAlgo6; Draw2D_BmpPrm bmp; sHeading.fontIdx = 5; Draw2D_drawString(handle, 620, 40, "Image Display Test", &sHeading); // sAlgo1.fontIdx = 1; // Draw2D_drawString(handle, INPUT_DISPLAY_WIDTH/2 - 120 , (DISPLAY_HEIGHT + INPUT_DISPLAY_HEIGHT)/2 - 75, "Display 1", &sAlgo1); // sAlgo1.fontIdx = 1; // Draw2D_drawString(handle, DISPLAY_WIDTH - (INPUT_DISPLAY_WIDTH2/2 + 120) , (DISPLAY_HEIGHT + INPUT_DISPLAY_HEIGHT2)/2 - 75, "Display 2", &sAlgo1); } return; } static vx_status app_init(AppObj *obj) { vx_status status = VX_SUCCESS; app_grpx_init_prms_t grpx_prms; 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); tivxVideoIOLoadKernels(obj->context); APP_PRINTF("Kernel loading done!\n"); } /* Initialize modules */ if (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_display1(obj->context, &obj->displayObj, "display_obj"); APP_PRINTF("Display init done!\n"); } appGrpxInitParamsInit(&grpx_prms, obj->context); grpx_prms.draw_callback = app_draw_graphics; appGrpxInit(&grpx_prms); return status; } 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] = {0}; vx_int32 graph_parameter_index; obj->graph = vxCreateGraph(obj->context); status = vxGetStatus((vx_reference)obj->graph); if (status == VX_SUCCESS) { status = vxSetReferenceName((vx_reference)obj->graph, "app_multi_cam_graph"); APP_PRINTF("Graph create done!\n"); } vx_int32 idx = 0; vx_object_array mosaic_in_arr1; vx_object_array mosaic_in_arr2; vx_object_array mosaic_in_arr3; vx_object_array mosaic_in_arr4; mosaic_in_arr1 = vxCreateObjectArray(obj->context, (vx_reference)obj->display_image1, 1); mosaic_in_arr2 = vxCreateObjectArray(obj->context, (vx_reference)obj->display_image2, 1); mosaic_in_arr3 = vxCreateObjectArray(obj->context, (vx_reference)obj->display_image1, 1); mosaic_in_arr4 = vxCreateObjectArray(obj->context, (vx_reference)obj->display_image2, 1); obj->imgMosaicObj.input_arr[0] = mosaic_in_arr1; obj->imgMosaicObj.input_arr[1] = mosaic_in_arr2; obj->imgMosaicObj.input_arr[2] = mosaic_in_arr3; obj->imgMosaicObj.input_arr[3] = mosaic_in_arr4; obj->imgMosaicObj.num_inputs = 4; vx_image display_in_image; 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]; if(status == VX_SUCCESS) { status = app_create_graph_display1(obj->graph, &obj->displayObj, display_in_image); APP_PRINTF("Display graph done!\n"); } if(status == VX_SUCCESS) { status = vxVerifyGraph(obj->graph); } return status; } vx_status app_run_graph(AppObj *obj) { uint32_t curFileNum; int32_t outputFileNum; uint32_t iterations = 1; vx_status status = VX_SUCCESS; uint32_t num_buf; num_buf = MAX_NUM_BUF; int32_t pipeline = -num_buf; int32_t enqueueCnt = 0; vx_int32 img_array_idx = -1; vx_uint32 test_counter = 0; if(status == VX_SUCCESS) { if(status == VX_SUCCESS) { for(int i = 0; i < 200; i++) { status = vxProcessGraph(obj->graph); std::cout << "Processed iterations: " << i << std::endl; } } } printf(" Ran %d times successfully!\n", 100); return status; } vx_status app_init_display1(vx_context context, DisplayObj *displayObj, char *objName) { vx_status status = VX_SUCCESS; if (vx_true_e == tivxIsTargetEnabled(TIVX_TARGET_DISPLAY1) && (1 == displayObj->display_option)) { memset(&displayObj->display_params1, 0, sizeof(tivx_display_params_t)); displayObj->display_config1 = vxCreateUserDataObject(context, "tivx_display_params_t", sizeof(tivx_display_params_t), NULL); APP_ASSERT_VALID_REF(displayObj->display_config1); vxSetReferenceName((vx_reference)displayObj->display_config1, "InputDisplayConfiguration"); displayObj->display_params1.opMode=TIVX_KERNEL_DISPLAY_ZERO_BUFFER_COPY_MODE; displayObj->display_params1.pipeId = 0; displayObj->display_params1.outWidth = INPUT_DISPLAY_WIDTH_DISPLAY; displayObj->display_params1.outHeight = INPUT_DISPLAY_HEIGHT_DISPLAY; displayObj->display_params1.posX = 0; displayObj->display_params1.posY = 0; status = vxCopyUserDataObject(displayObj->display_config1, 0, sizeof(tivx_display_params_t), &displayObj->display_params1, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST); APP_ASSERT(status==VX_SUCCESS); } return status; } void app_deinit_display1(DisplayObj *displayObj) { if (vx_true_e == tivxIsTargetEnabled(TIVX_TARGET_DISPLAY1) && (displayObj->display_option == 1)) { vxReleaseUserDataObject(&displayObj->display_config1); } } void app_delete_display1(DisplayObj *displayObj) { if (vx_true_e == tivxIsTargetEnabled(TIVX_TARGET_DISPLAY1) && (displayObj->display_option == 1)) { vxReleaseNode(&displayObj->node1); } } vx_status app_create_graph_display1(vx_graph graph, DisplayObj *displayObj, vx_image disp_image) { vx_status status = VX_SUCCESS; if (vx_true_e == tivxIsTargetEnabled(TIVX_TARGET_DISPLAY1) && (displayObj->display_option == 1)) { displayObj->node1 = tivxDisplayNode( graph, displayObj->display_config1, disp_image); status = vxGetStatus((vx_reference)displayObj->node1); if (VX_SUCCESS != status) { printf("# ERROR: Display is not enabled on this platform, please disable it in config \n"); } APP_ASSERT(VX_SUCCESS == status); status = vxSetNodeTarget(displayObj->node1, VX_TARGET_STRING, TIVX_TARGET_DISPLAY1); APP_ASSERT(status==VX_SUCCESS); vxSetReferenceName((vx_reference)displayObj->node1, "Output Display"); } return status; } inline vx_image vxCvMatToVxImage(const vx_context context, const cv::Mat &cv_image) { vx_df_image vx_image_type; switch (cv_image.type()) { case CV_8UC1: vx_image_type = VX_DF_IMAGE_U8; break; case CV_8UC3: vx_image_type = VX_DF_IMAGE_RGB; break; default: return NULL; } int width = cv_image.cols; int height = cv_image.rows; vx_image image = vxCreateImage(context, width, height, vx_image_type); vx_rectangle_t patch; patch.start_x = 0; patch.start_y = 0; patch.end_x = width; patch.end_y = height; vx_map_id map_id; vx_imagepatch_addressing_t addr; unsigned char *ptr; vx_status status = vxMapImagePatch(image, &patch, 0, &map_id, &addr, (void **)&ptr, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST, VX_NOGAP_X); if (status != VX_SUCCESS) { return NULL; } if (addr.stride_x != 1 && addr.stride_x != 3) { return NULL; } for (int y = 0; y < height; y++) { unsigned char *ptr_y = ptr + y * addr.stride_y; memcpy(ptr_y, cv_image.ptr(y), addr.stride_y); } status = vxUnmapImagePatch(image, map_id); if (status != VX_SUCCESS) { return NULL; } return image; } int main() { // read image from file std::string imgPath1 = "test.jpg"; cv::Mat cvimage1 = cv::imread(imgPath1); cv::cvtColor(cvimage1, cvimage1, cv::COLOR_BGR2RGB); // resize image cv::resize(cvimage1, cvimage1, cv::Size(1920/6, 1080/6)); if (cvimage1.empty()) { throw std::runtime_error("Failed to read image from file1"); } // read image from file std::string imgPath2 = "test2.jpg"; cv::Mat cvimage2 = cv::imread(imgPath2); cv::cvtColor(cvimage2, cvimage2, cv::COLOR_BGR2RGB); // resize image cv::resize(cvimage2, cvimage2, cv::Size(1920/6, 1080/6)); if (cvimage2.empty()) { throw std::runtime_error("Failed to read image from file2"); } appInit(); AppObj *obj = &gAppObj; vx_status status = VX_SUCCESS; obj->displayObj.display_option = 1; set_img_mosaic_params(&obj->imgMosaicObj); status = app_init(obj); vx_image image1 = vxCvMatToVxImage(obj->context, cvimage1); vx_image image2 = vxCvMatToVxImage(obj->context, cvimage2); obj->display_image1 = image1; obj->display_image2 = image2; status = app_create_graph(obj); status = app_run_graph(obj); vxReleaseImage(&obj->display_image1); vxReleaseImage(&obj->display_image2); app_delete_display1(&obj->displayObj); app_delete_img_mosaic(&obj->imgMosaicObj); vxReleaseGraph(&obj->graph); app_deinit_display1(&obj->displayObj); app_deinit_img_mosaic(&obj->imgMosaicObj, 4); if (1 == obj->displayObj.display_option) { appGrpxDeInit(); } tivxVideoIOUnLoadKernels(obj->context); tivxHwaUnLoadKernels(obj->context); vxReleaseContext(&obj->context); }
m2m display:
#include <iostream> #include <stdexcept> //OpenVX includes #include <VX/vx.h> extern "C" { #include <utils/app_init/include/app_init.h> #include <utils/grpx/include/app_grpx.h> #include "display_common.h" #include <TI/video_io_display.h> #include <TI/video_io_display_m2m.h> #include <TI/hwa_kernels.h> #include <TI/video_io_kernels.h> #include <TI/tivx.h> #include <TI/tivx_task.h> } #include "test_vximage.h" //OpenCV includes #include "opencv2/core.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" vx_status app_init_display1(vx_context context, DisplayObj *displayObj, char *objName); vx_status app_init_display2(vx_context context, DisplayObj *displayObj, char *objName); vx_status app_init_display3(vx_context context, DisplayObj *displayObj, char *objName); vx_status app_init_display4(vx_context context, DisplayObj *displayObj, char *objName); void app_deinit_display1(DisplayObj *displayObj); void app_deinit_display2(DisplayObj *displayObj); void app_deinit_display3(DisplayObj *displayObj); void app_deinit_display4(DisplayObj *displayObj); void app_delete_display1(DisplayObj *displayObj); void app_delete_display2(DisplayObj *displayObj); void app_delete_display3(DisplayObj *displayObj); void app_delete_display4(DisplayObj *displayObj); vx_status app_create_graph_display1(vx_graph graph, DisplayObj *displayObj, vx_image disp_image); vx_status app_create_graph_display2(vx_graph graph, DisplayObj *displayObj, vx_image disp_image); vx_status app_create_graph_display3(vx_graph graph, DisplayObj *displayObj, vx_image disp_image); vx_status app_create_graph_display4(vx_graph graph, DisplayObj *displayObj, vx_image disp_image); vx_status app_run_graph(AppObj *obj); void app_draw_graphics(Draw2D_Handle *handle, Draw2D_BufInfo *draw2dBufInfo, uint32_t update_type); vx_status app_create_graph(AppObj *obj); inline vx_image vxCvMatToVxImage(const vx_context context, const cv::Mat &cv_image); void app_draw_graphics(Draw2D_Handle *handle, Draw2D_BufInfo *draw2dBufInfo, uint32_t update_type) { AppObj *obj = &gAppObj; appGrpxDrawDefault(handle, draw2dBufInfo, update_type); if(update_type == 0) { Draw2D_FontPrm sHeading; Draw2D_FontPrm sAlgo1; Draw2D_FontPrm sAlgo2; Draw2D_FontPrm sAlgo3; Draw2D_FontPrm sAlgo4; Draw2D_FontPrm sAlgo5; Draw2D_FontPrm sAlgo6; Draw2D_BmpPrm bmp; sHeading.fontIdx = 5; Draw2D_drawString(handle, 620, 40, "Image Display Test", &sHeading); // sAlgo1.fontIdx = 1; // Draw2D_drawString(handle, INPUT_DISPLAY_WIDTH/2 - 120 , (DISPLAY_HEIGHT + INPUT_DISPLAY_HEIGHT)/2 - 75, "Display 1", &sAlgo1); // sAlgo1.fontIdx = 1; // Draw2D_drawString(handle, DISPLAY_WIDTH - (INPUT_DISPLAY_WIDTH2/2 + 120) , (DISPLAY_HEIGHT + INPUT_DISPLAY_HEIGHT2)/2 - 75, "Display 2", &sAlgo1); } return; } vx_status app_init(AppObj *obj) { app_grpx_init_prms_t grpx_prms; vx_status status = VX_SUCCESS; obj->context = vxCreateContext(); if(status == VX_SUCCESS) { status = vxGetStatus((vx_reference) obj->context); } tivxHwaLoadKernels(obj->context); tivxVideoIOLoadKernels(obj->context); /* Initialize modules */ if(status == VX_SUCCESS) { status = app_init_display1( obj->context, &obj->displayObj , "display1Obj"); } if(status == VX_SUCCESS) { status = app_init_display2( obj->context, &obj->displayObj , "display2Obj"); } if(status == VX_SUCCESS) { status = app_init_display3( obj->context, &obj->displayObj , "display3Obj"); } if(status == VX_SUCCESS) { status = app_init_display4( obj->context, &obj->displayObj , "display4Obj"); } if (1 == obj->displayObj.display_option) { appGrpxInitParamsInit(&grpx_prms, obj->context); grpx_prms.draw_callback = app_draw_graphics; appGrpxInit(&grpx_prms); } return status; } vx_status app_create_graph(AppObj *obj) { vx_status status = VX_SUCCESS; obj->graph = vxCreateGraph(obj->context); status = vxGetStatus((vx_reference) obj->graph); if (status == VX_SUCCESS) { status = app_create_graph_display1(obj->graph, &obj->displayObj, obj->display_image1); } if(status == VX_SUCCESS) { status = app_create_graph_display2(obj->graph, &obj->displayObj, obj->display_image2); } if (status == VX_SUCCESS) { status = app_create_graph_display3(obj->graph, &obj->displayObj, obj->display_image1); } if(status == VX_SUCCESS) { status = app_create_graph_display4(obj->graph, &obj->displayObj, obj->display_image2); } if(status == VX_SUCCESS) { status = vxVerifyGraph(obj->graph); } return status; } vx_status app_run_graph(AppObj *obj) { uint32_t curFileNum; int32_t outputFileNum; uint32_t iterations = 1; vx_status status = VX_SUCCESS; uint32_t num_buf; num_buf = MAX_NUM_BUF; int32_t pipeline = -num_buf; int32_t enqueueCnt = 0; vx_int32 img_array_idx = -1; vx_uint32 test_counter = 0; if(status == VX_SUCCESS) { if(status == VX_SUCCESS) { for(int i = 0; i < 200; i++) { status = vxProcessGraph(obj->graph); std::cout << "Processed iterations: " << i << std::endl; } } } printf(" Ran %d times successfully!\n", 100); return status; } vx_status app_init_display1(vx_context context, DisplayObj *displayObj, char *objName) { vx_status status = VX_SUCCESS; if (vx_true_e == tivxIsTargetEnabled(TIVX_TARGET_DISPLAY1) && (1 == displayObj->display_option)) { memset(&displayObj->display_params1, 0, sizeof(tivx_display_params_t)); displayObj->display_config1 = vxCreateUserDataObject(context, "tivx_display_params_t", sizeof(tivx_display_params_t), NULL); APP_ASSERT_VALID_REF(displayObj->display_config1); vxSetReferenceName((vx_reference)displayObj->display_config1, "InputDisplayConfiguration"); displayObj->display_params1.opMode=TIVX_KERNEL_DISPLAY_ZERO_BUFFER_COPY_MODE; displayObj->display_params1.pipeId = 1; displayObj->display_params1.outWidth = INPUT_DISPLAY_WIDTH; displayObj->display_params1.outHeight = INPUT_DISPLAY_HEIGHT; displayObj->display_params1.posX = 0; displayObj->display_params1.posY = 0; status = vxCopyUserDataObject(displayObj->display_config1, 0, sizeof(tivx_display_params_t), &displayObj->display_params1, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST); APP_ASSERT(status==VX_SUCCESS); } return status; } vx_status app_init_display2(vx_context context, DisplayObj *displayObj, char *objName) { vx_status status = VX_SUCCESS; if (vx_true_e == tivxIsTargetEnabled(TIVX_TARGET_DISPLAY2) && (1 == displayObj->display_option)) { memset(&displayObj->display_params2, 0, sizeof(tivx_display_params_t)); displayObj->display_config2 = vxCreateUserDataObject(context, "tivx_display_params_t", sizeof(tivx_display_params_t), NULL); APP_ASSERT_VALID_REF(displayObj->display_config2); vxSetReferenceName((vx_reference)displayObj->display_config2, "OutputDisplayConfiguration"); displayObj->display_params2.opMode=TIVX_KERNEL_DISPLAY_ZERO_BUFFER_COPY_MODE; displayObj->display_params2.pipeId = 0; displayObj->display_params2.outWidth = INPUT_DISPLAY_WIDTH; displayObj->display_params2.outHeight = INPUT_DISPLAY_HEIGHT; displayObj->display_params2.posX = (DISPLAY_WIDTH-INPUT_DISPLAY_WIDTH); displayObj->display_params2.posY = 0; status = vxCopyUserDataObject(displayObj->display_config2, 0, sizeof(tivx_display_params_t), &displayObj->display_params2, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST); APP_ASSERT(status==VX_SUCCESS); } return status; } vx_status app_init_display3(vx_context context, DisplayObj *displayObj, char *objName) { vx_status status = VX_SUCCESS; if (vx_true_e == tivxIsTargetEnabled(TIVX_TARGET_DISPLAY_M2M1) && (1 == displayObj->display_option)) { memset(&displayObj->display_params3, 0, sizeof(tivx_display_m2m_params_t)); // new tivx_display_m2m_params_init(&displayObj->display_params3); displayObj->display_config3 = vxCreateUserDataObject(context, "tivx_display_m2m_params_t", sizeof(tivx_display_m2m_params_t), &displayObj->display_params3), vxSetReferenceName((vx_reference)displayObj->display_config3, "OutputDisplayConfiguration"); displayObj->display_params3.instId = 0U; /* Only one pipeline is supported */ displayObj->display_params3.numPipe = 1U; displayObj->display_params3.pipeId[0U] = 3U; displayObj->display_params3.overlayId = 3U; // status = vxCopyUserDataObject(displayObj->display_config3, 0, sizeof(tivx_display_m2m_params_t), &displayObj->display_params3, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST); APP_ASSERT(status==VX_SUCCESS); } return status; } vx_status app_init_display4(vx_context context, DisplayObj *displayObj, char *objName) { vx_status status = VX_SUCCESS; if (vx_true_e == tivxIsTargetEnabled(TIVX_TARGET_DISPLAY_M2M1) && (1 == displayObj->display_option)) { memset(&displayObj->display_params4, 0, sizeof(tivx_display_m2m_params_t)); // new tivx_display_m2m_params_init(&displayObj->display_params4); displayObj->display_config4 = vxCreateUserDataObject(context, "tivx_display_m2m_params_t", sizeof(tivx_display_m2m_params_t), &displayObj->display_params4), vxSetReferenceName((vx_reference)displayObj->display_config4, "OutputDisplayConfiguration"); displayObj->display_params4.instId = 0U; /* Only one pipeline is supported */ displayObj->display_params4.numPipe = 1U; displayObj->display_params4.pipeId[0U] = 3U; displayObj->display_params4.overlayId = 3U; // status = vxCopyUserDataObject(displayObj->display_config4, 0, sizeof(tivx_display_m2m_params_t), &displayObj->display_params4, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST); APP_ASSERT(status==VX_SUCCESS); } return status; } void app_deinit_display1(DisplayObj *displayObj) { if (vx_true_e == tivxIsTargetEnabled(TIVX_TARGET_DISPLAY1) && (displayObj->display_option == 1)) { vxReleaseUserDataObject(&displayObj->display_config1); } } void app_deinit_display2(DisplayObj *displayObj) { if (vx_true_e == tivxIsTargetEnabled(TIVX_TARGET_DISPLAY2) && (displayObj->display_option == 1)) { vxReleaseUserDataObject(&displayObj->display_config2); } } void app_deinit_display3(DisplayObj *displayObj) { if (vx_true_e == tivxIsTargetEnabled(TIVX_TARGET_DISPLAY_M2M2) && (displayObj->display_option == 1)) { vxReleaseUserDataObject(&displayObj->display_config3); } } void app_deinit_display4(DisplayObj *displayObj) { if (vx_true_e == tivxIsTargetEnabled(TIVX_TARGET_DISPLAY_M2M1) && (displayObj->display_option == 1)) { vxReleaseUserDataObject(&displayObj->display_config4); } } void app_delete_display1(DisplayObj *displayObj) { if (vx_true_e == tivxIsTargetEnabled(TIVX_TARGET_DISPLAY1) && (displayObj->display_option == 1)) { vxReleaseNode(&displayObj->node1); } } void app_delete_display2(DisplayObj *displayObj) { if (vx_true_e == tivxIsTargetEnabled(TIVX_TARGET_DISPLAY2) && (displayObj->display_option == 1)) { vxReleaseNode(&displayObj->node2); } } void app_delete_display3(DisplayObj *displayObj) { if (vx_true_e == tivxIsTargetEnabled(TIVX_TARGET_DISPLAY_M2M1) && (displayObj->display_option == 1)) { vxReleaseNode(&displayObj->node3); } } void app_delete_display4(DisplayObj *displayObj) { if (vx_true_e == tivxIsTargetEnabled(TIVX_TARGET_DISPLAY_M2M2) && (displayObj->display_option == 1)) { vxReleaseNode(&displayObj->node4); } } vx_status app_create_graph_display1(vx_graph graph, DisplayObj *displayObj, vx_image disp_image) { vx_status status = VX_SUCCESS; if (vx_true_e == tivxIsTargetEnabled(TIVX_TARGET_DISPLAY1) && (displayObj->display_option == 1)) { displayObj->node1 = tivxDisplayNode( graph, displayObj->display_config1, disp_image); status = vxGetStatus((vx_reference)displayObj->node1); if (VX_SUCCESS != status) { printf("# ERROR: Display is not enabled on this platform, please disable it in config \n"); } APP_ASSERT(VX_SUCCESS == status); status = vxSetNodeTarget(displayObj->node1, VX_TARGET_STRING, TIVX_TARGET_DISPLAY1); APP_ASSERT(status==VX_SUCCESS); vxSetReferenceName((vx_reference)displayObj->node1, "Output Display"); } return status; } vx_status app_create_graph_display2(vx_graph graph, DisplayObj *displayObj, vx_image disp_image) { vx_status status = VX_SUCCESS; if (vx_true_e == tivxIsTargetEnabled(TIVX_TARGET_DISPLAY2) && (displayObj->display_option == 1)) { displayObj->node2 = tivxDisplayNode( graph, displayObj->display_config2, disp_image); status = vxGetStatus((vx_reference)displayObj->node2); if (VX_SUCCESS != status) { printf("# ERROR: Display is not enabled on this platform, please disable it in config \n"); } APP_ASSERT(VX_SUCCESS == status); status = vxSetNodeTarget(displayObj->node2, VX_TARGET_STRING, TIVX_TARGET_DISPLAY2); APP_ASSERT(status==VX_SUCCESS); vxSetReferenceName((vx_reference)displayObj->node2, "Input Display"); } return status; } vx_status app_create_graph_display3(vx_graph graph, DisplayObj *displayObj, vx_image disp_image) { vx_status status = VX_SUCCESS; if (vx_true_e == tivxIsTargetEnabled(TIVX_TARGET_DISPLAY_M2M1) && (displayObj->display_option == 1)) { displayObj->node3 = tivxDisplayM2MNode( graph, displayObj->display_config3, disp_image, disp_image); status = vxGetStatus((vx_reference)displayObj->node3); if (VX_SUCCESS != status) { printf("# ERROR: Display is not enabled on this platform, please disable it in config \n"); } APP_ASSERT(VX_SUCCESS == status); status = vxSetNodeTarget(displayObj->node3, VX_TARGET_STRING, TIVX_TARGET_DISPLAY_M2M1); APP_ASSERT(status==VX_SUCCESS); vxSetReferenceName((vx_reference)displayObj->node3, "Input Display"); } return status; } vx_status app_create_graph_display4(vx_graph graph, DisplayObj *displayObj, vx_image disp_image) { vx_status status = VX_SUCCESS; if (vx_true_e == tivxIsTargetEnabled(TIVX_TARGET_DISPLAY2) && (displayObj->display_option == 1)) { displayObj->node4 = tivxDisplayM2MNode( graph, displayObj->display_config2, disp_image, disp_image); status = vxGetStatus((vx_reference)displayObj->node4); if (VX_SUCCESS != status) { printf("# ERROR: Display is not enabled on this platform, please disable it in config \n"); } APP_ASSERT(VX_SUCCESS == status); status = vxSetNodeTarget(displayObj->node4, VX_TARGET_STRING, TIVX_TARGET_DISPLAY_M2M2); APP_ASSERT(status==VX_SUCCESS); vxSetReferenceName((vx_reference)displayObj->node4, "Input Display"); } return status; } inline vx_image vxCvMatToVxImage(const vx_context context, const cv::Mat &cv_image) { vx_df_image vx_image_type; switch (cv_image.type()) { case CV_8UC1: vx_image_type = VX_DF_IMAGE_U8; break; case CV_8UC3: vx_image_type = VX_DF_IMAGE_RGB; break; default: return NULL; } int width = cv_image.cols; int height = cv_image.rows; vx_image image = vxCreateImage(context, width, height, vx_image_type); vx_rectangle_t patch; patch.start_x = 0; patch.start_y = 0; patch.end_x = width; patch.end_y = height; vx_map_id map_id; vx_imagepatch_addressing_t addr; unsigned char *ptr; vx_status status = vxMapImagePatch(image, &patch, 0, &map_id, &addr, (void **)&ptr, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST, VX_NOGAP_X); if (status != VX_SUCCESS) { return NULL; } if (addr.stride_x != 1 && addr.stride_x != 3) { return NULL; } for (int y = 0; y < height; y++) { unsigned char *ptr_y = ptr + y * addr.stride_y; memcpy(ptr_y, cv_image.ptr(y), addr.stride_y); } status = vxUnmapImagePatch(image, map_id); if (status != VX_SUCCESS) { return NULL; } return image; } int main() { // read image from file std::string imgPath1 = "test.jpg"; cv::Mat cvimage1 = cv::imread(imgPath1); cv::cvtColor(cvimage1, cvimage1, cv::COLOR_BGR2RGB); // resize image cv::resize(cvimage1, cvimage1, cv::Size(1920, 1080)); if (cvimage1.empty()) { throw std::runtime_error("Failed to read image from file1"); } // read image from file std::string imgPath2 = "test2.jpg"; cv::Mat cvimage2 = cv::imread(imgPath2); cv::cvtColor(cvimage2, cvimage2, cv::COLOR_BGR2RGB); // resize image cv::resize(cvimage2, cvimage2, cv::Size(1920, 1080)); if (cvimage2.empty()) { throw std::runtime_error("Failed to read image from file2"); } appInit(); AppObj *obj = &gAppObj; vx_status status = VX_SUCCESS; obj->displayObj.display_option = 1; status = app_init(obj); vx_image image1 = vxCvMatToVxImage(obj->context, cvimage1); vx_image image2 = vxCvMatToVxImage(obj->context, cvimage2); obj->display_image1 = image1; obj->display_image2 = image2; status = app_create_graph(obj); status = app_run_graph(obj); vxReleaseImage(&obj->display_image1); vxReleaseImage(&obj->display_image2); app_delete_display1(&obj->displayObj); app_delete_display2(&obj->displayObj); app_delete_display3(&obj->displayObj); app_delete_display4(&obj->displayObj); vxReleaseGraph(&obj->graph); app_deinit_display1(&obj->displayObj); app_deinit_display2(&obj->displayObj); app_deinit_display3(&obj->displayObj); app_deinit_display4(&obj->displayObj); if (1 == obj->displayObj.display_option) { appGrpxDeInit(); } tivxVideoIOUnLoadKernels(obj->context); tivxHwaUnLoadKernels(obj->context); vxReleaseContext(&obj->context); }