/** @brief Source file of vendor ai net sample code. @file ai_2net.c @ingroup ai_net_sample @note Nothing. Copyright Novatek Microelectronics Corp. 2020. All rights reserved. */ /*-----------------------------------------------------------------------------*/ /* Including Files */ /*-----------------------------------------------------------------------------*/ #include #include #include #include #include #include "hdal.h" #include "hd_debug.h" #include "vendor_ai.h" #include "vendor_ai_cpu/vendor_ai_cpu.h" #include "vendor_ai_cpu_postproc.h" // platform dependent #if defined(__LINUX) #include //for pthread API #define MAIN(argc, argv) int main(int argc, char** argv) #define GETCHAR() getchar() #else #include #include //for pthread API #include //for sleep API #define sleep(x) vos_util_delay_ms(1000*(x)) #define msleep(x) vos_util_delay_ms(x) #define usleep(x) vos_util_delay_us(x) #include //for MAIN(), GETCHAR() API #define MAIN(argc, argv) EXAMFUNC_ENTRY(ai_2net, argc, argv) #define GETCHAR() NVT_EXAMSYS_GETCHAR() #endif #define DEBUG_MENU 1 #define CHKPNT printf("\033[37mCHK: %s, %s: %d\033[0m\r\n",__FILE__,__func__,__LINE__) #define DBGH(x) printf("\033[0;35m%s=0x%08X\033[0m\r\n", #x, x) #define DBGD(x) printf("\033[0;35m%s=%d\033[0m\r\n", #x, x) /////////////////////////////////////////////////////////////////////////////// #define NET_PATH_ID UINT32 #define VENDOR_AI_CFG 0x000f0000 //vendor ai config #define AI_RGB_BUFSIZE(w, h) (ALIGN_CEIL_4((w) * HD_VIDEO_PXLFMT_BPP(HD_VIDEO_PXLFMT_RGB888_PLANAR) / 8) * (h)) #define NET_VDO_SIZE_W 1920 //max for net #define NET_VDO_SIZE_H 1080 //max for net #define NN_RUN_NET_NUM 2 /////////////////////////////////////////////////////////////////////////////// /*-----------------------------------------------------------------------------*/ /* Type Definitions */ /*-----------------------------------------------------------------------------*/ typedef struct _MEM_PARM { UINT32 pa; UINT32 va; UINT32 size; UINT32 blk; } MEM_PARM; /*-----------------------------------------------------------------------------*/ /* Global Functions */ /*-----------------------------------------------------------------------------*/ static HD_RESULT mem_get(MEM_PARM *mem_parm, UINT32 size, UINT32 id) { HD_RESULT ret = HD_OK; UINT32 pa = 0; void *va = NULL; HD_COMMON_MEM_VB_BLK blk; blk = hd_common_mem_get_block(HD_COMMON_MEM_USER_DEFINIED_POOL + id, size, DDR_ID0); if (HD_COMMON_MEM_VB_INVALID_BLK == blk) { printf("hd_common_mem_get_block fail\r\n"); return HD_ERR_NG; } pa = hd_common_mem_blk2pa(blk); if (pa == 0) { printf("not get buffer, pa=%08x\r\n", (int)pa); return HD_ERR_NOMEM; } va = hd_common_mem_mmap(HD_COMMON_MEM_MEM_TYPE_CACHE, pa, size); /* Release buffer */ if (va == 0) { ret = hd_common_mem_munmap(va, size); if (ret != HD_OK) { printf("mem unmap fail\r\n"); return ret; } } mem_parm->pa = pa; mem_parm->va = (UINT32)va; mem_parm->size = size; mem_parm->blk = blk; return HD_OK; } static HD_RESULT mem_rel(MEM_PARM *mem_parm) { HD_RESULT ret = HD_OK; /* Release in buffer */ if (mem_parm->va) { ret = hd_common_mem_munmap((void *)mem_parm->va, mem_parm->size); if (ret != HD_OK) { printf("mem_uninit : (g_mem.va)hd_common_mem_munmap fail.\r\n"); return ret; } } //ret = hd_common_mem_release_block((HD_COMMON_MEM_VB_BLK)g_mem.pa); ret = hd_common_mem_release_block(mem_parm->blk); if (ret != HD_OK) { printf("mem_uninit : (g_mem.pa)hd_common_mem_release_block fail.\r\n"); return ret; } mem_parm->pa = 0; mem_parm->va = 0; mem_parm->size = 0; mem_parm->blk = (UINT32)-1; return HD_OK; } static HD_RESULT mem_alloc(MEM_PARM *mem_parm, CHAR* name, UINT32 size) { HD_RESULT ret = HD_OK; UINT32 pa = 0; void *va = NULL; //alloc private pool ret = hd_common_mem_alloc(name, &pa, (void**)&va, size, DDR_ID0); if (ret!= HD_OK) { return ret; } mem_parm->pa = pa; mem_parm->va = (UINT32)va; mem_parm->size = size; mem_parm->blk = (UINT32)-1; return HD_OK; } static HD_RESULT mem_free(MEM_PARM *mem_parm) { HD_RESULT ret = HD_OK; //free private pool ret = hd_common_mem_free(mem_parm->pa, (void *)mem_parm->va); if (ret!= HD_OK) { return ret; } mem_parm->pa = 0; mem_parm->va = 0; mem_parm->size = 0; mem_parm->blk = (UINT32)-1; return HD_OK; } static INT32 mem_load(MEM_PARM *mem_parm, const CHAR *filename) { FILE *fd; INT32 size = 0; fd = fopen(filename, "rb"); if (!fd) { printf("cannot read %s\r\n", filename); size = -1; goto exit; } fseek(fd, 0, SEEK_END); size = ftell(fd); fseek(fd, 0, SEEK_SET); // check "ai_in_buf" enough or not if (mem_parm->size < (UINT32)size) { printf("ERROR: ai_in_buf(%u) is not enough, input file(%u)\r\n", mem_parm->size, (UINT32)size); size = -1; goto exit; } if (size < 0) { printf("getting %s size failed\r\n", filename); goto exit; } else if ((INT32)fread((VOID *)mem_parm->va, 1, size, fd) != size) { printf("read size < %ld\r\n", size); size = -1; goto exit; } mem_parm->size = size; // we use cpu to read memory, which needs to deal cache flush. if(hd_common_mem_flush_cache((VOID *)mem_parm->va, mem_parm->size) != HD_OK) { printf("flush cache failed.\r\n"); } exit: if (fd) { fclose(fd); } return size; } /*-----------------------------------------------------------------------------*/ /* Input Functions */ /*-----------------------------------------------------------------------------*/ /////////////////////////////////////////////////////////////////////////////// typedef struct _NET_IN_CONFIG { CHAR input_filename[256]; UINT32 w; UINT32 h; UINT32 c; UINT32 loff; UINT32 fmt; } NET_IN_CONFIG; typedef struct _NET_IN { NET_IN_CONFIG in_cfg; MEM_PARM input_mem; UINT32 in_id; VENDOR_AI_BUF src_img; } NET_IN; static NET_IN *g_in = NULL; static HD_RESULT _load_buf(MEM_PARM *mem_parm, CHAR *filename, VENDOR_AI_BUF *p_buf, UINT32 w, UINT32 h, UINT32 c, UINT32 loff, UINT32 fmt) { INT32 file_len; #if 0 UINT32 key = 0; #endif file_len = mem_load(mem_parm, filename); if (file_len < 0) { printf("load buf(%s) fail\r\n", filename); return HD_ERR_NG; } printf("load buf(%s) ok\r\n", filename); p_buf->width = w; p_buf->height = h; p_buf->channel = c; p_buf->line_ofs = loff; p_buf->fmt = fmt; p_buf->pa = mem_parm->pa; p_buf->va = mem_parm->va; p_buf->sign = MAKEFOURCC('A','B','U','F'); p_buf->size = loff * h * 3 / 2; return HD_OK; } static HD_RESULT input_init(void) { HD_RESULT ret = HD_OK; int i; for (i = 0; i < 16; i++) { NET_IN* p_net = g_in + i; p_net->in_id = i; } return ret; } static HD_RESULT input_uninit(void) { HD_RESULT ret = HD_OK; return ret; } static INT32 input_mem_config(NET_PATH_ID net_path, HD_COMMON_MEM_INIT_CONFIG* p_mem_cfg, void* p_cfg, INT32 i) { return i; } static HD_RESULT input_set_config(NET_PATH_ID net_path, NET_IN_CONFIG* p_in_cfg) { HD_RESULT ret = HD_OK; NET_IN* p_net = g_in + net_path; UINT32 proc_id = p_net->in_id; memcpy((void*)&p_net->in_cfg, (void*)p_in_cfg, sizeof(NET_IN_CONFIG)); printf("proc_id(%u) set in_cfg: file(%s), buf=(%u,%u,%u,%u,%08x)\r\n", proc_id, p_net->in_cfg.input_filename, p_net->in_cfg.w, p_net->in_cfg.h, p_net->in_cfg.c, p_net->in_cfg.loff, p_net->in_cfg.fmt); return ret; } static HD_RESULT input_open(NET_PATH_ID net_path) { HD_RESULT ret = HD_OK; NET_IN* p_net = g_in + net_path; UINT32 proc_id = p_net->in_id; ret = mem_alloc(&p_net->input_mem, "ai_in_buf", AI_RGB_BUFSIZE(p_net->in_cfg.w, p_net->in_cfg.h)); if (ret != HD_OK) { printf("proc_id(%lu) alloc ai_in_buf fail\r\n", proc_id); return HD_ERR_FAIL; } ret = _load_buf(&p_net->input_mem, p_net->in_cfg.input_filename, &p_net->src_img, p_net->in_cfg.w, p_net->in_cfg.h, p_net->in_cfg.c, p_net->in_cfg.loff, p_net->in_cfg.fmt); if (ret != HD_OK) { printf("proc_id(%u) input_open fail=%d\n", proc_id, ret); } return ret; } static HD_RESULT input_close(NET_PATH_ID net_path) { HD_RESULT ret = HD_OK; NET_IN* p_net = g_in + net_path; mem_free(&p_net->input_mem); return ret; } static HD_RESULT input_start(NET_PATH_ID net_path) { HD_RESULT ret = HD_OK; return ret; } static HD_RESULT input_stop(NET_PATH_ID net_path) { HD_RESULT ret = HD_OK; return ret; } static HD_RESULT input_pull_buf(NET_PATH_ID net_path, VENDOR_AI_BUF *p_in, INT32 wait_ms) { HD_RESULT ret = HD_OK; NET_IN* p_net = g_in + net_path; memcpy((void*)p_in, (void*)&(p_net->src_img), sizeof(VENDOR_AI_BUF)); return ret; } /////////////////////////////////////////////////////////////////////////////// /*-----------------------------------------------------------------------------*/ /* Network Functions */ /*-----------------------------------------------------------------------------*/ typedef struct _NET_PROC_CONFIG { CHAR model_filename[256]; INT32 binsize; int job_method; int job_wait_ms; int buf_method; void *p_share_model; CHAR label_filename[256]; } NET_PROC_CONFIG; typedef struct _NET_PROC { NET_PROC_CONFIG net_cfg; MEM_PARM proc_mem; UINT32 proc_id; CHAR out_class_labels[MAX_CLASS_NUM * VENDOR_AIS_LBL_LEN]; MEM_PARM rslt_mem; MEM_PARM io_mem; } NET_PROC; static NET_PROC *g_net = NULL; static INT32 _getsize_model(char* filename) { FILE *bin_fd; UINT32 bin_size = 0; bin_fd = fopen(filename, "rb"); if (!bin_fd) { printf("get bin(%s) size fail\n", filename); return (-1); } fseek(bin_fd, 0, SEEK_END); bin_size = ftell(bin_fd); fseek(bin_fd, 0, SEEK_SET); fclose(bin_fd); return bin_size; } static UINT32 _load_model(CHAR *filename, UINT32 va) { FILE *fd; UINT32 file_size = 0, read_size = 0; const UINT32 model_addr = va; //DBG_DUMP("model addr = %08x\r\n", (int)model_addr); fd = fopen(filename, "rb"); if (!fd) { printf("load model(%s) fail\r\n", filename); return 0; } fseek ( fd, 0, SEEK_END ); file_size = ALIGN_CEIL_4( ftell(fd) ); fseek ( fd, 0, SEEK_SET ); read_size = fread ((void *)model_addr, 1, file_size, fd); if (read_size != file_size) { printf("size mismatch, real = %d, idea = %d\r\n", (int)read_size, (int)file_size); } fclose(fd); printf("load model(%s) ok\r\n", filename); return read_size; } static UINT32 _load_part_model(CHAR *filename, UINT32 part_size, UINT32 va) { FILE *fd; UINT32 read_size = 0; const UINT32 model_addr = va; fd = fopen(filename, "rb"); if (!fd) { printf("load model(%s) fail\r\n", filename); return 0; } read_size = fread ((void *)model_addr, 1, part_size, fd); if (read_size != part_size) { printf("size mismatch, real = %d, idea = %d\r\n", (int)read_size, (int)part_size); } fclose(fd); printf("load part_model(%s) ok\r\n", filename); return read_size; } static HD_RESULT _load_label(UINT32 addr, UINT32 line_len, const CHAR *filename) { FILE *fd; CHAR *p_line = (CHAR *)addr; fd = fopen(filename, "r"); if (!fd) { printf("load label(%s) fail\r\n", filename); return HD_ERR_NG; } while (fgets(p_line, line_len, fd) != NULL) { p_line[strlen(p_line) - 1] = '\0'; // remove newline character p_line += line_len; } if (fd) { fclose(fd); } printf("load label(%s) ok\r\n", filename); return HD_OK; } static HD_RESULT network_init(void) { HD_RESULT ret = HD_OK; int i; ret = hd_videoproc_init(); if (ret != HD_OK) { printf("hd_videoproc_init fail=%d\n", ret); return ret; } // config extend engine plugin, process scheduler { UINT32 schd = VENDOR_AI_PROC_SCHD_FAIR; vendor_ai_cfg_set(VENDOR_AI_CFG_PLUGIN_ENGINE, vendor_ai_cpu1_get_engine()); vendor_ai_cfg_set(VENDOR_AI_CFG_PROC_SCHD, &schd); } ret = vendor_ai_init(); if (ret != HD_OK) { printf("vendor_ai_init fail=%d\n", ret); return ret; } for (i = 0; i < 16; i++) { NET_PROC* p_net = g_net + i; p_net->proc_id = i; } return ret; } static HD_RESULT network_uninit(void) { HD_RESULT ret = HD_OK; ret = hd_videoproc_uninit(); if (ret != HD_OK) { printf("hd_videoproc_uninit fail=%d\n", ret); } ret = vendor_ai_uninit(); if (ret != HD_OK) { printf("vendor_ai_uninit fail=%d\n", ret); } return ret; } static INT32 network_mem_config(NET_PATH_ID net_path, HD_COMMON_MEM_INIT_CONFIG* p_mem_cfg, void* p_cfg, INT32 i) { NET_PROC* p_net = g_net + net_path; UINT32 proc_id; NET_PROC_CONFIG* p_proc_cfg = (NET_PROC_CONFIG*)p_cfg; p_net->proc_id = net_path; proc_id = p_net->proc_id; memcpy((void*)&p_net->net_cfg, (void*)p_proc_cfg, sizeof(NET_PROC_CONFIG)); if (strlen(p_net->net_cfg.model_filename) == 0) { printf("proc_id(%u) input model is null\r\n", proc_id); return HD_ERR_NG; } p_net->net_cfg.binsize = _getsize_model(p_net->net_cfg.model_filename); if (p_net->net_cfg.binsize <= 0) { printf("proc_id(%u) input model is not exist?\r\n", proc_id); return HD_ERR_NG; } printf("proc_id(%u) set net_mem_cfg: model-file(%s), binsize=%d\r\n", proc_id, p_net->net_cfg.model_filename, p_net->net_cfg.binsize); printf("proc_id(%u) set net_mem_cfg: label-file(%s)\r\n", proc_id, p_net->net_cfg.label_filename); // config common pool (in) p_mem_cfg->pool_info[i].type = HD_COMMON_MEM_USER_DEFINIED_POOL + proc_id; p_mem_cfg->pool_info[i].blk_size = p_net->net_cfg.binsize; p_mem_cfg->pool_info[i].blk_cnt = 1; p_mem_cfg->pool_info[i].ddr_id = DDR_ID0; i++; return i; } static HD_RESULT network_set_config(NET_PATH_ID net_path, NET_PROC_CONFIG* p_proc_cfg) { HD_RESULT ret = HD_OK; NET_PROC* p_net = g_net + net_path; UINT32 binsize = p_net->net_cfg.binsize; UINT32 proc_id; p_net->proc_id = net_path; proc_id = p_net->proc_id; memcpy((void*)&p_net->net_cfg, (void*)p_proc_cfg, sizeof(NET_PROC_CONFIG)); p_net->net_cfg.binsize = binsize; printf("proc_id(%u) set net_cfg: job-opt=(%u,%d), buf-opt(%u)\r\n", proc_id, p_net->net_cfg.job_method, (int)p_net->net_cfg.job_wait_ms, p_net->net_cfg.buf_method); // set buf opt { VENDOR_AI_NET_CFG_BUF_OPT cfg_buf_opt = {0}; cfg_buf_opt.method = p_net->net_cfg.buf_method; cfg_buf_opt.ddr_id = DDR_ID0; vendor_ai_net_set(proc_id, VENDOR_AI_NET_PARAM_CFG_BUF_OPT, &cfg_buf_opt); } // set job opt { VENDOR_AI_NET_CFG_JOB_OPT cfg_job_opt = {0}; cfg_job_opt.method = p_net->net_cfg.job_method; cfg_job_opt.wait_ms = p_net->net_cfg.job_wait_ms; cfg_job_opt.schd_parm = VENDOR_AI_FAIR_CORE_ALL; //FAIR dispatch to ALL core vendor_ai_net_set(proc_id, VENDOR_AI_NET_PARAM_CFG_JOB_OPT, &cfg_job_opt); } return ret; } static HD_RESULT network_alloc_io_buf(NET_PATH_ID net_path) { HD_RESULT ret = HD_OK; NET_PROC* p_net = g_net + net_path; UINT32 proc_id = p_net->proc_id; VENDOR_AI_NET_CFG_WORKBUF wbuf = {0}; ret = vendor_ai_net_get(proc_id, VENDOR_AI_NET_PARAM_CFG_WORKBUF, &wbuf); if (ret != HD_OK) { printf("proc_id(%lu) get VENDOR_AI_NET_PARAM_CFG_WORKBUF fail\r\n", proc_id); return HD_ERR_FAIL; } ret = mem_alloc(&p_net->io_mem, "ai_io_buf", wbuf.size); if (ret != HD_OK) { printf("proc_id(%lu) alloc ai_io_buf fail\r\n", proc_id); return HD_ERR_FAIL; } wbuf.pa = p_net->io_mem.pa; wbuf.va = p_net->io_mem.va; wbuf.size = p_net->io_mem.size; ret = vendor_ai_net_set(proc_id, VENDOR_AI_NET_PARAM_CFG_WORKBUF, &wbuf); if (ret != HD_OK) { printf("proc_id(%lu) set VENDOR_AI_NET_PARAM_CFG_WORKBUF fail\r\n", proc_id); return HD_ERR_FAIL; } printf("alloc_io_buf: work buf, pa = %#lx, va = %#lx, size = %lu\r\n", wbuf.pa, wbuf.va, wbuf.size); return ret; } static HD_RESULT network_free_io_buf(NET_PATH_ID net_path) { HD_RESULT ret = HD_OK; NET_PROC* p_net = g_net + net_path; if (p_net->io_mem.pa && p_net->io_mem.va) { mem_free(&p_net->io_mem); } return ret; } static HD_RESULT network_open(NET_PATH_ID net_path) { HD_RESULT ret = HD_OK; NET_PROC* p_net = g_net + net_path; UINT32 proc_id; p_net->proc_id = net_path; proc_id = p_net->proc_id; UINT32 loadsize = 0; if (strlen(p_net->net_cfg.model_filename) == 0) { printf("proc_id(%u) input model is null\r\n", proc_id); return 0; } if (p_net->net_cfg.p_share_model == NULL ) { mem_get(&p_net->proc_mem, p_net->net_cfg.binsize, proc_id); //load file loadsize = _load_model(p_net->net_cfg.model_filename, p_net->proc_mem.va); if (loadsize <= 0) { printf("proc_id(%u) input model load fail: %s\r\n", proc_id, p_net->net_cfg.model_filename); return 0; } // load label ret = _load_label((UINT32)p_net->out_class_labels, VENDOR_AIS_LBL_LEN, p_net->net_cfg.label_filename); if (ret != HD_OK) { printf("proc_id(%u) load_label fail=%d\n", proc_id, ret); return HD_ERR_FAIL; } // set model vendor_ai_net_set(proc_id, VENDOR_AI_NET_PARAM_CFG_MODEL, (VENDOR_AI_NET_CFG_MODEL*)&p_net->proc_mem); } else { //--- this net_path want to share other share_net model --- NET_PROC* p_share_net = (NET_PROC*)p_net->net_cfg.p_share_model; VENDOR_AI_NET_INFO net_info = {0}; // query share_net for necessary size( the size which can't reuse ) vendor_ai_net_get(p_share_net->proc_id, VENDOR_AI_NET_PARAM_INFO, &net_info); if (net_info.model_part1_size == 0) { printf("proc_id(%u) get share proc_id(%u) necessary size fail\r\n", proc_id, p_share_net->proc_id); return HD_ERR_FAIL; } ret = mem_alloc(&p_net->proc_mem, "ai_parm_buf", net_info.model_part1_size); if (ret != HD_OK) { printf("proc_id(%u) alloc ai_parm_buf fail\r\n", proc_id); return HD_ERR_FAIL; } // load file ( load share_net model for necessary part only ) loadsize = _load_part_model(p_share_net->net_cfg.model_filename, net_info.model_part1_size, p_net->proc_mem.va); if (loadsize <= 0) { printf("proc_id(%u) input model load fail: %s\r\n", proc_id, p_share_net->net_cfg.model_filename); return 0; } // load label ( load share_net label ) ret = _load_label((UINT32)p_net->out_class_labels, VENDOR_AIS_LBL_LEN, p_share_net->net_cfg.label_filename); if (ret != HD_OK) { printf("proc_id(%u) load_label fail=%d\n", proc_id, ret); return HD_ERR_FAIL; } // set model vendor_ai_net_set(proc_id, VENDOR_AI_NET_PARAM_CFG_MODEL, (VENDOR_AI_NET_CFG_MODEL*)&p_net->proc_mem); vendor_ai_net_set(proc_id, VENDOR_AI_NET_PARAM_CFG_SHAREMODEL, (VENDOR_AI_NET_CFG_MODEL*)&p_share_net->proc_mem); } // open vendor_ai_net_open(proc_id); if ((ret = network_alloc_io_buf(net_path)) != HD_OK) return ret; return ret; } static HD_RESULT network_close(NET_PATH_ID net_path) { HD_RESULT ret = HD_OK; NET_PROC* p_net = g_net + net_path; UINT32 proc_id = p_net->proc_id; if ((ret = network_free_io_buf(net_path)) != HD_OK) return ret; // close ret = vendor_ai_net_close(proc_id); if (p_net->net_cfg.p_share_model == NULL ) { mem_rel(&p_net->proc_mem); // common buffer } else { mem_free(&p_net->proc_mem); // private buffer } return ret; } static HD_RESULT network_dump_out_buf(NET_PATH_ID net_path, void *p_out) { HD_RESULT ret = HD_OK; NET_PROC* p_net = g_net + net_path; UINT32 proc_id = p_net->proc_id; VENDOR_AI_POSTPROC_RESULT_INFO *p_rslt_info = (VENDOR_AI_POSTPROC_RESULT_INFO *)(p_out); UINT32 i, j; printf("proc_id(%u) classification results:\r\n", proc_id); if (p_rslt_info) { for (i = 0; i < p_rslt_info->result_num; i++) { VENDOR_AI_POSTPROC_RESULT *p_rslt = &p_rslt_info->p_result[i]; for (j = 0; j < NN_POSTPROC_TOP_N; j++) { printf("%ld. no=%ld, label=%s, score=%f\r\n", j + 1, p_rslt->no[j], &p_net->out_class_labels[p_rslt->no[j] * VENDOR_AIS_LBL_LEN], p_rslt->score[j]); } } } return ret; } /////////////////////////////////////////////////////////////////////////////// typedef struct _VIDEO_LIVEVIEW { // (1) input NET_IN_CONFIG net_in_cfg; NET_PATH_ID in_path; // (2) network NET_PROC_CONFIG net_proc_cfg; NET_PATH_ID net_path; pthread_t proc_thread_id; UINT32 proc_start; UINT32 proc_exit; UINT32 proc_oneshot; } VIDEO_LIVEVIEW; static HD_RESULT init_module(void) { HD_RESULT ret; if ((ret = input_init()) != HD_OK) return ret; if ((ret = network_init()) != HD_OK) return ret; return HD_OK; } static HD_RESULT open_module(VIDEO_LIVEVIEW *p_stream) { HD_RESULT ret; if ((ret = input_open(p_stream->in_path)) != HD_OK) return ret; if ((ret = network_open(p_stream->net_path)) != HD_OK) return ret; return HD_OK; } static HD_RESULT close_module(VIDEO_LIVEVIEW *p_stream) { HD_RESULT ret; if ((ret = input_close(p_stream->in_path)) != HD_OK) return ret; if ((ret = network_close(p_stream->net_path)) != HD_OK) return ret; return HD_OK; } static HD_RESULT exit_module(void) { HD_RESULT ret; if ((ret = input_uninit()) != HD_OK) return ret; if ((ret = network_uninit()) != HD_OK) return ret; return HD_OK; } /////////////////////////////////////////////////////////////////////////////// static VOID *network_user_thread(VOID *arg); static HD_RESULT network_user_start(VIDEO_LIVEVIEW *p_stream) { HD_RESULT ret = HD_OK; p_stream->proc_start = 0; p_stream->proc_exit = 0; p_stream->proc_oneshot = 0; ret = vendor_ai_net_start(p_stream->net_path); if (HD_OK != ret) { printf("proc_id(%u) start fail !!\n", p_stream->net_path); } ret = pthread_create(&p_stream->proc_thread_id, NULL, network_user_thread, (VOID*)(p_stream)); if (ret < 0) { return HD_ERR_FAIL; } p_stream->proc_start = 1; p_stream->proc_exit = 0; p_stream->proc_oneshot = 0; return ret; } static HD_RESULT network_user_oneshot(VIDEO_LIVEVIEW *p_stream) { HD_RESULT ret = HD_OK; p_stream->proc_oneshot = 1; return ret; } static HD_RESULT network_user_stop(VIDEO_LIVEVIEW *p_stream) { HD_RESULT ret = HD_OK; p_stream->proc_exit = 1; if (p_stream->proc_thread_id) { pthread_join(p_stream->proc_thread_id, NULL); } //stop: should be call after last time proc ret = vendor_ai_net_stop(p_stream->net_path); if (HD_OK != ret) { printf("proc_id(%u) stop fail !!\n", p_stream->net_path); } return ret; } static VOID *network_user_thread(VOID *arg) { HD_RESULT ret = HD_OK; VIDEO_LIVEVIEW *p_stream = (VIDEO_LIVEVIEW*)arg; printf("\r\n"); while (p_stream->proc_start == 0) sleep(1); printf("\r\n"); while (p_stream->proc_exit == 0) { if (p_stream->proc_oneshot) { VENDOR_AI_BUF in_buf = {0}; //VENDOR_AI_BUF out_buf = {0}; VENDOR_AI_POSTPROC_RESULT_INFO out_buf = {0}; p_stream->proc_oneshot = 0; ret = input_pull_buf(p_stream->in_path, &in_buf, 0); if (HD_OK != ret) { printf("proc_id(%u) pull input fail !!\n", p_stream->in_path); goto skip; } printf("proc_id(%u) oneshot ...\n", p_stream->net_path); // set input image ret = vendor_ai_net_set(p_stream->net_path, VENDOR_AI_NET_PARAM_IN(0, 0), &in_buf); if (HD_OK != ret) { printf("proc_id(%u)push input fail !!\n", p_stream->net_path); goto skip; } // do net proc ret = vendor_ai_net_proc(p_stream->net_path); if (HD_OK != ret) { printf("proc_id(%u) proc fail !!\n", p_stream->net_path); goto skip; } // get output result ret = vendor_ai_net_get(p_stream->net_path, VENDOR_AI_NET_PARAM_OUT(VENDOR_AI_MAXLAYER, 0), &out_buf); if (HD_OK != ret) { printf("proc_id(%u) output get fail !!\n", p_stream->net_path); goto skip; } printf("proc_id(%u) oneshot done!\n", p_stream->net_path); ret = network_dump_out_buf(p_stream->net_path, &out_buf); if (HD_OK != ret) { printf("proc_id(%u) output dump fail !!\n", p_stream->net_path); goto skip; } } usleep(100); } skip: return 0; } /*-----------------------------------------------------------------------------*/ /* Interface Functions */ /*-----------------------------------------------------------------------------*/ MAIN(argc, argv) { VIDEO_LIVEVIEW stream[NN_RUN_NET_NUM] = {0}; //0: net proc HD_COMMON_MEM_INIT_CONFIG mem_cfg = {0}; NET_PROC_CONFIG *p_net_cfg = 0; INT32 idx; HD_RESULT ret; INT key; UINT32 i; //net_in NET_IN_CONFIG in_cfg[NN_RUN_NET_NUM] = { { .input_filename = "/mnt/sd/jpg/YUV420_SP_W512H376.bin", .w = 512, .h = 376, .c = 2, .loff = 512, .fmt = HD_VIDEO_PXLFMT_YUV420 }, { .input_filename = "/mnt/sd/jpg2/YUV420_SP_W512H376.bin", .w = 512, .h = 376, .c = 2, .loff = 512, .fmt = HD_VIDEO_PXLFMT_YUV420 } }; //net proc NET_PROC_CONFIG net_cfg[NN_RUN_NET_NUM] = { { .model_filename = "/mnt/sd/para/nvt_model.bin", .label_filename = "/mnt/sd/accuracy/labels.txt", .p_share_model = NULL, }, { .model_filename = "/mnt/sd/para2/nvt_model.bin", .label_filename = "/mnt/sd/accuracy2/labels.txt", .p_share_model = NULL, } }; if(argc < 2){ printf("usage : ai_2net (share_model) (job_opt) (job_sync) (buf_opt)\n"); printf(" * share_model: (0: off, 1: on)\n"); return -1; } idx = 1; // parse network config { int share_model = 0, job_method = 0, job_wait_ms = 0, buf_method = 0; if (argc > idx) { sscanf(argv[idx++], "%d", &share_model); } if (argc > idx) { sscanf(argv[idx++], "%d", &job_method); } if (argc > idx) { sscanf(argv[idx++], "%d", &job_wait_ms); } if (argc > idx) { sscanf(argv[idx++], "%d", &buf_method); } for (i = 0; i < NN_RUN_NET_NUM; i++) { net_cfg[i].job_method = job_method; net_cfg[i].job_wait_ms = job_wait_ms; net_cfg[i].buf_method = buf_method; // set share model if (share_model && i > 0) { net_cfg[i].p_share_model = &g_net[0]; } } } printf("\r\n\r\n"); // malloc for g_in & g_net g_in = (NET_IN *)malloc(sizeof(NET_IN)*16); g_net = (NET_PROC *)malloc(sizeof(NET_PROC)*16); if ((g_in == NULL) || (g_net == NULL)) { printf("fail to malloc g_in/g_net\n"); goto exit; } for (i = 0; i < NN_RUN_NET_NUM; i++) { stream[i].in_path = i; stream[i].net_path = i; } // init hdal ret = hd_common_init(0); if (ret != HD_OK) { printf("hd_common_init fail=%d\n", ret); goto exit; } // set project config for AI hd_common_sysconfig(0, (1<<16), 0, VENDOR_AI_CFG); //enable AI engine // init mem { INT32 idx = 0; // mempool index for (i = 0; i < NN_RUN_NET_NUM; i++) { input_mem_config(stream[i].in_path, &mem_cfg, 0, idx); // config common pool p_net_cfg = &net_cfg[i]; if (i == 0 || p_net_cfg->p_share_model == NULL) { idx = network_mem_config(stream[i].net_path, &mem_cfg, p_net_cfg, idx); } } } ret = hd_common_mem_init(&mem_cfg); if (HD_OK != ret) { printf("hd_common_mem_init err: %d\r\n", ret); goto exit; } // init all modules ret = init_module(); if (ret != HD_OK) { printf("init fail=%d\n", ret); goto exit; } // set open config for (i = 0; i < NN_RUN_NET_NUM; i++) { ret = input_set_config(stream[i].in_path, &in_cfg[i]); if (HD_OK != ret) { printf("proc_id(%u) input_set_config fail=%d\n", stream[i].in_path, ret); goto exit; } // get share model p_net_cfg = &net_cfg[i]; ret = network_set_config(stream[i].net_path, p_net_cfg); if (HD_OK != ret) { printf("proc_id(%u) network_set_config fail=%d\n", stream[i].net_path, ret); goto exit; } // open video_liveview modules ret = open_module(&stream[i]); if (ret != HD_OK) { printf("open fail=%d\n", ret); goto exit; } } // start for (i = 0; i < NN_RUN_NET_NUM; i++) { input_start(stream[i].in_path); network_user_start(&stream[i]); } printf("Enter q to quit\n"); printf("Enter a to run network1\n"); printf("Enter b to run network2\n"); printf("Enter r to run all networks\n"); do { key = GETCHAR(); if (key == 'r') { // run all stream once for (i = 0; i < NN_RUN_NET_NUM; i++) { network_user_oneshot(&stream[i]); } continue; } if (key == 'a') { // run stream[0] network_user_oneshot(&stream[0]); continue; } if (key == 'b') { // run stream[1] network_user_oneshot(&stream[1]); continue; } if (key == 'q' || key == 0x3) { break; } } while(1); // stop for (i = 0; i < NN_RUN_NET_NUM; i++) { input_stop(stream[i].in_path); network_user_stop(&stream[i]); } exit: // close video_liveview modules for (i = 0; i < NN_RUN_NET_NUM; i++) { ret = close_module(&stream[i]); if (ret != HD_OK) { printf("close fail=%d\n", ret); } } // uninit all modules ret = exit_module(); if (ret != HD_OK) { printf("exit fail=%d\n", ret); } // uninit memory ret = hd_common_mem_uninit(); if (ret != HD_OK) { printf("mem fail=%d\n", ret); } // uninit hdal ret = hd_common_uninit(); if (ret != HD_OK) { printf("common fail=%d\n", ret); } // free g_in & g_net if (g_in) free(g_in); if (g_net) free(g_net); return ret; }