/* ******************************************************************************* * Copyright (c) 2010-2022 VATICS(KNERON) Inc. All rights reserved. * * +-----------------------------------------------------------------+ * | THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED | * | AND COPIED IN ACCORDANCE WITH THE TERMS AND CONDITIONS OF SUCH | * | A LICENSE AND WITH THE INCLUSION OF THE THIS COPY RIGHT NOTICE. | * | THIS SOFTWARE OR ANY OTHER COPIES OF THIS SOFTWARE MAY NOT BE | * | PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY OTHER PERSON. THE | * | OWNERSHIP AND TITLE OF THIS SOFTWARE IS NOT TRANSFERRED. | * | | * | THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT | * | ANY PRIOR NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY | * | VATICS(KNERON) INC. | * +-----------------------------------------------------------------+ * ******************************************************************************* */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "application_init.h" #include "kdp2_host_stream.h" #include "fec_api.h" #include "event_recorder.h" #include "stdc_post_process.h" #include "bt_uart.h" #include "can_bus.h" #include "buzzer.h" #include "remote_ctrl.h" #include "handshake.h" //fifo queue buffer setting #define IMAGE_BUFFER_COUNT 3 #define RESULT_BUFFER_COUNT 3 #define RESULT_BUFFER_SIZE 512 * 1024 #define HOST_STREAM_CONFIG_PATH "./ini/host_stream.ini" extern void *kdp2_host_stream_image_thread(void *arg); extern void *kdp2_host_update_result_thread(void *arg); extern void *kdp2_host_video_thread(void *arg); extern void *kdp2_host_roi_image_thread(void *arg); extern void *kdp2_host_voc_thread(void *phandle); extern int app_header_send_inference(uint32_t buf_addr, bool *bl_run_next_inference, void* arg, unsigned char* image_buffer, VMF_VSRC_SSM_OUTPUT_INFO_T* vsrc_ssm_info); extern int app_header_recv_inference(uint32_t buf_addr, bool *bl_run_next_inference); bool _blDispatchRunning = true; //VMF_NNM_Fifoq_Manager_Enqueue_Image_Thread: This thread control argument. //true: keep running, false: this operation should only be invoked before terminating the process. bool _blFifoqManagerRunning = true; //VMF_NNM_Inference_Image_Dispatcher_Thread: This thread control argument. //true: keep running, false: this operation should only be invoked before terminating the process. extern bool _blRecvRunning; extern bool _blResultRunning; extern ssm_handle_t *gptSsmHandle; extern int g_iTerminate; unsigned int g_dwVocEnable = 0; unsigned int g_dwVocPixFmt = 0; unsigned int g_dwOnlyPerson = 0; unsigned int g_dwDrawBoxEnable = 0; unsigned int g_dwSegOverlayEnable = 0; /* 1: paint per-class colour overlay; 0: outline only */ unsigned int g_verbose_log = 0; /* 0=quiet, 1=per-frame class ratio log (web UI toggle) */ bool _blMainStanby = true; DETECT_INFO g_atDrawInfo[MAX_RESULT_BOX]; unsigned int g_dwResultCounts = 0; /* STDC segmentation map shared with draw-box thread */ uint8_t g_stdc_seg_map[STDC_SEG_MAP_MAX]; uint32_t g_stdc_seg_w = 0; uint32_t g_stdc_seg_h = 0; pthread_mutex_t g_stdc_seg_mutex = PTHREAD_MUTEX_INITIALIZER; int loadConfig(HOST_STREAM_INIT_OPT_T* pHostStreamInit) { dictionary* ini = NULL; const char* tmp = NULL; struct stat info; char search_str[30] = {0}; //! check file if (0 != stat(HOST_STREAM_CONFIG_PATH, &info)) return -1; if (!(info.st_mode & S_IFREG)) return -1; printf("iniparser_load %s \n", HOST_STREAM_CONFIG_PATH); ini = iniparser_load(HOST_STREAM_CONFIG_PATH); tmp = iniparser_getstring(ini, "sensor:sensor_cfg", NULL); if(tmp) pHostStreamInit->pszSensorConfigPath = strdup(tmp); tmp = iniparser_getstring(ini, "sensor:autoscene_config", NULL); if(tmp /*&& (app_mode != VMF_VSRC_APP_MODE_DMA422TO420)*/) // Disable autoscene when app_mode == VMF_VSRC_APP_MODE_DMA422TO420 pHostStreamInit->pszAutoSceneConfigPath = strdup(tmp); tmp = iniparser_getstring(ini, "sensor:fusion_cfg", NULL); if(tmp) pHostStreamInit->pszFusionConfigPath = strdup(tmp); tmp = iniparser_getstring(ini, "sensor:fec_calibrate_path", NULL); if(tmp) pHostStreamInit->pszFecCalibratePath = strdup(tmp); tmp = iniparser_getstring(ini, "sensor:fec_conf_path", NULL); if(tmp) pHostStreamInit->pszFecConfPath = strdup(tmp); pHostStreamInit->dwFecMode = iniparser_getint(ini, "sensor:fec_mode", 0); pHostStreamInit->dwFecAppType = iniparser_getint(ini, "sensor:initial_fec_app_type", 0); pHostStreamInit->dwEisEnable = iniparser_getint(ini, "sensor:eis_enable", 0); printf("[NNM] sensor_cfg: %s autoscene_config: %s \n", pHostStreamInit->pszSensorConfigPath, pHostStreamInit->pszAutoSceneConfigPath); if(pHostStreamInit->pszFusionConfigPath){ printf("[NNM] fusion_cfg: %s\n", pHostStreamInit->pszFusionConfigPath); } printf("[NNM] fec_calibrate: %s fec_conf: %s \n", pHostStreamInit->pszFecCalibratePath, pHostStreamInit->pszFecConfPath); pHostStreamInit->pszModelPath = strdup(iniparser_getstring(ini, "nnm:ModelPath", "nef/STDC_0520.nef")); pHostStreamInit->dwInferenceStream = iniparser_getint(ini, "nnm:InferenceStream", 1); pHostStreamInit->fThreshold = (float)iniparser_getdouble(ini, "nnm:Threshold", 0.5); pHostStreamInit->dwModelId = iniparser_getint(ini, "nnm:ModelId", 32769); pHostStreamInit->dwJobId = iniparser_getint(ini, "nnm:JobId", 200); pHostStreamInit->fFps = (float)iniparser_getdouble(ini, "nnm:Fps", 25); if (pHostStreamInit->fFps == 0) { pHostStreamInit->fFps = 1; printf("[Fps = 0], set a default fps %f.\n", pHostStreamInit->fFps); } pHostStreamInit->dwGetImageBufMode = iniparser_getint(ini, "nnm:GetImageBufMode", 0); pHostStreamInit->bRoiEnable = iniparser_getint(ini, "nnm:RoiEnable", 0); pHostStreamInit->dwRoiX = iniparser_getint(ini, "nnm:RoiX", 0); pHostStreamInit->dwRoiY = iniparser_getint(ini, "nnm:RoiY", 0); pHostStreamInit->bDrawBoxEnable = iniparser_getint(ini, "nnm:DrawBoxEnable", 0); pHostStreamInit->dwOnlyPerson = iniparser_getint(ini, "nnm:OnlyPerson", 0); g_dwOnlyPerson = pHostStreamInit->dwOnlyPerson; g_verbose_log = (unsigned int)iniparser_getint(ini, "nnm:verbose_log", 0); g_dwSegOverlayEnable = (unsigned int)iniparser_getint(ini, "nnm:SegOverlayEnable", 0); pHostStreamInit->dwDrawOnResize = iniparser_getint(ini, "nnm:DrawOnResize", 0); if (pHostStreamInit->bDrawBoxEnable && (pHostStreamInit->dwInferenceStream == 0) && (pHostStreamInit->dwDrawOnResize == 0)) { pHostStreamInit->dwDrawOnResize = 1; printf("[Setting Error] Force enabled DrawOnResize \n"); } if ((pHostStreamInit->dwDrawOnResize == 1) && (pHostStreamInit->dwInferenceStream != 0)) { pHostStreamInit->dwDrawOnResize = 0; printf("[Setting Error] Force disable DrawOnResize \n"); } pHostStreamInit->dwNnmSource= iniparser_getint(ini, "nnm:NnmSource", 0); pHostStreamInit->pszSsmName= strdup(iniparser_getstring(ini, "nnm:ssm_name", "vsrc_ssm_0")); pHostStreamInit->dwEncodeStreamCount = iniparser_getint(ini, "streamer:StreamCount", 3); pHostStreamInit->eMemType = iniparser_getint(ini, "streamer:MemType", 0); pHostStreamInit->dwEncodeStreamCount = ( pHostStreamInit->dwEncodeStreamCount > MAX_STREAM )?MAX_STREAM:pHostStreamInit->dwEncodeStreamCount; for (unsigned int i=0; i < MAX_STREAM; i++) { snprintf(search_str, 30, "stream%u:Codec", i); pHostStreamInit->tVEncoder[i].eCodecType = iniparser_getint(ini, search_str, 1); snprintf(search_str, 30, "stream%u:QP", i); pHostStreamInit->tVEncoder[i].dwQp = iniparser_getint(ini, search_str, 25); snprintf(search_str, 30, "stream%u:FPS", i); pHostStreamInit->tVEncoder[i].dwFps = iniparser_getint(ini, search_str, 25); snprintf(search_str, 30, "stream%u:Bitrate", i); pHostStreamInit->tVEncoder[i].dwBitrate = iniparser_getint(ini, search_str, 2000000); snprintf(search_str, 30, "stream%u:Virt_I_Interval", i); pHostStreamInit->tVEncoder[i].dwVirtIFrameInterval = iniparser_getint(ini, search_str, 0); snprintf(search_str, 30, "stream%u:GOP", i); pHostStreamInit->tVEncoder[i].dwGop = iniparser_getint(ini, search_str, 50); snprintf(search_str, 30, "stream%u:PIQ", i); pHostStreamInit->tVEncoder[i].dwPiq = iniparser_getint(ini, search_str, 0); snprintf(search_str, 30, "stream%u:Width", i); pHostStreamInit->tVEncoder[i].dwWidth = iniparser_getint(ini, search_str, 2560); snprintf(search_str, 30, "stream%u:Height", i); pHostStreamInit->tVEncoder[i].dwHeight = iniparser_getint(ini, search_str, 1920); snprintf(search_str, 30, "stream%u:KeepFrameRatio", i); pHostStreamInit->tVEncoder[i].dwKeepRatio = iniparser_getint(ini, search_str, 0); snprintf(search_str, 30, "stream%u:EncodeBufferSize", i); pHostStreamInit->tVEncoder[i].dwEncodeBufferSize = iniparser_getint(ini, search_str, 6291456); snprintf(search_str, 30, "stream%u:EncodeBufferAmount", i); pHostStreamInit->tVEncoder[i].dwEncodeBufferAmount = iniparser_getint(ini, search_str, 3); } pHostStreamInit->dwVocEnable = iniparser_getint(ini, "voc:voc_enable", 0); g_dwVocEnable = pHostStreamInit->dwVocEnable; pHostStreamInit->dwVocWidth = VMF_32_ALIGN(iniparser_getint(ini, "voc:VocWidth", -1)); pHostStreamInit->dwVocHeight = VMF_8_ALIGN(iniparser_getint(ini, "voc:VocHeight", -1)); /* ISP pipeline always outputs YM12 (planar YUV420, three separate planes). * The VOC (HDMI) display input must match. Hardcode YM12 to match SDK reference. */ (void)iniparser_getstring(ini, "voc:PixFmt", "YM12"); g_dwVocPixFmt = v4l2_fourcc('Y', 'M', '1', '2'); printf("[VOC] PixFmt: YM12 (0x%08X)\n", g_dwVocPixFmt); if(pHostStreamInit->dwEisEnable == 1) { FILE *fDeviceBufferEnable = NULL; if (pHostStreamInit->dwFecMode != FEC_MODE_1O && pHostStreamInit->dwFecMode != FEC_MODE_1R ) { printf("EIS mode does NOT support mode %u [Disable EIS]\n", pHostStreamInit->dwFecMode); pHostStreamInit->dwEisEnable = 0; } fDeviceBufferEnable = fopen(IMU_CONFIG_PATH,"r"); if(!fDeviceBufferEnable) { printf("[streamer] Cannot read %s in EIS mode. [Disable EIS]\n", IMU_CONFIG_PATH); pHostStreamInit->dwEisEnable = 0; } if (fDeviceBufferEnable) fclose(fDeviceBufferEnable); } printf("[NNM] Model: %s ImageWidth: %d ImageHeight: %d Threshold: %f Fps: %f \n", pHostStreamInit->pszModelPath, pHostStreamInit->tVEncoder[pHostStreamInit->dwInferenceStream].dwWidth, pHostStreamInit->tVEncoder[pHostStreamInit->dwInferenceStream].dwHeight, pHostStreamInit->fThreshold, pHostStreamInit->fFps); printf("[NNM] Model: %s dwModelId: %d dwJobId: %d \n", pHostStreamInit->pszModelPath, pHostStreamInit->dwModelId, pHostStreamInit->dwJobId); /* --- [event] section: violation event recording + upload --- */ { int ev_enable = iniparser_getint(ini, "event:enable", 0); const char *bt_dev = iniparser_getstring(ini, "event:bt_uart_dev", "/dev/ttyS1"); int bt_at_probe = iniparser_getint(ini, "event:bt_at_probe", 0); const char *aresx_ver = iniparser_getstring(ini, "event:aresx_version", "1.0.0"); const char *ev_up = iniparser_getstring(ini, "event:upload_url", "http://192.168.0.114:8081/api/upload"); const char *ev_sd = iniparser_getstring(ini, "event:sd_path", "/tmp/sdcard/events"); int ev_max_mb = iniparser_getint(ini, "event:sd_max_mb", 7168); int ev_delay = iniparser_getint(ini, "event:upload_delay_ms", 60000); int ev_dev = iniparser_getint(ini, "event:upload_dev", 0); /* device_id (event:device_id): raw Kn chip number string, e.g. "0xCE7B562C". * bt_name (event:bt_name): BLE broadcast name derived from kn, e.g. "AresX-562C". * * First-boot (device_id empty): get kn, build both strings, mark need_ini_save. * AT-probe flow (bt_at_probe==1): bt_set_module_name runs inside bt_uart_init(); * after it returns, persist bt_name + device_id and set bt_at_probe=0. */ const char *device_id_ini = iniparser_getstring(ini, "event:device_id", ""); char device_id[32]; /* raw kn number, e.g. "0xCE7B562C" */ char bt_name[32]; /* derived BLE name, e.g. "AresX-562C" */ int need_ini_save = 0; if (!device_id_ini || !*device_id_ini) { uint32_t kn = VMF_NNM_Get_Kn_Number(); snprintf(device_id, sizeof(device_id), "0x%08X", kn); snprintf(bt_name, sizeof(bt_name), "AresX-%04X", (unsigned)(kn & 0xFFFF)); printf("[BT] auto device_id=%s bt_name=%s\n", device_id, bt_name); iniparser_set(ini, "event:device_id", device_id); iniparser_set(ini, "event:bt_name", bt_name); need_ini_save = 1; } else { snprintf(device_id, sizeof(device_id), "%s", device_id_ini); const char *bt_name_ini = iniparser_getstring(ini, "event:bt_name", "BT-24"); snprintf(bt_name, sizeof(bt_name), "%s", bt_name_ini); printf("[BT] device_id=%s bt_name=%s (from INI)\n", device_id, bt_name); } /* Order matters: set_identity BEFORE init so s_bt_name is ready * when bt_uart_probe_and_upgrade() calls bt_set_module_name(). */ bt_uart_set_identity(aresx_ver, bt_name); bt_uart_init(bt_dev, bt_at_probe); /* After AT probe+upgrade: persist bt_name, disable at_probe for next boot. */ if (bt_at_probe) { iniparser_set(ini, "event:bt_name", bt_name); iniparser_set(ini, "event:bt_at_probe", "0"); need_ini_save = 1; } if (need_ini_save) { /* Use sed in-place replacement to update ONLY the specific keys we need to * persist. This preserves the original file structure, all other sections, * inline comments, and avoids iniparser_dump_ini stripping all comments and * potentially producing an unreadable flat-format output on some iniparser * versions. * * Pattern: match the key at the start of a line (with optional spaces around * '='), replace the value part. The sed expression targets the [event] block * values by their key names — safe because these keys only appear once. */ char cmd[512]; int rc = 0; /* device_id */ snprintf(cmd, sizeof(cmd), "sed -i 's|^device_id[[:space:]]*=.*|device_id = %s|' %s", device_id, HOST_STREAM_CONFIG_PATH); rc |= system(cmd); /* bt_name */ snprintf(cmd, sizeof(cmd), "sed -i 's|^bt_name[[:space:]]*=.*|bt_name = %s|' %s", bt_name, HOST_STREAM_CONFIG_PATH); rc |= system(cmd); /* bt_at_probe → 0 (only when we just ran the AT probe) */ if (bt_at_probe) { snprintf(cmd, sizeof(cmd), "sed -i 's|^bt_at_probe[[:space:]]*=.*|bt_at_probe = 0|' %s", HOST_STREAM_CONFIG_PATH); rc |= system(cmd); } if (rc == 0) printf("[BT] INI persisted via sed: bt_name=%s device_id=%s bt_at_probe=%d\n", bt_name, device_id, bt_at_probe ? 0 : bt_at_probe); else printf("[BT] WARNING: sed INI update returned %d (%s)\n", rc, HOST_STREAM_CONFIG_PATH); } int ev_spd_normal = iniparser_getint(ini, "can:speed_normal", 240); int ev_spd_alert = iniparser_getint(ini, "can:speed_alert", 35); int ev_spd_stop = iniparser_getint(ini, "can:speed_stop", 10); event_recorder_init(ev_up, ev_sd, ev_max_mb, ev_delay, ev_enable, device_id, ev_dev, ev_spd_normal, ev_spd_alert, ev_spd_stop); } /* --- [detect] section: runtime-tunable detection thresholds --- */ { g_thr_grass_roi = iniparser_getint(ini, "detect:thr_grass_roi", 750) / 1000.0f; g_thr_person_collision = iniparser_getint(ini, "detect:thr_person_col", 100) / 1000.0f; g_thr_car_collision = iniparser_getint(ini, "detect:thr_car_col", 200) / 1000.0f; g_thr_tree_collision = iniparser_getint(ini, "detect:thr_tree_col", 200) / 1000.0f; g_thr_bunker_collision = iniparser_getint(ini, "detect:thr_bunker_col", 200) / 1000.0f; g_thr_pond_collision = iniparser_getint(ini, "detect:thr_pond_col", 200) / 1000.0f; g_thr_person_alert = iniparser_getint(ini, "detect:thr_person_alt", 200) / 1000.0f; g_thr_car_alert = iniparser_getint(ini, "detect:thr_car_alt", 200) / 1000.0f; g_thr_tree_alert = iniparser_getint(ini, "detect:thr_tree_alt", 300) / 1000.0f; g_thr_bunker_alert = iniparser_getint(ini, "detect:thr_bunker_alt", 200) / 1000.0f; g_thr_pond_alert = iniparser_getint(ini, "detect:thr_pond_alt", 200) / 1000.0f; printf("[FW] detect thresholds: grass=%.3f p_col=%.3f c_col=%.3f t_col=%.3f" " p_alt=%.3f c_alt=%.3f\n", g_thr_grass_roi, g_thr_person_collision, g_thr_car_collision, g_thr_tree_collision, g_thr_person_alert, g_thr_car_alert); } /* --- [can] section: MCP2515 CAN bus via J15 SPI connector --- */ { int can_enable = iniparser_getint(ini, "can:enable", 0); const char *can_spidev = iniparser_getstring(ini, "can:spidev", "/dev/spidev1.0"); int can_speed = iniparser_getint(ini, "can:speed_kbps", 250); int can_id_raw = iniparser_getint(ini, "can:can_id", 0x100); if (can_enable) can_bus_init(can_spidev, can_speed, (uint32_t)can_id_raw); } buzzer_init(); if (remote_ctrl_init() != 0) printf("[FW] WARNING: remote_ctrl_init failed, remote disabled\n"); iniparser_freedict(ini); return 0; } void sig_kill(int signo) { printf("receive SIGNAL: %d\n", signo); if(gptSsmHandle)//get image sensor yuv data on HICO/HOST mode SSM_Reader_Wakeup(gptSsmHandle); _blMainStanby = false; _blDispatchRunning = false; _blRecvRunning = false; //kdp2_host_stream_image_thread _blResultRunning = false; //kdp2_host_update_result_thread g_iTerminate = 1; _blFifoqManagerRunning = false; VMF_NNM_Fifoq_Manager_Wakeup(); if (SIGSEGV == signo) { #ifdef DEBUG struct rlimit rlim, rlim_new; printf("Dump stack start...ulimit -c unlimited\n"); if (getrlimit(RLIMIT_CORE, &rlim) == 0) { rlim_new.rlim_cur = rlim_new.rlim_max = RLIM_INFINITY; if (setrlimit(RLIMIT_CORE, &rlim_new) != 0) { rlim_new.rlim_cur = rlim_new.rlim_max = rlim.rlim_max; (void) setrlimit(RLIMIT_CORE, &rlim_new); } } system("echo /tmp/core.%e.%p.%t > /proc/sys/kernel/core_pattern"); printf("Dump stack end...\n"); #endif fflush(stdout); signal(SIGSEGV, SIG_DFL); raise(SIGSEGV); } printf("sig_kill end\n"); } void print_usage(char* argv[]) { printf("Usage 1, setting by ini: %s, default auto load [%s] \r\n", argv[0], HOST_STREAM_CONFIG_PATH); } int parse_argument(int argc, char* argv[], HOST_STREAM_INIT_OPT_T* pHostStreamInit) { int ch; while ((ch = getopt(argc, argv, "c:a:m:i:j:w:h:t:f:")) != -1) { switch(ch) { case 'c': pHostStreamInit->pszSensorConfigPath = strdup(optarg); printf("SensorConfigPath = %s\n", pHostStreamInit->pszSensorConfigPath); break; case 'a': pHostStreamInit->pszAutoSceneConfigPath = strdup(optarg); printf("AutoSceneConfigPath = %s\n", pHostStreamInit->pszAutoSceneConfigPath); break; case 'm': pHostStreamInit->pszModelPath = strdup(optarg); printf("ModelPath = %s\n", pHostStreamInit->pszModelPath); break; case 'i': pHostStreamInit->dwModelId = atoi(optarg); break; case 'j': pHostStreamInit->dwJobId = atoi(optarg); break; case 't': pHostStreamInit->fThreshold = atof(optarg); break; case 'f': pHostStreamInit->fFps = atof(optarg); break; default: print_usage(argv); return -1; } } if (NULL == pHostStreamInit->pszModelPath ) { print_usage(argv); return -1; } return 0; } void free_stream_init(HOST_STREAM_INIT_OPT_T* pHostStreamInit) { if (pHostStreamInit->pszSensorConfigPath){ free(pHostStreamInit->pszSensorConfigPath); pHostStreamInit->pszSensorConfigPath = NULL; } if (pHostStreamInit->pszFusionConfigPath){ free(pHostStreamInit->pszFusionConfigPath); pHostStreamInit->pszFusionConfigPath = NULL; } if (pHostStreamInit->pszAutoSceneConfigPath){ free(pHostStreamInit->pszAutoSceneConfigPath); pHostStreamInit->pszAutoSceneConfigPath = NULL; } if (pHostStreamInit->pszFecCalibratePath){ free(pHostStreamInit->pszFecCalibratePath); pHostStreamInit->pszFecCalibratePath = NULL; } if (pHostStreamInit->pszFecConfPath){ free(pHostStreamInit->pszFecConfPath); pHostStreamInit->pszFecConfPath = NULL; } if (pHostStreamInit->pszModelPath){ free(pHostStreamInit->pszModelPath); pHostStreamInit->pszModelPath = NULL; } if (pHostStreamInit->pszSsmName){ free(pHostStreamInit->pszSsmName); pHostStreamInit->pszSsmName = NULL; } } int main (int argc, char* argv[]) { /* Force line-buffered stdout so printf output appears immediately even * when piped to tee (e.g. ./firmware 2>&1 | tee /tmp/fw.log). * Without this, the pipe triggers full-buffering and log appears in chunks. */ setvbuf(stdout, NULL, _IOLBF, 0); setvbuf(stderr, NULL, _IOLBF, 0); uint32_t major, minor, patch, build; pthread_t thread_f = 0; VMF_NNM_Get_Version(&major, &minor, &patch, &build); uint32_t kn_number = VMF_NNM_Get_Kn_Number(); /* Derive and print BLE handshake key for startup verification. * Expected: 58 48 c8 ff b2 eb b1 b8 69 92 b5 20 48 8d 1d 61 */ { uint8_t hs_key[HANDSHAKE_KEY_LEN]; handshake_derive_key(hs_key); printf("[INIT] handshake key: "); handshake_print_key(hs_key); } printf("\n\n**********************************************************\n"); printf("Kneron Firmware\n"); printf("Ver. %d.%d.%d.%d\n", major, minor, patch, build); printf("Build Time: %s %s\n", __DATE__, __TIME__); printf("Kn Number = 0x%08x\n",kn_number); printf("**********************************************************\n"); printf("HOST STREAM mode \n"); //pthread_t task_infcb_handle; //kmdw_inference_result_handler_callback_thread; pthread_t task_inf_data_handle; //VMF_NNM_Inference_Image_Dispatcher_Thread; pthread_t task_stream_image_handle; // <-> kdp2_host_stream_image_thread; //pthread_t task_usb_recv_handle; // <-> kdp2_usb_companion_image_thread; pthread_t task_update_result_handle; // <-> kdp2_host_update_result_thread; //pthread_t task_usb_send_handle; // <-> kdp2_usb_companion_result_thread; pthread_t task_buf_mgr_handle; pthread_t task_video_mgr_handle; pthread_t task_roi_image_handle; int ret = KP_SUCCESS; HOST_STREAM_INIT_OPT_T HostStreamInit; //for host stream mode/thread uint32_t ImageBufferSize = 0; memset(&HostStreamInit, 0, sizeof(HOST_STREAM_INIT_OPT_T)); pthread_mutex_init(&HostStreamInit.tSuspendpMutex, NULL); pthread_cond_init(&HostStreamInit.tSuspendCond, NULL); // Always load config from ini to get encoder settings if(0 != loadConfig(&HostStreamInit)) { goto EXIT; } // Command-line arguments override ini settings if(argc > 1) { if(parse_argument(argc, argv, &HostStreamInit) < 0) { goto EXIT; } } ImageBufferSize = HostStreamInit.tVEncoder[HostStreamInit.dwInferenceStream].dwWidth * HostStreamInit.tVEncoder[HostStreamInit.dwInferenceStream].dwHeight * 2; //! register signal signal(SIGTERM, sig_kill); signal(SIGKILL, sig_kill); signal(SIGINT, sig_kill); //SIGSEGV struct sigaction sa; memset(&sa, 0, sizeof(struct sigaction)); sigemptyset(&sa.sa_mask); sa.sa_handler = sig_kill; sa.sa_flags = SA_SIGINFO|SA_RESETHAND; // Reset signal handler to system default after signal triggered sigaction(SIGSEGV, &sa, NULL); printf("[%s] app_initialize \n", __func__); app_initialize(); HostStreamInit.ptDmaInfo = dma2d_init(); if(HostStreamInit.ptDmaInfo == NULL){ goto EXIT; } printf("[DBG] Before VMF_NNM_Load_Model_From_File: %s\n", HostStreamInit.pszModelPath); VMF_NNM_Load_Model_From_File(HostStreamInit.pszModelPath); printf("[DBG] After VMF_NNM_Load_Model_From_File\n"); VMF_NNM_Fifoq_Manager_Allocate_Buffer(IMAGE_BUFFER_COUNT, ImageBufferSize, RESULT_BUFFER_COUNT, RESULT_BUFFER_SIZE); printf("[DBG] After AllocateBuffer, ImageBufferSize=%u\n", ImageBufferSize); pthread_create(&task_stream_image_handle, NULL, kdp2_host_stream_image_thread, &HostStreamInit); pthread_create(&task_update_result_handle, NULL, kdp2_host_update_result_thread, &HostStreamInit); if(!HostStreamInit.dwNnmSource && HostStreamInit.dwEncodeStreamCount > 0) pthread_create(&task_video_mgr_handle, NULL, kdp2_host_video_thread, &HostStreamInit); if (HostStreamInit.bRoiEnable) pthread_create(&task_roi_image_handle, NULL, kdp2_host_roi_image_thread, &HostStreamInit); pthread_create(&task_buf_mgr_handle, NULL, VMF_NNM_Fifoq_Manager_Enqueue_Image_Thread, &_blFifoqManagerRunning); pthread_create(&task_inf_data_handle, NULL, VMF_NNM_Inference_Image_Dispatcher_Thread, &_blDispatchRunning); if(HostStreamInit.dwVocEnable) pthread_create(&thread_f, NULL, kdp2_host_voc_thread, &HostStreamInit); pthread_join(task_stream_image_handle, NULL); pthread_join(task_update_result_handle, NULL); if(!HostStreamInit.dwNnmSource && HostStreamInit.dwEncodeStreamCount > 0) pthread_join(task_video_mgr_handle, NULL); if (HostStreamInit.bRoiEnable) pthread_join(task_roi_image_handle, NULL); pthread_join(task_buf_mgr_handle, NULL); pthread_join(task_inf_data_handle, NULL); app_destroy(); //VMF_NNM_Inference_App_Destroy(); VMF_NNM_Fifoq_Manager_Release_All_Buffer(); ret = 0; EXIT: printf("%s free\n", __func__); remote_ctrl_cleanup(); free_fec_def_str(); free_stream_init(&HostStreamInit); if(HostStreamInit.ptDmaInfo) dma2d_release(HostStreamInit.ptDmaInfo); pthread_mutex_destroy(&HostStreamInit.tSuspendpMutex); pthread_cond_destroy(&HostStreamInit.tSuspendCond); printf("%s end\n", __func__); return ret; }