Hi TIers,
Recently, we use mosaic module to mosaic multiple images which are from 10 cameras, when we unplug some of the cameras, the rest of the images will blur, as shown bellow:
Connect 10 cameras at the same time, none of them are unplugged:
Connect 8 cameras at the same time, and 2 cameras are unplugged:
here is mosaic init:
and here is mosaic task:
#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 <VX/vx_khr_pipelining.h>
#include "app_common.h"
#include "app_socket_module.h"
#include "app_decode_module.h"
#include "app_img_mosaic_module.h"
#define APP_BUFFER_Q_DEPTH (4)
#define APP_PIPELINE_DEPTH (7)
typedef struct {
SocketObj socketObj_ar0233_b;
SocketObj socketObj_ar0147;
SocketObj socketObj_ar0143;
SocketObj socketObj_ar0233_a;
DecodeObj decodeObj_ar0233_b;
DecodeObj decodeObj_ar0147;
ImgMosaicObj mosaicObj;
tivx_event event_ar0233_b;
tivx_event event_ar0147;
// vx_graph graph_decode_ar0233_b;
// vx_graph graph_decode_ar0147;
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 en_out_bitstream_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_aewb;
int32_t enable_mosaic;
int32_t enable_encode;
int32_t enable_display;
int32_t enable_socket;
int32_t pipeline;
int32_t enqueueCnt;
int32_t dequeueCnt;
int32_t write_file;
tivx_task fpsFifo_task;
int fpsFifo_fd;
char fpsFifo_buf[1024];
vx_uint32 stop_task_fpsFifo;
vx_uint32 stop_task_done_fpsFifo;
App_FifoFps fpsFifoMsg;
pthread_mutex_t decode_0147_mutex; // canrx数据互斥锁
pthread_mutex_t socket_0233a_mutex; // canrx数据互斥锁
pthread_mutex_t socket_0143_mutex; // canrx数据互斥锁
pthread_mutex_t image_recv_mutex;
tivx_event event_print_fps;
} AppObj;
static vx_status app_init(AppObj *obj);
static vx_status app_run_graph_interactive(AppObj *obj);
static vx_status app_create_graph(AppObj *obj);
static void app_default_param_set(AppObj *obj);
static void app_pipeline_params_defaults(AppObj *obj);
static void app_parse_cmd_line_args(AppObj *obj, vx_int32 argc, vx_char *argv[]);
static void app_delete_graph(AppObj *obj);
static void app_run_task_delete(AppObj *obj);
static void app_deinit(AppObj *obj);
AppObj gAppObj;
vx_int32 app_yh_socket_recv_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);
// /*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");
return status;
}
static void app_pipeline_params_defaults(AppObj *obj)
{
obj->pipeline = -APP_BUFFER_Q_DEPTH + 1;
obj->enqueueCnt = 0;
obj->dequeueCnt = 0;
}
static void app_default_param_set(AppObj *obj)
{
app_pipeline_params_defaults(obj);
obj->is_interactive = 1;
obj->test_mode = 0;
obj->write_file = 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, "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;
}
}
}
else
if(strcmp(token, "enable_socket")==0)
{
token = strtok(NULL, s);
if(token != NULL)
{
obj->enable_socket = atoi(token);
if(obj->enable_socket > 1)
obj->enable_socket = 1;
}
}
else
if (strcmp(token, "udp_port_ar0233") == 0)
{
token = strtok(NULL, s);
if(token != NULL)
{
token[strlen(token) - 1] = 0;
obj->socketObj_ar0233_b.port = atoi(token);
}
}
else
if (strcmp(token, "udp_port_ar0147") == 0)
{
token = strtok(NULL, s);
if(token != NULL)
{
token[strlen(token) - 1] = 0;
obj->socketObj_ar0147.port = atoi(token);
}
}
else
if (strcmp(token, "udp_ip") == 0)
{
token = strtok(NULL, s);
if(token != NULL)
{
token[strlen(token) - 1] = 0;
strcpy(obj->socketObj_ar0147.udp_ip, token);
strcpy(obj->socketObj_ar0233_b.udp_ip, token);
printf("udp_ip is %s! \n", obj->socketObj_ar0233_b.udp_ip);
}
}
else
if (strcmp(token, "inWidth_ar0233") == 0)
{
token = strtok(NULL, s);
if(token != NULL)
{
token[strlen(token) - 1] = 0;
obj->decodeObj_ar0233_b.inWidth = atoi(token);
}
}
else
if (strcmp(token, "inWidth_ar0147") == 0)
{
token = strtok(NULL, s);
if(token != NULL)
{
token[strlen(token) - 1] = 0;
obj->decodeObj_ar0147.inWidth = atoi(token);
}
}
else
if (strcmp(token, "inHeight_ar0233") == 0)
{
token = strtok(NULL, s);
if(token != NULL)
{
token[strlen(token) - 1] = 0;
obj->decodeObj_ar0233_b.inHeight = atoi(token);
}
}
else
if (strcmp(token, "inHeight_ar0147") == 0)
{
token = strtok(NULL, s);
if(token != NULL)
{
token[strlen(token) - 1] = 0;
obj->decodeObj_ar0147.inHeight = atoi(token);
}
}
else
if (strcmp(token, "path_name_ar0233") == 0)
{
token = strtok(NULL, s);
if(token != NULL)
{
token[strlen(token) - 1] = 0;
strcpy(obj->socketObj_ar0233_a.path_name, token);
printf("udp_ip is %s! \n", obj->socketObj_ar0233_a.path_name);
}
}
else
if (strcmp(token, "path_name_ar0143") == 0)
{
token = strtok(NULL, s);
if(token != NULL)
{
token[strlen(token) - 1] = 0;
strcpy(obj->socketObj_ar0143.path_name, token);
printf("udp_ip is %s! \n", obj->socketObj_ar0143.path_name);
}
}
}
}
fclose(fp);
}
static void app_show_usage(vx_int32 argc, vx_char* argv[])
{
printf("\n");
printf(" app_yh_socket_recv Demo - (c) Yihang 2020\n");
printf(" ========================================================\n");
printf("\n");
printf(" Usage,\n");
printf(" %s --cfg <config file>\n", argv[0]);
printf("\n");
}
static void app_parse_cmd_line_args(AppObj *obj, vx_int32 argc, vx_char *argv[])
{
vx_int32 i;
// vx_bool set_test_mode = vx_false_e;
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);
}
}
return;
}
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)
{
vx_int32 idx, ch;
vx_int32 grid_size = calc_grid_size(numCh);
imgMosaicObj->out_width = DISPLAY_WIDTH;
imgMosaicObj->out_height = DISPLAY_HEIGHT;
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;
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 = APP_BUFFER_Q_DEPTH;
imgMosaicObj->params.enable_overlay = 0;
}
static void app_update_param_set(AppObj *obj)
{
vx_uint16 resized_width, resized_height;
appIssGetResizeParams(960, 540, 1920, 1080, &resized_width, &resized_height);
set_img_mosaic_params(&obj->mosaicObj, resized_width, resized_height, 3);
}
static uint32_t timer_cnt = 0;
void app_timer_fxn(int m)
{
AppObj *obj = &gAppObj;
timer_cnt++;
obj->socketObj_ar0233_b.cnt_fps++;
obj->socketObj_ar0147.cnt_fps++;
obj->socketObj_ar0143.cnt_fps++;
obj->socketObj_ar0233_a.cnt_fps++;
if(obj->socketObj_ar0233_b.cnt_fps > APP_SOCKET_CMD_FPS_TIMEOUT_CNT_SENCOND)
{
obj->socketObj_ar0233_b.fps = 0;
obj->socketObj_ar0233_b.cam_error_flag[0] = 1;
obj->socketObj_ar0233_b.cam_error_flag[1] = 1;
obj->socketObj_ar0233_b.cam_error_flag[2] = 1;
obj->socketObj_ar0233_b.cam_error_flag[3] = 1;
obj->socketObj_ar0233_b.cnt_fps = 0;
VX_PRINT(VX_ZONE_ERROR, "ar0233_b.cnt_fps > APP_SOCKET_CMD_FPS_TIMEOUT_CNT_SENCOND err\r\n");
}
if(obj->socketObj_ar0147.cnt_fps > APP_SOCKET_CMD_FPS_TIMEOUT_CNT_SENCOND)
{
obj->socketObj_ar0147.fps = 0;
obj->socketObj_ar0147.cam_error_flag[0] = 1;
obj->socketObj_ar0147.cam_error_flag[1] = 1;
obj->socketObj_ar0147.cam_error_flag[2] = 1;
obj->socketObj_ar0147.cam_error_flag[3] = 1;
obj->socketObj_ar0147.cnt_fps = 0;
VX_PRINT(VX_ZONE_ERROR, "ar0147.cnt_fps > APP_SOCKET_CMD_FPS_TIMEOUT_CNT_SENCOND err\r\n");
}
if(obj->socketObj_ar0143.cnt_fps > APP_SOCKET_CMD_FPS_TIMEOUT_CNT_SENCOND)
{
obj->socketObj_ar0143.fps = 0;
obj->socketObj_ar0143.cnt_fps = 0;
obj->socketObj_ar0143.cam_error_flag[0] = 1;
obj->socketObj_ar0143.cam_error_flag[1] = 1;
obj->socketObj_ar0143.cam_error_flag[2] = 1;
obj->socketObj_ar0143.cam_error_flag[3] = 1;
VX_PRINT(VX_ZONE_ERROR, "ar0143.cnt_fps > APP_SOCKET_CMD_FPS_TIMEOUT_CNT_SENCOND err\r\n");
}
if(obj->socketObj_ar0233_a.cnt_fps > APP_SOCKET_CMD_FPS_TIMEOUT_CNT_SENCOND)
{
obj->socketObj_ar0233_a.fps = 0;
obj->socketObj_ar0233_a.cnt_fps = 0;
obj->socketObj_ar0233_a.cam_error_flag[0] = 1;
obj->socketObj_ar0233_a.cam_error_flag[1] = 1;
obj->socketObj_ar0233_a.cam_error_flag[2] = 1;
obj->socketObj_ar0233_a.cam_error_flag[3] = 1;
VX_PRINT(VX_ZONE_ERROR, "ar0233_a.cnt_fps > APP_SOCKET_CMD_FPS_TIMEOUT_CNT_SENCOND err\r\n");
}
if(timer_cnt >= 10)
{
VX_PRINT(VX_ZONE_INFO, "APP_CAM_NAME_0233_A fps is %f\r\n", obj->fpsFifoMsg.fps[APP_CAM_NAME_0233_A]);
VX_PRINT(VX_ZONE_INFO, "APP_CAM_NAME_0143 fps is %f\r\n", obj->fpsFifoMsg.fps[APP_CAM_NAME_0143]);
VX_PRINT(VX_ZONE_INFO, "APP_CAM_NAME_0233_B fps is %f\r\n", obj->fpsFifoMsg.fps[APP_CAM_NAME_0233_B]);
VX_PRINT(VX_ZONE_INFO, "APP_CAM_NAME_0147 fps is %f\r\n", obj->fpsFifoMsg.fps[APP_CAM_NAME_0147]);
VX_PRINT(VX_ZONE_INFO, "APP_CAM_NAME_0147 cam 0 error status is %d\r\n", obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0147][0]);
VX_PRINT(VX_ZONE_INFO, "APP_CAM_NAME_0147 cam 1 error status is %d\r\n", obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0147][1]);
VX_PRINT(VX_ZONE_INFO, "APP_CAM_NAME_0147 cam 2 error status is %d\r\n", obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0147][2]);
VX_PRINT(VX_ZONE_INFO, "APP_CAM_NAME_0147 cam 3 error status is %d\r\n", obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0147][3]);
VX_PRINT(VX_ZONE_INFO, "APP_CAM_NAME_0233_A cam 0 error status is %d\r\n", obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0233_A][0]);
VX_PRINT(VX_ZONE_INFO, "APP_CAM_NAME_0233_A cam 1 error status is %d\r\n", obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0233_A][1]);
VX_PRINT(VX_ZONE_INFO, "APP_CAM_NAME_0233_A cam 2 error status is %d\r\n", obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0233_A][2]);
VX_PRINT(VX_ZONE_INFO, "APP_CAM_NAME_0233_A cam 3 error status is %d\r\n", obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0233_A][3]);
VX_PRINT(VX_ZONE_INFO, "APP_CAM_NAME_0233_B cam 0 error status is %d\r\n", obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0233_B][0]);
VX_PRINT(VX_ZONE_INFO, "APP_CAM_NAME_0233_B cam 1 error status is %d\r\n", obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0233_B][1]);
VX_PRINT(VX_ZONE_INFO, "APP_CAM_NAME_0233_B cam 2 error status is %d\r\n", obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0233_B][2]);
VX_PRINT(VX_ZONE_INFO, "APP_CAM_NAME_0233_B cam 3 error status is %d\r\n", obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0233_B][3]);
VX_PRINT(VX_ZONE_INFO, "APP_CAM_NAME_0143 cam 0 error status is %d\r\n", obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0143][0]);
VX_PRINT(VX_ZONE_INFO, "APP_CAM_NAME_0143 cam 1 error status is %d\r\n", obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0143][1]);
VX_PRINT(VX_ZONE_INFO, "APP_CAM_NAME_0143 cam 2 error status is %d\r\n", obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0143][2]);
VX_PRINT(VX_ZONE_INFO, "APP_CAM_NAME_0143 cam 3 error status is %d\r\n", obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0143][3]);
timer_cnt = 0;
}
}
static vx_status app_init(AppObj *obj)
{
vx_status 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");
}
status = tivxEventCreate(&obj->event_ar0147);
if(VX_SUCCESS != status)
{
APP_PRINTF("event_dof_graph create failed\n");
return status;
}
status = tivxEventCreate(&obj->event_ar0233_b);
if(VX_SUCCESS != status)
{
APP_PRINTF("event_dof_graph create failed\n");
return status;
}
status = tivxEventCreate(&obj->event_print_fps);
if(VX_SUCCESS != status)
{
APP_PRINTF("event_dof_graph create failed\n");
return status;
}
obj->mosaicObj.ptr_event_print_fps = &obj->event_print_fps;
if (pthread_mutex_init(&obj->decode_0147_mutex, NULL) != 0){
printf("Ddecode_0147_mutex CREATE ERROR!\n");
}
if (pthread_mutex_init(&obj->socket_0233a_mutex, NULL) != 0){
printf("socket_0233a_mutex CREATE ERROR!\n");
}
if (pthread_mutex_init(&obj->socket_0143_mutex, NULL) != 0){
printf("socket_0143_mutex CREATE ERROR!\n");
}
if (pthread_mutex_init(&obj->image_recv_mutex, NULL) != 0){
printf("socket_0143_mutex CREATE ERROR!\n");
}
if (pthread_mutex_init(&obj->socketObj_ar0147.socket_image_mutex, NULL) != 0){
printf("socket_0143_mutex CREATE ERROR!\n");
}
// 设置定时器,用于监测状态信号丢失
/*connect the signal to Habdler fuction*/
signal(SIGALRM, app_timer_fxn);
// 设置定时器周期为1s
struct itimerval itv;
//设置定时器启动时间
itv.it_value.tv_sec = 0; //timer start after 3 seconds later
itv.it_value.tv_usec = 1000;
// 设置定时器周期
itv.it_interval.tv_sec = 1;
itv.it_interval.tv_usec = 0;
setitimer(ITIMER_REAL,&itv,NULL);
APP_PRINTF("creat obj->mosaicObj.input_arr[0]\n");
app_update_param_set(obj);
obj->mosaicObj.ptr_decode_0147_mutex = &obj->decode_0147_mutex;
obj->mosaicObj.ptr_socket_0143_mutex = &obj->socket_0143_mutex;
obj->mosaicObj.ptr_socket_0233a_mutex = &obj->socket_0233a_mutex;
obj->mosaicObj.ptr_socket_image_mutex = &obj->socketObj_ar0147.socket_image_mutex;
app_init_img_mosaic(obj->context, &obj->mosaicObj, "img_mosaic_obj", 1);
vx_image input_img = vxCreateImage(obj->context, 960, 540, VX_DF_IMAGE_NV12);
obj->mosaicObj.input_arr[0] = vxCreateObjectArray(obj->context, (vx_reference)input_img, 3);
vxReleaseImage(&input_img);
obj->socketObj_ar0233_b.ptr_event = &obj->event_ar0233_b;
obj->socketObj_ar0233_b.appSocketType = APP_SOCKET_MODULE_TYPE_INTER_SOC_SERVER;
obj->socketObj_ar0233_b.ptr_decodeObj = &obj->decodeObj_ar0233_b;
status = app_init_socket(obj->context, &obj->socketObj_ar0233_b);
if(status != 0 )
{
printf("app_init_socket error\r\n");
}
APP_PRINTF("app_init_socket 0233 init done and return %d!\n", status);
// obj->socketObj_ar0147.ptr_socket_mutex =
obj->socketObj_ar0147.video_in = vx_false_e;
obj->socketObj_ar0147.ptr_event = &obj->event_ar0147;
obj->socketObj_ar0147.appSocketType = APP_SOCKET_MODULE_TYPE_INTER_SOC_SERVER;
obj->socketObj_ar0147.ptr_decodeObj = &obj->decodeObj_ar0147;
obj->socketObj_ar0147.images = (vx_image)vxGetObjectArrayItem(obj->mosaicObj.input_arr[0], 2);
status = app_init_socket(obj->context, &obj->socketObj_ar0147);
if(status != 0 )
{
printf("app_init_socket error\r\n");
}
APP_PRINTF("app_init_socket 0147 init done and return %d!\n", status);
// obj->socketObj_ar0143.ptr_event = &obj->event_ar0147;
obj->socketObj_ar0143.images = (vx_image)vxGetObjectArrayItem(obj->mosaicObj.input_arr[0], 0);
// obj->socketObj_ar0143.images = vxCreateImage(obj->context,
// 960,
// 540,
// VX_DF_IMAGE_NV12);
obj->socketObj_ar0143.ptr_socket_mutex = &obj->socket_0143_mutex;
obj->socketObj_ar0143.ptr_image_recv_mutex = &obj->image_recv_mutex;
obj->socketObj_ar0143.video_in = vx_false_e;
obj->socketObj_ar0143.appSocketType = APP_SOCKET_MODULE_TYPE_INTER_APP_SERVER;
obj->socketObj_ar0143.port = 143;
status = app_init_socket(obj->context, &obj->socketObj_ar0143);
if(status != 0 )
{
printf("app_init_socket error\r\n");
}
APP_PRINTF("app_init_socket 0143 init done and return %d!\n", status);
obj->socketObj_ar0233_a.ptr_socket_mutex = &obj->socket_0233a_mutex;
obj->socketObj_ar0233_a.ptr_image_recv_mutex = &obj->image_recv_mutex;
obj->socketObj_ar0233_a.video_in = vx_false_e;
obj->socketObj_ar0233_a.port = 233;
obj->socketObj_ar0233_a.images = (vx_image)vxGetObjectArrayItem(obj->mosaicObj.input_arr[0], 1);
// obj->socketObj_ar0233_a.images = vxCreateImage(obj->context,
// 960,
// 540,
// VX_DF_IMAGE_NV12);
obj->socketObj_ar0233_a.appSocketType = APP_SOCKET_MODULE_TYPE_INTER_APP_SERVER;
status = app_init_socket(obj->context, &obj->socketObj_ar0233_a);
if(status != 0 )
{
printf("app_init_socket error\r\n");
}
APP_PRINTF("app_init_socket0233_a init done and return %d!\n", status);
obj->decodeObj_ar0233_b.output_image = vxCreateImage(obj->context, 960, 540, VX_DF_IMAGE_NV12);
obj->decodeObj_ar0233_b.ptr_event = &obj->event_ar0233_b;
// obj->decodeObj_ar0233_b.ptr_socketObj = &obj->socketObj_ar0233_b;
status = app_init_decode(obj->context, &obj->decodeObj_ar0233_b);
if(status != 0 )
{
printf("app_init_decode error\r\n");
}
APP_PRINTF("app_init_decode 0233 init done and return %d!\n", status);
obj->decodeObj_ar0147.output_image = vxCreateImage(obj->context, 960, 540, VX_DF_IMAGE_NV12);
obj->decodeObj_ar0147.ptr_decode_mutex = &obj->decode_0147_mutex;
// obj->decodeObj_ar0147.output_image = (vx_image)vxGetObjectArrayItem(obj->mosaicObj.input_arr[0], 2);
obj->decodeObj_ar0147.ptr_event = &obj->event_ar0147;
// obj->decodeObj_ar0233_b.ptr_socketObj = &obj->socketObj_ar0233_b;
status = app_init_decode(obj->context, &obj->decodeObj_ar0147);
if(status != 0 )
{
printf("app_init_decode error\r\n");
}
APP_PRINTF("app_init_decode 0147 init done and return %d!\n", status);
// APP_PRINTF("Cam power on\n");
// appSensorPowerOn();
// APP_PRINTF("Cam power on complete\n");
/* Initialize modules */
// if (status == VX_SUCCESS)
// {
// status = 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", APP_BUFFER_Q_DEPTH);
// }
// if((1 == obj->enable_viss) && (status == VX_SUCCESS))
// {
// status = app_init_viss(obj->context, &obj->vissObj, &obj->sensorObj, "viss_obj");
// 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");
// 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");
// 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");
// }
appPerfPointSetName(&obj->total_perf , "TOTAL");
appPerfPointSetName(&obj->fileio_perf, "FILEIO");
return status;
}
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 vx_status app_fifo_send(AppObj *obj)
{
vx_status vxStatus = VX_SUCCESS;
uint8_t *buf;
while(1)
{
obj->fpsFifoMsg.fps[APP_CAM_NAME_0233_A] = obj->socketObj_ar0233_a.fps;
obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0233_A][0] = obj->socketObj_ar0233_a.cam_error_flag[0];
obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0233_A][1] = obj->socketObj_ar0233_a.cam_error_flag[1];
obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0233_A][2] = obj->socketObj_ar0233_a.cam_error_flag[2];
obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0233_A][3] = obj->socketObj_ar0233_a.cam_error_flag[3];
obj->fpsFifoMsg.fps[APP_CAM_NAME_0143] = obj->socketObj_ar0143.fps;
obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0143][0] = obj->socketObj_ar0143.cam_error_flag[0];
obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0143][1] = obj->socketObj_ar0143.cam_error_flag[1];
obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0143][2] = obj->socketObj_ar0143.cam_error_flag[2];
obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0143][3] = obj->socketObj_ar0143.cam_error_flag[3];
obj->fpsFifoMsg.fps[APP_CAM_NAME_0233_B] = obj->socketObj_ar0233_b.fps;
obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0233_B][0] = obj->socketObj_ar0233_b.cam_error_flag[0];
obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0233_B][1] = obj->socketObj_ar0233_b.cam_error_flag[1];
obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0233_B][2] = obj->socketObj_ar0233_b.cam_error_flag[2];
obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0233_B][3] = obj->socketObj_ar0233_b.cam_error_flag[3];
obj->fpsFifoMsg.fps[APP_CAM_NAME_0147] = obj->socketObj_ar0147.fps;
obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0147][0] = obj->socketObj_ar0147.cam_error_flag[0];
obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0147][1] = obj->socketObj_ar0147.cam_error_flag[1];
obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0147][2] = obj->socketObj_ar0147.cam_error_flag[2];
obj->fpsFifoMsg.cam_error_flag[APP_CAM_NAME_0147][3] = obj->socketObj_ar0147.cam_error_flag[3];
if(obj->fpsFifoMsg.fps[APP_CAM_NAME_0233_A] < 25 || obj->fpsFifoMsg.fps[APP_CAM_NAME_0233_A] > 35)
{
VX_PRINT(VX_ZONE_INFO, "CAM_NAME_0233_A fps out of range and value is %f\r\n", obj->fpsFifoMsg.fps[APP_CAM_NAME_0233_A]);
}
if(obj->fpsFifoMsg.fps[APP_CAM_NAME_0143] < 20 || obj->fpsFifoMsg.fps[APP_CAM_NAME_0143] > 30)
{
VX_PRINT(VX_ZONE_INFO, "CAM_NAME_0143 fps out of range and value is %f\r\n", obj->fpsFifoMsg.fps[APP_CAM_NAME_0143]);
}
if(obj->fpsFifoMsg.fps[APP_CAM_NAME_0233_B] < 25 || obj->fpsFifoMsg.fps[APP_CAM_NAME_0233_B] > 35)
{
VX_PRINT(VX_ZONE_INFO, "CAM_NAME_0233_B fps out of range and value is %f\r\n", obj->fpsFifoMsg.fps[APP_CAM_NAME_0233_B]);
}
if(obj->fpsFifoMsg.fps[APP_CAM_NAME_0147] < 15 || obj->fpsFifoMsg.fps[APP_CAM_NAME_0147] > 30)
{
VX_PRINT(VX_ZONE_INFO, "CAM_NAME_0147 fps out of range and value is %f\r\n", obj->fpsFifoMsg.fps[APP_CAM_NAME_0147]);
}
buf = &obj->fpsFifoMsg;
if(write(obj->fpsFifo_fd, buf, sizeof(App_FifoFps)) < 0) // 写入到FIFO中
{
perror("Write FIFO Failed");
}
// if(obj->decodeObj_ar0147.video_in
// && obj->socketObj_ar0143.video_in
// && obj->socketObj_ar0233_a.video_in)
// {
// obj->mosaicObj.video_in = vx_true_e;
// }
tivxTaskWaitMsecs(APP_SOCKET_CMD_FPS_INTER_IN_SENCOND * 1000);
}
return vxStatus;
}
void app_fps_fifo_task(void *app_var)
{
AppObj *obj = (AppObj *)app_var;
vx_status status = VX_SUCCESS;
printf("I am app_fps_fifo_task process.\n"); // 说明进程ID
// if(mkfifo(APP_FPS_FIFO_NAME, 0666) < 0 && errno!=EEXIST) // 创建FIFO管道
// perror("Create FIFO Failed");
if((obj->fpsFifo_fd = open(APP_FPS_FIFO_NAME, O_WRONLY)) < 0) // 以写打开一个FIFO
{
perror("Open FIFO Failed");
}
while((!obj->stop_task_fpsFifo) && (status == VX_SUCCESS))
{
status = app_fifo_send(obj);
}
close(obj->fpsFifo_fd);
obj->stop_task_done_fpsFifo = 1;
}
static int32_t app_run_task_create(AppObj *obj)
{
tivx_task_create_params_t params;
vx_status status;
tivxTaskSetDefaultCreateParams(¶ms);
params.task_main = app_socket_recv_task;
params.app_var = &obj->socketObj_ar0233_b;
obj->socketObj_ar0233_b.stop_task_done = 0;
obj->socketObj_ar0233_b.stop_task = 0;
status = tivxTaskCreate(&obj->socketObj_ar0233_b.task, ¶ms);
tivxTaskSetDefaultCreateParams(¶ms);
params.task_main = app_socket_recv_task;
params.app_var = &obj->socketObj_ar0147;
obj->socketObj_ar0147.stop_task_done = 0;
obj->socketObj_ar0147.stop_task = 0;
status = tivxTaskCreate(&obj->socketObj_ar0147.task, ¶ms);
tivxTaskSetDefaultCreateParams(¶ms);
params.task_main = app_socket_recv_task;
params.app_var = &obj->socketObj_ar0143;
obj->socketObj_ar0143.stop_task_done = 0;
obj->socketObj_ar0143.stop_task = 0;
status = tivxTaskCreate(&obj->socketObj_ar0143.task, ¶ms);
tivxTaskSetDefaultCreateParams(¶ms);
params.task_main = app_socket_recv_task;
params.app_var = &obj->socketObj_ar0233_a;
obj->socketObj_ar0233_a.stop_task_done = 0;
obj->socketObj_ar0233_a.stop_task = 0;
status = tivxTaskCreate(&obj->socketObj_ar0233_a.task, ¶ms);
// tivxTaskSetDefaultCreateParams(¶ms);
// params.task_main = app_decode_task;
// params.app_var = &obj->decodeObj_ar0233_b;
// // params.priority = TIVX_TASK_PRI_LOWEST - 3;
// obj->decodeObj_ar0233_b.stop_task_done = 0;
// obj->decodeObj_ar0233_b.stop_task = 0;
// status = tivxTaskCreate(&obj->decodeObj_ar0233_b.task, ¶ms);
// tivxTaskSetDefaultCreateParams(¶ms);
// params.task_main = app_decode_task;
// params.app_var = &obj->decodeObj_ar0147;
// // params.priority = TIVX_TASK_PRI_LOWEST - 3;
// obj->decodeObj_ar0147.stop_task_done = 0;
// obj->decodeObj_ar0147.stop_task = 0;
// status = tivxTaskCreate(&obj->decodeObj_ar0147.task, ¶ms);
#if 1
tivxTaskSetDefaultCreateParams(¶ms);
params.task_main = app_fps_fifo_task;
params.app_var = obj;
params.priority = TIVX_TASK_PRI_LOWEST;
obj->stop_task_done_fpsFifo = 0;
obj->stop_task_fpsFifo = 0;
status = tivxTaskCreate(&obj->fpsFifo_task, ¶ms);
#endif
tivxTaskSetDefaultCreateParams(¶ms);
params.task_main = app_mosaic_run_task;
params.app_var = &obj->mosaicObj;
params.priority = TIVX_TASK_PRI_LOWEST;
obj->mosaicObj.stop_task = 0;
obj->mosaicObj.stop_task_done = 0;
status = tivxTaskCreate(&obj->mosaicObj.task, ¶ms);
return status;
}
static vx_status app_run_graph_interactive(AppObj *obj)
{
vx_status status;
uint32_t done = 0;
char ch;
FILE *fp;
app_perf_point_t *perf_arr[1];
status = app_run_task_create(obj);
if(status == VX_FAILURE)
{
printf("app_tidl: ERROR: Unable to create task\n");
}
else
{
appPerfStatsResetAll();
while(1)
{
tivxEventWait(obj->event_print_fps, TIVX_EVENT_TIMEOUT_WAIT_FOREVER);
appPerfStatsPrintAll();
status = tivx_utils_graph_perf_print(obj->decodeObj_ar0233_b.graph);
appPerfPointPrint(&obj->decodeObj_ar0233_b.total_perf);
// appPerfPointPrint(&obj->total_perf);
printf("\n");
appPerfPointPrintFPS(&obj->decodeObj_ar0233_b.total_perf);
appPerfPointReset(&obj->decodeObj_ar0233_b.total_perf);
printf("\n");
appPerfStatsPrintAll();
status = tivx_utils_graph_perf_print(obj->decodeObj_ar0147.graph);
appPerfPointPrint(&obj->decodeObj_ar0147.total_perf);
printf("\n");
appPerfPointPrintFPS(&obj->decodeObj_ar0147.total_perf);
appPerfPointReset(&obj->decodeObj_ar0147.total_perf);
printf("\n");
appPerfStatsPrintAll();
status = tivx_utils_graph_perf_print(obj->mosaicObj.graph);
appPerfPointPrint(&obj->mosaicObj.total_perf);
printf("\n");
appPerfPointPrintFPS(&obj->mosaicObj.total_perf);
appPerfPointReset(&obj->mosaicObj.total_perf);
printf("\n");
// tivxTaskWaitMsecs(100000);
}
while(!done)
{
printf(menu);
ch = getchar();
printf("\n");
switch(ch)
{
case 'p':
appPerfStatsPrintAll();
status = tivx_utils_graph_perf_print(obj->decodeObj_ar0233_b.graph);
appPerfPointPrint(&obj->decodeObj_ar0233_b.total_perf);
// appPerfPointPrint(&obj->total_perf);
printf("\n");
appPerfPointPrintFPS(&obj->decodeObj_ar0233_b.total_perf);
appPerfPointReset(&obj->decodeObj_ar0233_b.total_perf);
printf("\n");
appPerfStatsPrintAll();
status = tivx_utils_graph_perf_print(obj->decodeObj_ar0147.graph);
appPerfPointPrint(&obj->decodeObj_ar0147.total_perf);
printf("\n");
appPerfPointPrintFPS(&obj->decodeObj_ar0147.total_perf);
appPerfPointReset(&obj->decodeObj_ar0147.total_perf);
printf("\n");
appPerfStatsPrintAll();
status = tivx_utils_graph_perf_print(obj->mosaicObj.graph);
appPerfPointPrint(&obj->mosaicObj.total_perf);
printf("\n");
appPerfPointPrintFPS(&obj->mosaicObj.total_perf);
appPerfPointReset(&obj->mosaicObj.total_perf);
printf("\n");
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->decodeObj_ar0233_b.graph);
}
appPerfStatsExportCloseFile(fp);
appPerfStatsResetAll();
}
else
{
printf("fp is null\n");
}
break;
case 's':
obj->write_file = 1;
break;
case 'x':
obj->socketObj_ar0233_b.stop_task = 1;
obj->socketObj_ar0147.stop_task = 1;
done = 1;
break;
}
}
app_run_task_delete(obj);
}
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];
// vx_int32 graph_parameter_index;
obj->decodeObj_ar0233_b.graph = vxCreateGraph(obj->context);
status = vxGetStatus((vx_reference)obj->decodeObj_ar0233_b.graph);
if (status == VX_SUCCESS)
{
status = vxSetReferenceName((vx_reference)obj->decodeObj_ar0233_b.graph, "Decode_0233_b");
APP_PRINTF("Graph create done!\n");
}
obj->decodeObj_ar0147.graph = vxCreateGraph(obj->context);
status = vxGetStatus((vx_reference)obj->decodeObj_ar0147.graph);
if (status == VX_SUCCESS)
{
status = vxSetReferenceName((vx_reference)obj->decodeObj_ar0147.graph, "Decode_0147");
APP_PRINTF("Graph create done!\n");
}
obj->mosaicObj.graph = vxCreateGraph(obj->context);
status = vxGetStatus((vx_reference)obj->mosaicObj.graph);
if (status == VX_SUCCESS)
{
status = vxSetReferenceName((vx_reference)obj->mosaicObj.graph, "mosaic");
APP_PRINTF("Mosaic Graph create done!\n");
}
if(status == VX_SUCCESS)
{
status = app_create_graph_decode(obj->decodeObj_ar0233_b.graph, &obj->decodeObj_ar0233_b);
APP_PRINTF("Decode ar0233 graph done!\n");
}
if(status == VX_SUCCESS)
{
status = app_create_graph_decode(obj->decodeObj_ar0147.graph, &obj->decodeObj_ar0147);
APP_PRINTF("Decode ar0233 graph done!\n");
}
if(status == VX_SUCCESS)
{
obj->mosaicObj.num_inputs = 1;
status = app_create_graph_img_mosaic(obj->mosaicObj.graph, &obj->mosaicObj);
APP_PRINTF("mosaic graph done!\n");
}
// if(status == VX_SUCCESS)
// {
// status = app_create_graph_decode(obj->decodeObj_ar0147.graph, &obj->decodeObj_ar0147);
// APP_PRINTF("Decode ar0233 graph done!\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 = APP_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 = APP_BUFFER_Q_DEPTH;
// graph_parameters_queue_params_list[graph_parameter_index].refs_list = (vx_reference*)&obj->imgMosaicObj.output_image[0];
// graph_parameter_index++;
// }
// if((obj->en_out_bitstream_write == 1) && (obj->enable_encode == 1))
// {
// add_graph_parameter_by_node_index(obj->graph, obj->encodeObj.node, 2);
// obj->encodeObj.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 = APP_BUFFER_Q_DEPTH;
// graph_parameters_queue_params_list[graph_parameter_index].refs_list = (vx_reference*)&obj->encodeObj.bitstream_obj[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 (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_mosaic == 1) && (status == VX_SUCCESS))
// {
// status = tivxSetNodeParameterNumBufByIndex(obj->imgMosaicObj.node, 1, APP_BUFFER_Q_DEPTH);
// APP_PRINTF("Pipeline params setup done!\n");
// }
// if((obj->enable_encode == 1) && (status == VX_SUCCESS))
// {
// status = tivxSetNodeParameterNumBufByIndex(obj->encodeObj.node, 2, APP_BUFFER_Q_DEPTH);
// APP_PRINTF("Pipeline params setup done!\n");
// }
// }
return status;
}
static void app_delete_graph(AppObj *obj)
{
app_delete_socket(&obj->socketObj_ar0233_b);
APP_PRINTF("app_delete_socket delete done!\n");
app_delete_decode(&obj->decodeObj_ar0233_b);
APP_PRINTF("app_delete_decode delete done!\n");
app_delete_socket(&obj->socketObj_ar0147);
APP_PRINTF("app_delete_socket delete done!\n");
app_delete_decode(&obj->decodeObj_ar0147);
APP_PRINTF("app_delete_decode delete done!\n");
}
static void app_deinit(AppObj *obj)
{
app_deinit_socket(&obj->socketObj_ar0233_b);
APP_PRINTF("Sensor deinit done!\n");
app_deinit_decode(&obj->decodeObj_ar0233_b);
APP_PRINTF("Capture deinit done!\n");
app_deinit_socket(&obj->socketObj_ar0147);
APP_PRINTF("Sensor deinit done!\n");
app_deinit_decode(&obj->decodeObj_ar0147);
APP_PRINTF("Capture deinit done!\n");
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_run_task_delete(AppObj *obj)
{
while(obj->socketObj_ar0233_b.stop_task_done==0)
{
tivxTaskWaitMsecs(100);
}
tivxTaskDelete(&obj->socketObj_ar0233_b.task);
while(obj->socketObj_ar0147.stop_task_done==0)
{
tivxTaskWaitMsecs(100);
}
tivxTaskDelete(&obj->decodeObj_ar0233_b.task);
while(obj->decodeObj_ar0233_b.stop_task_done==0)
{
tivxTaskWaitMsecs(100);
}
tivxTaskDelete(&obj->decodeObj_ar0233_b.task);
while(obj->decodeObj_ar0147.stop_task_done==0)
{
tivxTaskWaitMsecs(100);
}
tivxTaskDelete(&obj->decodeObj_ar0147.task);
}
and here is mosaic target file vx_img_mosaic_msc_target.c:
/*
*
* Copyright (c) 2019 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 <TI/tivx.h>
#include <TI/j7.h>
#include <TI/tivx_event.h>
#include <TI/tivx_img_proc.h>
#include <TI/tivx_target_kernel.h>
#include <tivx_kernels_target_utils.h>
#include <tivx_img_mosaic_host.h>
#include <ti/drv/vhwa/include/vhwa_m2mMsc.h>
#include <utils/mem/include/app_mem.h>
#include <utils/perf_stats/include/app_perf_stats.h>
/* ========================================================================== */
/* Macros & Typedefs */
/* ========================================================================== */
#define TIVX_IMAGE_MOSAIC_MAX_PLANES (2u) /* one plane for Y, one plane for C */
#define TIVX_IMAGE_MOSAIC_MSC_MAX_INST (2u)
/* ========================================================================== */
/* Structure Declarations */
/* ========================================================================== */
/* Mosaic MSC internal object */
typedef struct
{
Vhwa_M2mMscCreatePrms createArgs;
Vhwa_M2mMscParams msc_prms;
Fvid2_Handle handle;
tivx_event wait_for_compl;
Fvid2_FrameList inFrmList;
Fvid2_FrameList outFrmList;
Fvid2_Frame inFrm;
Fvid2_Frame outFrm;
Fvid2_CbParams cbPrms;
uint32_t msc_drv_inst_id;
uint64_t time;
uint32_t scIdx;
} tivxImgMosaicMscInstObj;
typedef struct
{
tivxImgMosaicMscInstObj inst_obj[TIVX_IMAGE_MOSAIC_MSC_MAX_INST];
Msc_Coeff coeffCfg;
tivxImgMosaicWindow *tmp_win[TIVX_IMAGE_MOSAIC_MSC_MAX_INST];
uint32_t tmp_in_ch[TIVX_IMAGE_MOSAIC_MSC_MAX_INST];
uint32_t tmp_ch_sel[TIVX_IMAGE_MOSAIC_MSC_MAX_INST];
tivx_obj_desc_object_array_t *in_arr_desc[TIVX_IMAGE_MOSAIC_MSC_MAX_INST];
tivx_obj_desc_image_t *in_img_desc[TIVX_IMAGE_MOSAIC_MSC_MAX_INST][TIVX_OBJECT_ARRAY_MAX_ITEMS];
app_perf_hwa_id_t app_hwa_inst_id[TIVX_IMAGE_MOSAIC_MSC_MAX_INST];
vx_uint32 max_msc_instances;
vx_uint32 msc_instance;
} tivxImgMosaicMscObj;
/* ========================================================================== */
/* Function Declarations */
/* ========================================================================== */
/* Interface API Functions */
static vx_status VX_CALLBACK tivxKernelImgMosaicMscCreate(
tivx_target_kernel_instance kernel,
tivx_obj_desc_t *obj_desc[],
vx_uint16 num_params,
void *priv_arg);
static vx_status VX_CALLBACK tivxKernelImgMosaicMscDelete(
tivx_target_kernel_instance kernel,
tivx_obj_desc_t *obj_desc[],
vx_uint16 num_params,
void *priv_arg);
static vx_status VX_CALLBACK tivxKernelImgMosaicMscProcess(
tivx_target_kernel_instance kernel,
tivx_obj_desc_t *obj_desc[],
vx_uint16 num_params,
void *priv_arg);
/* Local Functions */
static vx_status tivxKernelImgMosaicMscDrvCreate(
tivxImgMosaicMscInstObj *inst_obj, uint32_t inst_id);
static vx_status tivxKernelImgMosaicMscDrvDelete(
tivxImgMosaicMscInstObj *inst_obj);
static void tivxKernelImgMosaicMscDrvSetScCfg(
Msc_ScConfig *sc_cfg,
const tivx_obj_desc_image_t *in_img_desc,
const tivxImgMosaicWindow *window);
static int32_t tivxKernelImgMosaicMscDrvCompCb(
Fvid2_Handle handle,
void *appData);
static vx_status tivxKernelImgMosaicMscSetCoeffsCmd(tivxImgMosaicMscObj *msc_obj);
static void scale_set_coeff(
tivx_vpac_msc_coefficients_t *coeff,
uint32_t interpolation);
static vx_status tivxKernelImgMosaicMscDrvPrepare(
tivxImgMosaicMscInstObj *inst_obj,
const tivx_obj_desc_image_t *in_img_desc,
const tivxImgMosaicWindow *window,
const tivx_obj_desc_image_t* out_img_desc);
static vx_status tivxKernelImgMosaicMscDrvSubmit(tivxImgMosaicMscInstObj *inst_obj);
static void tivxKernelImgMosaicMscDrvWait(tivxImgMosaicMscInstObj *inst_obj);
static vx_status tivxKernelImgMosaicMscDrvGetReq(tivxImgMosaicMscInstObj *inst_obj);
/* ========================================================================== */
/* Global Variables */
/* ========================================================================== */
static tivx_target_kernel vx_imgMosaicMsc1_kernel = NULL;
static tivx_target_kernel vx_imgMosaicMsc2_kernel = NULL;
/* ========================================================================== */
/* Function Definitions */
/* ========================================================================== */
void tivxAddTargetKernelImgMosaicMsc(void)
{
char target_name[TIVX_TARGET_MAX_NAME];
/* Both scalars are used, but the target used it always MSC0 */
strncpy(target_name, TIVX_TARGET_VPAC_MSC1, TIVX_TARGET_MAX_NAME);
vx_imgMosaicMsc1_kernel = tivxAddTargetKernelByName(
TIVX_KERNEL_IMG_MOSAIC_NAME,
target_name,
tivxKernelImgMosaicMscProcess,
tivxKernelImgMosaicMscCreate,
tivxKernelImgMosaicMscDelete,
NULL,
NULL);
if(NULL == vx_imgMosaicMsc1_kernel)
{
VX_PRINT(VX_ZONE_ERROR, "Failed to Add Img Mosaic MSC TargetKernel\n");
}
strncpy(target_name, TIVX_TARGET_VPAC_MSC2, TIVX_TARGET_MAX_NAME);
vx_imgMosaicMsc2_kernel = tivxAddTargetKernelByName(
TIVX_KERNEL_IMG_MOSAIC_NAME,
target_name,
tivxKernelImgMosaicMscProcess,
tivxKernelImgMosaicMscCreate,
tivxKernelImgMosaicMscDelete,
NULL,
NULL);
if(NULL == vx_imgMosaicMsc2_kernel)
{
VX_PRINT(VX_ZONE_ERROR, "Failed to Add Img Mosaic MSC TargetKernel\n");
}
}
void tivxRemoveTargetKernelImgMosaicMsc(void)
{
vx_status status;
status = tivxRemoveTargetKernel(vx_imgMosaicMsc1_kernel);
if(status == VX_SUCCESS)
{
vx_imgMosaicMsc1_kernel = NULL;
}
else
{
VX_PRINT(VX_ZONE_ERROR, "Failed to Remove Img Mosaic MSC TargetKernel\n");
}
status = tivxRemoveTargetKernel(vx_imgMosaicMsc2_kernel);
if(status == VX_SUCCESS)
{
vx_imgMosaicMsc2_kernel = NULL;
}
else
{
VX_PRINT(VX_ZONE_ERROR, "Failed to Remove Img Mosaic MSC TargetKernel\n");
}
}
/* ========================================================================== */
/* OPENVX Callbacks */
/* ========================================================================== */
static vx_status VX_CALLBACK tivxKernelImgMosaicMscCreate(
tivx_target_kernel_instance kernel,
tivx_obj_desc_t *obj_desc[],
vx_uint16 num_params,
void *priv_arg)
{
vx_status status = VX_SUCCESS;
uint32_t i;
tivx_obj_desc_user_data_object_t *config_desc;
void *config_target_ptr;
tivx_obj_desc_image_t *out_img_desc;
tivx_obj_desc_object_array_t *input_image_arr_desc;
tivx_obj_desc_image_t *in_img_desc[TIVX_OBJECT_ARRAY_MAX_ITEMS];
tivxImgMosaicParams *params;
vx_int32 win;
vx_int32 num_inputs;
tivxImgMosaicMscObj *msc_obj = NULL;
for(i = 0U; i < num_params; i++)
{
if(NULL == obj_desc[i])
{
status = VX_FAILURE;
break;
}
}
if(VX_SUCCESS == status)
{
/* Alloc mosaic object */
msc_obj = tivxMemAlloc(sizeof(tivxImgMosaicMscObj), TIVX_MEM_EXTERNAL);
if(NULL == msc_obj)
{
status = VX_ERROR_NO_MEMORY;
}
else
{
tivxSetTargetKernelInstanceContext(kernel, msc_obj, sizeof(tivxImgMosaicMscObj));
}
}
if(VX_SUCCESS == status)
{
/* 0 - config, 1 - output image, 2 onwards is array of inputs */
num_inputs = num_params - 2U;
config_desc = (tivx_obj_desc_user_data_object_t *)
obj_desc[TIVX_IMG_MOSAIC_HOST_CONFIG_IDX];
config_target_ptr = tivxMemShared2TargetPtr(&config_desc->mem_ptr);
tivxMemBufferMap(
config_target_ptr,
config_desc->mem_size,
VX_MEMORY_TYPE_HOST,VX_READ_ONLY);
params = (tivxImgMosaicParams *) config_target_ptr;
if(params->num_windows > TIVX_IMG_MOSAIC_MAX_WINDOWS)
{
VX_PRINT(VX_ZONE_ERROR,
"Num windows %d greater than supported max %d\n",
params->num_windows, TIVX_IMG_MOSAIC_MAX_WINDOWS);
status = VX_FAILURE;
}
out_img_desc = (tivx_obj_desc_image_t *)
obj_desc[TIVX_IMG_MOSAIC_HOST_OUTPUT_IMAGE_IDX];
if(VX_SUCCESS == status)
{
for(win = 0U; win < params->num_windows; win++)
{
tivxImgMosaicWindow *window =
(tivxImgMosaicWindow *) ¶ms->windows[win];
vx_int32 in = window->input_select;
vx_int32 ch = window->channel_select;
if(in > num_inputs)
{
VX_PRINT(VX_ZONE_ERROR,
"Input ID %d greater than num_inputs %d\n",
in, num_inputs);
status = VX_FAILURE;
break;
}
input_image_arr_desc = (tivx_obj_desc_object_array_t *)
obj_desc[TIVX_IMG_MOSAIC_INPUT_START_IDX + in];
tivxGetObjDescList(
input_image_arr_desc->obj_desc_id,
(tivx_obj_desc_t **) &in_img_desc[0U],
input_image_arr_desc->num_items);
if(ch > input_image_arr_desc->num_items)
{
VX_PRINT(VX_ZONE_ERROR,
"Channel ID %d greater than num_items %d\n",
ch, input_image_arr_desc->num_items);
status = VX_FAILURE;
break;
}
if(((window->startX + window->width) > out_img_desc->width) ||
((window->startY + window->height) > out_img_desc->height))
{
VX_PRINT(VX_ZONE_ERROR,
"Window %d, does not fit within output image!\n", win);
status = VX_FAILURE;
}
}
}
VX_PRINT(VX_ZONE_INFO, "num_msc_instance = %d \n", params->num_msc_instances);
VX_PRINT(VX_ZONE_INFO, "msc_instance = %d \n", params->msc_instance);
if (params->num_msc_instances < TIVX_IMAGE_MOSAIC_MSC_MAX_INST)
{
msc_obj->max_msc_instances = params->num_msc_instances;
}
else
{
msc_obj->max_msc_instances = TIVX_IMAGE_MOSAIC_MSC_MAX_INST;
}
if (params->msc_instance > TIVX_IMAGE_MOSAIC_MSC_MAX_INST)
{
msc_obj->msc_instance = 0;
}
else
{
msc_obj->msc_instance = params->msc_instance;
}
tivxMemBufferUnmap(
config_target_ptr,
config_desc->mem_size,
VX_MEMORY_TYPE_HOST, VX_READ_ONLY);
}
if(VX_SUCCESS == status)
{
if (msc_obj->max_msc_instances == 2)
{
msc_obj->app_hwa_inst_id[0] = APP_PERF_HWA_MSC0;
msc_obj->app_hwa_inst_id[1] = APP_PERF_HWA_MSC1;
}
else if(msc_obj->max_msc_instances == 1)
{
if(msc_obj->msc_instance == 0)
{
msc_obj->app_hwa_inst_id[0] = APP_PERF_HWA_MSC0;
}
else if (msc_obj->msc_instance == 1)
{
msc_obj->app_hwa_inst_id[0] = APP_PERF_HWA_MSC1;
}
}
for (i = 0u; i < msc_obj->max_msc_instances; i ++)
{
if (0u == i)
{
msc_obj->inst_obj[i].scIdx = i;
}
else
{
msc_obj->inst_obj[i].scIdx = MSC_MAX_OUTPUT - 1U - i;
}
/* MSC driver create */
status = tivxKernelImgMosaicMscDrvCreate(&msc_obj->inst_obj[i], i);
}
}
if(VX_SUCCESS == status)
{
status = tivxKernelImgMosaicMscSetCoeffsCmd(msc_obj);
}
/* Free the allocated memory incase of error */
if(VX_SUCCESS != status)
{
if(msc_obj != NULL)
{
for (i = 0u; i < msc_obj->max_msc_instances; i ++)
{
/* MSC driver create */
status = tivxKernelImgMosaicMscDrvDelete(
&msc_obj->inst_obj[i]);
}
tivxMemFree(msc_obj, sizeof(tivxImgMosaicMscObj), TIVX_MEM_EXTERNAL);
}
}
return (status);
}
static vx_status VX_CALLBACK tivxKernelImgMosaicMscDelete(
tivx_target_kernel_instance kernel,
tivx_obj_desc_t *obj_desc[],
vx_uint16 num_params,
void *priv_arg)
{
vx_status status = VX_SUCCESS;
tivxImgMosaicMscObj *msc_obj = NULL;
uint32_t i;
vx_uint32 size;
for(i = 0U; i < num_params; i++)
{
if(NULL == obj_desc[i])
{
status = VX_FAILURE;
break;
}
}
status = tivxGetTargetKernelInstanceContext(kernel, (void **)&msc_obj, &size);
if ((VX_SUCCESS != status) || (NULL == msc_obj) || (sizeof(tivxImgMosaicMscObj) != size))
{
status = VX_FAILURE;
}
else
{
for (i = 0u; i < msc_obj->max_msc_instances; i ++)
{
status = tivxKernelImgMosaicMscDrvDelete(
&msc_obj->inst_obj[i]);
}
tivxMemFree(msc_obj, sizeof(tivxImgMosaicMscObj), TIVX_MEM_EXTERNAL);
}
return (status);
}
static vx_status VX_CALLBACK tivxKernelImgMosaicMscProcess(
tivx_target_kernel_instance kernel,
tivx_obj_desc_t *obj_desc[],
vx_uint16 num_params,
void *priv_arg)
{
vx_status status = VX_SUCCESS;
tivx_obj_desc_user_data_object_t *config_desc;
void *config_target_ptr;
tivx_obj_desc_image_t *out_img_desc;
tivx_obj_desc_image_t *in_img_desc;
void *output_image_target_ptr[2U];
vx_int32 win, in, ch, msc_cnt;
vx_int32 num_inputs;
tivxImgMosaicParams *params;
tivxImgMosaicMscObj *msc_obj = NULL;
vx_uint32 size, num_inst;
uint32_t do_process[TIVX_IMAGE_MOSAIC_MSC_MAX_INST];
vx_enum io_mem_type;
status = tivxGetTargetKernelInstanceContext(kernel, (void **)&msc_obj, &size);
if((VX_SUCCESS != status) || (NULL == msc_obj) || (sizeof(tivxImgMosaicMscObj) != size))
{
status = VX_FAILURE;
}
if(VX_SUCCESS == status)
{
/* Map config data - index 0 */
config_desc = (tivx_obj_desc_user_data_object_t *)
obj_desc[TIVX_IMG_MOSAIC_HOST_CONFIG_IDX];
config_target_ptr = tivxMemShared2TargetPtr(&config_desc->mem_ptr);
tivxMemBufferMap(
config_target_ptr,
config_desc->mem_size,
VX_MEMORY_TYPE_HOST,VX_READ_ONLY);
params = (tivxImgMosaicParams *) config_target_ptr;
if((params->enable_overlay==1) && (params->clear_count > 0U))
{
io_mem_type = VX_MEMORY_TYPE_HOST;
}
else
{
io_mem_type = TIVX_MEMORY_TYPE_DMA;
}
/* Map output image - index 1 */
out_img_desc = (tivx_obj_desc_image_t *)
obj_desc[TIVX_IMG_MOSAIC_HOST_OUTPUT_IMAGE_IDX];
output_image_target_ptr[0U] = tivxMemShared2TargetPtr(&out_img_desc->mem_ptr[0U]);
tivxMemBufferMap(
output_image_target_ptr[0U],
out_img_desc->mem_size[0U],
io_mem_type,VX_WRITE_ONLY);
if(out_img_desc->mem_ptr[1U].shared_ptr != NULL)
{
output_image_target_ptr[1U] = tivxMemShared2TargetPtr(&out_img_desc->mem_ptr[1U]);
tivxMemBufferMap(
output_image_target_ptr[1U],
out_img_desc->mem_size[1U],
io_mem_type,VX_WRITE_ONLY);
}
/* Memset output buffers for initial count */
if(params->clear_count > 0U)
{
memset(output_image_target_ptr[0U], 0U, out_img_desc->mem_size[0U]);
if(output_image_target_ptr[1U] != NULL)
{
memset(output_image_target_ptr[1U], 0x80U, out_img_desc->mem_size[1U]);
}
if(params->enable_overlay==1)
{
void vx_img_mosaic_draw_overlay_avp2(void *addr[], uint32_t pitch[], uint32_t width, uint32_t height);
void *addr[2];
uint32_t pitch[2];
uint32_t width, height;
addr[0] = output_image_target_ptr[0];
addr[1] = output_image_target_ptr[1];
width = out_img_desc->width;
height = out_img_desc->height;
pitch[0]= out_img_desc->imagepatch_addr[0].stride_y;
pitch[1]= out_img_desc->imagepatch_addr[1].stride_y;
vx_img_mosaic_draw_overlay_avp2(addr, pitch, width, height);
}
appMemCacheWb(output_image_target_ptr[0U], out_img_desc->mem_size[0U]);
if(output_image_target_ptr[1U] != NULL)
{
appMemCacheWb(output_image_target_ptr[1U], out_img_desc->mem_size[1U]);
}
params->clear_count--;
}
/* 0 - config, 1 - output image, 2 onwards is array of inputs */
num_inputs = num_params - 2U;
/* Perform scale operation for each of the output mosaic window */
for(win = 0U; win < params->num_windows; win += msc_obj->max_msc_instances)
{
if ((params->num_windows - win) < msc_obj->max_msc_instances)
{
num_inst = params->num_windows - win;
}
else
{
num_inst = msc_obj->max_msc_instances;
}
for (msc_cnt = 0u; (msc_cnt < num_inst) &&
(VX_SUCCESS == status); msc_cnt ++)
{
msc_obj->tmp_win[msc_cnt] =
(tivxImgMosaicWindow *) ¶ms->windows[win + msc_cnt];
in = msc_obj->tmp_win[msc_cnt]->input_select;
ch = msc_obj->tmp_win[msc_cnt]->channel_select;
if (in < num_inputs)
{
msc_obj->in_arr_desc[msc_cnt] = (tivx_obj_desc_object_array_t *)
obj_desc[TIVX_IMG_MOSAIC_INPUT_START_IDX + in];
tivxGetObjDescList(
msc_obj->in_arr_desc[msc_cnt]->obj_desc_id,
(tivx_obj_desc_t **) &msc_obj->in_img_desc[msc_cnt][0U],
msc_obj->in_arr_desc[msc_cnt]->num_items);
status = tivxKernelImgMosaicMscDrvPrepare(
&msc_obj->inst_obj[msc_cnt],
msc_obj->in_img_desc[msc_cnt][ch],
msc_obj->tmp_win[msc_cnt], out_img_desc);
if (VX_SUCCESS != status)
{
break;
}
msc_obj->tmp_in_ch[msc_cnt] = in;
msc_obj->tmp_ch_sel[msc_cnt] = ch;
do_process[msc_cnt] = 1;
}
else
{
do_process[msc_cnt] = 0;
}
}
for (msc_cnt = 0u; (msc_cnt < num_inst) &&
(VX_SUCCESS == status); msc_cnt ++)
{
if (do_process[msc_cnt])
{
msc_obj->inst_obj[msc_cnt].time =
tivxPlatformGetTimeInUsecs();
}
}
for (msc_cnt = 0u; (msc_cnt < num_inst) &&
(VX_SUCCESS == status); msc_cnt ++)
{
if (do_process[msc_cnt])
{
status = tivxKernelImgMosaicMscDrvSubmit(
&msc_obj->inst_obj[msc_cnt]);
}
}
for (msc_cnt = 0u; (msc_cnt < num_inst) &&
(VX_SUCCESS == status); msc_cnt ++)
{
if (do_process[msc_cnt])
{
tivxKernelImgMosaicMscDrvWait(
&msc_obj->inst_obj[msc_cnt]);
}
}
for (msc_cnt = 0u; (msc_cnt < num_inst) &&
(VX_SUCCESS == status); msc_cnt ++)
{
if (do_process[msc_cnt])
{
status = tivxKernelImgMosaicMscDrvGetReq(
&msc_obj->inst_obj[msc_cnt]);
}
}
for (msc_cnt = 0u; (msc_cnt < num_inst) &&
(VX_SUCCESS == status); msc_cnt ++)
{
if (do_process[msc_cnt])
{
msc_obj->inst_obj[msc_cnt].time =
tivxPlatformGetTimeInUsecs() - msc_obj->inst_obj[msc_cnt].time;
ch = msc_obj->tmp_win[msc_cnt]->channel_select;
in_img_desc = msc_obj->in_img_desc[msc_cnt][ch];
size = (in_img_desc->imagepatch_addr[0].dim_x *
in_img_desc->imagepatch_addr[0].dim_y) +
(in_img_desc->imagepatch_addr[1].dim_x *
in_img_desc->imagepatch_addr[1].dim_y);
appPerfStatsHwaUpdateLoad(msc_obj->app_hwa_inst_id[msc_cnt],
msc_obj->inst_obj[msc_cnt].time, size/* pixels processed */);
}
}
if (VX_SUCCESS != status)
{
break;
}
}
/* unmap config and output image buffer */
tivxMemBufferUnmap(
config_target_ptr,
config_desc->mem_size,
VX_MEMORY_TYPE_HOST, VX_READ_ONLY);
tivxMemBufferUnmap(
output_image_target_ptr[0U],
out_img_desc->mem_size[0U],
io_mem_type, VX_WRITE_ONLY);
if(out_img_desc->mem_ptr[1U].shared_ptr != NULL)
{
tivxMemBufferUnmap(
output_image_target_ptr[1U],
out_img_desc->mem_size[1U],
io_mem_type, VX_READ_ONLY);
}
}
return (status);
}
/* ========================================================================== */
/* Local Functions */
/* ========================================================================== */
static vx_status tivxKernelImgMosaicMscDrvCreate(tivxImgMosaicMscInstObj *inst_obj, uint32_t inst_id)
{
vx_status status = VX_SUCCESS;
/* Hard code to first instance */
inst_obj->msc_drv_inst_id = inst_id;
Vhwa_M2mMscCreatePrmsInit(&inst_obj->createArgs);
status = tivxEventCreate(&inst_obj->wait_for_compl);
if(VX_SUCCESS == status)
{
inst_obj->cbPrms.cbFxn = tivxKernelImgMosaicMscDrvCompCb;
inst_obj->cbPrms.appData = inst_obj;
inst_obj->handle = Fvid2_create(
FVID2_VHWA_M2M_MSC_DRV_ID,
inst_obj->msc_drv_inst_id,
&inst_obj->createArgs,
NULL,
&inst_obj->cbPrms);
if(NULL == inst_obj->handle)
{
VX_PRINT(VX_ZONE_ERROR, "Fvid2_create failed\n");
status = VX_ERROR_NO_RESOURCES;
}
else
{
Fvid2Frame_init(&inst_obj->inFrm);
Fvid2Frame_init(&inst_obj->outFrm);
}
}
else
{
VX_PRINT(VX_ZONE_ERROR, "Failed to allocate Event\n");
}
return (status);
}
static vx_status tivxKernelImgMosaicMscDrvDelete(tivxImgMosaicMscInstObj *inst_obj)
{
vx_status status = VX_SUCCESS;
if(NULL != inst_obj->handle)
{
Fvid2_delete(inst_obj->handle, NULL);
inst_obj->handle = NULL;
}
if(NULL != inst_obj->wait_for_compl)
{
tivxEventDelete(&inst_obj->wait_for_compl);
inst_obj->wait_for_compl = NULL;
}
return (status);
}
/* ========================================================================== */
/* Control Command Implementation */
/* ========================================================================== */
static vx_status tivxKernelImgMosaicMscSetCoeffsCmd(tivxImgMosaicMscObj *msc_obj)
{
vx_status status = VX_SUCCESS;
int32_t fvid2_status = FVID2_SOK;
uint32_t cnt;
tivx_vpac_msc_coefficients_t coeffs;
Msc_Coeff *coeffCfg;
scale_set_coeff(&coeffs, VX_INTERPOLATION_BILINEAR);
coeffCfg = &msc_obj->coeffCfg;
Msc_coeffInit(coeffCfg);
for (cnt = 0u; cnt < MSC_MAX_SP_COEFF_SET; cnt ++)
{
coeffCfg->spCoeffSet[cnt] = &coeffs.single_phase[cnt][0u];
}
for (cnt = 0u; cnt < MSC_MAX_MP_COEFF_SET; cnt ++)
{
coeffCfg->mpCoeffSet[cnt] = &coeffs.multi_phase[cnt][0u];
}
if (VX_SUCCESS == status)
{
fvid2_status = Fvid2_control(msc_obj->inst_obj[0u].handle, VHWA_M2M_IOCTL_MSC_SET_COEFF,
coeffCfg, NULL);
if (FVID2_SOK != fvid2_status)
{
VX_PRINT(VX_ZONE_ERROR,
"tivxKernelImgMosaicMscSetCoeffsCmd: Failed to create coefficients\n");
status = VX_FAILURE;
}
}
return (status);
}
static vx_status tivxKernelImgMosaicMscDrvPrepare(
tivxImgMosaicMscInstObj *inst_obj,
const tivx_obj_desc_image_t *in_img_desc,
const tivxImgMosaicWindow *window,
const tivx_obj_desc_image_t* out_img_desc)
{
vx_status status = VX_SUCCESS;
Vhwa_M2mMscParams *msc_prms;
Fvid2_Format *fmt;
Msc_ScConfig *sc_cfg;
Fvid2_Frame *frm;
uint32_t plane_cnt;
vx_uint32 startX, startY;
uint32_t scIdx;
msc_prms = &inst_obj->msc_prms;
Vhwa_m2mMscParamsInit(msc_prms);
/* Set input format */
fmt = &msc_prms->inFmt;
scIdx = inst_obj->scIdx;
if(in_img_desc->format == VX_DF_IMAGE_U8 ||in_img_desc->format == VX_DF_IMAGE_U16)
{
fmt->dataFormat = FVID2_DF_LUMA_ONLY;
}
else
{
fmt->dataFormat = FVID2_DF_YUV420SP_UV;
}
if(in_img_desc->format == VX_DF_IMAGE_U16)
{
fmt->ccsFormat = FVID2_CCSF_BITS12_UNPACKED16;
}
else
{
fmt->ccsFormat = FVID2_CCSF_BITS8_PACKED;
}
fmt->width = in_img_desc->imagepatch_addr[0U].dim_x;
fmt->height = in_img_desc->imagepatch_addr[0U].dim_y;
fmt->pitch[0U] = in_img_desc->imagepatch_addr[0U].stride_y;
fmt->pitch[1U] = in_img_desc->imagepatch_addr[1U].stride_y;
/* Set output format */
sc_cfg = &msc_prms->mscCfg.scCfg[scIdx]; /* Only one output used */
tivxKernelImgMosaicMscDrvSetScCfg(sc_cfg, in_img_desc, window);
fmt = &msc_prms->outFmt[scIdx]; /* Only one output used */
if(out_img_desc->format == VX_DF_IMAGE_U8 ||in_img_desc->format == VX_DF_IMAGE_U16)
{
fmt->dataFormat = FVID2_DF_LUMA_ONLY;
}
else
{
fmt->dataFormat = FVID2_DF_YUV420SP_UV;
}
if(out_img_desc->format == VX_DF_IMAGE_U16)
{
fmt->ccsFormat = FVID2_CCSF_BITS12_UNPACKED16;
}
else
{
fmt->ccsFormat = FVID2_CCSF_BITS8_PACKED;
}
fmt->width = sc_cfg->outWidth;
fmt->height = sc_cfg->outHeight;
/* Use the output overlay pitch */
fmt->pitch[0U] = out_img_desc->imagepatch_addr[0U].stride_y;
fmt->pitch[1U] = out_img_desc->imagepatch_addr[1U].stride_y;
status = Fvid2_control(
inst_obj->handle, VHWA_M2M_IOCTL_MSC_SET_PARAMS, msc_prms, NULL);
if(FVID2_SOK != status)
{
VX_PRINT(VX_ZONE_ERROR, "Fvid2_control Failed: Set Params\n");
status = VX_FAILURE;
}
else
{
status = VX_SUCCESS;
}
if(VX_SUCCESS == status)
{
frm = &inst_obj->inFrm;
for(plane_cnt = 0U; plane_cnt < TIVX_IMAGE_MOSAIC_MAX_PLANES; plane_cnt++)
{
frm->addr[plane_cnt] = tivxMemShared2PhysPtr(
in_img_desc->mem_ptr[plane_cnt].shared_ptr,
in_img_desc->mem_ptr[plane_cnt].mem_heap_region);
}
/* Adjust start X/Y so that we center the input when input size is less
* than the window size */
startX = window->startX + ((window->width - sc_cfg->outWidth) >> 1U);
startY = window->startY + ((window->height - sc_cfg->outHeight) >> 1U);
startX = ((startX >> 1U) << 1U); /* Make it even for YUV420SP */
startY = ((startY >> 1U) << 1U); /* Make it even for YUV420SP */
frm = &inst_obj->outFrm;
for(plane_cnt = 0U; plane_cnt < TIVX_IMAGE_MOSAIC_MAX_PLANES; plane_cnt++)
{
uint64_t temp;
temp = tivxMemShared2PhysPtr(
out_img_desc->mem_ptr[plane_cnt].shared_ptr,
out_img_desc->mem_ptr[plane_cnt].mem_heap_region);
/* Manipulate output overlay pointer to point to right offset
* to do scaling */
if(0U == plane_cnt)
{
frm->addr[plane_cnt] = temp +
(startY * out_img_desc->imagepatch_addr[0U].stride_y) +
startX;
}
else
{
frm->addr[plane_cnt] = temp +
((startY >> 1U) * out_img_desc->imagepatch_addr[0U].stride_y) +
startX;
}
}
}
return (status);
}
static vx_status tivxKernelImgMosaicMscDrvSubmit(tivxImgMosaicMscInstObj *inst_obj)
{
vx_status status = VX_SUCCESS;
Fvid2FrameList_init(&inst_obj->inFrmList);
Fvid2FrameList_init(&inst_obj->outFrmList);
/* Set up Framelist */
inst_obj->inFrmList.numFrames = 1U;
inst_obj->inFrmList.frames[0U] = &inst_obj->inFrm;
inst_obj->outFrmList.numFrames = MSC_MAX_OUTPUT;
inst_obj->outFrmList.frames[inst_obj->scIdx] = &inst_obj->outFrm;
/* Submit MSC Request*/
status = Fvid2_processRequest(
inst_obj->handle,
&inst_obj->inFrmList,
&inst_obj->outFrmList,
FVID2_TIMEOUT_FOREVER);
if(FVID2_SOK != status)
{
VX_PRINT(VX_ZONE_ERROR, "Failed to Submit Request\n");
status = VX_FAILURE;
}
return (status);
}
static void tivxKernelImgMosaicMscDrvWait(tivxImgMosaicMscInstObj *inst_obj)
{
/* Wait for Frame Completion */
tivxEventWait(inst_obj->wait_for_compl, TIVX_EVENT_TIMEOUT_WAIT_FOREVER);
}
static vx_status tivxKernelImgMosaicMscDrvGetReq(tivxImgMosaicMscInstObj *inst_obj)
{
vx_status status = VX_SUCCESS;
status = Fvid2_getProcessedRequest(
inst_obj->handle,
&inst_obj->inFrmList,
&inst_obj->outFrmList,
0U);
if(FVID2_SOK != status)
{
VX_PRINT(VX_ZONE_ERROR, "Failed to Get Processed Request\n");
/* status = VX_FAILURE; */
}
return (status);
}
static void tivxKernelImgMosaicMscDrvSetScCfg(
Msc_ScConfig *sc_cfg,
const tivx_obj_desc_image_t *in_img_desc,
const tivxImgMosaicWindow *window)
{
sc_cfg->enable = TRUE;
if(window->width > in_img_desc->imagepatch_addr[0U].dim_x)
{
/* Upscaling not supported - set MSC width same as input */
sc_cfg->outWidth = in_img_desc->imagepatch_addr[0U].dim_x;
}
else
{
sc_cfg->outWidth = window->width;
}
if(window->height > in_img_desc->imagepatch_addr[0U].dim_y)
{
/* Upscaling not supported - set MSC height same as input */
sc_cfg->outHeight = in_img_desc->imagepatch_addr[0U].dim_y;
}
else
{
sc_cfg->outHeight = window->height;
}
/* Crop setting - same as input size */
if(window->enable_roi == 0)
{
sc_cfg->inRoi.cropStartX = 0U;
sc_cfg->inRoi.cropStartY = 0U;
sc_cfg->inRoi.cropWidth = in_img_desc->imagepatch_addr[0U].dim_x;
sc_cfg->inRoi.cropHeight = in_img_desc->imagepatch_addr[0U].dim_y;
}
else
{
sc_cfg->inRoi.cropStartX = window->roiStartX;
sc_cfg->inRoi.cropStartY = window->roiStartY;
sc_cfg->inRoi.cropWidth = window->roiWidth;
sc_cfg->inRoi.cropHeight = window->roiHeight;
}
/* For Scale, multi phase coefficients are used. */
sc_cfg->filtMode = MSC_FILTER_MODE_MULTI_PHASE;
sc_cfg->phaseMode = MSC_PHASE_MODE_64PHASE;
sc_cfg->hsMpCoeffSel = MSC_MULTI_64PHASE_COEFF_SET_0;
sc_cfg->vsMpCoeffSel = MSC_MULTI_64PHASE_COEFF_SET_0;
sc_cfg->coeffShift = MSC_COEFF_SHIFT_8;
}
static void scale_set_coeff(
tivx_vpac_msc_coefficients_t *coeff,
uint32_t interpolation)
{
uint32_t i;
uint32_t idx;
uint32_t weight;
idx = 0;
coeff->single_phase[0][idx++] = 0;
coeff->single_phase[0][idx++] = 0;
coeff->single_phase[0][idx++] = 256;
coeff->single_phase[0][idx++] = 0;
coeff->single_phase[0][idx++] = 0;
idx = 0;
coeff->single_phase[1][idx++] = 0;
coeff->single_phase[1][idx++] = 0;
coeff->single_phase[1][idx++] = 256;
coeff->single_phase[1][idx++] = 0;
coeff->single_phase[1][idx++] = 0;
if(VX_INTERPOLATION_BILINEAR == interpolation)
{
idx = 0;
for(i = 0; i < 32; i++)
{
weight = i<<2;
coeff->multi_phase[0][idx++] = 0;
coeff->multi_phase[0][idx++] = 0;
coeff->multi_phase[0][idx++] = 256-weight;
coeff->multi_phase[0][idx++] = weight;
coeff->multi_phase[0][idx++] = 0;
}
idx = 0;
for(i = 0; i < 32; i++)
{
weight = (i+32)<<2;
coeff->multi_phase[1][idx++] = 0;
coeff->multi_phase[1][idx++] = 0;
coeff->multi_phase[1][idx++] = 256-weight;
coeff->multi_phase[1][idx++] = weight;
coeff->multi_phase[1][idx++] = 0;
}
idx = 0;
for(i = 0; i < 32; i++)
{
weight = i<<2;
coeff->multi_phase[2][idx++] = 0;
coeff->multi_phase[2][idx++] = 0;
coeff->multi_phase[2][idx++] = 256-weight;
coeff->multi_phase[2][idx++] = weight;
coeff->multi_phase[2][idx++] = 0;
}
idx = 0;
for(i = 0; i < 32; i++)
{
weight = (i+32)<<2;
coeff->multi_phase[3][idx++] = 0;
coeff->multi_phase[3][idx++] = 0;
coeff->multi_phase[3][idx++] = 256-weight;
coeff->multi_phase[3][idx++] = weight;
coeff->multi_phase[3][idx++] = 0;
}
}
else /* STR_VX_INTERPOLATION_NEAREST_NEIGHBOR */
{
idx = 0;
for(i = 0; i < 32; i++)
{
coeff->multi_phase[0][idx++] = 0;
coeff->multi_phase[0][idx++] = 0;
coeff->multi_phase[0][idx++] = 256;
coeff->multi_phase[0][idx++] = 0;
coeff->multi_phase[0][idx++] = 0;
}
idx = 0;
for(i = 0; i < 32; i++)
{
coeff->multi_phase[1][idx++] = 0;
coeff->multi_phase[1][idx++] = 0;
coeff->multi_phase[1][idx++] = 0;
coeff->multi_phase[1][idx++] = 256;
coeff->multi_phase[1][idx++] = 0;
}
idx = 0;
for(i = 0; i < 32; i++)
{
coeff->multi_phase[2][idx++] = 0;
coeff->multi_phase[2][idx++] = 0;
coeff->multi_phase[2][idx++] = 256;
coeff->multi_phase[2][idx++] = 0;
coeff->multi_phase[2][idx++] = 0;
}
idx = 0;
for(i = 0; i < 32; i++)
{
coeff->multi_phase[3][idx++] = 0;
coeff->multi_phase[3][idx++] = 0;
coeff->multi_phase[3][idx++] = 0;
coeff->multi_phase[3][idx++] = 256;
coeff->multi_phase[3][idx++] = 0;
}
}
}
/* ========================================================================== */
/* Driver Callbacks */
/* ========================================================================== */
static int32_t tivxKernelImgMosaicMscDrvCompCb(Fvid2_Handle handle, void *appData)
{
tivxImgMosaicMscInstObj *inst_obj = (tivxImgMosaicMscInstObj *) appData;
if(NULL != inst_obj)
{
tivxEventPost(inst_obj->wait_for_compl);
}
return FVID2_SOK;
}
what's the matter with it?
Regards,
Jason