#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sample_comm.h" #include "sample_comm_aov.h" #include "sample_comm_periph.h" #include "sample_comm_thrd_pool.h" #define MAX_STREAM_SIZE (1024 * 1024 * 1024) #define VENC_MAX_PACK_NUM 5 #define SDCARD_MOUNT_PATH "/tmp/sd" #define DEVICES_BIND_DONE_BASE "bind@/devices/platform/soc" #define DEVICES_UNBIND_DONE_BASE "unbind@/devices/platform/soc" #define SDCARD_DEVICE1 "10040000.sdhci" #define SDCARD_DEVICE2 "10020000.sdhci" #define SDCARD_DRIVER "/sys/bus/platform/drivers/sdhci-lotus" #define SDCARD_ACTION_ADD "add" #define SDCARD_ACTION_REMOVE "remove" static xmedia_bool g_transfer_drv_already_load = XMEDIA_FALSE; static xmedia_bool g_audio_already_open = XMEDIA_FALSE; #ifdef AOV_APP_TIMESTAMP typedef struct time_stamp { xmedia_u64 drv_resume_start; xmedia_u64 app_in; xmedia_u64 vpss_in; xmedia_u64 svp_in; xmedia_u64 svp_out; xmedia_u64 app_out; xmedia_u64 drv_suspend_end; } time_stamp; static time_stamp timestamp[15] = {0}; static xmedia_s32 test_num = -1; #endif static sample_aov_work_mode g_media_work_mode = MEDIA_WORK_NORMAL; static sample_aov_init_param g_aov_init_param = {0}; static xmedia_bool g_venc_save_all = XMEDIA_FALSE; static xmedia_bool g_venc_thread = XMEDIA_FALSE; static xmedia_bool g_work_aov_thread = XMEDIA_FALSE; static pthread_mutex_t g_sync_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t g_npu_detect_mutex = PTHREAD_MUTEX_INITIALIZER; static sem_t g_venc_steram_save_start_sem; static sem_t g_venc_steram_save_stop_sem; thread_pool_t *g_aov_thrd_pool_handle = NULL; static xmedia_s32 g_misc_fd = 0; sample_aov_detect_t g_aov_detect; #ifdef SUPPORT_SENSOR_PWDN_MODE static xmedia_bool support_sensor_pwdn_standby[VI_MAX_DEV_NUM] = {0}; #endif xmedia_s32 sample_aov_system(xmedia_char *command) { FILE* fp = popen(command, "w"); if (fp == NULL) { SAMPLE_ERR("aov system command open fail \n"); return XMEDIA_FAILURE; } pclose(fp); return XMEDIA_SUCCESS; } xmedia_s32 sample_aov_drv_audio_load() { g_audio_already_open = XMEDIA_TRUE; return XMEDIA_SUCCESS; } xmedia_s32 sample_aov_drv_audio_unload() { g_audio_already_open = XMEDIA_FALSE; return XMEDIA_SUCCESS; } #ifdef AOV_APP_TIMESTAMP // precision : 10ms. xmedia_u64 sample_aov_get_debug_timestamp() { xmedia_s32 s32Ret = XMEDIA_FAILURE; xmedia_pm_rtc_info rtc_info = {0}; s32Ret = xmedia_pm_get_rtc_info(&rtc_info); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("xmedia_pm_get_rtc_info fail\n"); return 0; } return (rtc_info.rtc_current_time); } #endif static xmedia_s32 sample_aov_drv_sdcard_load() { xmedia_s32 s32Ret = XMEDIA_SUCCESS; xmedia_char buf[256] = {0}; pthread_mutex_lock(&g_sync_mutex); memset(buf, 0 , sizeof(buf)); snprintf(buf, 256, "%s", SDCARD_ACTION_ADD); //demo板使用SDIO0连接SD卡,若硬件修改为SDIO1连接SD卡,需将SDCARD_USE_SDIO0宏修改为0 #if SDCARD_USE_SDIO0 sample_comm_periph_drv_bind(SDCARD_DEVICE1, SDCARD_DRIVER, buf); #else sample_comm_periph_drv_bind(SDCARD_DEVICE2, SDCARD_DRIVER, buf); #endif s32Ret = sample_comm_periph_mount_sdcard(SDCARD_MOUNT_PATH, 2000); if(s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("mount SD failed!\n"); g_transfer_drv_already_load = XMEDIA_FALSE; } else { g_transfer_drv_already_load = XMEDIA_TRUE; } pthread_mutex_unlock(&g_sync_mutex); return XMEDIA_SUCCESS; } static xmedia_s32 sample_aov_drv_sdcard_unload() { xmedia_char buf[256] = {0}; pthread_mutex_lock(&g_sync_mutex); sample_comm_periph_umount_sdcard(SDCARD_MOUNT_PATH); memset(buf, 0 , sizeof(buf)); snprintf(buf, 256, "%s", SDCARD_ACTION_REMOVE); //demo板使用SDIO0连接SD卡,若硬件修改为SDIO1连接SD卡,需将SDCARD_USE_SDIO0宏修改为0 #if SDCARD_USE_SDIO0 sample_comm_periph_drv_unbind(SDCARD_DEVICE1, SDCARD_DRIVER, buf); #else sample_comm_periph_drv_unbind(SDCARD_DEVICE2, SDCARD_DRIVER, buf); #endif g_transfer_drv_already_load = XMEDIA_FALSE; pthread_mutex_unlock(&g_sync_mutex); return XMEDIA_SUCCESS; } #if 0 static xmedia_s32 sample_aov_isp_set_max_exptime(xmedia_u32 isp_pipe) { xmedia_s32 s32Ret = XMEDIA_FAILURE; xmedia_ae_exposure_attr exp_attr = {0}; media_comm_isp_sensor_info sns_info = {0}; media_comm_isp_get_sensor_info(isp_pipe, &sns_info); s32Ret = xmedia_ae_get_exposure_attr(isp_pipe, &exp_attr); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("xmedia_ae_get_exposure_attr fail\n"); return s32Ret; } exp_attr.auto_attr.exp_time_range.max = (1000 / sns_info.frame_rate) * 1000;//us s32Ret = xmedia_ae_set_exposure_attr(isp_pipe, &exp_attr); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("xmedia_ae_get_exposure_attr fail\n"); return s32Ret; } return XMEDIA_SUCCESS; } static xmedia_s32 sample_aov_isp_set_mode(xmedia_u32 isp_pipe, aov_media_state media_state) { xmedia_s32 s32Ret = XMEDIA_FAILURE; xmedia_isp_attr isp_attr = {0}; media_comm_isp_sensor_info sns_info = {0}; media_comm_isp_get_sensor_info(isp_pipe, &sns_info); s32Ret = xmedia_isp_get_attr(isp_pipe, &isp_attr); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("xmedia_ae_get_exposure_attr fail\n"); return s32Ret; } if (media_state == MEDIA_STATE_AOV || media_state == MEDIA_STATE_AOV_SAVE) { isp_attr.fps = (isp_attr.fps >= 30)?(sns_info.frame_rate - 5):(sns_info.frame_rate); } else { isp_attr.fps = sns_info.frame_rate; } s32Ret = xmedia_isp_set_attr(isp_pipe, &isp_attr); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("xmedia_ae_get_exposure_attr fail\n"); return s32Ret; } return XMEDIA_SUCCESS; } #endif static xmedia_s32 sample_aov_sensor_resume(xmedia_u32 isp_pipe) { xmedia_s32 s32Ret = XMEDIA_SUCCESS; #ifdef SUPPORT_SENSOR_PWDN_MODE if(g_misc_fd != -1 && support_sensor_pwdn_standby[isp_pipe] == XMEDIA_TRUE) { ioctl(g_misc_fd, XMEDIA_MISC_SENSOR_PWDN_RESUME, &isp_pipe); } #endif xmedia_sensor_low_power(isp_pipe, XMEDIA_FALSE); s32Ret = xmedia_sensor_resume(isp_pipe); return s32Ret; } #ifdef APP_STANDBY_SENSOR static xmedia_s32 sample_aov_sensor_standby(xmedia_u32 isp_pipe) { xmedia_s32 s32Ret = XMEDIA_FAILURE; LOOP: s32Ret = xmedia_isp_wait_state(isp_pipe, XMEDIA_ISP_WAIT_TYPE_FE_END, 2000); if (s32Ret == XMEDIA_SUCCESS) { s32Ret = xmedia_sensor_standby(isp_pipe); xmedia_sensor_low_power(isp_pipe, XMEDIA_TRUE); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("sensor standby set fail , try again\n"); } else { for (xmedia_s32 i = 0; i < g_aov_init_param.isp_param.isp_pipe_num; i++) { if(g_aov_init_param.isp_param.isp_pipe[i] == isp_pipe) { g_aov_init_param.sensor_status[i] = SENSOR_STATUS_STANDBY; } } } } else { SAMPLE_ERR("wait isp fe state start fail %#x\n",s32Ret); goto LOOP; } return XMEDIA_SUCCESS; } // 线程执行函数 xmedia_void sensor_standby_job_func(xmedia_void *arg) { xmedia_u32 isp_pipe = *(xmedia_u32 *)arg; sample_aov_sensor_standby(isp_pipe); return ; } xmedia_s32 start_sensor_standby_nonblocking(xmedia_s32* isp_pipe) { xmedia_s32 s32Ret = 0; s32Ret = sample_comm_thrd_job_submit(g_aov_thrd_pool_handle, &sensor_standby_job_func, isp_pipe); return s32Ret; } #else static xmedia_s32 sample_aov_set_sensor_mode(sample_aov_work_mode work_mode) { misc_aov_state aov_state = {0}; aov_state.en_aov_mode = (work_mode == MEDIA_WORK_AOV ? XMEDIA_TRUE : XMEDIA_FALSE); aov_state.frame_num = 1; return ioctl(g_misc_fd, XMEDIA_MISC_AOV_SET_SENSOR_MODE, (xmedia_u32)&aov_state, NULL); } #endif xmedia_s32 sample_aov_ae_modify_path(xmedia_u32 isp_pipe) { xmedia_s32 s32Ret = 0; xmedia_s32 node_cnt = 0; xmedia_isp_ae_route ae_route_attr = {0}; s32Ret = xmedia_ae_get_route_attr(0, &ae_route_attr); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("get ae route fail\n"); return s32Ret; } ae_route_attr.route_node[node_cnt].int_time = 33; ae_route_attr.route_node[node_cnt].sys_gain = 1024; node_cnt++; ae_route_attr.route_node[node_cnt].int_time = 33; ae_route_attr.route_node[node_cnt].sys_gain = 1024*2; node_cnt++; ae_route_attr.route_node[node_cnt].int_time = 5000; ae_route_attr.route_node[node_cnt].sys_gain = 1024*2; node_cnt++; ae_route_attr.route_node[node_cnt].int_time = 5000; ae_route_attr.route_node[node_cnt].sys_gain = 1024*4; node_cnt++; ae_route_attr.route_node[node_cnt].int_time = 10000; ae_route_attr.route_node[node_cnt].sys_gain = 1024*4; node_cnt++; ae_route_attr.route_node[node_cnt].int_time = 10000; ae_route_attr.route_node[node_cnt].sys_gain = 109993; node_cnt++; ae_route_attr.route_node[node_cnt].int_time = 1000 * 1000; ae_route_attr.route_node[node_cnt].sys_gain = 109993; node_cnt++; ae_route_attr.route_node[node_cnt].int_time = 1000 * 1000; ae_route_attr.route_node[node_cnt].sys_gain = 3519776; node_cnt++; ae_route_attr.route_node[node_cnt].int_time = 1000 * 1000; ae_route_attr.route_node[node_cnt].sys_gain = 35197760; ae_route_attr.total_num = node_cnt; s32Ret = xmedia_ae_set_route_attr(isp_pipe, &ae_route_attr); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("set ae route fail\n"); } return s32Ret; } /**************************************************************************** **aov start processs: *** | delta0 | app | delta1 | **************** ** por---auxcode----drv_resume----app-----drv_suspend----set rtc_timeout---soc power off ----* **delta0: use rtc resume set rtc_timeout; = (rtc_delta_time - rtc_last_suspend_time - rtc_timeout).* **delta_time1: drv_suspend; = rtc_last_suspend_time - last app_end_timestamp; * **keep work time + suspend = rtc_timeout,should get delta0 & delta1. * ****/ xmedia_s32 sample_aov_set_suspend_time() { xmedia_s32 s32Ret = XMEDIA_FAILURE; xmedia_pm_attr pm_attr = {0}; xmedia_pm_rtc_info rtc_info = {0}; xmedia_u32 app_time = 0; static xmedia_s32 delta_time0 = 0; static xmedia_s32 delta_time1 = 0; static xmedia_u64 app_end_timestamp = 0; static xmedia_bool rtc_time_amend_end = XMEDIA_FALSE; static xmedia_bool update_rtc_time_end = XMEDIA_FALSE; s32Ret = xmedia_pm_get_rtc_info(&rtc_info); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("xmedia_pm_get_rtc_info fail\n"); return XMEDIA_FAILURE; } if (rtc_time_amend_end == XMEDIA_TRUE) { if (delta_time0 == 0 && delta_time1 == 0) { delta_time0 = rtc_info.rtc_delta_time - rtc_info.rtc_last_suspend_time - g_aov_init_param.suspend_time; delta_time1 = rtc_info.rtc_last_suspend_time - app_end_timestamp; g_aov_init_param.suspend_time -= delta_time0; } app_time = rtc_info.rtc_current_time - rtc_info.rtc_delta_time; if ((app_time + delta_time1 + RTC_SAFE_THRESOHLD_MS) > g_aov_init_param.suspend_time || update_rtc_time_end == XMEDIA_FALSE) { pm_attr.rtc_attr.rtc_enable = XMEDIA_TRUE; pm_attr.rtc_attr.rtc_timeout = (g_aov_init_param.suspend_time / 10);//10ms 精度: /10; s32Ret = xmedia_pm_set_attr(&pm_attr); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("pm set fail \n"); } SAMPLE_PRT("dudu debug delta0 %d delta1 %d rtc_timeout %d \n",delta_time0, delta_time1, g_aov_init_param.suspend_time); update_rtc_time_end = XMEDIA_TRUE; } } else { pm_attr.rtc_attr.rtc_enable = XMEDIA_TRUE; pm_attr.rtc_attr.rtc_timeout = (g_aov_init_param.suspend_time / 10);//10ms 精度: /10; s32Ret = xmedia_pm_set_attr(&pm_attr); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("pm set fail \n"); } app_end_timestamp = rtc_info.rtc_current_time; rtc_time_amend_end = XMEDIA_TRUE; } return XMEDIA_SUCCESS; } xmedia_void sample_aov_suspend() { sample_aov_set_suspend_time(); #ifdef AOV_APP_TIMESTAMP if(test_num != -1) { timestamp[test_num].app_out = sample_aov_get_debug_timestamp(); } if (test_num == 11) { for (test_num = 0; test_num < 10; test_num ++) { SAMPLE_PRT("debug aov %d test : drv_resume_in[%lld] app_in[%lld] vpss_in[%lld] svp_in[%lld] svp_out[%lld] app_out[%lld] drv_suspend_end[%lld]\n", test_num, timestamp[test_num].drv_resume_start, timestamp[test_num].app_in, timestamp[test_num].vpss_in,timestamp[test_num].svp_in, timestamp[test_num].svp_out,timestamp[test_num].app_out,timestamp[test_num].drv_suspend_end); } sleep(20); test_num = -1; memset(timestamp, 0, sizeof (timestamp)); } test_num ++; #endif xmedia_pm_suspend(); #ifdef AOV_APP_TIMESTAMP timestamp[test_num].app_in = sample_aov_get_debug_timestamp(); xmedia_pm_rtc_info rtc_info = {0}; xmedia_pm_get_rtc_info(&rtc_info); timestamp[test_num].drv_resume_start = rtc_info.rtc_delta_time; if (test_num >= 1) { timestamp[test_num - 1].drv_suspend_end = rtc_info.rtc_last_suspend_time; } #endif #ifdef APP_STANDBY_SENSOR //isp driver has do sensor resume for (xmedia_s32 i = 0; i < g_aov_init_param.isp_param.isp_pipe_num; i++) { g_aov_init_param.sensor_status[i] = SENSOR_STATUS_RESUME; } #endif return; } static xmedia_s32 sample_aov_npu_set_work_mode(sample_aov_work_mode work_mode) { xmedia_s32 s32Ret = XMEDIA_SUCCESS; xmedia_s32 i = 0; xmedia_svp_aov_attr yolov5_attr = {0}; xmedia_bool cur_npu_mode = XMEDIA_TRUE; sample_aov_vpss_npu_param *npu_param = XMEDIA_NULL; npu_param = &(g_aov_init_param.npu_param); for (i = 0; i < npu_param->npu_detect_num; i++) { if (npu_param->en_switch_mode[i] == XMEDIA_FALSE) { continue; } s32Ret = xmedia_svp_task_get_attr(npu_param->npu_svp_handle[i], &yolov5_attr); if (XMEDIA_SUCCESS != s32Ret) { SAMPLE_ERR("svp get task attr fail.\n"); return s32Ret; } cur_npu_mode = (MEDIA_WORK_AOV == work_mode) ? XMEDIA_TRUE : XMEDIA_FALSE; if (cur_npu_mode == yolov5_attr.aov_only_target) { return XMEDIA_SUCCESS; } yolov5_attr.aov_only_target = cur_npu_mode; s32Ret = xmedia_svp_task_set_attr(npu_param->npu_svp_handle[i], &yolov5_attr); if(s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("svp set task attr fail.\n"); return XMEDIA_FAILURE; } } return XMEDIA_SUCCESS; } static xmedia_void sample_aov_venc_set_stream_save_start() { sem_post(&g_venc_steram_save_start_sem); } static xmedia_void sample_aov_venc_get_stream_save_stop() { sem_wait(&g_venc_steram_save_stop_sem); } static xmedia_void sample_aov_venc_set_save_all(xmedia_bool en_save) { pthread_mutex_lock(&g_sync_mutex); g_venc_save_all = en_save; pthread_mutex_unlock(&g_sync_mutex); } static xmedia_void sample_aov_venc_get_save_all(xmedia_bool *en_save) { pthread_mutex_lock(&g_sync_mutex); *en_save = g_venc_save_all; pthread_mutex_unlock(&g_sync_mutex); } static xmedia_s32 sample_aov_venc_stream_write(FILE* pFd, xmedia_venc_stream* venc_stream) { xmedia_s32 i; for (i = 0; i < venc_stream->pack_count; i++) { fwrite(venc_stream->pack[i].vir_addr + venc_stream->pack[i].offset, venc_stream->pack[i].len - venc_stream->pack[i].offset, 1, pFd); } return XMEDIA_SUCCESS; } static xmedia_s32 sample_aov_venc_get_transfer_path(xmedia_s32 venc_chn, xmedia_char *file_path) { xmedia_s32 s32Ret = XMEDIA_FAILURE; xmedia_venc_chn_attr venc_chn_attr = {0}; xmedia_char buf[256] = {0}; struct stat file_stat = {0}; static xmedia_s32 path_count = 0; s32Ret = xmedia_venc_get_chn_attr(venc_chn, &venc_chn_attr); if (XMEDIA_SUCCESS != s32Ret) { SAMPLE_ERR("xmedia_venc_get_chn_attr chn[%d] failed with %#x!\n", venc_chn, s32Ret); return s32Ret; } switch (venc_chn_attr.venc_attr.en_type) { case PT_H264: snprintf(buf, 255, ""SDCARD_MOUNT_PATH"/stream_chn%d_%d%s", venc_chn, path_count, ".h264"); break; case PT_H265: snprintf(buf, 255, ""SDCARD_MOUNT_PATH"/stream_chn%d_%d%s", venc_chn, path_count, ".h265"); break; case PT_JPEG: snprintf(buf, 255, ""SDCARD_MOUNT_PATH"/stream_chn%d_%d%s", venc_chn, path_count, ".jpg"); break; case PT_MJPEG: snprintf(buf, 255, ""SDCARD_MOUNT_PATH"/stream_chn%d_%d%s", venc_chn, path_count, ".mjpeg"); break; default: SAMPLE_ERR("venc type is invail exit stream thread \n"); return XMEDIA_FAILURE; } strcpy(file_path, buf); s32Ret = stat(file_path, &file_stat); if (s32Ret < 0) { SAMPLE_PRT("get stream file fail, create file.\n"); return XMEDIA_SUCCESS; } if (file_stat.st_size > MAX_STREAM_SIZE) { path_count ++; } return XMEDIA_SUCCESS; } static xmedia_s32 sample_aov_venc_save_stream(sample_aov_work_mode work_mode) { xmedia_s32 s32Ret = XMEDIA_FAILURE; xmedia_s32 i = 0; xmedia_s32 milli_sec = 1; xmedia_venc_chn_status chn_stat = {0}; xmedia_venc_stream venc_stream = {0}; xmedia_char file_path[256] = {0}; FILE * venc_fd[VENC_MAX_CHN_NUM] = {XMEDIA_NULL}; sample_aov_venc_param *venc_param = XMEDIA_NULL; xmedia_s32 cur_frame_num = 0; xmedia_bool save_all_stream = XMEDIA_FALSE; venc_param = &(g_aov_init_param.venc_param); for (i = 0; i < venc_param->venc_chn_num; i++) { s32Ret = sample_aov_venc_get_transfer_path(venc_param->venc_chn[i], file_path); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("get venc type fail \n"); return XMEDIA_FAILURE; } venc_fd[i] = fopen(file_path,"ab"); if (venc_fd[i] == XMEDIA_NULL) { SAMPLE_ERR("open aov chn fd fail,file_path:%s,errno:%s\n", file_path, strerror(errno)); return XMEDIA_FAILURE; } } memset(&venc_stream, 0, sizeof(venc_stream)); venc_stream.pack = (xmedia_venc_pack*)malloc(sizeof(xmedia_venc_pack) * VENC_MAX_PACK_NUM); NORMAL_SAVE: #if 0 //暂不考虑normal buf 满再写的方案 sample_aov_venc_get_save_all(&save_all_stream); if (MEDIA_WORK_AOV == work_mode && save_all_stream == XMEDIA_FALSE) { for (i = 0; i < venc_param->venc_chn_num; i++) { s32Ret = xmedia_venc_query_status(venc_param->venc_chn[i], &chn_stat); if (XMEDIA_SUCCESS != s32Ret) { SAMPLE_ERR("xmedia_venc_query_status chn[%d] failed with %#x!\n", venc_param->venc_chn[i], s32Ret); } else { if ((venc_param->chn_max_size[i] - chn_stat.left_stream_bytes) > venc_param->chn_threshold_size[i]) { chn_stat.left_stream_frames = 0;//未达到阈值,暂时不写 } } cur_frame_num |= chn_stat.left_stream_frames; } if (cur_frame_num == 0) { goto NORMAL_SAVE; } } #endif //获取完成当前帧 STREAM_SAVE_CONTINUE: for (i = 0; i < venc_param->venc_chn_num; i++) { s32Ret = xmedia_venc_query_status(venc_param->venc_chn[i], &chn_stat); if (XMEDIA_SUCCESS != s32Ret) { SAMPLE_ERR("xmedia_venc_query_status chn[%d] failed with %#x!\n", venc_param->venc_chn[i], s32Ret); } if (chn_stat.cur_packs == 0) { continue; } venc_stream.pack_count = chn_stat.cur_packs; s32Ret = xmedia_venc_get_stream(venc_param->venc_chn[i], &venc_stream, milli_sec); if (XMEDIA_SUCCESS != s32Ret) { SAMPLE_ERR("xmedia_venc_get_stream chn %d failed with %#x! \n",venc_param->venc_chn[i], s32Ret); } sample_aov_venc_stream_write(venc_fd[i], &venc_stream); s32Ret = xmedia_venc_release_stream(venc_param->venc_chn[i], &venc_stream); if (XMEDIA_SUCCESS != s32Ret) { SAMPLE_ERR("xmedia_venc_release_stream failed!\n"); } if (chn_stat.left_stream_frames > 0) { chn_stat.left_stream_frames -= 1; } cur_frame_num |= chn_stat.left_stream_frames; } if (cur_frame_num != 0) { cur_frame_num = 0; goto STREAM_SAVE_CONTINUE; } sample_aov_venc_get_save_all(&save_all_stream); if (MEDIA_WORK_NORMAL == work_mode && XMEDIA_FALSE == save_all_stream) { goto NORMAL_SAVE;//normal达到阈值再写卡 } else { for (i = 0; i < venc_param->venc_chn_num; i++) { s32Ret = xmedia_venc_query_status(venc_param->venc_chn[i], &chn_stat); if (XMEDIA_SUCCESS != s32Ret) { SAMPLE_ERR("xmedia_venc_query_status chn[%d] failed with %#x!\n", venc_param->venc_chn[i], s32Ret); } cur_frame_num |= chn_stat.left_stream_frames; } if (cur_frame_num != 0) { cur_frame_num = 0; goto STREAM_SAVE_CONTINUE; } } free(venc_stream.pack); venc_stream.pack = XMEDIA_NULL; for (i = 0; i < venc_param->venc_chn_num; i++) { if (venc_fd[i] != XMEDIA_NULL) { fflush(venc_fd[i]); fsync(fileno(venc_fd[i])); fclose(venc_fd[i]); venc_fd[i] = XMEDIA_NULL; } } if (work_mode == MEDIA_WORK_NORMAL) { sample_aov_venc_set_save_all(XMEDIA_FALSE);//reset } return XMEDIA_SUCCESS; } static xmedia_bool sample_aov_venc_get_aov_buf_full(xmedia_void) { xmedia_s32 s32Ret = XMEDIA_FAILURE; xmedia_bool buf_full = XMEDIA_FALSE; xmedia_s32 i = 0; xmedia_venc_chn_status stat = {0}; sample_aov_venc_param *venc_param = XMEDIA_NULL; #if 1 static xmedia_s32 last_frame_size[VENC_MAX_CHN_NUM] = {0}; static xmedia_s32 cur_frame_size[VENC_MAX_CHN_NUM] = {0}; static xmedia_s32 max_frame_size[VENC_MAX_CHN_NUM] = {0}; #endif venc_param = &(g_aov_init_param.venc_param); for (i = 0; i < venc_param->venc_chn_num; i++) { if (venc_param->en_aov[i] != XMEDIA_TRUE) { continue; } s32Ret = xmedia_venc_query_status(venc_param->venc_chn[i], &stat); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("get buf full state venc query fail chn[%d] \n",venc_param->venc_chn[i]); } if (venc_param->chn_max_size[i] - stat.left_stream_bytes <= venc_param->chn_threshold_size[i]) { buf_full |= XMEDIA_TRUE; break; } else { buf_full |= XMEDIA_FALSE; } if (stat.left_stream_frames >= VENC_STR_BUF_DEFAULT_MAX_FRAME_COUNT) { buf_full |= XMEDIA_TRUE; break; } else { buf_full |= XMEDIA_FALSE; } // update aov mode chn_threshold , use 2 * (last max size frame). #if 1 cur_frame_size[i] = stat.left_stream_bytes; last_frame_size[i] = cur_frame_size[i] - last_frame_size[i]; max_frame_size[i] = (max_frame_size[i] > last_frame_size[i]) ? max_frame_size[i] : last_frame_size[i]; venc_param->chn_threshold_size[i] = ((venc_param->chn_threshold_size[i] / 2) > max_frame_size[i]) ? venc_param->chn_threshold_size[i] : max_frame_size[i] * 2; #if 0 SAMPLE_PRT("DEBUG VENC CHN%d\n",venc_param->venc_chn[i]); SAMPLE_PRT("cur frame: %d\n",stat.left_stream_frames); SAMPLE_PRT("max_size: %d\n", venc_param->chn_max_size[i]); SAMPLE_PRT("used: %d\n",stat.left_stream_bytes); SAMPLE_PRT("remaining: %d\n",venc_param->chn_max_size[i]- stat.left_stream_bytes); SAMPLE_PRT("threshold: %d\n",venc_param->chn_threshold_size[i]); SAMPLE_PRT("last_frame:%d\n",last_frame_size[i]); SAMPLE_PRT("max_frame: %d\n",max_frame_size[i]); #endif last_frame_size[i] = stat.left_stream_bytes; #endif } return buf_full; } static xmedia_s32 sample_aov_venc_clear_buf(xmedia_s32 venc_chn) { xmedia_s32 s32Ret = XMEDIA_FAILURE; xmedia_venc_recv_pic_param recv_param = {0}; recv_param.recv_pic_num = -1; s32Ret = xmedia_venc_stop_recv_frame(venc_chn); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("aov clear buf stop recv chn[%d] frame fail\n",venc_chn); return XMEDIA_FAILURE; } s32Ret = xmedia_venc_reset_chn(venc_chn); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("aov clear buf reset chn[%d] frame fail\n",venc_chn); return XMEDIA_FAILURE; } s32Ret = xmedia_venc_start_recv_frame(venc_chn, &recv_param); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("aov clear buf start recv chn[%d] frame fail\n",venc_chn); return XMEDIA_FAILURE; } return XMEDIA_SUCCESS; } static xmedia_void sample_aov_work_aov_save_resume() { sample_aov_drv_sdcard_load(); sample_aov_venc_set_stream_save_start(); } static xmedia_void sample_aov_work_aov_save_suspend() { sample_aov_venc_get_stream_save_stop(); sample_aov_drv_sdcard_unload(); } static xmedia_s32 sample_aov_work_normal_pipe_resume() { xmedia_s32 s32Ret = XMEDIA_FAILURE; xmedia_venc_recv_pic_param recv_param = {0}; recv_param.recv_pic_num = -1; xmedia_s32 i = 0; xmedia_s32 j = 0; sample_aov_isp_param *isp_param = XMEDIA_NULL; sample_aov_vpss_normal_only_param *vpss_param = XMEDIA_NULL; sample_aov_venc_param *venc_param = XMEDIA_NULL; isp_param = &(g_aov_init_param.isp_param); vpss_param = &(g_aov_init_param.vpss_param); venc_param = &(g_aov_init_param.venc_param); //npu not only target sample_aov_npu_set_work_mode(MEDIA_WORK_NORMAL); sample_aov_drv_sdcard_load(); // restart aov no used vpss ochn for (i = 0; i < vpss_param->vpss_pipe_num; i++) { for (j = 0; j < vpss_param->vpss_ochn_num[i]; j++) { s32Ret = xmedia_vpss_enable_ochn(vpss_param->vpss_pipe[i], vpss_param->vpss_ochn[i][j]); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("normal ressume enable vpss pipe %d ochn[%d] fail\n", vpss_param->vpss_pipe[i], vpss_param->vpss_ochn[i][j]); } } } // restart aov no used venc chn for (i = 0; i < venc_param->venc_chn_num; i++) { if (venc_param->en_aov[i] == XMEDIA_TRUE) { continue;//only restart normal chn } s32Ret = xmedia_venc_start_recv_frame(venc_param->venc_chn[i], &recv_param); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("normal resume start recv chn[%d] fail\n",venc_param->venc_chn[i]); } } sample_aov_venc_set_stream_save_start(); #ifndef APP_STANDBY_SENSOR sample_aov_set_sensor_mode(MEDIA_WORK_NORMAL); #endif for (i = 0; i < isp_param->isp_pipe_num; i++) { sample_aov_sensor_resume(isp_param->isp_pipe[i]); } return XMEDIA_SUCCESS; } static xmedia_s32 sample_aov_work_normal_pipe_suspend() { xmedia_s32 s32Ret = XMEDIA_FAILURE; xmedia_s32 i = 0, j = 0; #ifdef APP_STANDBY_SENSOR xmedia_s32 sensor_standby_flag = 0, need_delay = 0; #endif sample_aov_isp_param *isp_param = XMEDIA_NULL; sample_aov_vpss_normal_only_param *vpss_param = XMEDIA_NULL; sample_aov_venc_param *venc_param = XMEDIA_NULL; isp_param = &(g_aov_init_param.isp_param); vpss_param = &(g_aov_init_param.vpss_param); venc_param = &(g_aov_init_param.venc_param); #ifdef APP_STANDBY_SENSOR for (i = 0; i < isp_param->isp_pipe_num; i++) { start_sensor_standby_nonblocking(&isp_param->isp_pipe[i]); sensor_standby_flag |= 1 << i; } #else sample_aov_set_sensor_mode(MEDIA_WORK_AOV); #endif #ifdef IVE_DETECT_SUPPORT for (i = 0; i < isp_param->isp_pipe_num; i++) { g_aov_detect.ive_param[i].is_first_frm = XMEDIA_TRUE; } #endif sample_aov_venc_set_save_all(XMEDIA_TRUE); sample_aov_venc_get_stream_save_stop(); // stop aov no used venc chn, clear aov chn for (i = 0; i < venc_param->venc_chn_num; i++) { if (venc_param->en_aov[i] != XMEDIA_TRUE) { s32Ret = xmedia_venc_stop_recv_frame(venc_param->venc_chn[i]); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("normal suspend stop recv chn[%d] fail\n",venc_param->venc_chn[i]); } } else { sample_aov_venc_clear_buf(venc_param->venc_chn[i]); } } // stop aov no used vpss ochn for (i = 0; i < vpss_param->vpss_pipe_num; i++) { for (j = 0; j < vpss_param->vpss_ochn_num[i]; j++) { s32Ret = xmedia_vpss_disable_ochn(vpss_param->vpss_pipe[i], vpss_param->vpss_ochn[i][j]); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("normal suspend disable vpss pipe %d ochn[%d] fail\n", vpss_param->vpss_pipe[i], vpss_param->vpss_ochn[i][j]); } } } // npu only target sample_aov_npu_set_work_mode(MEDIA_WORK_AOV); sample_aov_drv_sdcard_unload(); #ifdef APP_STANDBY_SENSOR j = 0; while(sensor_standby_flag != 0) { need_delay = 1; for (i = 0; i < isp_param->isp_pipe_num; i++) { if(g_aov_init_param.sensor_status[i] == SENSOR_STATUS_STANDBY) { sensor_standby_flag &= ~(1 << i); need_delay = 0; } } //print alert if(++j % 10000 == 0) { SAMPLE_ERR("Maybe something error in sensor standby!!!\n"); } if(need_delay) usleep(500); } #endif return XMEDIA_SUCCESS; } #ifdef IVE_DETECT_SUPPORT static xmedia_s32 sample_aov_ive_mmz_alloc(xmedia_u64 *pu64_phy_addr, xmedia_void **pp_vir_addr, const xmedia_char *str_mmb, const xmedia_char *str_zone, xmedia_u32 u32_len) { *pu64_phy_addr = xmedia_mmz_alloc(str_zone, str_mmb, u32_len); if (*pu64_phy_addr == 0) { return XMEDIA_FAILURE; } *pp_vir_addr = xmedia_mmz_map(*pu64_phy_addr, u32_len, 0); if (*pp_vir_addr == XMEDIA_NULL) { return XMEDIA_FAILURE; } return XMEDIA_SUCCESS; } static xmedia_s32 sample_aov_ive_mmz_free(xmedia_u64 u64_phy_addr, xmedia_void *p_vir_addr) { xmedia_s32 s32Ret = XMEDIA_FAILURE; if (u64_phy_addr == 0 || p_vir_addr == XMEDIA_NULL) { SAMPLE_ERR("sys_mmz_free fail.\n"); return XMEDIA_FAILURE; } s32Ret = xmedia_mmz_unmap(p_vir_addr); if (s32Ret != XMEDIA_SUCCESS) { return XMEDIA_FAILURE; } return xmedia_mmz_free(u64_phy_addr); } static xmedia_s32 sample_aov_ive_create_image(xmedia_ive_image_s* pst_img, xmedia_u32 u32width, xmedia_u32 u32height) { xmedia_u32 u32size = 0; xmedia_s32 s32Ret = XMEDIA_FAILURE; if (XMEDIA_NULL == pst_img) { SAMPLE_ERR("create_image is NULL.\n"); return XMEDIA_FAILURE; } pst_img->u32width = u32width; pst_img->u32height = u32height; pst_img->au32stride[0] = (pst_img->u32width + (8 - pst_img->u32width % 8) % 8); u32size = pst_img->au32stride[0] * pst_img->u32height; s32Ret = sample_aov_ive_mmz_alloc(&pst_img->au64phyaddr[0], (xmedia_void**)&pst_img->au64viraddr[0], "ive_img", XMEDIA_NULL, u32size); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("Mmz Alloc fail,Error(%#x)\n", s32Ret); return s32Ret; } return XMEDIA_SUCCESS; } static xmedia_s32 sample_aov_ive_create_mem_info(xmedia_ive_mem_info_s* pst_mem_info, xmedia_u32 u32size) { xmedia_s32 s32Ret; if (NULL == pst_mem_info) { SAMPLE_ERR("pst_mem_info is null\n"); return XMEDIA_FAILURE; } pst_mem_info->u32size = u32size; s32Ret = sample_aov_ive_mmz_alloc(&pst_mem_info->u64phyaddr, (xmedia_void**)&pst_mem_info->u64viraddr, "ive_mem", XMEDIA_NULL, u32size); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("Mmz Alloc fail,Error(%#x)\n", s32Ret); return XMEDIA_FAILURE; } return XMEDIA_SUCCESS; } static xmedia_s32 sample_aov_ive_dma_image(xmedia_video_frame_info *pst_frame_info,xmedia_ive_dst_image_s *pst_dst,xmedia_bool b_instant) { xmedia_s32 s32Ret; xmedia_ive_handle h_ive_handle; xmedia_ive_src_data_s st_src_data; xmedia_ive_dst_data_s st_dst_data; xmedia_ive_dma_ctrl_s st_ctrl = {XMEDIA_IVE_DMA_MODE_DIRECT_COPY,0}; xmedia_bool b_finish = XMEDIA_FALSE; xmedia_bool b_block = XMEDIA_TRUE; //fill src st_src_data.u64phyaddr = pst_frame_info->frame.addr.y_phy_addr; st_src_data.u32width = pst_frame_info->frame.width; st_src_data.u32height = pst_frame_info->frame.height; st_src_data.u32stride = pst_frame_info->frame.stride.y_stride; //fill dst st_dst_data.u64phyaddr = pst_dst->au64phyaddr[0]; st_dst_data.u32width = pst_dst->u32width; st_dst_data.u32height = pst_dst->u32height; st_dst_data.u32stride = pst_dst->au32stride[0]; s32Ret = xmedia_ive_dma(&h_ive_handle,&st_src_data,&st_dst_data,&st_ctrl,b_instant); if (XMEDIA_SUCCESS != s32Ret) { SAMPLE_ERR("xmedia_ive_dma failed! \n"); return s32Ret; } if (XMEDIA_TRUE == b_instant) { s32Ret = xmedia_ive_query(h_ive_handle,&b_finish,b_block); while(ERR_CODE_IVE_QUERY_TIMEOUT == s32Ret) { usleep(100); s32Ret = xmedia_ive_query(h_ive_handle,&b_finish,b_block); } if (XMEDIA_SUCCESS != s32Ret) { SAMPLE_ERR("xmedia_ive_query failed! \n"); return s32Ret; } } return XMEDIA_SUCCESS; } static xmedia_s32 sample_aov_ive_init(xmedia_void) { xmedia_s32 s32Ret = XMEDIA_FAILURE; xmedia_u8 u8WndSz = 0; xmedia_s32 i = 0, j = 0; memset(&g_aov_detect, 0, sizeof(sample_aov_detect_t)); s32Ret = xmedia_md_init(); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("ive md init fail.\n"); return XMEDIA_FAILURE; } for (i = 0; i < g_aov_init_param.isp_param.isp_pipe_num; i++) { g_aov_detect.ive_param[i].stMdAttr.en_alg_mode = XMEDIA_MD_ALG_MODE_REF; g_aov_detect.ive_param[i].stMdAttr.en_sad_mode = XMEDIA_IVE_SAD_MODE_MB_8X8; g_aov_detect.ive_param[i].stMdAttr.en_sad_out_ctrl = XMEDIA_IVE_SAD_OUT_CTRL_THRESH; g_aov_detect.ive_param[i].stMdAttr.u16_sad_thr = 1600; g_aov_detect.ive_param[i].stMdAttr.u32_width = NPU_CHN_WIDTH; g_aov_detect.ive_param[i].stMdAttr.u32_height = NPU_CHN_HEIGHT; g_aov_detect.ive_param[i].stMdAttr.st_add_ctrl.u0q16x = 32768; g_aov_detect.ive_param[i].stMdAttr.st_add_ctrl.u0q16y = 32768; g_aov_detect.ive_param[i].stMdAttr.st_ccl_ctrl.en_mode = XMEDIA_IVE_CCL_MODE_4C; u8WndSz = ( 1 << (2 + g_aov_detect.ive_param[i].stMdAttr.en_sad_mode)); g_aov_detect.ive_param[i].stMdAttr.st_ccl_ctrl.u16_init_area_thr = 180; g_aov_detect.ive_param[i].stMdAttr.st_ccl_ctrl.u16_step = u8WndSz; g_aov_detect.ive_param[i].is_first_frm = XMEDIA_TRUE; g_aov_detect.ive_param[i].md_chn = i; for (j = 0; j < AOV_IVE_MD_IMAGE_NUM; j++) { s32Ret = sample_aov_ive_create_image(&g_aov_detect.ive_param[i].astImg[j], NPU_CHN_WIDTH, NPU_CHN_HEIGHT); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("ive create img fail.\n"); goto ive_err0; } } s32Ret = sample_aov_ive_create_mem_info(&g_aov_detect.ive_param[i].stBlob, sizeof(xmedia_ive_ccblob_s)); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("ive create mem fail.\n"); goto ive_err1; } s32Ret = xmedia_md_create_chn(g_aov_detect.ive_param[i].md_chn, &(g_aov_detect.ive_param[i].stMdAttr)); if (XMEDIA_SUCCESS != s32Ret) { goto ive_err2; } } return XMEDIA_SUCCESS; ive_err2: xmedia_md_exit(); ive_err1: for (i = 0; i < g_aov_init_param.isp_param.isp_pipe_num; i++) { if(g_aov_detect.ive_param[i].stBlob.u64phyaddr != 0 && g_aov_detect.ive_param[i].stBlob.u64viraddr != XMEDIA_NULL) sample_aov_ive_mmz_free(g_aov_detect.ive_param[i].stBlob.u64phyaddr, (xmedia_void *)(xmedia_ulong)g_aov_detect.ive_param[i].stBlob.u64viraddr); } ive_err0: for (i = 0; i < g_aov_init_param.isp_param.isp_pipe_num; i++) { for (j = 0; j < AOV_IVE_MD_IMAGE_NUM; j++) { if(g_aov_detect.ive_param[i].astImg[j].au64phyaddr[0] != 0 && g_aov_detect.ive_param[i].astImg[j].au64viraddr[0] != XMEDIA_NULL) sample_aov_ive_mmz_free(g_aov_detect.ive_param[i].astImg[j].au64phyaddr[0], (xmedia_void *)(xmedia_ulong)g_aov_detect.ive_param[i].astImg[j].au64viraddr[0]); } } return XMEDIA_FAILURE; } static xmedia_s32 sample_aov_ive_exit(xmedia_void) { xmedia_s32 s32Ret = XMEDIA_FAILURE; xmedia_s32 i = 0, j = 0; for (i = 0; i < g_aov_init_param.isp_param.isp_pipe_num; i++) { s32Ret = xmedia_md_destroy_chn(g_aov_detect.ive_param[i].md_chn); if (XMEDIA_SUCCESS != s32Ret) { SAMPLE_ERR("xmedia_md_destroy_chn fail.\n"); } sample_aov_ive_mmz_free(g_aov_detect.ive_param[i].stBlob.u64phyaddr, (xmedia_void *)(xmedia_ulong)g_aov_detect.ive_param[i].stBlob.u64viraddr); for (j = 0; j < AOV_IVE_MD_IMAGE_NUM; j++) { sample_aov_ive_mmz_free(g_aov_detect.ive_param[i].astImg[j].au64phyaddr[0], (xmedia_void *)(xmedia_ulong)g_aov_detect.ive_param[i].astImg[j].au64viraddr[0]); } } xmedia_md_exit(); return XMEDIA_SUCCESS; } static xmedia_bool sample_aov_svp_ive_detect(xmedia_video_frame_info *video_frame, aov_ive_param *ive_param) { xmedia_s32 s32Ret = XMEDIA_FAILURE; xmedia_ive_ccblob_s *pst_blob = XMEDIA_NULL; if(ive_param == XMEDIA_NULL) { SAMPLE_ERR("input ive_param is NULL!\n"); return XMEDIA_FALSE; } s32Ret = sample_aov_ive_dma_image(video_frame, &ive_param->astImg[ive_param->cur_idx], XMEDIA_TRUE); if (XMEDIA_SUCCESS != s32Ret) { SAMPLE_ERR("aov_ive_dma_image, ret = 0x%x\n", s32Ret); return XMEDIA_FALSE; } if (XMEDIA_TRUE == ive_param->is_first_frm) { ive_param->is_first_frm = XMEDIA_FALSE; goto CHANGE_IDX; } s32Ret = xmedia_md_process(ive_param->md_chn, &ive_param->astImg[ive_param->cur_idx], &ive_param->astImg[1 - ive_param->cur_idx], XMEDIA_NULL, &ive_param->stBlob); if (XMEDIA_SUCCESS != s32Ret) { SAMPLE_ERR("xmedia_md_process, ret = 0x%x\n", s32Ret); return XMEDIA_FALSE; } pst_blob = (xmedia_ive_ccblob_s*)(xmedia_ulong)ive_param->stBlob.u64viraddr; if (pst_blob->u8_region_num > 0) { goto CHANGE_IDX; } else { return XMEDIA_FALSE; } CHANGE_IDX: //Change reference and current frame index ive_param->cur_idx = 1 - ive_param->cur_idx; return XMEDIA_TRUE; } #endif xmedia_void normal_job_func(xmedia_void *arg) { xmedia_s32 milli_sec = 2000; xmedia_s32 s32Ret = XMEDIA_FAILURE; xmedia_video_frame_info video_frame = {0}; xmedia_svp_task_input task_input = {0}; xmedia_s32 i = 0, index; sample_aov_vpss_npu_param *npu_param = XMEDIA_NULL; sample_aov_normal_npu_notice npu_notice = XMEDIA_NULL; xmedia_svp_aov_detect_output svp_result; sample_aov_isp_param *isp_param = XMEDIA_NULL; isp_param = &(g_aov_init_param.isp_param); index = *(xmedia_s32*)arg; if(index >= isp_param->isp_pipe_num) { SAMPLE_ERR("invalid index(%d)!!!\n", index); return; } npu_param = &(g_aov_init_param.npu_param); npu_notice = g_aov_init_param.npu_notice_callback; s32Ret = xmedia_vpss_acquire_ochn_frame(npu_param->vpss_pipe[index], npu_param->vpss_ochn[index], &video_frame, milli_sec); if (XMEDIA_SUCCESS != s32Ret) { SAMPLE_ERR("Warning, acquire pipe[%d] vpss ochn[%d] frame fail ret = 0x%x\n", npu_param->vpss_pipe[index], npu_param->vpss_ochn[index], s32Ret); goto END; } task_input.frame_num = 1; task_input.frame = &video_frame; s32Ret = xmedia_svp_task_process(npu_param->npu_svp_handle[index], &task_input, &svp_result); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("xmedia_svp_process failed with %#x!\n", s32Ret); svp_result.is_exist = XMEDIA_FALSE; } s32Ret = xmedia_vpss_release_ochn_frame(npu_param->vpss_pipe[index], npu_param->vpss_ochn[index], &video_frame); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("xmedia_vpss_release_ochn_frame failed with %#x!\n", s32Ret); } if(svp_result.is_exist == XMEDIA_FALSE) g_aov_detect.svp_detect_none_cnt[index]++; else g_aov_detect.svp_detect_none_cnt[index] = 0; if(g_aov_detect.svp_detect_none_cnt[index] >= NPU_NORMAL_STATE_CONTINUE_COUNT) { if (npu_notice != NULL) { npu_notice(MEDIA_WORK_AOV); for (i = 0; i < isp_param->isp_pipe_num; i++) { g_aov_detect.svp_detect_none_cnt[i] = 0; } } else { SAMPLE_ERR("npu notice callback not register \n"); } } END: g_aov_detect.detect_complete_flag[index] = 1; } static xmedia_void sample_aov_npu_normal_proc() { xmedia_s32 s32Ret = XMEDIA_FAILURE; xmedia_s32 i = 0, detect_flag = 0, need_delay = 0; static xmedia_s32 index[AOV_SUPPORT_MAX_SENSOR_NUM]; sample_aov_isp_param *isp_param = XMEDIA_NULL; isp_param = &(g_aov_init_param.isp_param); for (i = 0; i < isp_param->isp_pipe_num; i++) { index[i] = i; g_aov_detect.detect_complete_flag[i] = 0; s32Ret = sample_comm_thrd_job_submit(g_aov_thrd_pool_handle, &normal_job_func, &index[i]); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("submit normal job[%d] failed!!!\n", i); continue; } detect_flag |= 1 << i; } while(detect_flag != 0) { need_delay = 1; for (i = 0; i < isp_param->isp_pipe_num; i++) { if(g_aov_detect.detect_complete_flag[i] == 1) { detect_flag &= ~(1 << i); g_aov_detect.detect_complete_flag[i] = 0; need_delay = 0; } } if(need_delay) usleep(500); } } xmedia_void aov_job_func(xmedia_void *arg) { xmedia_s32 milli_sec = 2000; sample_aov_isp_param *isp_param = XMEDIA_NULL; sample_aov_vpss_npu_param *npu_param = XMEDIA_NULL; xmedia_s32 index = 0, s32Ret = XMEDIA_FAILURE; xmedia_svp_task_input task_input = {0}; xmedia_video_frame_info video_frame = {0}; #ifdef IVE_DETECT_SUPPORT xmedia_bool ive_detect = XMEDIA_TRUE; #endif npu_param = &(g_aov_init_param.npu_param); isp_param = &(g_aov_init_param.isp_param); index = *(xmedia_s32*)arg; if(index >= isp_param->isp_pipe_num) { SAMPLE_ERR("invalid index(%d)!!!\n", index); return; } #ifdef APP_STANDBY_SENSOR sample_aov_sensor_standby(isp_param->isp_pipe[index]); #endif #ifdef AOV_APP_TIMESTAMP timestamp[test_num].vpss_in = sample_aov_get_debug_timestamp(); #endif s32Ret = xmedia_vpss_acquire_ochn_frame(npu_param->vpss_pipe[index], npu_param->vpss_ochn[index], &video_frame, milli_sec); if (XMEDIA_SUCCESS != s32Ret) { SAMPLE_ERR("Warning, acquire pipe[%d] vpss ochn[%d] frame fail ret = 0x%x\n", npu_param->vpss_pipe[index], npu_param->vpss_ochn[index], s32Ret); g_aov_detect.svp_result[index].is_exist = XMEDIA_FALSE; goto END; } #ifdef AOV_APP_TIMESTAMP timestamp[test_num].svp_in = sample_aov_get_debug_timestamp(); #endif task_input.frame_num = 1; task_input.frame = &video_frame; #ifdef IVE_DETECT_SUPPORT ive_detect = sample_aov_svp_ive_detect(&video_frame, &g_aov_detect.ive_param[index]); if (g_aov_detect.ive_param[index].is_first_frm == XMEDIA_TRUE) { g_aov_detect.ive_param[index].is_first_frm = XMEDIA_FALSE; } if (ive_detect == XMEDIA_FALSE) { g_aov_detect.svp_result[index].is_exist = XMEDIA_FALSE; } else #endif { s32Ret = xmedia_svp_task_process(npu_param->npu_svp_handle[index], &task_input, &g_aov_detect.svp_result[index]); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("xmedia_svp_process failed with %#x!\n", s32Ret); g_aov_detect.svp_result[index].is_exist = XMEDIA_FALSE; } } s32Ret = xmedia_vpss_release_ochn_frame(npu_param->vpss_pipe[index], npu_param->vpss_ochn[index], &video_frame); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("xmedia_vpss_release_ochn_frame failed with %#x!\n", s32Ret); } #ifdef IVE_DETECT_SUPPORT if(g_aov_detect.svp_result[index].is_exist == XMEDIA_TRUE) g_aov_detect.ive_param[index].is_first_frm = XMEDIA_TRUE; #endif END: g_aov_detect.detect_complete_flag[index] = 1; } static xmedia_void sample_aov_npu_aov_proc(xmedia_bool *is_exist) { xmedia_s32 s32Ret = XMEDIA_FAILURE; xmedia_s32 i = 0, detect_flag = 0, need_delay = 0; static xmedia_s32 index[AOV_SUPPORT_MAX_SENSOR_NUM]; sample_aov_isp_param *isp_param = XMEDIA_NULL; *is_exist = XMEDIA_FALSE; isp_param = &(g_aov_init_param.isp_param); for (i = 0; i < isp_param->isp_pipe_num; i++) { index[i] = i; g_aov_detect.detect_complete_flag[i] = 0; s32Ret = sample_comm_thrd_job_submit(g_aov_thrd_pool_handle, &aov_job_func, &index[i]); if (s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("submit aov job[%d] failed!!!\n", i); continue; } detect_flag |= 1 << i; } while(detect_flag != 0) { need_delay = 1; for (i = 0; i < isp_param->isp_pipe_num; i++) { if(g_aov_detect.detect_complete_flag[i] == 1) { *is_exist |= g_aov_detect.svp_result[i].is_exist; detect_flag &= ~(1 << i); need_delay = 0; } } if(need_delay) usleep(500); } #ifdef AOV_APP_TIMESTAMP timestamp[test_num].svp_out = sample_aov_get_debug_timestamp(); #endif return ; } static xmedia_void* sample_aov_venc_stream_thread(xmedia_void* p) { sample_aov_work_mode work_mode = MEDIA_WORK_NORMAL; VENC_THREAD_IDEL: sem_wait(&g_venc_steram_save_start_sem); sample_comm_aov_get_work_mode(&work_mode); if (g_venc_thread == XMEDIA_FALSE) { return XMEDIA_NULL; } sample_aov_venc_save_stream(work_mode); sem_post(&g_venc_steram_save_stop_sem); goto VENC_THREAD_IDEL; return XMEDIA_NULL; } static xmedia_void* sample_aov_work_thread(xmedia_void* p) { xmedia_bool goal_is_exist = XMEDIA_FALSE; xmedia_bool venc_buf_full = XMEDIA_FALSE; xmedia_bool first_aov_state = XMEDIA_TRUE; sample_aov_work_mode work_mode = MEDIA_WORK_NORMAL; sample_aov_normal_npu_notice npu_notice = XMEDIA_NULL; sample_aov_normal_resume normal_resume = XMEDIA_NULL; sample_aov_normal_suspend normal_suspend = XMEDIA_NULL; npu_notice = g_aov_init_param.npu_notice_callback; normal_resume = g_aov_init_param.normal_resume_callback; normal_suspend = g_aov_init_param.normal_suspend_callback; while(g_work_aov_thread) { sample_comm_aov_get_work_mode(&work_mode); if (work_mode == MEDIA_WORK_NORMAL) { //normal npu set results only. sample_aov_npu_normal_proc(); } else { if (first_aov_state != XMEDIA_TRUE) { //aov get npu goal state. sample_aov_npu_aov_proc(&goal_is_exist); if (goal_is_exist == XMEDIA_TRUE) { //goal is exist switch normal. resume normal pipe only. sample_comm_aov_set_work_mode(MEDIA_WORK_NORMAL); sample_aov_work_normal_pipe_resume(); if (npu_notice != XMEDIA_NULL) { npu_notice(MEDIA_WORK_NORMAL); } else { SAMPLE_ERR("npu notice callback not register \n"); } if (normal_resume != XMEDIA_NULL) { normal_resume(); } first_aov_state = XMEDIA_TRUE; continue; } else { //goal is nit exist, get venc buf state . venc_buf_full = sample_aov_venc_get_aov_buf_full(); if (venc_buf_full == XMEDIA_TRUE) { sample_aov_work_aov_save_resume(); sample_aov_work_aov_save_suspend(); } else { } } }else { //normal switch aov first. suspend normal pipe. if (normal_suspend != XMEDIA_NULL) { normal_suspend(); } sample_aov_work_normal_pipe_suspend(); first_aov_state = XMEDIA_FALSE; } sample_aov_suspend(); } } return XMEDIA_NULL; } xmedia_void sample_comm_aov_init(sample_aov_init_param *aov_init_param) { memcpy(&g_aov_init_param, aov_init_param, sizeof(sample_aov_init_param)); pthread_mutex_init(&g_sync_mutex, NULL); pthread_mutex_init(&g_npu_detect_mutex, NULL); sem_init(&g_venc_steram_save_start_sem, 0, 1); sem_init(&g_venc_steram_save_stop_sem, 0, 0); for (xmedia_s32 i = 0; i < g_aov_init_param.isp_param.isp_pipe_num; i++) { sample_aov_ae_modify_path(g_aov_init_param.isp_param.isp_pipe[i]); #ifdef APP_STANDBY_SENSOR g_aov_init_param.sensor_status[i] = SENSOR_STATUS_START; #endif } g_aov_thrd_pool_handle = sample_comm_thrd_pool_init(g_aov_init_param.isp_param.isp_pipe_num, g_aov_init_param.isp_param.isp_pipe_num * 2); sample_aov_drv_sdcard_load(); #ifdef IVE_DETECT_SUPPORT sample_aov_ive_init(); #endif } xmedia_void sample_comm_aov_exit(xmedia_void) { #ifdef IVE_DETECT_SUPPORT sample_aov_ive_exit(); #endif if(g_aov_thrd_pool_handle) { sample_comm_thrd_pool_destroy(g_aov_thrd_pool_handle); g_aov_thrd_pool_handle = NULL; } sem_destroy(&g_venc_steram_save_start_sem); sem_destroy(&g_venc_steram_save_stop_sem); pthread_mutex_lock(&g_sync_mutex); pthread_mutex_unlock(&g_sync_mutex); pthread_mutex_destroy(&g_sync_mutex); pthread_mutex_lock(&g_npu_detect_mutex); pthread_mutex_unlock(&g_npu_detect_mutex); pthread_mutex_destroy(&g_npu_detect_mutex); } xmedia_void sample_comm_aov_set_work_mode(sample_aov_work_mode work_mode) { pthread_mutex_lock(&g_sync_mutex); g_media_work_mode = work_mode; if (work_mode == MEDIA_WORK_AOV) { SAMPLE_ERR("--------->debug switch to aov<------\n"); } else { SAMPLE_ERR("--------->debug switch to normal<--------\n"); } pthread_mutex_unlock(&g_sync_mutex); } xmedia_void sample_comm_aov_get_work_mode(sample_aov_work_mode *work_mode) { pthread_mutex_lock(&g_sync_mutex); *work_mode = g_media_work_mode; pthread_mutex_unlock(&g_sync_mutex); } xmedia_s32 sample_comm_aov_npu_init(xmedia_void) { xmedia_s32 s32Ret = XMEDIA_FAILURE; s32Ret = xmedia_tde_init(); if (XMEDIA_SUCCESS != s32Ret) { SAMPLE_ERR("tde init fail"); return s32Ret; } s32Ret = xmedia_svp_init(); if (XMEDIA_SUCCESS != s32Ret) { SAMPLE_ERR("svp init fail"); return s32Ret; } return XMEDIA_SUCCESS; } xmedia_s32 sample_comm_aov_npu_create(xmedia_s32 *handle, xmedia_svp_task_cfg *task_cfg) { xmedia_s32 s32Ret = XMEDIA_FAILURE; xmedia_svp_aov_attr yolov5_attr = {0}; s32Ret = xmedia_svp_task_create(handle, *task_cfg); if (XMEDIA_SUCCESS != s32Ret) { SAMPLE_ERR("------------- svp create fail--please check your npu model name & path.\n"); return s32Ret; } s32Ret = xmedia_svp_task_get_attr(*handle, &yolov5_attr); if (XMEDIA_SUCCESS != s32Ret) { SAMPLE_ERR("svp get task attr fail.\n"); xmedia_svp_task_destroy(*handle); xmedia_svp_uninit(); return s32Ret; } yolov5_attr.aov_only_target = XMEDIA_FALSE; s32Ret = xmedia_svp_task_set_attr(*handle, &yolov5_attr); if(s32Ret != XMEDIA_SUCCESS) { SAMPLE_ERR("svp set task attr fail.\n"); xmedia_svp_task_destroy(*handle); return XMEDIA_FAILURE; } return XMEDIA_SUCCESS; } xmedia_s32 sample_comm_aov_npu_destroy(xmedia_s32 handle) { xmedia_s32 s32Ret = XMEDIA_FAILURE; s32Ret = xmedia_svp_task_destroy(handle); if (XMEDIA_SUCCESS != s32Ret) { SAMPLE_ERR("svp destroy error\n"); } return s32Ret; } xmedia_void sample_comm_aov_npu_exit(xmedia_void) { xmedia_svp_uninit(); xmedia_tde_exit(); } xmedia_s32 sample_comm_aov_venc_thread_create(xmedia_void) { pthread_attr_t venc_thread_creat; pthread_t venc_thread; if (g_venc_thread == XMEDIA_TRUE) { SAMPLE_ERR("venc get stream thread already create \n"); return XMEDIA_SUCCESS; } g_venc_thread = XMEDIA_TRUE; pthread_attr_init(&venc_thread_creat); pthread_attr_setdetachstate(&venc_thread_creat, PTHREAD_CREATE_DETACHED); return pthread_create(&venc_thread, &venc_thread_creat, sample_aov_venc_stream_thread, XMEDIA_NULL); } xmedia_s32 sample_comm_aov_venc_thread_destroy(xmedia_void) { if (XMEDIA_TRUE == g_venc_thread) { g_venc_thread = XMEDIA_FALSE; } return XMEDIA_SUCCESS; } xmedia_s32 sample_comm_aov_work_thread_create(xmedia_void) { pthread_attr_t work_aov_creat; pthread_t work_aov_thraed; if (g_work_aov_thread == XMEDIA_TRUE) { SAMPLE_ERR("venc get stream thread already create \n"); return XMEDIA_SUCCESS; } g_work_aov_thread = XMEDIA_TRUE; pthread_attr_init(&work_aov_creat); pthread_attr_setdetachstate(&work_aov_creat, PTHREAD_CREATE_DETACHED); return pthread_create(&work_aov_thraed, &work_aov_creat, sample_aov_work_thread, XMEDIA_NULL); } xmedia_s32 sample_comm_aov_work_thread_destroy(xmedia_void) { if (XMEDIA_TRUE == g_work_aov_thread) { g_work_aov_thread = XMEDIA_FALSE; } return XMEDIA_SUCCESS; } xmedia_s32 sample_comm_aov_misc_init(misc_aov_isp_info *isp_info) { if(isp_info == XMEDIA_NULL) { SAMPLE_ERR("invalid input parameter!\n"); return XMEDIA_FAILURE; } if(isp_info->isp_pipe_num == 0) { SAMPLE_ERR("invalid isp_pipe_num!\n"); return XMEDIA_FAILURE; } #ifdef SUPPORT_SENSOR_PWDN_MODE for(xmedia_s32 i = 0; i < isp_info->isp_pipe_num; i++) { support_sensor_pwdn_standby[i] = isp_info->support_sensor_pwdn_standby[i]; } #endif g_misc_fd = open("/dev/misc", O_RDONLY); if(g_misc_fd == -1) { SAMPLE_ERR("open /dev/misc failed, errno:%d %s\n", errno, strerror(errno)); return XMEDIA_FAILURE; } return ioctl(g_misc_fd, XMEDIA_MISC_AOV_INIT, (xmedia_u32)isp_info, NULL); } xmedia_s32 sample_comm_aov_get_misc_fd(xmedia_void) { return g_misc_fd; }