Part Number: PROCESSOR-SDK-DRA8X
Tool/software: TI C/C++ Compiler
Dear TI
I use the camera which has ISP in camera module, The sensor is AR0233, the ISP is GW5200, the serializer is TI953, the deserializer is TI960 in TDA4M board, the AR0233 and ISP is power on automatic work by itself, it can automatic send picture to TI953. we don't need control ISP and AR0233. the resolution ratio of camera is 1920*1080, the type is YUV4228Bit, the detailed type is YUYV
The board is J721E DRA829/TDA4VM bought fromTI company; I use the version 1.0 SDK.
so I modify [vision_apps\apps\basic_demos\app_single_cam\app_single_cam_main.c], I modify the code and make the openvx_node be capture_node -> display_node, I upload this C file; I also chang the code in (imaging\sensor_drv\src\ar0233), I change the register data of TI953, change the register address of TI953, modify the code in imaging\sensor_drv\src\ar0233\iss_sensor_ar0233.c to disable ar0233.
The most important point is I change some parameters of struct (prms->createPrms), the path is [tiovx\kernels_j7\hwa\capture\vx_capture_target.c function: static vx_status VX_CALLBACK tivxCaptureCreate()], after change the parameters , I call the function:
/* Creating FVID2 handle */
if (VX_SUCCESS == status)
{
Fvid2CbParams_init(&prms->drvCbPrms);
prms->drvCbPrms.cbFxn = (Fvid2_CbFxn) &captDrvCallback;
prms->drvCbPrms.appData = prms;
VX_PRINT(VX_ZONE_ERROR,"the value of raw_capture: %d\r\n", prms->raw_capture);
// prms->raw_capture = 0; // yuv_imagex
if (prms->raw_capture == 0) {
VX_PRINT(VX_ZONE_ERROR,"Start set prms\r\n");
prms->createPrms.chCfg[0].inCsiDataType = FVID2_CSI2_DF_YUV422_8B;
prms->createPrms.chCfg[0].outFmt.dataFormat = FVID2_DF_YUV422I_YUYV;
prms->createPrms.chCfg[0].outFmt.ccsFormat = FVID2_CCSF_BITS8_UNPACKED16;
prms->createPrms.chCfg[0].outFmt.pitch[0] = 0xf00*2;
prms->createPrms.chCfg[0].outFmt.fieldMerged[0] = 1;
prms->createPrms.chCfg[0].outFmt.scanFormat = 0x02;
prms->createPrms.frameDropBufLen = 2148960;
prms->createPrms.chCfg[0].outFmt.height = 1080;
prms->createPrms.chCfg[0].outFmt.width = 1920;
}
prms->drvHandle = Fvid2_create(
CSIRX_CAPT_DRV_ID,
prms->instId,
&prms->createPrms,
&prms->createStatus,
&prms->drvCbPrms);
if ((NULL == prms->drvHandle) ||
(prms->createStatus.retVal != FVID2_SOK))
{
VX_PRINT(VX_ZONE_ERROR, ": Capture Create Failed!!!\r\n");
status = VX_FAILURE;
}
else
{
/* Set CSIRX D-PHY configuration parameters */
Csirx_initDPhyCfg(&prms->dphyCfg);
prms->dphyCfg.inst = prms->instId;
fvid2_status = Fvid2_control(
prms->drvHandle, IOCTL_CSIRX_SET_DPHY_CONFIG,
&prms->dphyCfg, NULL);
if (FVID2_SOK != fvid2_status)
{
status = VX_FAILURE;
VX_PRINT(VX_ZONE_ERROR, ": Failed to set PHY Parameters!!!\r\n");
}
}
}
/* * * Copyright (c) 2018 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 "app_single_cam_main.h" #include <utils/iss/include/app_iss.h> #include "ldc_lut_1920x1080.h" static char availableSensorNames[ISS_SENSORS_MAX_SUPPORTED_SENSOR][ISS_SENSORS_MAX_NAME]; static vx_uint8 num_sensors_found; static IssSensor_CreateParams sensorParams; static uint8_t ldc_lut[] = LDC_LUT_1920_1080; #define LDC_TABLE_WIDTH (1920) #define LDC_TABLE_HEIGHT (1080) #define LDC_DS_FACTOR (2) #define LDC_BLOCK_WIDTH (64) #define LDC_BLOCK_HEIGHT (32) #define LDC_PIXEL_PAD (1) char *app_get_test_file_path() { char *tivxPlatformGetEnv(char *env_var); #if defined(SYSBIOS) return tivxPlatformGetEnv("VX_TEST_DATA_PATH"); #else return getenv("VX_TEST_DATA_PATH"); #endif } /* * Utility API used to add a graph parameter from a node, node parameter index */ 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(¶meter); } vx_status app_init(AppObj *obj) { vx_status status = VX_FAILURE; char* sensor_list[ISS_SENSORS_MAX_SUPPORTED_SENSOR]; vx_uint8 count = 0; char ch = 0xFF; vx_uint8 selectedSensor = 0xFF; obj->stop_task = 0; obj->stop_task_done = 0; obj->context = vxCreateContext(); APP_ASSERT_VALID_REF(obj->context); tivxHwaLoadKernels(obj->context); tivxImagingLoadKernels(obj->context); APP_PRINTF("tivxImagingLoadKernels done\n"); memset(availableSensorNames, 0, ISS_SENSORS_MAX_SUPPORTED_SENSOR*ISS_SENSORS_MAX_NAME); for(count=0;count<ISS_SENSORS_MAX_SUPPORTED_SENSOR;count++) { sensor_list[count] = availableSensorNames[count]; } status = appEnumerateImageSensor(sensor_list, &num_sensors_found); if(VX_SUCCESS != status) { printf("appCreateImageSensor returned %d\n", status); return status; } if(obj->is_interactive) { while(selectedSensor > (num_sensors_found-1)) { printf("%d sensor(s) found \n", num_sensors_found); printf("Supported sensor list: \n"); for(count=0;count<num_sensors_found;count++) { printf("%c : %s \n", count+'a', sensor_list[count]); } printf("Select a sensor \n"); ch = getchar(); printf("\n"); selectedSensor = ch - 'a'; if(selectedSensor > (num_sensors_found-1)) { printf("Invalid selection %c. Try again \n", ch); } } while ((ch != '0') && (ch != '1')) { fflush (stdin); printf ("LDC Selection Yes(1)/No(0)\n"); ch = getchar(); } obj->ldc_enable = ch - '0'; } else { selectedSensor = obj->sensor_sel; if(selectedSensor > (num_sensors_found-1)) { printf("Invalid sensor selection %d \n", selectedSensor); return VX_FAILURE; } } obj->sensor_name = sensor_list[selectedSensor]; printf("Sensor selected : %s\n", obj->sensor_name); obj->table_width = LDC_TABLE_WIDTH; obj->table_height = LDC_TABLE_HEIGHT; obj->ds_factor = LDC_DS_FACTOR; /* Display initialization */ memset(&obj->display_params, 0, sizeof(tivx_display_params_t)); obj->display_params.opMode = TIVX_KERNEL_DISPLAY_ZERO_BUFFER_COPY_MODE; obj->display_params.pipeId = 2; obj->display_params.outHeight = 1080; obj->display_params.outWidth = 1920; obj->display_params.posX = 0; obj->display_params.posY = 0; obj->scaler_enable = vx_false_e; appPerfPointSetName(&obj->total_perf , "TOTAL"); return status; } vx_status app_deinit(AppObj *obj) { vx_status status = VX_FAILURE; tivxHwaUnLoadKernels(obj->context); APP_PRINTF("tivxHwaUnLoadKernels done\n"); tivxImagingUnLoadKernels(obj->context); APP_PRINTF("tivxImagingUnLoadKernels done\n"); status = vxReleaseContext(&obj->context); if(VX_SUCCESS == status) { APP_PRINTF("vxReleaseContext done\n"); } else { printf("Error: vxReleaseContext returned 0x%x \n", status); } return status; } /* * Graph, * viss_config * | * v * input_img -> VISS -----> LDC -----> output_img * */ vx_status app_create_graph(AppObj *obj) { vx_status status = VX_SUCCESS; int32_t sensor_init_status = -1; obj->configuration = NULL; obj->raw = NULL; obj->y12 = NULL; obj->uv12_c1 = NULL; obj->y8_r8_c2 = NULL; obj->uv8_g8_c3 = NULL; obj->s8_b8_c4 = NULL; obj->histogram = NULL; obj->h3a_aew_af = NULL; unsigned int image_width = obj->width_in; unsigned int image_height = obj->height_in; uint32_t table_width, table_height; vx_imagepatch_addressing_t image_addr; vx_rectangle_t rect; int32_t dcc_buff_size; const vx_char dcc_2a_user_data_object_name[] = "dcc_2a"; vx_map_id dcc_2a_buf_map_id; uint8_t * dcc_2a_buf; const vx_char dcc_ldc_user_data_object_name[] = "dcc_ldc"; vx_map_id dcc_ldc_buf_map_id; uint8_t * dcc_ldc_buf; const vx_char dcc_viss_user_data_object_name[] = "dcc_viss"; uint8_t * dcc_viss_buf; vx_map_id dcc_viss_buf_map_id; tivx_raw_image raw_image = 0; vx_image not_raw_image = 0; vx_user_data_object capture_config; vx_uint8 num_capture_frames = 1; tivx_capture_params_t local_capture_config; uint32_t buf_id, loopCnt;//, loop_id, num_buf, loopCnt, frameIdx; const vx_char capture_user_data_object_name[] = "tivx_capture_params_t"; uint32_t sensor_features_enabled = 0; uint32_t sensor_features_supported = 0; uint32_t sensor_dcc_enabled = 0; uint32_t sensor_wdr_enabled = 0; uint32_t sensor_exp_control_enabled = 0; uint32_t sensor_gain_control_enabled = 0; vx_image display_image = NULL; #define Q_DEPTH 1 vx_graph_parameter_queue_params_t graph_parameters_queue_params_list[Q_DEPTH]; printf("Querying %s \n", obj->sensor_name); memset(&sensorParams, 0, sizeof(sensorParams)); status = appQueryImageSensor(obj->sensor_name, &sensorParams); if(VX_SUCCESS != status) { printf("appQueryImageSensor returned %d\n", status); return status; } /* Check for supported sensor features. It is upto the application to decide which features should be enabled. This demo app enables WDR, DCC and 2A if the sensor supports it. */ sensor_features_supported = sensorParams.sensorInfo.features; if(ISS_SENSOR_FEATURE_COMB_COMP_WDR_MODE == (sensor_features_supported & ISS_SENSOR_FEATURE_COMB_COMP_WDR_MODE)) { APP_PRINTF("WDR mode is supported \n"); sensor_features_enabled |= ISS_SENSOR_FEATURE_COMB_COMP_WDR_MODE; sensor_wdr_enabled = 1; }else { APP_PRINTF("WDR mode is not supported. Defaulting to linear \n"); sensor_features_enabled |= ISS_SENSOR_FEATURE_LINEAR_MODE; sensor_wdr_enabled = 0; } if(ISS_SENSOR_FEATURE_MANUAL_EXPOSURE == (sensor_features_supported & ISS_SENSOR_FEATURE_MANUAL_EXPOSURE)) { APP_PRINTF("Expsoure control is supported \n"); sensor_features_enabled |= ISS_SENSOR_FEATURE_MANUAL_EXPOSURE; sensor_exp_control_enabled = 1; } if(ISS_SENSOR_FEATURE_MANUAL_GAIN == (sensor_features_supported & ISS_SENSOR_FEATURE_MANUAL_GAIN)) { APP_PRINTF("Gain control is supported \n"); sensor_features_enabled |= ISS_SENSOR_FEATURE_MANUAL_GAIN; sensor_gain_control_enabled = 1; } if(ISS_SENSOR_FEATURE_CFG_UC1 == (sensor_features_supported & ISS_SENSOR_FEATURE_CFG_UC1)) { APP_PRINTF("CMS Usecase is supported \n"); sensor_features_enabled |= ISS_SENSOR_FEATURE_CFG_UC1; } switch(sensorParams.sensorInfo.aewbMode) { case ALGORITHMS_ISS_AEWB_MODE_NONE: obj->aewb_cfg.ae_mode = ALGORITHMS_ISS_AE_DISABLED; obj->aewb_cfg.awb_mode = ALGORITHMS_ISS_AWB_MANUAL; break; case ALGORITHMS_ISS_AEWB_MODE_AWB: obj->aewb_cfg.ae_mode = ALGORITHMS_ISS_AE_DISABLED; obj->aewb_cfg.awb_mode = ALGORITHMS_ISS_AWB_AUTO; break; case ALGORITHMS_ISS_AEWB_MODE_AE: obj->aewb_cfg.ae_mode = ALGORITHMS_ISS_AE_AUTO; obj->aewb_cfg.awb_mode = ALGORITHMS_ISS_AWB_MANUAL; break; case ALGORITHMS_ISS_AEWB_MODE_AEWB: obj->aewb_cfg.ae_mode = ALGORITHMS_ISS_AE_AUTO; obj->aewb_cfg.awb_mode = ALGORITHMS_ISS_AWB_AUTO; break; } if(obj->aewb_cfg.ae_mode == ALGORITHMS_ISS_AE_DISABLED) { if(sensor_exp_control_enabled || sensor_gain_control_enabled ) { obj->aewb_cfg.ae_mode = ALGORITHMS_ISS_AE_MANUAL; } } if(ISS_SENSOR_FEATURE_DCC_SUPPORTED == (sensor_features_supported & ISS_SENSOR_FEATURE_DCC_SUPPORTED)) { sensor_features_enabled |= ISS_SENSOR_FEATURE_DCC_SUPPORTED; sensor_dcc_enabled = 1; }else { sensor_dcc_enabled = 0; } APP_PRINTF("Sensor width = %d\n", sensorParams.sensorInfo.raw_params.width); APP_PRINTF("Sensor height = %d\n", sensorParams.sensorInfo.raw_params.height); APP_PRINTF("Sensor DCC ID = %d\n", sensorParams.dccId); APP_PRINTF("Sensor Supported Features = 0x%x\n", sensor_features_supported); APP_PRINTF("Sensor Enabled Features = 0x%x\n", sensor_features_enabled); sensor_init_status = appInitImageSensor(obj->sensor_name, sensor_features_enabled, 0x1);/*Mask = 1 for camera # 0*/ if(0 != sensor_init_status) { printf("Error initializing sensor %s \n", obj->sensor_name); return VX_FAILURE; } image_width = sensorParams.sensorInfo.raw_params.width; image_height = sensorParams.sensorInfo.raw_params.height; obj->cam_dcc_id = sensorParams.dccId; /* Assuming same dataformat for all exposures. This may not be true for staggered HDR. WIll be handled later for(count = 0;count<raw_params.num_exposures;count++) { memcpy(&(raw_params.format[count]), &(sensorProperties.sensorInfo.dataFormat), sizeof(tivx_raw_image_format_t)); } */ /* Sensor driver does not support metadata yet. */ APP_PRINTF("Creating graph \n"); obj->graph = vxCreateGraph(obj->context); APP_ASSERT_VALID_REF(obj->graph); APP_ASSERT(vx_true_e == tivxIsTargetEnabled(TIVX_TARGET_VPAC_VISS1)); APP_PRINTF("Initializing params for capture node \n"); /* Setting to num buf of capture node */ APP_PRINTF("Initializing params for capture node \n"); //raw_image = tivxCreateRawImage(obj->context, &sensorParams.sensorInfo.raw_params); not_raw_image = vxCreateImage( obj->context, image_width, image_height, VX_DF_IMAGE_RGBX ); APP_ASSERT_VALID_REF( not_raw_image ); obj->num_cap_buf = NUM_BUFS; /* allocate Input and Output refs, multiple refs created to allow pipelining of graph */ for(buf_id=0; buf_id<obj->num_cap_buf; buf_id++) { // obj->cap_frames[buf_id] = vxCreateObjectArray(obj->context, (vx_reference)raw_image, num_capture_frames); obj->cap_frames[buf_id] = vxCreateObjectArray(obj->context, (vx_reference)not_raw_image, num_capture_frames); } /* Config initialization */ tivx_capture_params_init(&local_capture_config); local_capture_config.enableCsiv2p0Support = (uint32_t)vx_true_e; local_capture_config.numDataLanes = sensorParams.sensorInfo.numDataLanes; APP_PRINTF("local_capture_config.numDataLanes = %d \n", local_capture_config.numDataLanes); for (loopCnt = 0U; loopCnt < local_capture_config.numDataLanes; loopCnt++) { local_capture_config.dataLanesMap[loopCnt] = sensorParams.sensorInfo.dataLanesMap[loopCnt]; APP_PRINTF("local_capture_config.dataLanesMap[%d] = %d \n", loopCnt, local_capture_config.dataLanesMap[loopCnt]); } capture_config = vxCreateUserDataObject(obj->context, capture_user_data_object_name, sizeof(tivx_capture_params_t), &local_capture_config); APP_PRINTF("capture_config = 0x%p \n", capture_config); APP_PRINTF("Creating capture node \n"); obj->capture_node = tivxCaptureNode(obj->graph, capture_config, obj->cap_frames[0]); APP_ASSERT_VALID_REF( obj->capture_node ); APP_PRINTF("obj->capture_node = 0x%p \n", obj->capture_node); vxReleaseUserDataObject(&capture_config); vxSetNodeTarget(obj->capture_node, VX_TARGET_STRING, TIVX_TARGET_CAPTURE1); //obj->raw = (tivx_raw_image)vxGetObjectArrayItem(obj->cap_frames[0], 0); obj->not_raw = (vx_image)vxGetObjectArrayItem(obj->cap_frames[0], 0); //tivxReleaseRawImage(&raw_image); vxReleaseImage( ¬_raw_image ); if ( sensor_dcc_enabled ) { printf( " sensor dcc enabled \n" ); } if ( sensor_wdr_enabled ) { printf( " sensor wdr enabled \n" ); } #if 0 ///========================================================================= // VISS Node ///========================================================================= obj->num_viss_out_buf = 3; obj->y8_r8_c2 = vxCreateImage(obj->context, image_width, image_height, VX_DF_IMAGE_NV12/*VX_DF_IMAGE_U8*/); obj->uv8_g8_c3 = NULL; obj->y12 = vxCreateImage(obj->context, image_width, image_height, VX_DF_IMAGE_U16); obj->uv12_c1 = vxCreateImage(obj->context, image_width, image_height/2, VX_DF_IMAGE_U16); obj->s8_b8_c4 = vxCreateImage(obj->context, image_width, image_height, VX_DF_IMAGE_U8); obj->histogram = vxCreateDistribution(obj->context, 256, 0, 256); /* VISS Initialize parameters */ tivx_vpac_viss_params_init(&obj->viss_params); obj->viss_params.sensor_dcc_id = obj->cam_dcc_id; obj->viss_params.ee_mode = 0; obj->viss_params.mux_output0 = 0; obj->viss_params.mux_output1 = 0; obj->viss_params.mux_output2 = 4; obj->viss_params.mux_output3 = 0; obj->viss_params.mux_output4 = 3; obj->viss_params.h3a_in = 3; obj->viss_params.h3a_aewb_af_mode = 0; obj->viss_params.chroma_mode = 0; if(sensor_wdr_enabled == 1) { obj->viss_params.bypass_glbce = 0; }else { obj->viss_params.bypass_glbce = 1; } obj->viss_params.bypass_nsf4 = 1; obj->configuration = vxCreateUserDataObject(obj->context, "tivx_vpac_viss_params_t", sizeof(tivx_vpac_viss_params_t), &obj->viss_params); /* Create h3a_aew_af output buffer (uninitialized) */ obj->h3a_aew_af = vxCreateUserDataObject(obj->context, "tivx_h3a_data_t", sizeof(tivx_h3a_data_t), NULL); if(sensor_dcc_enabled) { dcc_buff_size = appIssGetDCCSizeVISS(obj->sensor_name, sensor_wdr_enabled); if(dcc_buff_size<0) { printf("Invalid DCC size for VISS \n"); return VX_FAILURE; } obj->dcc_param_viss = vxCreateUserDataObject( obj->context, (const vx_char*)&dcc_viss_user_data_object_name, dcc_buff_size, NULL ); vxMapUserDataObject( obj->dcc_param_viss, 0, dcc_buff_size, &dcc_viss_buf_map_id, (void **)&dcc_viss_buf, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST, 0 ); status = appIssGetDCCBuffVISS(obj->sensor_name, sensor_wdr_enabled, dcc_viss_buf, dcc_buff_size); if(status != VX_SUCCESS) { printf("Error getting VISS DCC buffer \n"); return VX_FAILURE; } vxUnmapUserDataObject(obj->dcc_param_viss, dcc_viss_buf_map_id); }else { obj->dcc_param_viss = NULL; } obj->ae_awb_result = vxCreateUserDataObject(obj->context, "tivx_ae_awb_params_t", sizeof(tivx_ae_awb_params_t), NULL); if (vxGetStatus((vx_reference)obj->ae_awb_result) != VX_SUCCESS) { APP_PRINTF("obj->ae_awb_result) create failed\n"); return VX_FAILURE; } obj->delay_2a_res = vxCreateDelay(obj->context, (vx_reference)(obj->ae_awb_result), 2); if (vxGetStatus((vx_reference)obj->delay_2a_res) != VX_SUCCESS) { APP_PRINTF("obj->delay_2a_res create failed\n"); return VX_FAILURE; } obj->node_viss = tivxVpacVissNode( obj->graph, obj->configuration, (vx_user_data_object)vxGetReferenceFromDelay(obj->delay_2a_res, -1), obj->dcc_param_viss, obj->raw, NULL, NULL, obj->y8_r8_c2, NULL, NULL, obj->h3a_aew_af, NULL ); vxSetReferenceName((vx_reference)obj->node_viss, "VISS_Processing"); vxSetNodeTarget(obj->node_viss, VX_TARGET_STRING, TIVX_TARGET_VPAC_VISS1); //***************************************************************** // Set number of buffers to allocate at output of a node parameter. //***************************************************************** tivxSetNodeParameterNumBufByIndex(obj->node_viss, 6u, obj->num_cap_buf); APP_PRINTF("VISS Set Reference done\n"); ///=============================================================================== /// AewbNode tivxAewbNode ///=============================================================================== obj->aewb_cfg.sensor_dcc_id = obj->cam_dcc_id; obj->aewb_cfg.sensor_img_format = 0; obj->aewb_cfg.sensor_img_phase = 3; obj->aewb_cfg.awb_num_skip_frames = 0; obj->aewb_cfg.ae_num_skip_frames = 0; obj->aewb_cfg.channel_id = 0; obj->aewb_config = vxCreateUserDataObject(obj->context, "tivx_aewb_config_t", sizeof(tivx_aewb_config_t), &obj->aewb_cfg); if(sensor_dcc_enabled) { dcc_buff_size = appIssGetDCCSize2A(obj->sensor_name, sensor_wdr_enabled); if(dcc_buff_size<0) { printf("Invalid DCC size for 2A \n"); return VX_FAILURE; } obj->dcc_param_2a = vxCreateUserDataObject( obj->context, (const vx_char*)&dcc_2a_user_data_object_name, dcc_buff_size, NULL ); vxMapUserDataObject( obj->dcc_param_2a, 0, dcc_buff_size, &dcc_2a_buf_map_id, (void **)&dcc_2a_buf, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST, 0 ); status = appIssGetDCCBuff2A(obj->sensor_name, sensor_wdr_enabled, dcc_2a_buf, dcc_buff_size); if(status != VX_SUCCESS) { printf("Error getting 2A DCC buffer \n"); return VX_FAILURE; } vxUnmapUserDataObject(obj->dcc_param_2a, dcc_2a_buf_map_id); }else { obj->dcc_param_2a = NULL; } obj->node_aewb = tivxAewbNode(obj->graph, obj->aewb_config, obj->histogram, obj->h3a_aew_af, (vx_user_data_object)vxGetReferenceFromDelay(obj->delay_2a_res, -1), (vx_user_data_object)vxGetReferenceFromDelay(obj->delay_2a_res, 0), obj->dcc_param_2a); vxSetNodeTarget(obj->node_aewb, VX_TARGET_STRING, TIVX_TARGET_IPU1_0); tivxSetNodeParameterNumBufByIndex(obj->node_aewb, 4u, NUM_BUFS); if(NULL != obj->node_aewb) vxSetReferenceName((vx_reference)obj->node_aewb, "2A_AlgNode"); else { APP_PRINTF("tivxAewbNode returned NULL \n"); return VX_FAILURE; } APP_PRINTF("AEWB Set Reference done\n"); ///==================================================================== // if ldc enabled create a tivxVpacLdcNode ///==================================================================== if (obj->ldc_enable) { printf ("Enabling LDC \n"); obj->dcc_param_ldc = NULL; if (1 == sensor_dcc_enabled) { dcc_buff_size = appIssGetDCCSizeLDC(obj->sensor_name, sensor_wdr_enabled); if (dcc_buff_size > 0) { obj->dcc_param_ldc = vxCreateUserDataObject( obj->context, (const vx_char*)&dcc_ldc_user_data_object_name, dcc_buff_size, NULL ); vxMapUserDataObject( obj->dcc_param_ldc, 0, dcc_buff_size, &dcc_ldc_buf_map_id, (void **)&dcc_ldc_buf, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST, 0 ); status = appIssGetDCCBuffLDC(obj->sensor_name, sensor_wdr_enabled, dcc_ldc_buf, dcc_buff_size); if(status != VX_SUCCESS) { printf("Error getting LDC DCC buffer \n"); return VX_FAILURE; } vxUnmapUserDataObject(obj->dcc_param_ldc, dcc_ldc_buf_map_id); } } table_width = (((obj->table_width / (1 << obj->ds_factor)) + 1u) + 15u) & (~15u); table_height = ((obj->table_height / (1 << obj->ds_factor)) + 1u); /* Mesh Image */ obj->mesh_img = vxCreateImage(obj->context, table_width, table_height, VX_DF_IMAGE_U32); /* Copy Mesh table */ rect.start_x = 0; rect.start_y = 0; rect.end_x = table_width; rect.end_y = table_height; image_addr.dim_x = table_width; image_addr.dim_y = table_height; image_addr.stride_x = 4u; image_addr.stride_y = table_width * 4u; status = vxCopyImagePatch(obj->mesh_img, &rect, 0, &image_addr, ldc_lut, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST); if (VX_SUCCESS != status) { APP_PRINTF("Copy Image Failed\n"); return VX_FAILURE; } /* LDC Output image in NV12 format */ obj->ldc_out = vxCreateImage(obj->context, /*image_width*/obj->table_width, /*image_height*/obj->table_height, VX_DF_IMAGE_NV12); /* Mesh Parameters */ obj->mesh_params_obj = vxCreateUserDataObject(obj->context, "tivx_vpac_ldc_mesh_params_t", sizeof(tivx_vpac_ldc_mesh_params_t), NULL); memset(&obj->mesh_params, 0, sizeof(tivx_vpac_ldc_mesh_params_t)); tivx_vpac_ldc_mesh_params_init(&obj->mesh_params); obj->mesh_params.mesh_frame_width = obj->table_width; obj->mesh_params.mesh_frame_height = obj->table_height; obj->mesh_params.subsample_factor = obj->ds_factor; vxCopyUserDataObject(obj->mesh_params_obj, 0, sizeof(tivx_vpac_ldc_mesh_params_t), &obj->mesh_params, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST); /* Block Size parameters */ obj->region_params_obj = vxCreateUserDataObject(obj->context, "tivx_vpac_ldc_region_params_t", sizeof(tivx_vpac_ldc_region_params_t), NULL); obj->region_params.out_block_width = LDC_BLOCK_WIDTH; obj->region_params.out_block_height = LDC_BLOCK_HEIGHT; obj->region_params.pixel_pad = LDC_PIXEL_PAD; vxCopyUserDataObject(obj->region_params_obj, 0, sizeof(tivx_vpac_ldc_region_params_t), &obj->region_params, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST); /* LDC Configuration */ tivx_vpac_ldc_params_init(&obj->ldc_params); obj->ldc_params.luma_interpolation_type = 1; obj->ldc_params.dcc_camera_id = obj->cam_dcc_id; obj->ldc_param_obj = vxCreateUserDataObject(obj->context, "tivx_vpac_ldc_params_t", sizeof(tivx_vpac_ldc_params_t), NULL); vxCopyUserDataObject(obj->ldc_param_obj, 0, sizeof(tivx_vpac_ldc_params_t), &obj->ldc_params, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST); if (NULL == obj->dcc_param_ldc) { /* obj->node_ldc = tivxVpacLdcNode(obj->graph, obj->ldc_param_obj, NULL, obj->region_params_obj, obj->mesh_params_obj, obj->mesh_img, NULL, obj->y8_r8_c2, obj->ldc_out, NULL); */ obj->node_ldc = tivxVpacLdcNode(obj->graph, obj->ldc_param_obj, NULL, obj->region_params_obj, obj->mesh_params_obj, obj->mesh_img, NULL, obj->not_raw, obj->ldc_out, NULL); } else { /* obj->node_ldc = tivxVpacLdcNode(obj->graph, obj->ldc_param_obj, NULL, NULL, NULL, NULL, obj->dcc_param_ldc, obj->y8_r8_c2, obj->ldc_out, NULL); */ obj->node_ldc = tivxVpacLdcNode(obj->graph, obj->ldc_param_obj, NULL, NULL, NULL, NULL, obj->dcc_param_ldc, obj->not_raw, obj->ldc_out, NULL); } vxSetReferenceName((vx_reference)obj->node_ldc, "LDC_Processing"); vxSetNodeTarget(obj->node_ldc, VX_TARGET_STRING, TIVX_TARGET_VPAC_LDC1); tivxSetNodeParameterNumBufByIndex(obj->node_ldc, 7u, obj->num_cap_buf); if((obj->table_width != obj->display_params.outWidth) || (obj->table_height != obj->display_params.outHeight)) { vx_uint16 scaler_out_w, scaler_out_h; obj->scaler_enable = vx_true_e; appIssGetResizeParams(obj->table_width, obj->table_height, obj->display_params.outWidth, obj->display_params.outHeight, &scaler_out_w, &scaler_out_h); obj->scaler_out_img = vxCreateImage(obj->context, scaler_out_w, scaler_out_h, VX_DF_IMAGE_NV12); // ================================= // scale the display image // ================================= obj->scalerNode = tivxVpacMscScaleNode(obj->graph, obj->ldc_out, obj->scaler_out_img, NULL, NULL, NULL, NULL); tivxSetNodeParameterNumBufByIndex(obj->scalerNode, 1u, obj->num_cap_buf); obj->display_params.outHeight = scaler_out_h; obj->display_params.outWidth = scaler_out_w; display_image = obj->scaler_out_img; }else /**/ { obj->scaler_enable = vx_false_e; display_image = obj->ldc_out; } } else /*ldc_enable*/ { if((image_width != obj->display_params.outWidth) || (image_height != obj->display_params.outHeight)) { vx_uint16 scaler_out_w, scaler_out_h; obj->scaler_enable = vx_true_e; appIssGetResizeParams(image_width, image_height, obj->display_params.outWidth, obj->display_params.outHeight, &scaler_out_w, &scaler_out_h); obj->scaler_out_img = vxCreateImage(obj->context, scaler_out_w, scaler_out_h, VX_DF_IMAGE_NV12); // ================================= // scale the display image // ================================= // obj->scalerNode = tivxVpacMscScaleNode(obj->graph, obj->y8_r8_c2, obj->scaler_out_img, NULL, NULL, NULL, NULL); obj->scalerNode = tivxVpacMscScaleNode(obj->graph, obj->not_raw, obj->scaler_out_img, NULL, NULL, NULL, NULL); tivxSetNodeParameterNumBufByIndex(obj->scalerNode, 1u, obj->num_cap_buf); vxSetNodeTarget(obj->scalerNode, VX_TARGET_STRING, TIVX_TARGET_VPAC_MSC1); obj->display_params.outHeight = scaler_out_h; obj->display_params.outWidth = scaler_out_w; display_image = obj->scaler_out_img; }else { obj->scaler_enable = vx_false_e; // =============================================== // Here is the display image // =============================================== // display_image = obj->y8_r8_c2; display_image = obj->not_raw; } } #endif display_image = obj->not_raw; if(NULL == display_image) { printf("Error : Display input is uninitialized \n"); return VX_FAILURE; } else { obj->display_params.posX = (1920U - obj->display_params.outWidth)/2; obj->display_params.posY = (1080U - obj->display_params.outHeight)/2; obj->display_param_obj = vxCreateUserDataObject(obj->context, "tivx_display_params_t", sizeof(tivx_display_params_t), &obj->display_params); obj->displayNode = tivxDisplayNode(obj->graph, obj->display_param_obj, display_image); } vxSetNodeTarget(obj->displayNode, VX_TARGET_STRING, TIVX_TARGET_DISPLAY1); APP_PRINTF("Display Set Target done\n"); int graph_parameter_num = 0; /* input @ node index 1, becomes graph parameter 0 */ add_graph_parameter_by_node_index(obj->graph, obj->capture_node, 1); /* set graph schedule config such that graph parameter @ index 0 is enqueuable */ graph_parameters_queue_params_list[graph_parameter_num].graph_parameter_index = 0; graph_parameters_queue_params_list[graph_parameter_num].refs_list_size = obj->num_cap_buf; graph_parameters_queue_params_list[graph_parameter_num].refs_list = (vx_reference*)&(obj->cap_frames[0]); graph_parameter_num++; tivxSetGraphPipelineDepth(obj->graph, obj->num_cap_buf); /* Schedule mode auto is used, here we dont need to call vxScheduleGraph * Graph gets scheduled automatically as refs are enqueued to it */ vxSetGraphScheduleConfig(obj->graph, VX_GRAPH_SCHEDULE_MODE_QUEUE_AUTO, Q_DEPTH, graph_parameters_queue_params_list ); APP_PRINTF("vxSetGraphScheduleConfig done\n"); status = vxVerifyGraph(obj->graph); APP_ASSERT(status==VX_SUCCESS); #if 0 if(vx_true_e == obj->scaler_enable) { tivx_vpac_msc_coefficients_t sc_coeffs; vx_reference refs[1]; printf("Scaler is enabled\n"); tivx_vpac_msc_coefficients_params_init(&sc_coeffs); obj->sc_coeff_obj = vxCreateUserDataObject(obj->context, "tivx_vpac_msc_coefficients_t", sizeof(tivx_vpac_msc_coefficients_t), NULL); vxCopyUserDataObject(obj->sc_coeff_obj, 0, sizeof(tivx_vpac_msc_coefficients_t), &sc_coeffs, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST); refs[0] = (vx_reference)obj->sc_coeff_obj; tivxNodeSendCommand(obj->scalerNode, 0u, TIVX_VPAC_MSC_CMD_SET_COEFF, refs, 1u); } else { printf("Scaler is disabled\n"); } #endif tivxExportGraphToDot(obj->graph, ".", "single_cam_graph"); APP_PRINTF("app_create_graph exiting\n"); return status; } vx_status app_delete_graph(AppObj *obj) { uint32_t buf_id; vx_status status = VX_SUCCESS; if(NULL != obj->capture_node) { APP_PRINTF("releasing capture node\n"); status |= vxReleaseNode(&obj->capture_node); } if(NULL != obj->node_viss) { APP_PRINTF("releasing node_viss\n"); status |= vxReleaseNode(&obj->node_viss); } if(NULL != obj->node_aewb) { APP_PRINTF("releasing node_aewb\n"); status |= vxReleaseNode(&obj->node_aewb); } if(NULL != obj->displayNode) { APP_PRINTF("releasing displayNode\n"); status |= vxReleaseNode(&obj->displayNode); } status |= tivxReleaseRawImage(&obj->raw); APP_PRINTF("releasing raw image done\n"); for(buf_id=0; buf_id<obj->num_cap_buf; buf_id++) { if(NULL != obj->cap_frames[buf_id]) { APP_PRINTF("releasing cap_frame # %d\n", buf_id); status |= vxReleaseObjectArray(&(obj->cap_frames[buf_id])); } } for(buf_id=0; buf_id<obj->num_viss_out_buf; buf_id++) { if(NULL != obj->viss_out_luma[buf_id]) { APP_PRINTF("releasing y8 buffer # %d\n", buf_id); status |= vxReleaseImage(&(obj->viss_out_luma[buf_id])); } } if(NULL != obj->y12) { APP_PRINTF("releasing y12\n"); status |= vxReleaseImage(&obj->y12); } if(NULL != obj->uv12_c1) { APP_PRINTF("releasing uv12_c1\n"); status |= vxReleaseImage(&obj->uv12_c1); } if(NULL != obj->s8_b8_c4) { APP_PRINTF("releasing s8_b8_c4\n"); status |= vxReleaseImage(&obj->s8_b8_c4); } if(NULL != obj->y8_r8_c2) { APP_PRINTF("releasing y8_r8_c2\n"); status |= vxReleaseImage(&obj->y8_r8_c2); } if(NULL != obj->uv8_g8_c3) { APP_PRINTF("releasing uv8_g8_c3\n"); status |= vxReleaseImage(&obj->uv8_g8_c3); } if(NULL != obj->histogram) { APP_PRINTF("releasing histogram\n"); status |= vxReleaseDistribution(&obj->histogram); } if(NULL != obj->configuration) { APP_PRINTF("releasing configuration\n"); status |= vxReleaseUserDataObject(&obj->configuration); } if (NULL != obj->delay_2a_res) { status |= vxReleaseDelay(&obj->delay_2a_res); } if (NULL != obj->ae_awb_result) { status |= vxReleaseUserDataObject(&obj->ae_awb_result); APP_PRINTF("releasing ae_awb_result done\n"); } if(NULL != obj->h3a_aew_af) { APP_PRINTF("releasing h3a_aew_af\n"); status |= vxReleaseUserDataObject(&obj->h3a_aew_af); } if(NULL != obj->aewb_config) { APP_PRINTF("releasing aewb_config\n"); status |= vxReleaseUserDataObject(&obj->aewb_config); } if(NULL != obj->dcc_param_viss) { APP_PRINTF("releasing VISS DCC Data Object\n"); status |= vxReleaseUserDataObject(&obj->dcc_param_viss); } if(NULL != obj->display_param_obj) { APP_PRINTF("releasing Display Param Data Object\n"); status |= vxReleaseUserDataObject(&obj->display_param_obj); } if(NULL != obj->dcc_param_2a) { APP_PRINTF("releasing 2A DCC Data Object\n"); status |= vxReleaseUserDataObject(&obj->dcc_param_2a); } if(NULL != obj->dcc_param_ldc) { APP_PRINTF("releasing LDC DCC Data Object\n"); status |= vxReleaseUserDataObject(&obj->dcc_param_ldc); } if (obj->ldc_enable) { if (NULL != obj->mesh_img) { APP_PRINTF("releasing LDC Mesh Image \n"); status |= vxReleaseImage(&obj->mesh_img); } if (NULL != obj->ldc_out) { APP_PRINTF("releasing LDC Output Image \n"); status |= vxReleaseImage(&obj->ldc_out); } if (NULL != obj->mesh_params_obj) { APP_PRINTF("releasing LDC Mesh Parameters Object\n"); status |= vxReleaseUserDataObject(&obj->mesh_params_obj); } if (NULL != obj->ldc_param_obj) { APP_PRINTF("releasing LDC Parameters Object\n"); status |= vxReleaseUserDataObject(&obj->ldc_param_obj); } if (NULL != obj->region_params_obj) { APP_PRINTF("releasing LDC Region Parameters Object\n"); status |= vxReleaseUserDataObject(&obj->region_params_obj); } if(NULL != obj->node_ldc) { APP_PRINTF("releasing LDC Node \n"); status |= vxReleaseNode(&obj->node_ldc); } } if(vx_true_e == obj->scaler_enable) { if (NULL != obj->scaler_out_img) { APP_PRINTF("releasing Scaler Output Image \n"); status |= vxReleaseImage(&obj->scaler_out_img); } if(NULL != obj->scalerNode) { APP_PRINTF("releasing Scaler Node \n"); status |= vxReleaseNode(&obj->scalerNode); } if (NULL != obj->sc_coeff_obj) { APP_PRINTF("release Scalar coefficient data object \n"); status |= vxReleaseUserDataObject(&obj->sc_coeff_obj); } } APP_PRINTF("releasing graph\n"); status |= vxReleaseGraph(&obj->graph); APP_PRINTF("releasing graph done\n"); return status; } vx_status app_run_graph(AppObj *obj) { vx_status status = VX_SUCCESS; vx_uint32 i; vx_uint32 frm_loop_cnt; uint32_t buf_id; uint32_t num_refs_capture; vx_object_array out_capture_frames; int graph_parameter_num = 0; if(NULL == obj->sensor_name) { printf("sensor name is NULL \n"); return VX_FAILURE; } status = appStartImageSensor(obj->sensor_name, 0x1); /* Enqueue buf for pipe up but don't trigger graph execution */ for(buf_id=0; buf_id<obj->num_cap_buf-1; buf_id++) { graph_parameter_num = 0; tivxGraphParameterEnqueueReadyRef(obj->graph, graph_parameter_num, (vx_reference*)&(obj->cap_frames[buf_id]), 1, TIVX_GRAPH_PARAMETER_ENQUEUE_FLAG_PIPEUP); graph_parameter_num++; } graph_parameter_num = 0; /* Need to trigger again since display holds on to a buffer */ vxGraphParameterEnqueueReadyRef(obj->graph, graph_parameter_num, (vx_reference*)&obj->cap_frames[obj->num_cap_buf-1], 1); graph_parameter_num++; /* The application reads and processes the same image "frm_loop_cnt" times The output may change because on VISS, parameters are updated every frame based on AEWB results AEWB result is avaialble after 1 frame and is applied after 2 frames Therefore, first 2 output images will have wrong colors */ frm_loop_cnt = obj->num_frames_to_run; frm_loop_cnt += obj->num_cap_buf; if(obj->is_interactive) { /* in interactive mode loop for ever */ frm_loop_cnt = 0xFFFFFFFF; } for(i=0; i<frm_loop_cnt; i++) { appPerfPointBegin(&obj->total_perf); graph_parameter_num = 0; vxGraphParameterDequeueDoneRef(obj->graph, graph_parameter_num, (vx_reference*)&out_capture_frames, 1, &num_refs_capture); graph_parameter_num++; APP_PRINTF(" frm_loop_cnt %d...\n", i); graph_parameter_num = 0; vxGraphParameterEnqueueReadyRef(obj->graph, graph_parameter_num, (vx_reference*)&out_capture_frames, 1); graph_parameter_num++; appPerfPointEnd(&obj->total_perf); if(obj->stop_task) { break; } } vxWaitGraph(obj->graph); /* Dequeue buf for pipe down */ for(buf_id=0; buf_id<obj->num_cap_buf-2; buf_id++) { APP_PRINTF(" Dequeuing capture # %d...\n", buf_id); graph_parameter_num = 0; vxGraphParameterDequeueDoneRef(obj->graph, graph_parameter_num, (vx_reference*)&out_capture_frames, 1, &num_refs_capture); graph_parameter_num++; } status = appStopImageSensor(obj->sensor_name); return status; } static void app_run_task(void *app_var) { AppObj *obj = (AppObj *)app_var; appPerfStatsCpuLoadResetAll(); app_run_graph(obj); obj->stop_task_done = 1; } static int32_t app_run_task_create(AppObj *obj) { tivx_task_create_params_t params; int32_t status; tivxTaskSetDefaultCreateParams(¶ms); params.task_main = app_run_task; params.app_var = obj; obj->stop_task_done = 0; obj->stop_task = 0; status = tivxTaskCreate(&obj->task, ¶ms); return status; } static void app_run_task_delete(AppObj *obj) { while(obj->stop_task_done==0) { tivxTaskWaitMsecs(100); } tivxTaskDelete(&obj->task); } static char menu[] = { "\n" "\n ==========================" "\n Demo : Single Camera w/ 2A" "\n ==========================" "\n" "\n p: Print performance statistics" "\n" #ifdef _APP_DEBUG_ "\n s: Save Sensor RAW, VISS Output and H3A output images to File System" "\n" #endif "\n e: Export performance statistics" "\n" "\n x: Exit" "\n" "\n Enter Choice: " }; 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!=0) { printf("ERROR: Unable to create task\n"); } else { while(!done) { printf(menu); ch = getchar(); printf("\n"); switch(ch) { case 'p': appPerfStatsPrintAll(); tivx_utils_graph_perf_print(obj->graph); appPerfPointPrint(&obj->total_perf); printf("\n"); appPerfPointPrintFPS(&obj->total_perf); printf("\n"); break; #ifdef _APP_DEBUG_ case 's': save_debug_images(obj); break; #endif case 'e': perf_arr[0] = &obj->total_perf; fp = appPerfStatsExportOpenFile(".", "apps_basic_demos_single_camera"); if (NULL != fp) { appPerfStatsExportAll(fp, perf_arr, 1); tivx_utils_graph_perf_export(fp, obj->graph); appPerfStatsExportCloseFile(fp); appPerfStatsResetAll(); } else { printf("fp is null\n"); } break; case 'x': obj->stop_task = 1; done = 1; break; } } app_run_task_delete(obj); } status = appStopImageSensor(obj->sensor_name); return status; } static void app_show_usage(int argc, char* argv[]) { printf("\n"); printf(" Single Camera Demo - (c) Texas Instruments 2019\n"); printf(" ========================================================\n"); printf("\n"); printf(" Usage,\n"); printf(" %s --cfg <config file>\n", argv[0]); printf("\n"); } #ifdef _APP_DEBUG_ #define MAX_FNAME 128 vx_status save_debug_images(AppObj *obj) { int num_bytes_io = 0; static int file_index = 0; char raw_image_fname[MAX_FNAME]; char yuv_image_fname[MAX_FNAME]; char h3a_image_fname[MAX_FNAME]; char failsafe_test_data_path[3] = "./"; char * test_data_path = app_get_test_file_path(); if(NULL == test_data_path) { printf("Test data path is NULL. Defaulting to current folder \n"); test_data_path = failsafe_test_data_path; } snprintf(raw_image_fname, MAX_FNAME, "%s/%s_%04d.raw", test_data_path, "img", file_index); printf("RAW file name %s \n", raw_image_fname); num_bytes_io = write_output_image_raw(raw_image_fname, obj->raw); if(num_bytes_io < 0) { printf("Error writing to RAW file \n"); return VX_FAILURE; } snprintf(yuv_image_fname, MAX_FNAME, "%s/%s_%04d.yuv", test_data_path, "img_viss", file_index); printf("YUV file name %s \n", yuv_image_fname); num_bytes_io = write_output_image_nv12_8bit(yuv_image_fname, obj->y8_r8_c2); if(num_bytes_io < 0) { printf("Error writing to VISS NV12 file \n"); return VX_FAILURE; } if(obj->scaler_enable) { snprintf(yuv_image_fname, MAX_FNAME, "%s/%s_%04d.yuv", test_data_path, "img_msc", file_index); printf("YUV file name %s \n", yuv_image_fname); num_bytes_io = write_output_image_nv12_8bit(yuv_image_fname, obj->scaler_out_img); if(num_bytes_io < 0) { printf("Error writing to MSC NV12 file \n"); return VX_FAILURE; } } if(obj->ldc_enable) { snprintf(yuv_image_fname, MAX_FNAME, "%s/%s_%04d.yuv", test_data_path, "img_ldc", file_index); printf("YUV file name %s \n", yuv_image_fname); num_bytes_io = write_output_image_nv12_8bit(yuv_image_fname, obj->ldc_out); if(num_bytes_io < 0) { printf("Error writing to LDC NV12 file \n"); return VX_FAILURE; } } snprintf(h3a_image_fname, MAX_FNAME, "%s/%s_%04d.bin", test_data_path, "h3a", file_index); printf("H3A file name %s \n", h3a_image_fname); num_bytes_io = write_h3a_image(h3a_image_fname, obj->h3a_aew_af); if(num_bytes_io < 0) { printf("Error writing to H3A file \n"); return VX_FAILURE; } file_index++; return VX_SUCCESS; } vx_int32 write_output_image_fp(FILE * fp, vx_image out_image) { vx_uint32 width, height; vx_df_image df; vx_imagepatch_addressing_t image_addr; vx_rectangle_t rect; vx_map_id map_id1, map_id2; void *data_ptr1, *data_ptr2; vx_uint32 num_bytes_per_pixel = 1; vx_uint32 num_luma_bytes_written_to_file, num_chroma_bytes_written_to_file, num_bytes_written_to_file; vxQueryImage(out_image, VX_IMAGE_WIDTH, &width, sizeof(vx_uint32)); vxQueryImage(out_image, VX_IMAGE_HEIGHT, &height, sizeof(vx_uint32)); vxQueryImage(out_image, VX_IMAGE_FORMAT, &df, sizeof(vx_df_image)); printf("out width = %d\n", width); printf("out height = %d\n", height); printf("out format = %d\n", df); rect.start_x = 0; rect.start_y = 0; rect.end_x = width; rect.end_y = height; vxMapImagePatch(out_image, &rect, 0, &map_id1, &image_addr, &data_ptr1, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST, VX_NOGAP_X ); if(!data_ptr1) { printf("data_ptr1 is NULL \n"); fclose(fp); return -1; } num_luma_bytes_written_to_file = fwrite(data_ptr1, 1, width*height*num_bytes_per_pixel, fp); fflush(fp); vxMapImagePatch(out_image, &rect, 1, &map_id2, &image_addr, &data_ptr2, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST, VX_NOGAP_X ); if(!data_ptr2) { printf("data_ptr2 is NULL \n"); fclose(fp); return -1; } num_chroma_bytes_written_to_file = fwrite(data_ptr2, 1, width*(height/2)*num_bytes_per_pixel, fp); fflush(fp); num_bytes_written_to_file = num_luma_bytes_written_to_file + num_chroma_bytes_written_to_file; vxUnmapImagePatch(out_image, map_id1); vxUnmapImagePatch(out_image, map_id2); return num_bytes_written_to_file; } vx_int32 write_output_image_nv12_8bit(char * file_name, vx_image out_nv12) { FILE * fp = fopen(file_name, "wb"); if(!fp) { APP_PRINTF("Unable to open file %s\n", file_name); return -1; } vx_uint32 len1 = write_output_image_fp(fp, out_nv12); fclose(fp); APP_PRINTF("%d bytes written to %s\n", len1, file_name); return len1; } vx_int32 write_output_image_raw(char * file_name, tivx_raw_image raw_image) { FILE * fp = fopen(file_name, "wb"); vx_uint32 width, height; vx_imagepatch_addressing_t image_addr; vx_rectangle_t rect; vx_map_id map_id; void *data_ptr; vx_uint32 num_bytes_per_pixel = 2; /*Mayank : Hardcoded to 12b Unpacked format*/ vx_uint32 num_bytes_written_to_file; tivx_raw_image_format_t format; if(!fp) { APP_PRINTF("Unable to open file %s\n", file_name); return -1; } tivxQueryRawImage(raw_image, TIVX_RAW_IMAGE_WIDTH, &width, sizeof(vx_uint32)); tivxQueryRawImage(raw_image, TIVX_RAW_IMAGE_HEIGHT, &height, sizeof(vx_uint32)); tivxQueryRawImage(raw_image, TIVX_RAW_IMAGE_FORMAT, &format, sizeof(format)); APP_PRINTF("in width = %d\n", width); APP_PRINTF("in height = %d\n", height); APP_PRINTF("in format = %d\n", format.pixel_container); rect.start_x = 0; rect.start_y = 0; rect.end_x = width; rect.end_y = height; tivxMapRawImagePatch(raw_image, &rect, 0, &map_id, &image_addr, &data_ptr, VX_READ_ONLY, VX_MEMORY_TYPE_HOST, TIVX_RAW_IMAGE_PIXEL_BUFFER ); if(!data_ptr) { APP_PRINTF("data_ptr is NULL \n"); fclose(fp); return -1; } num_bytes_written_to_file = fwrite(data_ptr, 1, width*height*num_bytes_per_pixel, fp); fflush(fp); fclose(fp); APP_PRINTF("%d bytes written to %s\n", num_bytes_written_to_file, file_name); return num_bytes_written_to_file; } vx_int32 write_h3a_image(char * file_name, vx_user_data_object out_h3a) { FILE * fp = fopen(file_name, "wb"); tivx_h3a_data_t *h3a_data = NULL; vx_map_id h3a_buf_map_id; vx_uint8 *h3a_payload = NULL; vx_uint32 h3a_size = 0; if(!fp) { APP_PRINTF("Unable to open file %s\n", file_name); return -1; } vxMapUserDataObject( out_h3a, 0, sizeof(tivx_h3a_data_t), &h3a_buf_map_id, (void **)&h3a_data, VX_READ_ONLY, VX_MEMORY_TYPE_HOST, 0 ); h3a_payload = h3a_data->data;// + 12; /*C model 12-byte header*/ h3a_size = fwrite(h3a_payload, 1, TIVX_VPAC_VISS_MAX_H3A_STAT_NUMBYTES, fp); APP_PRINTF("%d bytes saved from H3A output buffer \n", h3a_size); fflush(fp); fclose(fp); vxUnmapUserDataObject(out_h3a, h3a_buf_map_id); return h3a_size; } #endif //_APP_DEBUG_ vx_char default_sensor_name[ISS_SENSORS_MAX_NAME] = SENSOR_SONY_IMX390_UB953_D3; void app_set_cfg_default(AppObj *obj) { obj->width_in = 1920; obj->height_in = 1080; obj->width_out = 1920; obj->height_out = 1080; obj->is_interactive = 1; obj->ldc_enable = 0; obj->sensor_name = default_sensor_name; } static void app_parse_cfg_file(AppObj *obj, char *cfg_file_name) { FILE *fp = fopen(cfg_file_name, "r"); char line_str[1024]; char *token; if(fp==NULL) { printf("# ERROR: Unable to open config file [%s]. Switching to interactive mode\n", cfg_file_name); obj->is_interactive = 1; } while(fgets(line_str, sizeof(line_str), fp)!=NULL) { char s[]=" \t"; if (strchr(line_str, '#')) { continue; } /* get the first token */ token = strtok(line_str, s); if(strcmp(token, "sensor_index")==0) { token = strtok(NULL, s); obj->sensor_sel = atoi(token); printf("sensor_selection = [%d]\n", obj->sensor_sel); } else if(strcmp(token, "ldc_enable")==0) { token = strtok(NULL, s); obj->ldc_enable = atoi(token); printf("ldc_enable = [%d]\n", obj->ldc_enable); } else if(strcmp(token, "num_frames_to_run")==0) { token = strtok(NULL, s); obj->num_frames_to_run = atoi(token); printf("num_frames_to_run = [%d]\n", obj->num_frames_to_run); } else if(strcmp(token, "is_interactive")==0) { token = strtok(NULL, s); obj->is_interactive = atoi(token); printf("is_interactive = [%d]\n", obj->is_interactive); } else { APP_PRINTF("Invalid token [%s]\n", token); } } fclose(fp); if(obj->width_in<128) obj->width_in = 128; if(obj->height_in<128) obj->height_in = 128; if(obj->width_out<128) obj->width_out = 128; if(obj->height_out<128) obj->height_out = 128; } vx_status app_parse_cmd_line_args(AppObj *obj, int argc, char *argv[]) { app_set_cfg_default(obj); int i; if(argc==1) { app_show_usage(argc, argv); printf("Defaulting to interactive mode \n"); obj->is_interactive = 1; return VX_SUCCESS; } 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]); break; } else if(strcmp(argv[i], "--help")==0) { app_show_usage(argc, argv); return VX_FAILURE; } } return VX_SUCCESS; } #ifdef _APP_DEBUG_ vx_int32 write_output_image_nv12(char * file_name, vx_image out_nv12) { FILE * fp = fopen(file_name, "wb"); if(!fp) { APP_PRINTF("Unable to open file %s\n", file_name); return -1; } vx_uint32 len1 = write_output_image_fp(fp, out_nv12); fclose(fp); APP_PRINTF("%d bytes written to %s\n", len1, file_name); return len1; } #endif AppObj gAppObj; int app_single_cam_main(int argc, char* argv[]) { AppObj *obj = &gAppObj; vx_status status = VX_FAILURE; status = app_parse_cmd_line_args(obj, argc, argv); if(VX_SUCCESS == status) { status = app_init(obj); if(VX_SUCCESS == status) { APP_PRINTF("app_init done\n"); status = app_create_graph(obj); if(VX_SUCCESS == status) { APP_PRINTF("app_create_graph done\n"); if(obj->is_interactive) { status = app_run_graph_interactive(obj); } else { status = app_run_graph(obj); } if(VX_SUCCESS == status) { APP_PRINTF("app_run_graph done\n"); status = app_delete_graph(obj); if(VX_SUCCESS == status) { APP_PRINTF("app_delete_graph done\n"); } else { printf("Error : app_delete_graph returned 0x%x \n", status); } } else { printf("Error : app_run_graph_xx returned 0x%x \n", status); } } else { printf("Error : app_create_graph returned 0x%x is_interactive =%d \n", status, obj->is_interactive); } } else { printf("Error : app_init returned 0x%x \n", status); } status = app_deinit(obj); if(VX_SUCCESS == status) { APP_PRINTF("app_deinit done\n"); } else { printf("Error : app_deinit returned 0x%x \n", status); } appDeInitImageSensor(obj->sensor_name); } else { printf("Error: app_parse_cmd_line_args returned 0x%x \n", status); } return 0; }