#include "PrjInc.h" #include "PhotoFastSliceEncode.h" #include "kwrap/debug.h" #include "kwrap/perf.h" #include "hdal.h" #include "vf_gfx.h" #include "SizeConvert.h" #include "exif/Exif.h" #include "vendor_videoenc.h" #include "GxImageFile.h" #include "NamingRule/NameRule_Custom.h" #include "sys_fastboot.h" #include "UIApp/ExifVendor.h" #include "PhotoFastCapDateImprint.h" #include "PhotoFast.h" #include #include "DxHunting.h" #include "UIAppPhoto_Param.h" #include "DCF.h" #include "sys_usrmem.h" #if HUNTING_CAMERA_MCU == ENABLE #include #include "sf_sd_common.h" #endif #define VDO_YUV_BUFSIZE(w, h, pxlfmt) ALIGN_CEIL_4(((w) * (h) * HD_VIDEO_PXLFMT_BPP(pxlfmt)) / 8) #define VDO_RAW_BUFSIZE(w, h, pxlfmt) (ALIGN_CEIL_4((w) * HD_VIDEO_PXLFMT_BPP(pxlfmt) / 8) * (h)) /********************************************************************************** * independent thumbnail *********************************************************************************/ #define PHOTOFAST_FAST_CLOSE 0 #define PHOTOFAST_FAST_STAMP 1 #define PHOTOFAST_SLICE_ENC_DBG_DUMP 0 #define PHOTOFAST_SLICE_ENC_DBG_PRIMARY_YUV 0 #define PHOTOFAST_SLICE_ENC_DBG_SLICE_YUV 0 #define PHOTOFAST_SLICE_ENC_DBG_PRIMARY_JPG 0 #define PHOTOFAST_SLICE_ENC_DBG_SCREENNAIL_JPG 0 #define PHOTOFAST_SLICE_ENC_DBG_THUMBNAIL_JPG 0 #define PHOTOFAST_SLICE_ENC_QUEUE12_MAX_SIZE 1 #define PHOTOFAST_SLICE_ENC_QUEUE23_MAX_SIZE 1 #if PHOTOFAST_SLICE_ENC_DBG_PRIMARY_JPG || PHOTOFAST_SLICE_ENC_DBG_SCREENNAIL_JPG || PHOTOFAST_SLICE_ENC_DBG_THUMBNAIL_JPG #define PHOTOFAST_SLICE_ENC_DBG_JPG 1 #else #define PHOTOFAST_SLICE_ENC_DBG_JPG 0 #endif #if PHOTOFAST_SLICE_ENC_DBG_DUMP #define PHOTOFAST_SLICE_ENC_DUMP(fmtstr, args...) DBG_DUMP(fmtstr, ##args) /* debug dump macro */ #else #define PHOTOFAST_SLICE_ENC_DUMP(fmtstr, args...) #endif typedef struct { UINT32 va; UINT32 pa; HD_COMMON_MEM_VB_BLK blk; UINT32 blk_size; UINT32 used_size; } PhotoFast_MEM_Info; typedef struct { HD_PATH_ID enc_path_id; PhotoFast_MEM_Info hd_enc_internal_buf_mem_info; PhotoFast_MEM_Info yuv_buf_mem_info; PhotoFast_MEM_Info bs_buf_mem_info; } PhotoFast_SliceEncode_Info; extern void PhotoFast_Cal_Jpg_Size(USIZE *psrc, USIZE *pdest , URECT *pdestwin); static HD_DIM PhotoFast_SliceEncode_Get_Encode_Max_Size(void); static UINT32 PhotoFast_SliceEncode_Get_Encode_Max_Bitrate(HD_VIDEO_PXLFMT vproc_out_pxlfmt); static INT32 PhotoFast_SliceEncode_Get_Comm_Buffer(PhotoFast_MEM_Info* mem_info); static INT32 PhotoFast_SliceEncode_Release_Comm_Buffer(PhotoFast_MEM_Info mem_info); static INT32 PhotoFast_SliceEncode_Encode_Screennail(HD_VIDEO_FRAME* video_frame_in); #if PHOTOFAST_FAST_STAMP == ENABLE INT32 PhotoFastCapDateImprint_Src_GenYuvData( HD_VIDEO_FRAME *video_frame, PhotoFast_SliceSize_Info* src_slice_info, PhotoFast_SliceSize_Info* dst_slice_info) { HD_VIDEO_FRAME video_frame_src_stamp = *video_frame; UINT32 dst_last_slice_scale_height = (src_slice_info->last_slice_height * dst_slice_info->slice_height) / src_slice_info->slice_height; if(dst_last_slice_scale_height > dst_slice_info->last_slice_height) { video_frame_src_stamp.dim.h = video_frame_src_stamp.dim.h - ((src_slice_info->last_slice_height * (dst_last_slice_scale_height - dst_slice_info->last_slice_height)) / dst_last_slice_scale_height); video_frame_src_stamp.ph[0] = video_frame_src_stamp.dim.h; video_frame_src_stamp.ph[1] = video_frame_src_stamp.dim.h; } return PhotoFastCapDateImprint_GenYuvData(&video_frame_src_stamp); } #endif static UINT32 PhotoFast_PHY2VIRT(UINT32 pa_pos, UINT32 pa_start, UINT32 va) { if(pa_pos < pa_start){ DBG_ERR("pa_pos(%lx) must greater than pa_start(%lx)!\r\n", pa_pos, pa_start); return 0; } else if(va == 0 || pa_start == 0 || pa_pos == 0){ DBG_ERR("va & pa & pa_start can't be zero!\r\n"); return 0; } return (va + (pa_pos - pa_start)); } static PhotoFast_SliceEncode_Info* PhotoFast_SliceEncode_Get_Info(const PHOTO_ENC_JPG_TYPE type) { static PhotoFast_SliceEncode_Info info[PHOTO_ENC_JPG_TYPE_MAX_ID] = {0}; return &info[type]; } static void PhotoFast_SliceEncode_Get_Src_Slice_Info( const PhotoFast_SliceSize_Info *dst_info, PhotoFast_SliceSize_Info *src_info, const HD_VIDEO_FRAME video_frame) { src_info->slice_num = dst_info->slice_num; src_info->width = video_frame.dim.w; src_info->height = video_frame.dim.h; if(src_info->slice_num > 1){ src_info->slice_height = ALIGN_CEIL((src_info->height) / src_info->slice_num, 2); src_info->last_slice_height = ALIGN_CEIL(src_info->height - src_info->slice_height * (src_info->slice_num - 1), 2); } else{ src_info->slice_height = video_frame.dim.h; src_info->last_slice_height = src_info->slice_height; } if(src_info->slice_height * (src_info->slice_num - 1) >= src_info->height){ DBG_ERR("aligned total slice height(%lu * %lu + %lu = %lu) exceed photo height(%lu)!\n", src_info->slice_height, src_info->slice_num - 1, src_info->last_slice_height, src_info->height); } PHOTOFAST_SLICE_ENC_DUMP("Src Slice Info: size = {%lu,%lu} slice num = {%lu} slice height = {%lu} last slice height = {%lu}\r\n", src_info->width, src_info->height, src_info->slice_num, src_info->slice_height, src_info->last_slice_height); } INT32 PhotoFast_SliceEncode_Get_Max_Dst_Slice_Buffer_Size(HD_VIDEO_PXLFMT pxl_fmt) { HD_DIM dim = PhotoFast_SliceEncode_Get_Encode_Max_Size(); UINT32 reserved_buffer = 0; UINT32 max_buffer_size = VDO_YUV_BUFSIZE(ALIGN_CEIL(dim.w, 16), ALIGN_CEIL(dim.h, 16), pxl_fmt) + reserved_buffer; return max_buffer_size; } static INT32 PhotoFast_SliceEncode_Get_Dst_Slice_Info(PhotoFast_SliceSize_Info *info, UINT32 cap_size_w, UINT32 cap_size_h, UINT32 slice_num) { info->width = cap_size_w; info->height = cap_size_h; info->slice_num = slice_num; if(info->height == 1080 && slice_num == 1){ info->slice_height = info->height; } else{ info->slice_height = ALIGN_CEIL_16(info->height / info->slice_num); } if(info->slice_height * (info->slice_num - 1) > info->height){ DBG_ERR("calculate last slice height error!(slice_height = %lu, slice_num = %lu, photo height = %lu)\n", info->slice_height, info->slice_num, info->height); return E_SYS; } info->last_slice_height = info->height - (info->slice_height * (info->slice_num - 1)); PHOTOFAST_SLICE_ENC_DUMP("Dst Slice Info: size = {%lu,%lu} slice num = {%lu} slice height = {%lu} last slice height = {%lu}\r\n", info->width, info->height, info->slice_num, info->slice_height, info->last_slice_height); return E_OK; } INT32 PhotoFast_SliceEncode_Get_Curr_Dst_Slice_Info(PhotoFast_SliceSize_Info *info, const HD_VIDEO_FRAME src_frame) { UINT32 cap_size_w = GetPhotoSizeWidth(SysGetFlag(FL_PHOTO_SIZE)); UINT32 cap_size_h = GetPhotoSizeHeight(SysGetFlag(FL_PHOTO_SIZE)); UINT32 max_slice_num; UINT32 slice_num; unsigned int cap_size = cap_size_w * cap_size_h; unsigned int buf_size = CFG_PHOTOFAST_SLICE_ENC_PRIMARY_BUF_WIDTH * CFG_PHOTOFAST_SLICE_ENC_PRIMARY_BUF_HEIGHT; if(buf_size > cap_size){ max_slice_num = 1; slice_num = 1; } else{ PHOTOFAST_SLICE_ENC_DUMP("cap_size = %lu buf_size = %lu\n", cap_size, buf_size); UINT32 lines = (buf_size / cap_size_w); UINT32 slice_height = ALIGN_CEIL(lines, 16); max_slice_num = (cap_size_h / slice_height) + (cap_size_h % slice_height ? 1 : 0); UINT32 tmp_src_h = src_frame.dim.h / 2; UINT32 tmp_dst_h = cap_size_h / 16; UINT32 found_common_factor = 0; UINT32 i; for (i = 1; i <= (tmp_src_h > tmp_dst_h ? tmp_dst_h : tmp_src_h) ; ++i) { if (tmp_src_h % i == 0 && tmp_dst_h % i == 0) { PHOTOFAST_SLICE_ENC_DUMP("common factor = %d\n", i); if(max_slice_num < i){ found_common_factor = i; break; } } } if(found_common_factor){ slice_num = found_common_factor; PHOTOFAST_SLICE_ENC_DUMP("use common factor %d\n ", slice_num); } else{ slice_num = max_slice_num; PHOTOFAST_SLICE_ENC_DUMP("use max slice num %d\n ", slice_num); } } return PhotoFast_SliceEncode_Get_Dst_Slice_Info(info, cap_size_w, cap_size_h, slice_num); } static UINT32 PhotoFast_SliceEncode_Get_Max_Dst_Slice_Info(PhotoFast_SliceSize_Info *info) { static PhotoFast_SliceSize_Info max_slice_info = {0}; UINT32 max_slice_num; UINT32 slice_num; INT32 ret = E_OK; UIAPP_PHOTO_SENSOR_INFO *sensor_info = UIAppPhoto_get_SensorInfo(0); unsigned int buf_size = CFG_PHOTOFAST_SLICE_ENC_PRIMARY_BUF_WIDTH * CFG_PHOTOFAST_SLICE_ENC_PRIMARY_BUF_HEIGHT; /* search max slice (slice height * slice width) */ if(!max_slice_info.slice_height || !max_slice_info.width){ UINT8 cap_idx = 0; for(cap_idx = PHOTO_MAX_CAP_SIZE ; cap_idx <= PHOTO_MIN_CAP_SIZE ; cap_idx++) { HD_DIM tmp_cap_size = {0}; PhotoFast_SliceSize_Info tmp_slice_info = {0}; tmp_cap_size = (HD_DIM){GetPhotoSizeWidth(cap_idx), GetPhotoSizeHeight(cap_idx)}; if(buf_size > (tmp_cap_size.w * tmp_cap_size.h)){ max_slice_num = 1; slice_num = 1; } else{ PHOTOFAST_SLICE_ENC_DUMP("cap_size = %lu buf_size = %lu\n", tmp_cap_size.w * tmp_cap_size.h, buf_size); UINT32 lines = (buf_size / tmp_cap_size.w); UINT32 slice_height = ALIGN_CEIL(lines, 16); max_slice_num = (tmp_cap_size.h / slice_height) + (tmp_cap_size.h % slice_height ? 1 : 0); UINT32 tmp_src_h = sensor_info->sSize.h / 2; UINT32 tmp_dst_h = tmp_cap_size.h / 16; UINT32 found_common_factor = 0; UINT32 i; for (i = 1; i <= (tmp_src_h > tmp_dst_h ? tmp_dst_h : tmp_src_h) ; ++i) { if (tmp_src_h % i == 0 && tmp_dst_h % i == 0) { PHOTOFAST_SLICE_ENC_DUMP("common factor = %d\n", i); if(max_slice_num < i){ found_common_factor = i; break; } } } if(found_common_factor){ slice_num = found_common_factor; PHOTOFAST_SLICE_ENC_DUMP("use common factor %d\n ", slice_num); } else{ slice_num = max_slice_num; PHOTOFAST_SLICE_ENC_DUMP("use max slice num %d\n ", slice_num); } } ret = PhotoFast_SliceEncode_Get_Dst_Slice_Info(&tmp_slice_info, tmp_cap_size.w, tmp_cap_size.h, slice_num); if((tmp_slice_info.slice_height * tmp_slice_info.width) > (max_slice_info.slice_height * max_slice_info.width)){ max_slice_info = tmp_slice_info; } } PHOTOFAST_SLICE_ENC_DUMP("max dst slice = {%lu, %lu}, cap idx = %lu\n", max_slice_info.width, max_slice_info.slice_height, cap_idx); } *info = max_slice_info; return ret; } static HD_DIM PhotoFast_SliceEncode_Get_Encode_Max_Size(void) { PhotoFast_SliceSize_Info info; if(PhotoFast_SliceEncode_Get_Max_Dst_Slice_Info(&info) != E_OK) return (HD_DIM){0, 0}; HD_DIM dim_max_slice = {info.width, info.slice_height}; return dim_max_slice; } static UINT32 PhotoFast_SliceEncode_Get_Encode_Max_Bitrate(HD_VIDEO_PXLFMT vproc_out_pxlfmt) { const UINT32 ratio = CFG_PHOTOFAST_SLICE_ENC_BS_BUF_RATIO; UINT32 bitrate; HD_DIM dim = PhotoFast_SliceEncode_Get_Encode_Max_Size(); if(dim.w == 0 || dim.h == 0){ DBG_ERR("can't get max size\r\n"); return 0; } bitrate = (dim.w * dim.h * HD_VIDEO_PXLFMT_BPP(vproc_out_pxlfmt) / ratio); PHOTOFAST_SLICE_ENC_DUMP("vproc_out_pxlfmt = {%lx}, dim = {%lu, %lu}, ratio = {%lu}, bitrate = {%lu}\r\n", vproc_out_pxlfmt, dim.w, dim.h, ratio, bitrate); return bitrate; } static INT32 PhotoFast_SliceEncode_Encode_Config_Path(HD_PATH_ID enc_path, HD_DIM max_dim, UINT32 bitrate) { HD_RESULT ret; HD_VIDEOENC_PATH_CONFIG video_enc_path_config = {0}; video_enc_path_config.max_mem.codec_type = HD_CODEC_TYPE_JPEG; video_enc_path_config.max_mem.max_dim = max_dim; video_enc_path_config.max_mem.bitrate = bitrate; video_enc_path_config.max_mem.enc_buf_ms = 1500; video_enc_path_config.max_mem.svc_layer = HD_SVC_DISABLE; video_enc_path_config.max_mem.ltr = FALSE; video_enc_path_config.max_mem.rotate = FALSE; video_enc_path_config.max_mem.source_output = FALSE; video_enc_path_config.isp_id = 0; PHOTOFAST_SLICE_ENC_DUMP("hd_videoenc_set HD_VIDEOENC_PARAM_PATH_CONFIG max_dim={%lu, %lu} bitrate={%lu}\r\n", max_dim, bitrate); ret = hd_videoenc_set(enc_path, HD_VIDEOENC_PARAM_PATH_CONFIG, &video_enc_path_config); if (ret != HD_OK) { DBG_ERR("hd_videoenc_set HD_VIDEOENC_PARAM_PATH_CONFIG failed(%d)\r\n", ret); } return (ret == HD_OK) ? E_OK : E_SYS; } static INT32 PhotoFast_SliceEncode_Encode_Set_Out( const HD_PATH_ID enc_path_id, const UINT32 quality) { HD_RESULT ret; HD_VIDEOENC_OUT enc_out = {0}; enc_out.codec_type = HD_CODEC_TYPE_JPEG; enc_out.jpeg.retstart_interval = 0; enc_out.jpeg.image_quality = quality; PHOTOFAST_SLICE_ENC_DUMP("hd_videoenc_set HD_VIDEOENC_PARAM_OUT_ENC_PARAM path_id={%lx} image_quality={%lu}\r\n", enc_path_id, enc_out.jpeg.image_quality); ret = hd_videoenc_set(enc_path_id, HD_VIDEOENC_PARAM_OUT_ENC_PARAM, &enc_out); if (ret != HD_OK) { DBG_ERR("set_enc_param_out = %d\r\n", ret); return E_SYS; } return E_OK; } static INT32 PhotoFast_SliceEncode_Encode_Get_Out(const HD_PATH_ID enc_path_id, UINT32* quality) { HD_RESULT ret; HD_VIDEOENC_OUT enc_out = {0}; ret = hd_videoenc_get(enc_path_id, HD_VIDEOENC_PARAM_OUT_ENC_PARAM, &enc_out); if (ret != HD_OK) { DBG_ERR("hd_videoenc_get = %d\r\n", ret); return E_SYS; } *quality = enc_out.jpeg.image_quality; PHOTOFAST_SLICE_ENC_DUMP("hd_videoenc_get HD_VIDEOENC_PARAM_OUT_ENC_PARAM path_id={%lx} image_quality={%lu}\r\n", enc_path_id, enc_out.jpeg.image_quality); return E_OK; } static INT32 PhotoFast_SliceEncode_Encode_Set_In( const HD_PATH_ID enc_path_id, const HD_VIDEO_PXLFMT vproc_out_pxlfmt, const HD_DIM dim) { HD_RESULT ret; HD_VIDEOENC_IN enc_in = {0}; enc_in.dir = HD_VIDEO_DIR_NONE; enc_in.pxl_fmt = vproc_out_pxlfmt; enc_in.dim = dim; enc_in.frc = HD_VIDEO_FRC_RATIO(1,1); PHOTOFAST_SLICE_ENC_DUMP("hd_videoenc_set HD_VIDEOENC_PARAM_IN path_id={%lx} dim={%lu, %lu} pxlfmt={%lx}\r\n", enc_path_id, enc_in.dim, vproc_out_pxlfmt); ret = hd_videoenc_set(enc_path_id, HD_VIDEOENC_PARAM_IN, &enc_in); if(ret != HD_OK){ DBG_ERR("hd_videoenc_set HD_VIDEOENC_PARAM_IN failed(path_id=%lx, ret=%d)!", enc_path_id, ret); return E_SYS; } return E_OK; } INT32 PhotoFast_SliceEncode_Open(const HD_PATH_ID vproc_path_id) { HD_RESULT ret = HD_OK; PhotoFast_SliceSize_Info dst_slice_info = {0}; HD_DIM dim = {0}; UINT32 bitrate = 0; HD_PATH_ID venc_path_id = 0; HD_VIDEOPROC_OUT vproc_out = {0}; HD_VIDEO_PXLFMT vproc_out_pxlfmt = 0; UINT8 first_out_port = 0; /* 0 & 1 used by ImageApp_Photo, encode path can be shared by different sensor */ HD_IN_ID in = HD_VIDEOENC_IN(0, first_out_port); HD_OUT_ID out = HD_VIDEOENC_OUT(0, first_out_port); /* calculate dst slice info */ if(PhotoFast_SliceEncode_Get_Max_Dst_Slice_Info(&dst_slice_info) != E_OK){ goto EXIT; } for (unsigned int i = 0; i < SENSOR_CAPS_COUNT; i++) { /* get vproc out frame format ( = venc in) */ ret = hd_videoproc_get(vproc_path_id, HD_VIDEOPROC_PARAM_OUT, (VOID*)&vproc_out); if(ret != HD_OK){ DBG_ERR("hd_videoproc_get HD_VIDEOPROC_PARAM_OUT failed(path_id=%lx, ret=%d)!", vproc_path_id, ret); vproc_out_pxlfmt = HD_VIDEO_PXLFMT_YUV420; } else{ vproc_out_pxlfmt = vproc_out.pxlfmt; } } ret = hd_videoenc_init(); if (ret != HD_OK && ret != HD_ERR_UNINIT){ DBG_ERR("hd_videoenc_init failed (%d)\r\n", ret); goto EXIT; } in = HD_VIDEOENC_IN(0, first_out_port); out = HD_VIDEOENC_OUT(0, first_out_port); ret = hd_videoenc_open(in, out, &venc_path_id); if (ret != HD_OK ){ DBG_ERR("hd_videoenc_open(%lx, %lx) failed(%d)!\r\n", in, out, ret); goto EXIT; } for(int i=0 ; ienc_path_id = venc_path_id; /* calculate max buffer for slice */ info->yuv_buf_mem_info.blk_size = PhotoFast_SliceEncode_Get_Max_Dst_Slice_Buffer_Size(vproc_out_pxlfmt); if(PhotoFast_SliceEncode_Get_Max_Dst_Slice_Info(&max_info) != E_OK) goto EXIT; bitrate = PhotoFast_SliceEncode_Get_Encode_Max_Bitrate(vproc_out_pxlfmt); if(bitrate == 0){ DBG_ERR("Calculate bitrate error!\r\n"); goto EXIT; } dim = (HD_DIM){max_info.width, max_info.slice_height}; PhotoFast_SliceEncode_Encode_Config_Path(info->enc_path_id, dim, bitrate * 2); break; } case PHOTO_ENC_JPG_SCREENNAIL: { info->enc_path_id = venc_path_id; #if HUNTING_CAMERA_MCU == ENABLE UIMenuStoreInfo *puiPara = sf_ui_para_get(); info->yuv_buf_mem_info.blk_size = VDO_YUV_BUFSIZE(sf_get_screen_nail_width(puiPara->SendPicSize), sf_get_screen_nail_height(puiPara->SendPicSize), vproc_out_pxlfmt); dim = (HD_DIM){sf_get_screen_nail_width(puiPara->SendPicSize), sf_get_screen_nail_height(puiPara->SendPicSize)}; bitrate = ((sf_get_screen_nail_width(puiPara->SendPicSize)) * (sf_get_screen_nail_height(puiPara->SendPicSize))*3/(2*JPG_COMERESSED_RATIO_8)) * 8; #else info->yuv_buf_mem_info.blk_size = VDO_YUV_BUFSIZE(CFG_SCREENNAIL_W, CFG_SCREENNAIL_H, vproc_out_pxlfmt); dim = (HD_DIM){CFG_SCREENNAIL_W, CFG_SCREENNAIL_H}; bitrate = SCREENNAIL_TARGETBYTERATE * 8; #endif break; } case PHOTO_ENC_JPG_THUMBNAIL: { info->enc_path_id = venc_path_id; info->yuv_buf_mem_info.blk_size = VDO_YUV_BUFSIZE(CFG_THUMBNAIL_W, CFG_THUMBNAIL_H, vproc_out_pxlfmt); dim = (HD_DIM){CFG_THUMBNAIL_W, CFG_THUMBNAIL_H}; bitrate = THUMBNAIL_TARGETBYTERATE * 8; break; } } if(PhotoFast_SliceEncode_Get_Comm_Buffer(&info->yuv_buf_mem_info) != E_OK) return E_SYS; } EXIT: return (ret == HD_OK) ? E_OK : E_SYS; } INT32 PhotoFast_SliceEncode_Close(void) { HD_RESULT ret; HD_PATH_ID path_id = 0; for(int i=0 ; ienc_path_id){ ret = hd_videoenc_close(info->enc_path_id); if (ret != HD_OK){ DBG_ERR("hd_videoenc_close failed(%d)!\r\n",ret); } path_id = info->enc_path_id; } if(info->yuv_buf_mem_info.va){ PhotoFast_SliceEncode_Release_Comm_Buffer(info->yuv_buf_mem_info); memset(&info->yuv_buf_mem_info, 0, sizeof(PhotoFast_MEM_Info)); } } if ((ret = hd_videoenc_uninit()) != HD_OK){ DBG_ERR("hd_videoenc_uninit failed (%d)\r\n", ret); } return (ret == HD_OK) ? E_OK : E_SYS; } static INT32 PhotoFast_SliceEncode_Get_Comm_Buffer(PhotoFast_MEM_Info* mem_info) { mem_info->blk = hd_common_mem_get_block(HD_COMMON_MEM_COMMON_POOL, mem_info->blk_size, DDR_ID0); // Get block from mem pool if (mem_info->blk == HD_COMMON_MEM_VB_INVALID_BLK) { DBG_ERR("hd_common_mem_get_block failed!(size=%lx)\n", mem_info->blk_size); return E_SYS; } mem_info->pa = hd_common_mem_blk2pa(mem_info->blk); if (mem_info->pa == 0) { DBG_ERR("hd_common_mem_blk2pa failed!(blk=0x%x)\n", mem_info->blk); return E_SYS; } mem_info->va = (UINT32)hd_common_mem_mmap(HD_COMMON_MEM_MEM_TYPE_CACHE, mem_info->pa, mem_info->blk_size); if (mem_info->va == 0) { DBG_ERR("hd_common_mem_mmap failed!\r\n"); return E_SYS; } PHOTOFAST_SLICE_ENC_DUMP("hd_common_mem_get_block blk_size={%lx} pa={%lx} va={%lx}\r\n", mem_info->blk_size, mem_info->pa, mem_info->va); return E_OK; } static INT32 PhotoFast_SliceEncode_Release_Comm_Buffer(PhotoFast_MEM_Info mem_info) { if(mem_info.blk != HD_COMMON_MEM_VB_INVALID_BLK ){ hd_common_mem_release_block(mem_info.blk); } if(mem_info.va){ hd_common_mem_munmap((void*) mem_info.va, mem_info.blk_size); } PHOTOFAST_SLICE_ENC_DUMP("hd_common_mem_release_block blk_size={%lx} pa={%lx} va={%lx}\r\n", mem_info.blk_size, mem_info.pa, mem_info.va); return E_OK; } static INT32 PhotoFast_SliceEncode_Alloc_Buffer(PhotoFast_MEM_Info* info, char* name) { HD_RESULT ret; void *va_ptr; HD_COMMON_MEM_DDR_ID ddr_id = DDR_ID0; #if PHOTOFAST_FAST_CLOSE if ((ret = hd_common_mem_alloc("NVTMPP_TEMP", &info->pa, (void **)&va_ptr, info->blk_size, ddr_id)) != HD_OK) { #else if ((ret = hd_common_mem_alloc(name, &info->pa, (void **)&va_ptr, info->blk_size, ddr_id)) != HD_OK) { #endif DBG_ERR("hd_common_mem_alloc failed(size:%d name:%s)\r\n", ret, name); return E_SYS; } info->va = (UINT32)va_ptr; PHOTOFAST_SLICE_ENC_DUMP("hd_common_mem_alloc name={%s} blk_size={%lx} pa={%lx} va={%lx}\r\n", name, info->blk_size, info->pa, info->va); return E_OK; } static INT32 PhotoFast_SliceEncode_Alloc_Buffer_Retry(PhotoFast_MEM_Info* info, char* name, UINT8 timeout, UINT32 delay_ms) { INT32 ret; UINT8 cnt = 0; do{ if(cnt > 0){ DBG_WRN("retrying %u...\n", cnt); vos_util_delay_ms(delay_ms); } ret = PhotoFast_SliceEncode_Alloc_Buffer(info, name); if(ret == E_OK) break; } while(++cnt < timeout); return ret; } static INT32 PhotoFast_SliceEncode_Free_Buffer(PhotoFast_MEM_Info* info) { HD_RESULT ret; PHOTOFAST_SLICE_ENC_DUMP("free bs buffer(va:%lx)\r\n", info->va); if ((ret = hd_common_mem_free(info->pa, (void*) info->va)) != HD_OK) { DBG_ERR("hd_common_mem_free failed(%d)\r\n", ret); return E_SYS; } info->va = 0; info->pa = 0; info->blk = HD_COMMON_MEM_VB_INVALID_BLK; return E_OK; } static INT32 PhotoFast_SliceEncode_Get_Enc_Buffer_Info(const HD_PATH_ID enc_path_id, PhotoFast_MEM_Info* info) { HD_RESULT ret; HD_VIDEOENC_BUFINFO enc_buf_info = {0}; if ((ret = hd_videoenc_get(enc_path_id, HD_VIDEOENC_PARAM_BUFINFO, &enc_buf_info)) != HD_OK) { DBG_ERR("hd_videoenc_get HD_VIDEOENC_PARAM_BUFINFO failed!(%d)\n", ret); return E_SYS; } info->pa = enc_buf_info.buf_info.phy_addr; info->blk_size = enc_buf_info.buf_info.buf_size; info->va = (UINT32)hd_common_mem_mmap(HD_COMMON_MEM_MEM_TYPE_CACHE, info->pa, info->blk_size); if (info->va == 0) { DBG_ERR("enc_vir_addr mmap error!!\r\n\r\n"); return E_SYS; } PHOTOFAST_SLICE_ENC_DUMP("hd_videoenc_get HD_VIDEOENC_PARAM_BUFINFO blk_size={%lx} pa={%lx} va={%lx}\r\n", info->blk_size, info->pa, info->va); return E_OK; } static INT32 PhotoFast_SliceEncode_Init_VF_GFX_Slice( VF_GFX_SCALE* vf_gfx_scale_param, const HD_VIDEO_FRAME* video_frame, const PhotoFast_MEM_Info dst_buffer_info, const PhotoFast_SliceSize_Info src_slice_info, const PhotoFast_SliceSize_Info dst_slice_info, const UINT8 slice_idx) { HD_RESULT ret; UINT32 addr_src[HD_VIDEO_MAX_PLANE] = {0}; UINT32 addr_dst[HD_VIDEO_MAX_PLANE] = {0}; UINT32 loff_src[HD_VIDEO_MAX_PLANE] = {0}; UINT32 loff_dst[HD_VIDEO_MAX_PLANE] = {0}; UINT32 offset; UINT32 scr_slice_height = (slice_idx == (src_slice_info.slice_num - 1)) ? src_slice_info.last_slice_height : src_slice_info.slice_height; UINT32 dst_slice_height = (slice_idx == (dst_slice_info.slice_num - 1)) ? dst_slice_info.last_slice_height : dst_slice_info.slice_height; UINT32 dst_scale_slice_height = (slice_idx == (dst_slice_info.slice_num - 1)) ? (src_slice_info.last_slice_height * dst_slice_info.slice_height / src_slice_info.slice_height) : dst_slice_info.slice_height; /* dst img */ addr_dst[0] = dst_buffer_info.pa; loff_dst[0] = dst_slice_info.width; addr_dst[1] = addr_dst[0] + loff_dst[0] * dst_slice_height; loff_dst[1] = dst_slice_info.width; ret = vf_init_ex(&vf_gfx_scale_param->dst_img, dst_slice_info.width, dst_slice_height, video_frame->pxlfmt, loff_dst, addr_dst); if (ret != HD_OK) { DBG_ERR("vf_init_ex dst failed(%d)\r\n", ret); return E_SYS; } vf_gfx_scale_param->engine = 0; vf_gfx_scale_param->src_region.x = 0; vf_gfx_scale_param->src_region.y = 0; vf_gfx_scale_param->src_region.w = src_slice_info.width; vf_gfx_scale_param->src_region.h = scr_slice_height; vf_gfx_scale_param->dst_region.x = 0; vf_gfx_scale_param->dst_region.y = 0; vf_gfx_scale_param->dst_region.w = dst_slice_info.width; vf_gfx_scale_param->dst_region.h = dst_scale_slice_height; vf_gfx_scale_param->dst_img.blk = dst_buffer_info.blk; vf_gfx_scale_param->quality = HD_GFX_SCALE_QUALITY_NULL; offset = video_frame->loff[HD_VIDEO_PINDEX_Y] * slice_idx * src_slice_info.slice_height; addr_src[0] = video_frame->phy_addr[HD_VIDEO_PINDEX_Y] + offset; addr_src[1] = video_frame->phy_addr[HD_VIDEO_PINDEX_UV] + offset/2; loff_src[0] = video_frame->loff[HD_VIDEO_PINDEX_Y]; loff_src[1] = video_frame->loff[HD_VIDEO_PINDEX_UV]; if ((ret = vf_init_ex(&vf_gfx_scale_param->src_img, src_slice_info.width, scr_slice_height, video_frame->pxlfmt, loff_src, addr_src)) != HD_OK) { DBG_ERR("vf_init_ex dst failed(%d)\r\n", ret); return E_SYS; } PHOTOFAST_SLICE_ENC_DUMP("[Slice %lu] src dim{%lu, %lu} src region{%lu, %lu, %lu, %lu} addr{y:%lx uv:%lx}\r\n", slice_idx, vf_gfx_scale_param->src_img.dim.w, vf_gfx_scale_param->src_img.dim.h, vf_gfx_scale_param->src_region.x, vf_gfx_scale_param->src_region.y, vf_gfx_scale_param->src_region.w, vf_gfx_scale_param->src_region.h, addr_src[0], addr_src[1] ); PHOTOFAST_SLICE_ENC_DUMP("[Slice %lu] dst dim{%lu, %lu} dst region{%lu, %lu, %lu, %lu} addr{y:%lx uv:%lx}\r\n", slice_idx, vf_gfx_scale_param->dst_img.dim.w, vf_gfx_scale_param->dst_img.dim.h, vf_gfx_scale_param->dst_region.x, vf_gfx_scale_param->dst_region.y, vf_gfx_scale_param->dst_region.w, vf_gfx_scale_param->dst_region.h, addr_dst[0], addr_dst[1] ); if(slice_idx == (dst_slice_info.slice_num - 1) && dst_scale_slice_height < dst_slice_info.last_slice_height ){ HD_GFX_DRAW_RECT draw_rect = {0}; draw_rect.dst_img.dim = vf_gfx_scale_param->dst_img.dim; draw_rect.dst_img.ddr_id = vf_gfx_scale_param->dst_img.ddr_id; draw_rect.dst_img.format = vf_gfx_scale_param->dst_img.pxlfmt; draw_rect.dst_img.p_phy_addr[0] = vf_gfx_scale_param->dst_img.phy_addr[0]; draw_rect.dst_img.p_phy_addr[1] = vf_gfx_scale_param->dst_img.phy_addr[1]; draw_rect.dst_img.lineoffset[0] = vf_gfx_scale_param->dst_img.loff[0]; draw_rect.dst_img.lineoffset[1] = vf_gfx_scale_param->dst_img.loff[1]; draw_rect.color = LV_USER_CFG_STAMP_COLOR_BACKGROUND; draw_rect.thickness = 1; draw_rect.type = HD_GFX_RECT_SOLID; draw_rect.rect = (HD_IRECT){0, 0, vf_gfx_scale_param->dst_img.dim.w, vf_gfx_scale_param->dst_img.dim.h}; hd_gfx_draw_rect(&draw_rect); } return E_OK; } #if 1//PHOTOFAST_SLICE_ENC_DBG_PRIMARY_YUV INT32 PhotoFast_SliceEncode_Dump_Frame(const HD_VIDEO_FRAME video_frame, UINT32 format) { char fileName[128] = {0}; FST_FILE fp = NULL; UINT32 size; UINT32 va; static UINT32 cnt = 0; if(format == HD_VIDEO_PXLFMT_YUV420){ size = VDO_YUV_BUFSIZE(video_frame.dim.w, video_frame.dim.h, video_frame.pxlfmt); }else{ // video_frame.pxlfmt = HD_VIDEO_PXLFMT_RAW12; size = VDO_RAW_BUFSIZE(video_frame.dim.w, video_frame.dim.h, video_frame.pxlfmt); } va = (UINT32)hd_common_mem_mmap(HD_COMMON_MEM_MEM_TYPE_CACHE, video_frame.phy_addr[0], size); if (va == 0) { DBG_ERR("hd_common_mem_mmap error!r\n"); return E_SYS; } if(format == HD_VIDEO_PXLFMT_YUV420){ sprintf(fileName, "A:\\frame_%lux%lu_fmt%lx.dat", video_frame.dim.w, video_frame.dim.h, video_frame.pxlfmt); }else{ sprintf(fileName, "A:\\frame_%lux%lu_fmt%lx_%02d.raw", video_frame.dim.w, video_frame.dim.h, video_frame.pxlfmt, cnt); cnt++; } fp = FileSys_OpenFile(fileName, FST_CREATE_ALWAYS | FST_OPEN_WRITE); FileSys_WriteFile(fp, (UINT8*)va, &size, 0, NULL); FileSys_FlushFile(fp); FileSys_CloseFile(fp); hd_common_mem_munmap((void*) va, size); return E_OK; } #endif #if PHOTOFAST_SLICE_ENC_DBG_SLICE_YUV static INT32 PhotoFast_SliceEncode_Dump_Slice( const HD_VIDEO_FRAME* video_frame, const PhotoFast_SliceSize_Info dst_slice_info, const UINT8 slice_idx, const UINT32 pa) { char fileName[128] = {0}; UINT32 dst_slice_height = (slice_idx == (dst_slice_info.slice_num - 1)) ? dst_slice_info.last_slice_height : dst_slice_info.slice_height; UINT32 va; UINT32 size; FST_FILE fp = NULL; size = VDO_YUV_BUFSIZE(dst_slice_info.width, dst_slice_height, video_frame->pxlfmt); va = (UINT32)hd_common_mem_mmap(HD_COMMON_MEM_MEM_TYPE_CACHE, pa, size); if (va == 0) { DBG_ERR("hd_common_mem_mmap error!r\n"); return E_SYS; } sprintf(fileName, "A:\\slice%u_%lux%lu_fmt%lx.dat", slice_idx, dst_slice_info.width, dst_slice_height, video_frame->pxlfmt); fp = FileSys_OpenFile(fileName, FST_CREATE_ALWAYS | FST_OPEN_WRITE); FileSys_WriteFile(fp, (UINT8*)va, &size, 0, NULL); FileSys_FlushFile(fp); FileSys_CloseFile(fp); hd_common_mem_munmap((void*) va, size); return E_OK; } #endif #if PHOTOFAST_SLICE_ENC_DBG_JPG static INT32 PhotoFast_SliceEncode_Dump_JPG(const PhotoFast_MEM_Info* info, char* name) { char fileName[128] = {0}; FST_FILE fp = NULL; UINT32 size = info->used_size; sprintf(fileName, "A:\\%s.jpg", name); fp = FileSys_OpenFile(fileName, FST_CREATE_ALWAYS | FST_OPEN_WRITE); FileSys_WriteFile(fp, (UINT8*)info->va, &size, 0, NULL); FileSys_FlushFile(fp); FileSys_CloseFile(fp); return E_OK; } #endif ER PhotoFast_SliceEncode_Scale_YUV( VF_GFX_SCALE *pscale, const HD_VIDEO_FRAME *psrc, const PhotoFast_MEM_Info mem_info, USIZE *pdest_sz, URECT *pdestwin, HD_VIDEO_PXLFMT pxl_fmt) { UINT32 blk_size; UINT32 addr[HD_VIDEO_MAX_PLANE] = {0}; UINT32 loff[HD_VIDEO_MAX_PLANE] = {0}; VF_GFX_DRAW_RECT fill_rect = {0}; HD_RESULT hd_ret; blk_size = VDO_YUV_BUFSIZE(pdest_sz->w, pdest_sz->h, pxl_fmt); if (blk_size > mem_info.blk_size) { DBG_ERR("Request blk_size(%d) > pComBufInfo->blk_size(%d)\r\n", blk_size, mem_info.blk_size); return E_SYS; } memcpy(&pscale->src_img, psrc, sizeof(HD_VIDEO_FRAME)); // set dest addr[0] = mem_info.pa; loff[0] = ALIGN_CEIL_4(pdest_sz->w); if(pxl_fmt == HD_VIDEO_PXLFMT_YUV420 ){ addr[1] = addr[0] + loff[0] * pdest_sz->h; loff[1] = ALIGN_CEIL_4(pdest_sz->w); }else{ addr[1] = addr[0] + loff[0] * pdest_sz->h; loff[1] = ALIGN_CEIL_4(pdest_sz->w); addr[2] = addr[0] + loff[0] * pdest_sz->h + (loff[1] * pdest_sz->h)/2; loff[2] = ALIGN_CEIL_4(pdest_sz->w); } if ((hd_ret = vf_init_ex(&(pscale->dst_img), pdest_sz->w, pdest_sz->h, pxl_fmt, loff, addr)) != HD_OK) { DBG_ERR("vf_init_ex dst failed(%d)\r\n", hd_ret); } if ((pdest_sz->w != pdestwin->w ) || (pdest_sz->h != pdestwin->h)) { // clear buffer by black //gximg_fill_data((VDO_FRAME *)&(pscale->dst_img), GXIMG_REGION_MATCH_IMG, COLOR_YUV_BLACK); memcpy((void *)&(fill_rect.dst_img), (void *)&(pscale->dst_img), sizeof(HD_VIDEO_FRAME)); fill_rect.color = COLOR_RGB_BLACK; fill_rect.rect.x = 0; fill_rect.rect.y = 0; fill_rect.rect.w = pdest_sz->w; fill_rect.rect.h = pdest_sz->h; fill_rect.type = HD_GFX_RECT_SOLID; fill_rect.thickness = 0; fill_rect.engine = 0; if ((hd_ret = vf_gfx_draw_rect(&fill_rect)) != HD_OK) { DBG_ERR("vf_gfx_draw_rect failed(%d)\r\n", hd_ret); } } // set config pscale->engine = 0; pscale->src_region.x = 0; pscale->src_region.y = 0; pscale->src_region.w = psrc->dim.w; pscale->src_region.h = psrc->dim.h; pscale->dst_region.x = pdestwin->x; pscale->dst_region.y = pdestwin->y; pscale->dst_region.w = pdestwin->w; pscale->dst_region.h = pdestwin->h; pscale->dst_img.blk = mem_info.blk; pscale->quality = HD_GFX_SCALE_QUALITY_NULL; vf_gfx_scale(pscale, 1); pscale->dst_img.count = 0; pscale->dst_img.timestamp = hd_gettime_us(); return E_OK; } static INT32 PhotoFast_SliceEncode_Scale_Screennail( const HD_VIDEO_FRAME* video_frame_in, HD_VIDEO_FRAME* video_frame_out) { INT32 ret; PhotoFast_SliceEncode_Info* slice_enc_info = PhotoFast_SliceEncode_Get_Info(PHOTO_ENC_JPG_SCREENNAIL); PhotoFast_MEM_Info screennail_buffer_info = slice_enc_info->yuv_buf_mem_info; VF_GFX_SCALE vf_gfx_scale = {0}; URECT dest_win = {0}; USIZE src_size = {0}, dest_size = {0}; src_size.w = video_frame_in->dim.w; src_size.h = video_frame_in->dim.h; #if HUNTING_CAMERA_MCU == ENABLE UIMenuStoreInfo *puiPara = sf_ui_para_get(); dest_size.w = sf_get_screen_nail_width(puiPara->SendPicSize); dest_size.h = sf_get_screen_nail_height(puiPara->SendPicSize); #else dest_size.w = CFG_SCREENNAIL_W; dest_size.h = CFG_SCREENNAIL_H; #endif PhotoFast_Cal_Jpg_Size(&src_size, &dest_size , &dest_win); ret = PhotoFast_SliceEncode_Scale_YUV(&vf_gfx_scale, video_frame_in, screennail_buffer_info, &dest_size, &dest_win, HD_VIDEO_PXLFMT_YUV420); if(ret != E_OK){ return ret; } *video_frame_out = vf_gfx_scale.dst_img; return E_OK; } #if CFG_PHOTOFAST_SLICE_ENC_RC_SCREENNAIL static INT32 PhotoFast_SliceEncode_Encode_Screennail_RC(HD_VIDEO_FRAME* video_frame_in, UINT8* screennail_quality) { UINT8 quality = *screennail_quality; INT8 direction = 0; INT32 ret = E_OK; PhotoFast_SliceEncode_Info* slice_encode_screennail_info = PhotoFast_SliceEncode_Get_Info(PHOTO_ENC_JPG_SCREENNAIL); #if HUNTING_CAMERA_MCU == ENABLE UIMenuStoreInfo *puiPara = sf_ui_para_get(); const int COMEPRESSED_RATIO = JPG_COMERESSED_RATIO_12; const UINT32 ubount = (((sf_get_screen_nail_width(puiPara->SendPicSize)) * (sf_get_screen_nail_height(puiPara->SendPicSize))*3/(2*COMEPRESSED_RATIO)) + (((sf_get_screen_nail_width(puiPara->SendPicSize)) * (sf_get_screen_nail_height(puiPara->SendPicSize))*3/(2*COMEPRESSED_RATIO)) * 20 / 100)); const UINT32 lbount = (((sf_get_screen_nail_width(puiPara->SendPicSize)) * (sf_get_screen_nail_height(puiPara->SendPicSize))*3/(2*COMEPRESSED_RATIO)) - (((sf_get_screen_nail_width(puiPara->SendPicSize)) * (sf_get_screen_nail_height(puiPara->SendPicSize))*3/(2*COMEPRESSED_RATIO)) * 20 / 100)); #else const UINT32 ubount = CFG_PHOTOFAST_SLICE_ENC_RC_SCREENNAIL_UBOUND; const UINT32 lbount = CFG_PHOTOFAST_SLICE_ENC_RC_SCREENNAIL_LBOUND; #endif bool stop_flag = false; do { PHOTOFAST_SLICE_ENC_DUMP("screennail quality = %lu\n", quality); *screennail_quality = quality; ret = PhotoFast_SliceEncode_Encode_Set_Out(slice_encode_screennail_info->enc_path_id, quality); if(ret != E_OK){ goto EXIT; } ret = PhotoFast_SliceEncode_Encode_Screennail(video_frame_in); if ( (ret != E_OK) && (ret != HD_ERR_NOMEM)){ goto EXIT; } if((slice_encode_screennail_info->bs_buf_mem_info.used_size > ubount) || (ret == HD_ERR_NOMEM)){ if(direction == 1){ quality -= CFG_PHOTOFAST_SLICE_ENC_RC_SCREENNAIL_QUALITY_STEP; stop_flag = true; /* current step > ubound and next prev step < lbound , stop rc flow (choose prev step)*/ continue; } else{ direction = -1; if(quality == 0){ DBG_WRN("lowest quality reached, stop rc flow!\n"); goto EXIT; } else if(quality > CFG_PHOTOFAST_SLICE_ENC_RC_SCREENNAIL_QUALITY_STEP) quality -= CFG_PHOTOFAST_SLICE_ENC_RC_SCREENNAIL_QUALITY_STEP; else{ quality = 0; } } } else if(slice_encode_screennail_info->bs_buf_mem_info.used_size < lbount){ if(stop_flag){ break; } if(direction == -1){ DBG_WRN("back search due to low resolution of CFG_PHOTOFAST_SLICE_ENC_RC_SCREENNAIL_QUALITY_STEP(%lu), stop rc flow\n", CFG_PHOTOFAST_SLICE_ENC_RC_SCREENNAIL_QUALITY_STEP); break; } else{ direction = 1; if(quality >= 99){ quality = 99; DBG_WRN("highest quality reached, stop rc flow!\n"); goto EXIT; } else if(quality < (99 - CFG_PHOTOFAST_SLICE_ENC_RC_SCREENNAIL_QUALITY_STEP)) quality += CFG_PHOTOFAST_SLICE_ENC_RC_SCREENNAIL_QUALITY_STEP; else{ quality = 99; } } } else{ break; } } while(1); EXIT: return ret; } #endif static INT32 PhotoFast_SliceEncode_Scale_Thumbnail( const HD_VIDEO_FRAME* video_frame_in, HD_VIDEO_FRAME* video_frame_out) { INT32 ret; VF_GFX_SCALE vf_gfx_scale = {0}; URECT dest_win = {0}; USIZE src_size = {0}, dest_size = {0}; PhotoFast_SliceEncode_Info* slice_enc_info = PhotoFast_SliceEncode_Get_Info(PHOTO_ENC_JPG_THUMBNAIL); PhotoFast_MEM_Info thumbnail_buffer_info = slice_enc_info->yuv_buf_mem_info; src_size.w = video_frame_in->dim.w; src_size.h = video_frame_in->dim.h; dest_size.w = CFG_THUMBNAIL_W; dest_size.h = CFG_THUMBNAIL_H; PhotoFast_Cal_Jpg_Size(&src_size, &dest_size , &dest_win); ret = PhotoFast_SliceEncode_Scale_YUV(&vf_gfx_scale, video_frame_in, thumbnail_buffer_info, &dest_size, &dest_win, HD_VIDEO_PXLFMT_YUV420); if(ret != E_OK){ return ret; } *video_frame_out = vf_gfx_scale.dst_img; return E_OK; } static INT32 PhotoFast_SliceEncode_Encode_Thumbnail(HD_VIDEO_FRAME* video_frame_in) { HD_RESULT ret; PhotoFast_SliceEncode_Info* slice_enc_info = PhotoFast_SliceEncode_Get_Info(PHOTO_ENC_JPG_THUMBNAIL); HD_PATH_ID enc_path_id = slice_enc_info->enc_path_id; UINT32 enc_jpg_va = 0; HD_VIDEOENC_BS bs_data_pull = {0}; if ((ret = hd_videoenc_start(slice_enc_info->enc_path_id)) != HD_OK) { DBG_ERR("hd_videoenc_start failed!(%d)\n", ret); goto EXIT; } PhotoFast_SliceEncode_Get_Enc_Buffer_Info(enc_path_id, &slice_enc_info->hd_enc_internal_buf_mem_info); ret = hd_videoenc_push_in_buf(enc_path_id, video_frame_in, NULL, PHOTOFAST_HD_PUSH_PULL_TIMEOUT_MS); // -1 = blocking mode if (ret != HD_OK) { DBG_ERR("hd_videoenc_push_in_buf failed!(%d)\r\n", ret); goto EXIT; } ret = hd_videoenc_pull_out_buf(enc_path_id, &bs_data_pull, PHOTOFAST_HD_PUSH_PULL_TIMEOUT_MS); // -1 = blocking mode if (ret != HD_OK) { DBG_ERR("hd_videoenc_pull_out_buf failed!(%d)\r\n", ret); goto EXIT; } enc_jpg_va = PhotoFast_PHY2VIRT(bs_data_pull.video_pack[0].phy_addr, slice_enc_info->hd_enc_internal_buf_mem_info.pa, slice_enc_info->hd_enc_internal_buf_mem_info.va); if(enc_jpg_va == 0){ ret = HD_ERR_SYS; goto EXIT; } PHOTOFAST_SLICE_ENC_DUMP("copy bs data (%lx -> %lx) , size = %lx\r\n", enc_jpg_va, slice_enc_info->bs_buf_mem_info.va, bs_data_pull.video_pack[0].size); if(bs_data_pull.video_pack[0].size > slice_enc_info->bs_buf_mem_info.blk_size){ DBG_ERR("bs overflow!(data size: %lx buffer size: %lx)\r\n", bs_data_pull.video_pack[0].size, slice_enc_info->bs_buf_mem_info.blk_size); ret = HD_ERR_NOMEM; goto EXIT; } memcpy((VOID*)slice_enc_info->bs_buf_mem_info.va, (VOID*)enc_jpg_va, bs_data_pull.video_pack[0].size); slice_enc_info->bs_buf_mem_info.used_size = bs_data_pull.video_pack[0].size; EXIT: /* unmap hdal internal buffer */ if(slice_enc_info->hd_enc_internal_buf_mem_info.va){ if (hd_common_mem_munmap((void *)slice_enc_info->hd_enc_internal_buf_mem_info.va, slice_enc_info->hd_enc_internal_buf_mem_info.blk_size) != HD_OK) { DBG_ERR("hd_common_mem_munmap error!(va:%lx size:%lx)\r\n", slice_enc_info->hd_enc_internal_buf_mem_info.va, slice_enc_info->hd_enc_internal_buf_mem_info.blk_size); } memset(&slice_enc_info->hd_enc_internal_buf_mem_info, 0, sizeof(PhotoFast_MEM_Info)); } if(bs_data_pull.video_pack[0].size){ hd_videoenc_release_out_buf(enc_path_id, &bs_data_pull); } if ((hd_videoenc_stop(enc_path_id)) != HD_OK) { DBG_ERR("hd_videoenc_stop failed(%d)\r\n", ret); } return (ret == HD_OK) ? E_OK : E_SYS; } static INT32 PhotoFast_SliceEncode_Encode_Screennail(HD_VIDEO_FRAME* video_frame_in) { HD_RESULT ret; PhotoFast_SliceEncode_Info* slice_enc_info = PhotoFast_SliceEncode_Get_Info(PHOTO_ENC_JPG_SCREENNAIL); HD_PATH_ID enc_path_id = slice_enc_info->enc_path_id; UINT32 enc_jpg_va = 0; HD_VIDEOENC_BS bs_data_pull = {0}; if ((ret = hd_videoenc_start(slice_enc_info->enc_path_id)) != HD_OK) { DBG_ERR("hd_videoenc_start failed!(%d)\n", ret); goto EXIT; } PhotoFast_SliceEncode_Get_Enc_Buffer_Info(enc_path_id, &slice_enc_info->hd_enc_internal_buf_mem_info); ret = hd_videoenc_push_in_buf(enc_path_id, video_frame_in, NULL, PHOTOFAST_HD_PUSH_PULL_TIMEOUT_MS); // -1 = blocking mode if (ret != HD_OK) { DBG_ERR("hd_videoenc_push_in_buf failed!(%d)\r\n", ret); goto EXIT; } ret = hd_videoenc_pull_out_buf(enc_path_id, &bs_data_pull, PHOTOFAST_HD_PUSH_PULL_TIMEOUT_MS); // -1 = blocking mode if (ret != HD_OK) { DBG_ERR("hd_videoenc_pull_out_buf failed!(%d)\r\n", ret); goto EXIT; } enc_jpg_va = PhotoFast_PHY2VIRT(bs_data_pull.video_pack[0].phy_addr, slice_enc_info->hd_enc_internal_buf_mem_info.pa, slice_enc_info->hd_enc_internal_buf_mem_info.va); if(enc_jpg_va == 0){ ret = HD_ERR_SYS; goto EXIT; } PHOTOFAST_SLICE_ENC_DUMP("copy bs data (%lx -> %lx) , size = %lx\r\n", enc_jpg_va, slice_enc_info->bs_buf_mem_info.va, bs_data_pull.video_pack[0].size); if(bs_data_pull.video_pack[0].size > slice_enc_info->bs_buf_mem_info.blk_size){ DBG_ERR("bs overflow!(data size: %lx buffer size: %lx)\r\n", bs_data_pull.video_pack[0].size, slice_enc_info->bs_buf_mem_info.blk_size); ret = HD_ERR_NOMEM; goto EXIT; } memcpy((VOID*)slice_enc_info->bs_buf_mem_info.va, (VOID*)enc_jpg_va, bs_data_pull.video_pack[0].size); slice_enc_info->bs_buf_mem_info.used_size = bs_data_pull.video_pack[0].size; EXIT: /* unmap hdal internal buffer */ if(slice_enc_info->hd_enc_internal_buf_mem_info.va){ if (hd_common_mem_munmap((void *)slice_enc_info->hd_enc_internal_buf_mem_info.va, slice_enc_info->hd_enc_internal_buf_mem_info.blk_size) != HD_OK) { DBG_ERR("hd_common_mem_munmap error!(va:%lx size:%lx)\r\n", slice_enc_info->hd_enc_internal_buf_mem_info.va, slice_enc_info->hd_enc_internal_buf_mem_info.blk_size); } memset(&slice_enc_info->hd_enc_internal_buf_mem_info, 0, sizeof(PhotoFast_MEM_Info)); } if(bs_data_pull.video_pack[0].size){ hd_videoenc_release_out_buf(enc_path_id, &bs_data_pull); } if (hd_videoenc_stop(enc_path_id) != HD_OK) { DBG_ERR("hd_videoenc_stop failed(%d)\r\n", ret); } return (ret == HD_OK) ? E_OK : ret; } static UINT32 PhotoFast_GetScreenNailSize(void) { UINT32 uiImageSize, ScreenNailSize; UINT32 BitStreamSize; ScreenNailSize = CFG_SCREENNAIL_SIZE; uiImageSize = UI_GetData(FL_PHOTO_SIZE); if (uiImageSize < ScreenNailSize) { #if HUNTING_CAMERA_MCU == ENABLE UIMenuStoreInfo *puiPara = sf_ui_para_get(); BitStreamSize = (sf_get_screen_nail_width(puiPara->SendPicSize)) * (sf_get_screen_nail_height(puiPara->SendPicSize)) / 2; #else BitStreamSize = CFG_SCREENNAIL_W * CFG_SCREENNAIL_H / 2; #endif } else { BitStreamSize = 0; } DBG_IND("[cap]ScreenNail BitStreamSize =%d K\r\n", BitStreamSize / 1024); return BitStreamSize; } static INT32 PhotoFast_SliceEncode_Encode_Primary( const HD_VIDEO_FRAME* video_frame, const PhotoFast_SliceSize_Info src_slice_info, const PhotoFast_SliceSize_Info dst_slice_info, UINT32* enc_bs_accum_size, UINT8* primary_quality ) { PhotoFast_SliceEncode_Info* slice_enc_info = PhotoFast_SliceEncode_Get_Info(PHOTO_ENC_JPG_PRIMARY); HD_PATH_ID enc_path_id = slice_enc_info->enc_path_id; PhotoFast_MEM_Info yuv_buffer_info = slice_enc_info->yuv_buf_mem_info; PhotoFast_MEM_Info enc_bs_buf_info = slice_enc_info->bs_buf_mem_info; HD_RESULT ret = 0; VF_GFX_SCALE vf_gfx_scale_param = {0}; UINT32 enc_jpg_va = 0; UINT32 enc_bs_buf_ptr = 0; BOOL restart = FALSE; /* config which slice stamp should be attached */ #if !PHOTOFAST_FAST_STAMP const UINT8 slice_idx_of_date_stamp = dst_slice_info.slice_num - 1; #endif HD_VIDEOENC_BS bs_data_pull; do { restart = FALSE; if ((ret = hd_videoenc_start(enc_path_id)) != HD_OK) { DBG_ERR("hd_videoenc_start failed!(%d)\n", ret); goto EXIT; } if(PhotoFast_SliceEncode_Get_Enc_Buffer_Info(enc_path_id, &slice_enc_info->hd_enc_internal_buf_mem_info) != E_OK) goto EXIT; /* reserve space(CFG_JPG_HEADER_SIZE) for header */ enc_bs_buf_ptr = enc_bs_buf_info.va + CFG_JPG_HEADER_SIZE; *enc_bs_accum_size = 0; for(UINT8 slice_idx=0 ; slice_idx 1){ vf_gfx_scale_param.dst_img.reserved[1] = MAKEFOURCC('P','A','R','T'); vf_gfx_scale_param.dst_img.reserved[2] = (dst_slice_info.slice_num << 16) | slice_idx; } else{ vf_gfx_scale_param.dst_img.reserved[1] = 0; vf_gfx_scale_param.dst_img.reserved[2] = 0; } /* src img */ #if PHOTOFAST_SLICE_ENC_DBG_SLICE_YUV PhotoFast_SliceEncode_Dump_Slice( video_frame, dst_slice_info, slice_idx, vf_gfx_scale_param.dst_img.phy_addr[0] ); #endif PHOTOFAST_SLICE_ENC_DUMP("[Slice %lu] reserved[2]:%lx dst_img.dim:{%lu, %lu}\r\n", slice_idx, vf_gfx_scale_param.dst_img.reserved[2], vf_gfx_scale_param.dst_img.dim.w, vf_gfx_scale_param.dst_img.dim.h ); ret = hd_videoenc_push_in_buf(enc_path_id, &vf_gfx_scale_param.dst_img, NULL, PHOTOFAST_HD_PUSH_PULL_TIMEOUT_MS); // -1 = blocking mode if (ret != HD_OK) { DBG_ERR("hd_videoenc_push_in_buf failed!(%d)\r\n", ret); goto EXIT; } ret = hd_videoenc_pull_out_buf(enc_path_id, &bs_data_pull, PHOTOFAST_HD_PUSH_PULL_TIMEOUT_MS); // -1 = blocking mode if (ret != HD_OK) { DBG_ERR("hd_videoenc_pull_out_buf failed!(%d)\r\n", ret); goto EXIT; } PHOTOFAST_SLICE_ENC_DUMP("[Slice %lu] pack pa:%lx , size:%lx\r\n", slice_idx, bs_data_pull.video_pack[0].phy_addr, bs_data_pull.video_pack[0].size ); enc_jpg_va = PhotoFast_PHY2VIRT(bs_data_pull.video_pack[0].phy_addr, slice_enc_info->hd_enc_internal_buf_mem_info.pa, slice_enc_info->hd_enc_internal_buf_mem_info.va); if(enc_jpg_va == 0){ ret = HD_ERR_SYS; goto EXIT; } if((*enc_bs_accum_size + bs_data_pull.video_pack[0].size + CFG_JPG_HEADER_SIZE + PhotoFast_GetScreenNailSize()) < enc_bs_buf_info.blk_size){ PHOTOFAST_SLICE_ENC_DUMP("[Slice %u] enc accum size: %lx , slice size:%lx , bs buf size: %lx buffer ptr:%lx , jpg va: %lx\r\n", slice_idx, *enc_bs_accum_size, bs_data_pull.video_pack[0].size, enc_bs_buf_info.blk_size, enc_bs_buf_ptr, enc_jpg_va ); memcpy((void *)enc_bs_buf_ptr, (void *)enc_jpg_va, bs_data_pull.video_pack[0].size); (*enc_bs_accum_size) += bs_data_pull.video_pack[0].size; enc_bs_buf_ptr += bs_data_pull.video_pack[0].size; hd_videoenc_release_out_buf(enc_path_id, &bs_data_pull); memset(&bs_data_pull, 0, sizeof(HD_VIDEOENC_BS)); /* marked as released */ } /* restart process */ else{ UINT32 quality_old = 0, quality_new = 0; DBG_WRN("[Slice %lu] bs buffer overflow!(primary bs buffer size:%lx bs accum size:%lx)\r\n", slice_idx, enc_bs_buf_info.blk_size - (CFG_JPG_HEADER_SIZE + PhotoFast_GetScreenNailSize()), (*enc_bs_accum_size + bs_data_pull.video_pack[0].size) ); /* check old quality */ PhotoFast_SliceEncode_Encode_Get_Out(slice_enc_info->enc_path_id, &quality_old); if(quality_old == 1){ restart = FALSE; } else if(quality_old <= CFG_PHOTOFAST_SLICE_ENC_QUALITY_STEP){ quality_new = 1; restart = TRUE; } else if(quality_old > CFG_PHOTOFAST_SLICE_ENC_QUALITY_STEP){ quality_new = quality_old - CFG_PHOTOFAST_SLICE_ENC_QUALITY_STEP; restart = TRUE; } else{ restart = FALSE; } /* check restart */ if(restart == FALSE){ ret = HD_ERR_SYS; goto EXIT; } else{ DBG_WRN("reset quality %lu -> %lu\r\n", quality_old, quality_new); if ((ret = hd_videoenc_stop(enc_path_id)) != HD_OK) { goto EXIT; } *primary_quality = quality_new; if((ret = PhotoFast_SliceEncode_Encode_Set_Out(slice_enc_info->enc_path_id, quality_new) != HD_OK)) goto EXIT; break; } } } if(restart == TRUE) { hd_videoenc_release_out_buf(enc_path_id, &bs_data_pull); memset(&bs_data_pull, 0, sizeof(HD_VIDEOENC_BS)); /* marked as released */ /* unmap hdal internal buffer */ if(slice_enc_info->hd_enc_internal_buf_mem_info.va){ ret = hd_common_mem_munmap((void *)slice_enc_info->hd_enc_internal_buf_mem_info.va, slice_enc_info->hd_enc_internal_buf_mem_info.blk_size); if (ret != HD_OK) { DBG_ERR("hd_common_mem_munmap error!(va:%lx size:%lx)\r\n", slice_enc_info->hd_enc_internal_buf_mem_info.va, slice_enc_info->hd_enc_internal_buf_mem_info.blk_size); } memset(&slice_enc_info->hd_enc_internal_buf_mem_info, 0, sizeof(PhotoFast_MEM_Info)); } } else{ break; } } while(1); EXIT: /* unmap hdal internal buffer */ if(slice_enc_info->hd_enc_internal_buf_mem_info.va){ if (hd_common_mem_munmap((void *)slice_enc_info->hd_enc_internal_buf_mem_info.va, slice_enc_info->hd_enc_internal_buf_mem_info.blk_size) != HD_OK) { DBG_ERR("hd_common_mem_munmap error!(va:%lx size:%lx)\r\n", slice_enc_info->hd_enc_internal_buf_mem_info.va, slice_enc_info->hd_enc_internal_buf_mem_info.blk_size); } memset(&slice_enc_info->hd_enc_internal_buf_mem_info, 0, sizeof(PhotoFast_MEM_Info)); } if(bs_data_pull.video_pack[0].size){ hd_videoenc_release_out_buf(enc_path_id, &bs_data_pull); memset(&bs_data_pull, 0, sizeof(HD_VIDEOENC_BS)); /* marked as released */ } if (hd_videoenc_stop(enc_path_id) != HD_OK) { DBG_WRN("hd_videoenc_stop failed!(%d)\n", ret); } return (ret == HD_OK) ? E_OK : E_SYS; } INT32 PhotoFast_SliceEncode(const HD_PATH_ID vproc_path_id, const HD_VIDEO_FRAME *p_video_frame) { HD_RESULT ret = HD_OK; PhotoFast_SliceEncode_Info* slice_encode_primary_info = PhotoFast_SliceEncode_Get_Info(PHOTO_ENC_JPG_PRIMARY); PhotoFast_SliceEncode_Info* slice_encode_screennail_info = PhotoFast_SliceEncode_Get_Info(PHOTO_ENC_JPG_SCREENNAIL); PhotoFast_SliceEncode_Info* slice_encode_thumbnail_info = PhotoFast_SliceEncode_Get_Info(PHOTO_ENC_JPG_THUMBNAIL); PhotoFast_SliceSize_Info src_slice_info = {0}, dst_slice_info = {0}; HD_VIDEO_FRAME video_frame = *p_video_frame; HD_VIDEO_FRAME video_frame_out_screennail = {0}; HD_VIDEO_FRAME video_frame_out_thumbnail = {0}; // HD_PATH_ID vproc_path_id = 0; HD_VIDEOPROC_OUT vproc_out = {0}; HD_VIDEO_PXLFMT vproc_out_pxlfmt = 0; PhotoFast_MEM_Info exif_mem_info = {0}; UINT32 enc_accum_size = 0; VOS_TICK tick_start, tick_end; static UINT8 primary_quality = CFG_PHOTOFAST_SLICE_ENC_INIT_QUALITY_PRIMARY; static UINT8 screennail_quality = CFG_PHOTOFAST_SLICE_ENC_INIT_QUALITY_SCREENNAIL; // VOS_TICK tick_primary_s, tick_primary_e; // VOS_TICK tick_screennail_s, tick_screennail_e; // VOS_TICK tick_thumbnail_s, tick_thumbnail_e; // VOS_TICK tick_stamp_s, tick_stamp_e; // VOS_TICK tick_combine_s, tick_combine_e; #if HUNTING_CAMERA_MCU == ENABLE UIMenuStoreInfo *puiPara = sf_ui_para_get(); #endif vos_perf_mark(&tick_start); /******************************************************************* * Get vproc info ******************************************************************/ /* get vproc out frame format ( = venc in) */ ret = hd_videoproc_get(vproc_path_id, HD_VIDEOPROC_PARAM_OUT, (VOID*)&vproc_out); if(ret != HD_OK){ DBG_ERR("hd_videoproc_get HD_VIDEOPROC_PARAM_OUT failed(path_id=%lx, ret=%d)!", vproc_path_id, ret); vproc_out_pxlfmt = HD_VIDEO_PXLFMT_YUV420; } else{ vproc_out_pxlfmt = vproc_out.pxlfmt; } /******************************************************************* * Calculate dst slice info ******************************************************************/ if(PhotoFast_SliceEncode_Get_Curr_Dst_Slice_Info(&dst_slice_info, video_frame) != E_OK){ return NVTEVT_CONSUME; } DBG_DUMP("slice num = %u\n", dst_slice_info.slice_num); #if PHOTOFAST_SLICE_ENC_DBG_PRIMARY_YUV PhotoFast_SliceEncode_Dump_Frame(video_frame, HD_VIDEO_PXLFMT_YUV420); #endif /******************************************************************* * Init Date Buffer ******************************************************************/ // if (UI_GetData(FL_DATE_STAMP) != DATEIMPRINT_OFF) { // Ux_SendEvent(&CustomPhotoObjCtrl, NVTEVT_EXE_INIT_DATE_BUF, 0); // } /******************************************************************* * Calculate src slice info ******************************************************************/ PhotoFast_SliceEncode_Get_Src_Slice_Info(&dst_slice_info, &src_slice_info, video_frame); /******************************************************************* * Allocate slice buffer ******************************************************************/ slice_encode_thumbnail_info->bs_buf_mem_info.blk_size = (CFG_THUMBNAIL_W * CFG_THUMBNAIL_H) / 2; if(PhotoFast_SliceEncode_Alloc_Buffer(&slice_encode_thumbnail_info->bs_buf_mem_info, "slice_enc_thumbnail") != E_OK){ goto EXIT; } #if CFG_PHOTOFAST_SLICE_ENC_RC_SCREENNAIL #if HUNTING_CAMERA_MCU == ENABLE slice_encode_screennail_info->bs_buf_mem_info.blk_size = (((sf_get_screen_nail_width(puiPara->SendPicSize)) * (sf_get_screen_nail_height(puiPara->SendPicSize))*3/(2*JPG_COMERESSED_RATIO_8)) + (((sf_get_screen_nail_width(puiPara->SendPicSize)) * (sf_get_screen_nail_height(puiPara->SendPicSize))*3/(2*JPG_COMERESSED_RATIO_8)) * 20 / 100)); #else slice_encode_screennail_info->bs_buf_mem_info.blk_size = CFG_PHOTOFAST_SLICE_ENC_RC_SCREENNAIL_UBOUND; #endif #else slice_encode_screennail_info->bs_buf_mem_info.blk_size = PhotoFast_GetScreenNailSize(); #endif if(PhotoFast_SliceEncode_Alloc_Buffer(&slice_encode_screennail_info->bs_buf_mem_info, "slice_enc_screennail") != E_OK){ goto EXIT; } // slice_encode_primary_info->bs_buf_mem_info.blk_size = (VDO_YUV_BUFSIZE(dst_slice_info.width, dst_slice_info.height, video_frame.pxlfmt) / (CFG_PHOTOFAST_SLICE_ENC_BS_BUF_RATIO)) + CFG_JPG_HEADER_SIZE + PhotoFast_GetScreenNailSize() ; slice_encode_primary_info->bs_buf_mem_info.blk_size = ((PhotoFast_SliceEncode_Get_Encode_Max_Bitrate(HD_VIDEO_PXLFMT_YUV420)/ 8) * (dst_slice_info.slice_num + 1)) + CFG_JPG_HEADER_SIZE + PhotoFast_GetScreenNailSize() ; if(PhotoFast_SliceEncode_Alloc_Buffer(&slice_encode_primary_info->bs_buf_mem_info, "slice_enc_primary") != E_OK){ goto EXIT; } PhotoFastCapDateImprint_GenYuvData(&video_frame); /* check free mem */ #if POWERON_FAST_BOOT_MSG == ENABLE nvt_cmdsys_runcmd("nvtmpp info"); #endif /******************************************************************* * Screennail & Thumbnail Scale ******************************************************************/ /* screennail scale */ if(PhotoFast_SliceEncode_Scale_Screennail(&video_frame, &video_frame_out_screennail) != E_OK){ goto EXIT; } /* thumbnail scale, 2pass from screennail */ if(PhotoFast_SliceEncode_Scale_Thumbnail(&video_frame_out_screennail, &video_frame_out_thumbnail) != E_OK){ goto EXIT; } /******************************************************************* * Primary ******************************************************************/ /* slice encode */ PhotoFast_SliceEncode_Encode_Set_In(slice_encode_primary_info->enc_path_id, vproc_out_pxlfmt, (HD_DIM) {dst_slice_info.width, dst_slice_info.height}); PhotoFast_SliceEncode_Encode_Set_Out(slice_encode_primary_info->enc_path_id, CFG_PHOTOFAST_SLICE_ENC_INIT_QUALITY_PRIMARY); if(PhotoFast_SliceEncode_Encode_Primary(&video_frame, src_slice_info, dst_slice_info, &enc_accum_size, &primary_quality) != E_OK){ goto EXIT; } slice_encode_primary_info->bs_buf_mem_info.used_size = enc_accum_size; #if PHOTOFAST_SLICE_ENC_DBG_PRIMARY_JPG PhotoFast_MEM_Info bs_buf_mem_info = slice_encode_primary_info->bs_buf_mem_info; /* skip header and write accum size */ bs_buf_mem_info.va += CFG_JPG_HEADER_SIZE; /* dump file */ PhotoFast_SliceEncode_Dump_JPG(&bs_buf_mem_info, "primary"); #endif /******************************************************************* * Screennail & Thumbnail Encode ******************************************************************/ /* screennail encode */ #if HUNTING_CAMERA_MCU == ENABLE PhotoFast_SliceEncode_Encode_Set_In(slice_encode_screennail_info->enc_path_id, vproc_out_pxlfmt, (HD_DIM) {(sf_get_screen_nail_width(puiPara->SendPicSize)), (sf_get_screen_nail_height(puiPara->SendPicSize))}); #else PhotoFast_SliceEncode_Encode_Set_In(slice_encode_screennail_info->enc_path_id, vproc_out_pxlfmt, (HD_DIM) {CFG_SCREENNAIL_W, CFG_SCREENNAIL_H}); #endif #if CFG_PHOTOFAST_SLICE_ENC_RC_SCREENNAIL if(PhotoFast_SliceEncode_Encode_Screennail_RC(&video_frame_out_screennail, &screennail_quality) != E_OK){ goto EXIT; } #else PhotoFast_SliceEncode_Encode_Set_Out(slice_encode_screennail_info->enc_path_id, CFG_PHOTOFAST_SLICE_ENC_INIT_QUALITY_SCREENNAIL); if(PhotoFast_SliceEncode_Encode_Screennail(&video_frame_out_screennail) != E_OK){ goto EXIT; } #endif #if PHOTOFAST_SLICE_ENC_DBG_SCREENNAIL_JPG /* dump file */ PhotoFast_SliceEncode_Dump_JPG(&slice_encode_screennail_info->bs_buf_mem_info, "screennail"); #endif /* thumbnail encode */ PhotoFast_SliceEncode_Encode_Set_In(slice_encode_thumbnail_info->enc_path_id, vproc_out_pxlfmt, (HD_DIM) {CFG_THUMBNAIL_W, CFG_THUMBNAIL_H}); PhotoFast_SliceEncode_Encode_Set_Out(slice_encode_thumbnail_info->enc_path_id, CFG_PHOTOFAST_SLICE_ENC_INIT_QUALITY_THUMBNAIL); if(PhotoFast_SliceEncode_Encode_Thumbnail(&video_frame_out_thumbnail) != E_OK){ goto EXIT; } #if PHOTOFAST_SLICE_ENC_DBG_THUMBNAIL_JPG /* dump file */ PhotoFast_SliceEncode_Dump_JPG(&slice_encode_thumbnail_info->bs_buf_mem_info, "thumbnail"); #endif /******************************************************************* * Combine All Images ******************************************************************/ exif_mem_info.blk_size = CFG_JPG_HEADER_SIZE; if(PhotoFast_SliceEncode_Alloc_Buffer(&exif_mem_info, "slice_enc_exif") != E_OK) goto EXIT; MEM_RANGE exif_data = {.addr = exif_mem_info.va, .size = exif_mem_info.blk_size}; MEM_RANGE thumb_jpg = {.addr = slice_encode_thumbnail_info->bs_buf_mem_info.va, .size = slice_encode_thumbnail_info->bs_buf_mem_info.used_size}; MEM_RANGE pri_jpg = {.addr = slice_encode_primary_info->bs_buf_mem_info.va + CFG_JPG_HEADER_SIZE, .size = slice_encode_primary_info->bs_buf_mem_info.used_size}; MEM_RANGE scr_jpg = {.addr = slice_encode_screennail_info->bs_buf_mem_info.va, .size = slice_encode_screennail_info->bs_buf_mem_info.used_size}; MEM_RANGE dst_jpg_file = { 0 }; // /* exif */ ExifVendor_Write0thIFD(EXIF_HDL_ID_1); ExifVendor_WriteExifIFD(EXIF_HDL_ID_1); ExifVendor_Write0thIntIFD(EXIF_HDL_ID_1); if (EXIF_CreateExif(EXIF_HDL_ID_1, &exif_data, &thumb_jpg) != EXIF_ER_OK) { DBG_ERR("Create Exif fail\r\n"); exif_data.size = 0; } // /* combine jpg */ GxImgFile_CombineJPG(&exif_data, &pri_jpg, &scr_jpg, &dst_jpg_file); PHOTOFAST_SLICE_ENC_DUMP("exif{%lx, %lx} thumb{%lx, %lx} primary{%lx, %lx} scr{%lx, %lx} dst{%lx, %lx}\r\n", exif_data.addr, exif_data.size, thumb_jpg.addr, thumb_jpg.size, pri_jpg.addr, pri_jpg.size, exif_data.addr, exif_data.size, dst_jpg_file.addr, dst_jpg_file.size ); /******************************************************************* * Output jpg file ******************************************************************/ // extern INT32 ImageApp_Photo_WriteCB(UINT32 Addr, UINT32 Size, UINT32 Fmt, UINT32 uiPathId); if(dst_jpg_file.addr > (slice_encode_primary_info->bs_buf_mem_info.va + slice_encode_primary_info->bs_buf_mem_info.blk_size)){ DBG_ERR("primary buffer overflow during combine jpg!\r\n"); } vos_perf_mark(&tick_end); DBG_DUMP("elapsed time of slice encode without write file = %lu us\n", tick_end - tick_start); extern INT32 PhotoFast_WriteFile(UINT32 Addr, UINT32 Size, UINT32 Fmt, UINT32 uiPathId, char* path); if(PhotoFast_Wait_FileSys(FASTBOOT_WAIT_FILESYS_TIMEOUT_MS) != E_OK){ goto EXIT; } if(PhotoFast_Wait_FileNaming(FASTBOOT_WAIT_FILESYS_TIMEOUT_MS) != E_OK){ goto EXIT; } PhotoFast_WriteFile( dst_jpg_file.addr, dst_jpg_file.size, NAMERULE_FMT_JPG, 0, 0); EXIT: /* check user bs buffer is freed */ if(slice_encode_primary_info->bs_buf_mem_info.va){ PhotoFast_SliceEncode_Free_Buffer(&slice_encode_primary_info->bs_buf_mem_info); } if(slice_encode_screennail_info->bs_buf_mem_info.va){ PhotoFast_SliceEncode_Free_Buffer(&slice_encode_screennail_info->bs_buf_mem_info); } if(slice_encode_thumbnail_info->bs_buf_mem_info.va){ PhotoFast_SliceEncode_Free_Buffer(&slice_encode_thumbnail_info->bs_buf_mem_info); } /* check exif buffer is freed */ if(exif_mem_info.va){ PhotoFast_SliceEncode_Free_Buffer(&exif_mem_info); } return NVTEVT_CONSUME; } #if POWERON_FAST_SLICE_ENC_VER2 == ENABLE /* task update */ #define FLG_PHOTO_FAST_SLICE_ENC_STA_IDLE FLGPTN_BIT(0) #define FLG_PHOTO_FAST_SLICE_ENC_STA_STOPPED FLGPTN_BIT(1) #define FLG_PHOTO_FAST_SLICE_ENC_STA_STARTED FLGPTN_BIT(2) /* caller update */ #define FLG_PHOTO_FAST_SLICE_ENC_CMD_START FLGPTN_BIT(3) #define FLG_PHOTO_FAST_SLICE_ENC_CMD_STOP FLGPTN_BIT(4) #include "../lfqueue/lfqueue.h" typedef struct { THREAD_HANDLE task_id; UINT run; UINT is_running; ID flag_id; void *user_data; INT32 (*callback)(void* user_data); } PhotoFast_SliceEncode_Task_Param; THREAD_RETTYPE _PhotoFast_SliceEncode_Worker(void* arg) { PhotoFast_SliceEncode_Task_Param* param = (PhotoFast_SliceEncode_Task_Param*) arg; FLGPTN flag = 0, wait_flag = 0; if(param == NULL) goto EXIT; wait_flag = FLG_PHOTO_FAST_SLICE_ENC_CMD_START | FLG_PHOTO_FAST_SLICE_ENC_CMD_STOP ; clr_flg(param->flag_id, FLG_PHOTO_FAST_SLICE_ENC_STA_IDLE); while(param->run) { param->is_running = 1; set_flg(param->flag_id, FLG_PHOTO_FAST_SLICE_ENC_STA_IDLE); PROFILE_TASK_IDLE(); wai_flg(&flag, param->flag_id, wait_flag, TWF_ORW | TWF_CLR); PROFILE_TASK_BUSY(); clr_flg(param->flag_id, FLG_PHOTO_FAST_SLICE_ENC_STA_IDLE); if(flag & FLG_PHOTO_FAST_SLICE_ENC_CMD_STOP){ break; } if(flag & FLG_PHOTO_FAST_SLICE_ENC_CMD_START){ set_flg(param->flag_id, FLG_PHOTO_FAST_SLICE_ENC_STA_STARTED); if(param->callback){ param->callback(param->user_data); } } } EXIT: param->is_running = 0; set_flg(param->flag_id, FLG_PHOTO_FAST_SLICE_ENC_STA_STOPPED); THREAD_RETURN(0); } typedef struct { UINT8 terminate:1; } PhotoFast_SliceEncode_Queue_Comm_Param; typedef struct { HD_VIDEO_FRAME frame; PhotoFast_SliceEncode_Queue_Comm_Param comm; } PhotoFast_SliceEncode_Queue12_Param; typedef struct { UINT8* jpg_combined_addr; UINT32 jpg_combined_size; UINT8* jpg_thumb_addr; UINT32 jpg_thumb_size; PhotoFast_MEM_Info mem_info_combined; PhotoFast_MEM_Info mem_info_thumb; PhotoFast_SliceEncode_Queue_Comm_Param comm; #if PHOTOFAST_FAST_CLOSE char file_path[NMC_TOTALFILEPATH_MAX_LEN]; UINT32 nextFolderID; UINT32 nextFileID; #endif } PhotoFast_SliceEncode_Queue23_Param; typedef struct { UINT8 max_cnt; UINT8 cnt; lfqueue_t* queue12; /* shared with CB1 */ lfqueue_t* queue23; /* shared with CB3 */ HD_PATH_ID vproc_path_id; } PhotoFast_SliceEncode_CB2_Param; typedef struct { UINT8 max_cnt; UINT8 cnt; lfqueue_t* queue23; /* shared with CB2 */ } PhotoFast_SliceEncode_CB3_Param; static PhotoFast_SliceEncode_Task_Param task2_param = {0}; static PhotoFast_SliceEncode_Task_Param task3_param = {0}; static PhotoFast_SliceEncode_CB2_Param cb2_param = {0}; static PhotoFast_SliceEncode_CB3_Param cb3_param = {0}; static lfqueue_t queue12 = {0}; static lfqueue_t queue23 = {0}; INT32 PhotoFast_Sliceencode2_Enq_Frame(const HD_VIDEO_FRAME* video_frame) { if(lfqueue_size(&queue12) >= PHOTOFAST_SLICE_ENC_QUEUE12_MAX_SIZE){ return E_SYS; } PhotoFast_SliceEncode_Queue12_Param* queue_ele_out = NULL; queue_ele_out = (PhotoFast_SliceEncode_Queue12_Param*) malloc(sizeof(PhotoFast_SliceEncode_Queue12_Param)); memset(queue_ele_out, 0, sizeof(PhotoFast_SliceEncode_Queue12_Param)); queue_ele_out->frame = *video_frame; while (lfqueue_enq(&queue12, (void*) queue_ele_out) == -1) { vos_util_delay_ms(1); DBG_ERR("ENQ Full ?\r\n"); } return E_OK; } INT32 PhotoFast_Sliceencode2_Stop(void) { PhotoFast_SliceEncode_Queue12_Param* queue_ele_out = NULL; queue_ele_out = (PhotoFast_SliceEncode_Queue12_Param*) malloc(sizeof(PhotoFast_SliceEncode_Queue12_Param)); memset(queue_ele_out, 0, sizeof(PhotoFast_SliceEncode_Queue12_Param)); queue_ele_out->comm.terminate = 1; while (lfqueue_enq(&queue12, (void*) queue_ele_out) == -1) { vos_util_delay_ms(1); DBG_ERR("ENQ Full ?\r\n"); } return E_OK; } INT32 PhotoFast_SliceEncode_CB2(void* user_data) { INT32 ret = E_OK; PhotoFast_SliceEncode_CB2_Param* param = NULL; PhotoFast_SliceEncode_Queue12_Param* queue_ele_in = NULL; PhotoFast_SliceEncode_Queue23_Param* queue_ele_out = NULL; HD_RESULT hd_ret = HD_OK; PhotoFast_SliceEncode_Info* slice_encode_primary_info = PhotoFast_SliceEncode_Get_Info(PHOTO_ENC_JPG_PRIMARY); PhotoFast_SliceEncode_Info* slice_encode_screennail_info = PhotoFast_SliceEncode_Get_Info(PHOTO_ENC_JPG_SCREENNAIL); PhotoFast_SliceEncode_Info* slice_encode_thumbnail_info = PhotoFast_SliceEncode_Get_Info(PHOTO_ENC_JPG_THUMBNAIL); PhotoFast_SliceSize_Info src_slice_info = {0}, dst_slice_info = {0}; HD_VIDEO_FRAME video_frame_out_screennail = {0}; HD_VIDEO_FRAME video_frame_out_thumbnail = {0}; HD_PATH_ID vproc_path_id = 0; HD_VIDEOPROC_OUT vproc_out = {0}; HD_VIDEO_PXLFMT vproc_out_pxlfmt = 0; PhotoFast_MEM_Info exif_mem_info = {0}; UINT32 enc_accum_size = 0; static UINT8 primary_quality = CFG_PHOTOFAST_SLICE_ENC_INIT_QUALITY_PRIMARY; static UINT8 screennail_quality = CFG_PHOTOFAST_SLICE_ENC_INIT_QUALITY_SCREENNAIL; if(!user_data){ DBG_ERR("user_data can't be null!\n"); ret = E_SYS; goto EXIT; } param = (PhotoFast_SliceEncode_CB2_Param*) user_data; param->cnt = 0; vproc_path_id = param->vproc_path_id; DBG_DUMP("enter cb2 loop\n"); /******************************************************************* * Get vproc info ******************************************************************/ /* 3dnr ref path output sensor sized frame */ // ImageApp_Photo_Get_Hdal_Path(vid_in, PHOTO_HDAL_VPRC_3DNR_REF_PATH, (UINT32 *)&vproc_path_id); /* get vproc out frame format ( = venc in) */ hd_ret = hd_videoproc_get(vproc_path_id, HD_VIDEOPROC_PARAM_OUT, (VOID*)&vproc_out); if(hd_ret != HD_OK){ DBG_ERR("hd_videoproc_get HD_VIDEOPROC_PARAM_OUT failed(path_id=%lx, ret=%d)!", vproc_path_id, ret); vproc_out_pxlfmt = HD_VIDEO_PXLFMT_YUV420; } else{ vproc_out_pxlfmt = vproc_out.pxlfmt; } /* pull out vprc frame is in the CB1 */ /******************************************************************* * Init Date Buffer ******************************************************************/ // if (UI_GetData(FL_DATE_STAMP) != DATEIMPRINT_OFF) { // Ux_SendEvent(&CustomPhotoObjCtrl, NVTEVT_EXE_INIT_DATE_BUF, 0); // } /******************************************************************* * Allocate slice buffer ******************************************************************/ slice_encode_thumbnail_info->bs_buf_mem_info.blk_size = (CFG_THUMBNAIL_W * CFG_THUMBNAIL_H) / 2; if(PhotoFast_SliceEncode_Alloc_Buffer(&slice_encode_thumbnail_info->bs_buf_mem_info, "slice_enc_thumbnail") != E_OK){ goto EXIT; } // slice_encode_screennail_info->bs_buf_mem_info.blk_size = PhotoFast_GetScreenNailSize(); // if(PhotoFast_SliceEncode_Alloc_Buffer(&slice_encode_screennail_info->bs_buf_mem_info, "slice_enc_screennail") != E_OK){ // goto EXIT; // } exif_mem_info.blk_size = CFG_JPG_HEADER_SIZE; if(PhotoFast_SliceEncode_Alloc_Buffer(&exif_mem_info, "slice_enc_exif") != E_OK) goto EXIT; do{ queue_ele_in = (PhotoFast_SliceEncode_Queue12_Param*)lfqueue_deq(param->queue12); if(queue_ele_in == NULL){ vos_util_delay_ms(1); continue; } if(queue_ele_in->comm.terminate){ DBG_ERR("abort CB2\n"); free(queue_ele_in); queue_ele_in = NULL; goto EXIT; } DBG_IND("process frame %lu\n", param->cnt); /******************************************************************* * Calculate dst slice info ******************************************************************/ if(PhotoFast_SliceEncode_Get_Curr_Dst_Slice_Info(&dst_slice_info, queue_ele_in->frame) != E_OK){ goto EXIT; } /******************************************************************* * Calculate src slice info ******************************************************************/ PhotoFast_SliceEncode_Get_Src_Slice_Info(&dst_slice_info, &src_slice_info, queue_ele_in->frame); #if PHOTOFAST_FAST_STAMP == ENABLE /******************************************************************* * Stamp on the src frame ******************************************************************/ if(PhotoFastCapDateImprint_Src_GenYuvData(&queue_ele_in->frame, &src_slice_info, &dst_slice_info) != E_OK){ goto EXIT; } #endif slice_encode_primary_info->bs_buf_mem_info.blk_size = (VDO_YUV_BUFSIZE(dst_slice_info.width, dst_slice_info.height, queue_ele_in->frame.pxlfmt) / (CFG_PHOTOFAST_SLICE_ENC_BS_BUF_RATIO)) + CFG_JPG_HEADER_SIZE + PhotoFast_GetScreenNailSize() ; if(PhotoFast_SliceEncode_Alloc_Buffer_Retry( &slice_encode_primary_info->bs_buf_mem_info, "slice_enc_primary", 50, 100 ) != E_OK){ goto EXIT; } slice_encode_screennail_info->bs_buf_mem_info.blk_size = PhotoFast_GetScreenNailSize(); if(PhotoFast_SliceEncode_Alloc_Buffer_Retry( &slice_encode_screennail_info->bs_buf_mem_info, "slice_enc_screennail", 50, 100 ) != E_OK){ goto EXIT; } /******************************************************************* * Screennail & Thumbnail Scale ******************************************************************/ /* screennail scale */ if(PhotoFast_SliceEncode_Scale_Screennail(&queue_ele_in->frame, &video_frame_out_screennail) != E_OK){ goto EXIT; } /* thumbnail scale, 2pass from screennail */ if(PhotoFast_SliceEncode_Scale_Thumbnail(&video_frame_out_screennail, &video_frame_out_thumbnail) != E_OK){ goto EXIT; } #if !PHOTOFAST_FAST_STAMP PhotoFastCapDateImprint_GenYuvData(&video_frame_out_screennail); PhotoFastCapDateImprint_GenYuvData(&video_frame_out_thumbnail); #endif /******************************************************************* * Primary ******************************************************************/ /* slice encode */ PhotoFast_SliceEncode_Encode_Set_In(slice_encode_primary_info->enc_path_id, vproc_out_pxlfmt, (HD_DIM) {dst_slice_info.width, dst_slice_info.height}); PhotoFast_SliceEncode_Encode_Set_Out(slice_encode_primary_info->enc_path_id, primary_quality); if(PhotoFast_SliceEncode_Encode_Primary(&queue_ele_in->frame, src_slice_info, dst_slice_info, &enc_accum_size, &primary_quality) != E_OK){ goto EXIT; } slice_encode_primary_info->bs_buf_mem_info.used_size = enc_accum_size; /******************************************************************* * Screennail & Thumbnail Encode ******************************************************************/ /* screennail encode */ #if HUNTING_CAMERA_MCU == ENABLE UIMenuStoreInfo *puiPara = sf_ui_para_get(); PhotoFast_SliceEncode_Encode_Set_In(slice_encode_screennail_info->enc_path_id, vproc_out_pxlfmt, (HD_DIM) {(sf_get_screen_nail_width(puiPara->SendPicSize)), (sf_get_screen_nail_height(puiPara->SendPicSize))}); #else PhotoFast_SliceEncode_Encode_Set_In(slice_encode_screennail_info->enc_path_id, vproc_out_pxlfmt, (HD_DIM) {CFG_SCREENNAIL_W, CFG_SCREENNAIL_H}); #endif #if CFG_PHOTOFAST_SLICE_ENC_RC_SCREENNAIL if(PhotoFast_SliceEncode_Encode_Screennail_RC(&video_frame_out_screennail, &screennail_quality) != E_OK){ goto EXIT; } #else PhotoFast_SliceEncode_Encode_Set_Out(slice_encode_screennail_info->enc_path_id, CFG_PHOTOFAST_SLICE_ENC_INIT_QUALITY_SCREENNAIL); if(PhotoFast_SliceEncode_Encode_Screennail(&video_frame_out_screennail) != E_OK){ goto EXIT; } #endif /* thumbnail encode */ PhotoFast_SliceEncode_Encode_Set_In(slice_encode_thumbnail_info->enc_path_id, vproc_out_pxlfmt, (HD_DIM) {CFG_THUMBNAIL_W, CFG_THUMBNAIL_H}); PhotoFast_SliceEncode_Encode_Set_Out(slice_encode_thumbnail_info->enc_path_id, CFG_PHOTOFAST_SLICE_ENC_INIT_QUALITY_THUMBNAIL); if(PhotoFast_SliceEncode_Encode_Thumbnail(&video_frame_out_thumbnail) != E_OK){ goto EXIT; } /******************************************************************* * Combine All Images ******************************************************************/ // exif_mem_info.blk_size = CFG_JPG_HEADER_SIZE; // if(PhotoFast_SliceEncode_Alloc_Buffer(&exif_mem_info, "slice_enc_exif") != E_OK) // goto EXIT; MEM_RANGE exif_data = {.addr = exif_mem_info.va, .size = exif_mem_info.blk_size}; MEM_RANGE thumb_jpg = {.addr = slice_encode_thumbnail_info->bs_buf_mem_info.va, .size = slice_encode_thumbnail_info->bs_buf_mem_info.used_size}; MEM_RANGE pri_jpg = {.addr = slice_encode_primary_info->bs_buf_mem_info.va + CFG_JPG_HEADER_SIZE, .size = slice_encode_primary_info->bs_buf_mem_info.used_size}; MEM_RANGE scr_jpg = {.addr = slice_encode_screennail_info->bs_buf_mem_info.va, .size = slice_encode_screennail_info->bs_buf_mem_info.used_size}; MEM_RANGE dst_jpg_file = { 0 }; /* exif */ ExifVendor_Write0thIFD(EXIF_HDL_ID_1); ExifVendor_WriteExifIFD(EXIF_HDL_ID_1); ExifVendor_Write0thIntIFD(EXIF_HDL_ID_1); ExifVendor_WriteGPSIFD(EXIF_HDL_ID_1); if (EXIF_CreateExif(EXIF_HDL_ID_1, &exif_data, &thumb_jpg) != EXIF_ER_OK) { DBG_ERR("Create Exif fail\r\n"); exif_data.size = 0; } /* combine jpg */ GxImgFile_CombineJPG(&exif_data, &pri_jpg, &scr_jpg, &dst_jpg_file); // if(PhotoCapMsgCb){ // PhotoCapMsgCb(IMG_CAP_CBMSG_JPEG_OK, NULL); // } /* check overflow */ if(dst_jpg_file.addr > (slice_encode_primary_info->bs_buf_mem_info.va + slice_encode_primary_info->bs_buf_mem_info.blk_size)){ DBG_ERR("primary buffer overflow during combine jpg!\r\n"); } /* enqueue jpg buffer info */ queue_ele_out = (PhotoFast_SliceEncode_Queue23_Param*) malloc(sizeof(PhotoFast_SliceEncode_Queue23_Param)); memset(queue_ele_out, 0, sizeof(PhotoFast_SliceEncode_Queue23_Param)); queue_ele_out->jpg_combined_addr = (UINT8*) dst_jpg_file.addr; queue_ele_out->jpg_combined_size = dst_jpg_file.size; queue_ele_out->jpg_thumb_addr = (UINT8*) scr_jpg.addr; queue_ele_out->jpg_thumb_size = scr_jpg.size; queue_ele_out->mem_info_combined = slice_encode_primary_info->bs_buf_mem_info; queue_ele_out->mem_info_thumb = slice_encode_screennail_info->bs_buf_mem_info; #if PHOTOFAST_FAST_CLOSE UINT32 nextFolderID = 0, nextFileID = 0; DCF_GetNextID(&nextFolderID,&nextFileID); queue_ele_out->nextFolderID = nextFolderID; queue_ele_out->nextFileID = nextFileID; DCF_MakeObjPath(nextFolderID, nextFileID, DCF_FILE_TYPE_JPG, queue_ele_out->file_path); DCF_AddDBfile(queue_ele_out->file_path); DBG_DUMP("%s added to DCF\r\n", queue_ele_out->file_path); #endif while(1) { if(lfqueue_size(param->queue23) >= PHOTOFAST_SLICE_ENC_QUEUE23_MAX_SIZE){ vos_util_delay_ms(1); continue; } else{ while (lfqueue_enq(param->queue23, (void*) queue_ele_out) == -1) { DBG_ERR("ENQ Full ?\r\n"); } break; } } /* check is vproc frame released */ if(queue_ele_in->frame.phy_addr[0]){ if ((ret = hd_videoproc_release_out_buf(vproc_path_id, &(queue_ele_in->frame)))!= HD_OK) { DBG_ERR("hd_videoproc_release_out_buf failed(%d)\r\n", ret); } } if(queue_ele_in){ free(queue_ele_in); queue_ele_in = NULL; } param->cnt++; sf_set_cont_shot(param->cnt); if(param->cnt >= param->max_cnt) break; #if SF_NO_SD_SEND == ENABLE if(PhotoFast_Wait_FileSys(1) != E_OK){ goto EXIT; } #endif } while(1); EXIT: // if(slice_encode_screennail_info->bs_buf_mem_info.va){ // PhotoFast_SliceEncode_Free_Buffer(&slice_encode_screennail_info->bs_buf_mem_info); // } if(slice_encode_thumbnail_info->bs_buf_mem_info.va){ PhotoFast_SliceEncode_Free_Buffer(&slice_encode_thumbnail_info->bs_buf_mem_info); } /* check exif buffer is freed */ if(exif_mem_info.va){ PhotoFast_SliceEncode_Free_Buffer(&exif_mem_info); } if(param->cnt < param->max_cnt){ queue_ele_out = (PhotoFast_SliceEncode_Queue23_Param*) malloc(sizeof(PhotoFast_SliceEncode_Queue23_Param)); memset(queue_ele_out, 0, sizeof(PhotoFast_SliceEncode_Queue23_Param)); queue_ele_out->comm.terminate = 1; lfqueue_enq(param->queue23, (void*) queue_ele_out); extern void flow_preview_set_stop_flag(BOOL flag); flow_preview_set_stop_flag(TRUE); } DBG_DUMP("task2 job finished\n"); return ret; } INT32 PhotoFast_SliceEncode_CB3(void* user_data) { INT32 ret = E_OK; PhotoFast_SliceEncode_CB3_Param* param = NULL; PhotoFast_SliceEncode_Queue23_Param* queue_ele_in = NULL; VOS_TICK t1, t2, t3, t4; if(!user_data){ DBG_ERR("user_data can't be null!\n"); ret = E_SYS; goto EXIT; } param = (PhotoFast_SliceEncode_CB3_Param*) user_data; param->cnt = 0; do{ queue_ele_in = (PhotoFast_SliceEncode_Queue23_Param*)lfqueue_deq(param->queue23); if(queue_ele_in == NULL){ vos_util_delay_ms(1); continue; } if(queue_ele_in->comm.terminate){ DBG_ERR("abort CB3\n"); free(queue_ele_in); queue_ele_in = NULL; goto EXIT; } /******************************************************************* * Output jpg file ******************************************************************/ extern INT32 PhotoFast_WriteFile(UINT32 Addr, UINT32 Size, UINT32 Fmt, UINT32 uiPathId, char* Path); #if SF_NO_SD_SEND == ENABLE if( PhotoFast_Wait_FileSys(FASTBOOT_WAIT_FILESYS_TIMEOUT_MS) != E_OK || PhotoFast_Wait_FileNaming(FASTBOOT_WAIT_FILESYS_TIMEOUT_MS) != E_OK){ DBG_WRN("filesys not ready, store data into mem\n"); SYS_USRMEM usrmem = {0}; if(sys_usrmem_init(&usrmem) == E_OK){ sys_usrmem_write_photo( &usrmem, (UINT32) queue_ele_in->jpg_combined_addr, queue_ele_in->jpg_combined_size ); } } else #else if(PhotoFast_Wait_FileSys(FASTBOOT_WAIT_FILESYS_TIMEOUT_MS) != E_OK){ goto EXIT; } if(PhotoFast_Wait_FileNaming(FASTBOOT_WAIT_FILESYS_TIMEOUT_MS) != E_OK){ goto EXIT; } #endif { vos_perf_mark(&t1); #if !PHOTOFAST_FAST_CLOSE PhotoFast_WriteFile( (UINT32)queue_ele_in->jpg_combined_addr, queue_ele_in->jpg_combined_size, NAMERULE_FMT_JPG, 0, 0); #else PhotoFast_WriteFile( (UINT32)queue_ele_in->jpg_combined_addr, queue_ele_in->jpg_combined_size, NAMERULE_FMT_JPG, 0, queue_ele_in->file_path); #endif vos_perf_mark(&t2); { char tmp[NMC_TOTALFILEPATH_MAX_LEN] = {'\0'}; #if !PHOTOFAST_FAST_CLOSE extern CHAR* PhotoFast_GetLastWriteFilePath(void); char* file_path = PhotoFast_GetLastWriteFilePath(); #else char file_path[NMC_TOTALFILEPATH_MAX_LEN]; #if HUNTING_CAMERA_MCU == ENABLE sprintf(tmp, "W%03ld%04ld.JPG", queue_ele_in->nextFolderID, queue_ele_in->nextFileID); strncpy(file_path, tmp, strlen(queue_ele_in->file_path) - 1); DBG_IND("last send file:%s\r\n", file_path); #else strncpy(file_path, FilePath, strlen(queue_ele_in->file_path) - 1); #endif #endif #if HUNTING_CAMERA_MCU == ENABLE char tmp2[64] = {'\0'}; #endif #if HUNTING_CAMERA_MCU == ENABLE #if USE_RTOS_MMC_CHECK SF_RTOS_ST_MMC_DEV *mmc_dev = SF_RtosStrgCheckWorkableDev(); if(mmc_dev != NULL) { if(mmc_dev->dcf_handle < 0) { DBG_ERR("dcf_handle err\n"); } if(mmc_dev->dev_type == MMC_DEV_SD) { snprintf(tmp, sizeof(tmp), "%c%s%s", 'A', PHOTO_THUMB_PATH, file_path); /* DCF 8.3 naming rule */ } else { snprintf(tmp, sizeof(tmp), "%c%s%s", 'B', PHOTO_THUMB_PATH, file_path); /* DCF 8.3 naming rule */ } } #else snprintf(tmp, sizeof(tmp), "%c%s%s", 'B', PHOTO_THUMB_PATH, file_path); /* DCF 8.3 naming rule */ #endif #else UINT32 length = strlen(file_path); snprintf(tmp, sizeof(tmp), "%s%s", PHOTO_THUMB_PATH, file_path + length - 12); /* DCF 8.3 naming rule */ snprintf(tmp + strlen(tmp) - 3, sizeof(tmp), "%s", "JPG"); #endif DBG_IND("PHOTO THUMB %s\n", tmp); vos_perf_mark(&t3); if((TRUE != sf_is_card_full() && (mmc_dev->dev_type == MMC_DEV_SD)) || (TRUE != sf_is_emmc_full() && (mmc_dev->dev_type == MMC_DEV_EMMC))) { FST_FILE fp = FileSys_OpenFile(tmp, FST_CREATE_ALWAYS | FST_OPEN_WRITE); FileSys_WriteFile(fp, (UINT8*)queue_ele_in->jpg_thumb_addr, &queue_ele_in->jpg_thumb_size, 0, NULL); FileSys_FlushFile(fp); FileSys_CloseFile(fp); #if HUNTING_CAMERA_MCU == ENABLE memset(tmp, '\0', sizeof(tmp)); snprintf(tmp, sizeof(tmp), "%s/%s", mmc_dev->dev_type == MMC_DEV_EMMC ? SF_SEND_LIST_EMMC_DIR : SF_SEND_LIST_DIR, file_path); /* DCF 8.3 naming rule */ snprintf(tmp2, sizeof(tmp2), "%s", file_path); /* DCF 8.3 naming rule */ sf_file_thumb_cfg_fill(tmp, tmp2, queue_ele_in->jpg_thumb_size, SF_FILE_TYPE_PIC_SMALL); DBG_IND("PHOTO THUMB %s \n %s\n %s\n", tmp, tmp2,file_path); DBG_IND("%s:%d thumbfileSize:%d thumbfileName:%s thumbfilePath:%s\n", __FUNCTION__, __LINE__,queue_ele_in->jpg_thumb_size,tmp2,tmp); #endif } } vos_perf_mark(&t4); DBG_DUMP("CB3 cost %lu ms(%lu , %lu , %lu)\n", vos_perf_duration(t1, t4) / 1000, vos_perf_duration(t1, t2) / 1000, vos_perf_duration(t2, t3) / 1000, vos_perf_duration(t3, t4) / 1000 ); } /* check user bs buffer is freed */ if(queue_ele_in->mem_info_combined.va){ PhotoFast_SliceEncode_Free_Buffer(&queue_ele_in->mem_info_combined); } if(queue_ele_in->mem_info_thumb.va){ PhotoFast_SliceEncode_Free_Buffer(&queue_ele_in->mem_info_thumb); } if(queue_ele_in){ free(queue_ele_in); queue_ele_in = NULL; } param->cnt++; if(param->cnt >= param->max_cnt) break; } while(1); EXIT: DBG_DUMP("task3 job finished\n"); return ret; } static INT32 PhotoFast_SliceEncode_Init_Flag(ID* flag_id, char* name) { INT32 ret = E_OK; if(vos_flag_create(flag_id, NULL, name) != E_OK){ DBG_ERR("create flag(%s) failed!\n", name); ret = E_SYS; goto EXIT; } clr_flg(*flag_id, FLG_PHOTO_FAST_SLICE_ENC_STA_IDLE); clr_flg(*flag_id, FLG_PHOTO_FAST_SLICE_ENC_STA_STOPPED); clr_flg(*flag_id, FLG_PHOTO_FAST_SLICE_ENC_STA_STARTED); clr_flg(*flag_id, FLG_PHOTO_FAST_SLICE_ENC_CMD_START); clr_flg(*flag_id, FLG_PHOTO_FAST_SLICE_ENC_CMD_STOP); EXIT: return ret; } static INT32 PhotoFast_SliceEncode_Uninit_Flag(ID* flag_id) { INT32 ret = E_OK; if(vos_flag_destroy(*flag_id) != E_OK){ DBG_ERR("destroy flag failed!\n"); ret = E_SYS; goto EXIT; } *flag_id = 0; EXIT: return ret; } VOID PhotoFast_SliceEncode2_Close(VOID) { FLGPTN flag = 0; DBG_DUMP("PhotoFast_SliceEncode2_Close\n"); /* stop cmd */ set_flg(task2_param.flag_id, FLG_PHOTO_FAST_SLICE_ENC_CMD_STOP); #if !PHOTOFAST_FAST_CLOSE set_flg(task3_param.flag_id, FLG_PHOTO_FAST_SLICE_ENC_CMD_STOP); #else if(DrvGPIO_GetPhotoMovieModeFromMonitor() == DX_HUNTING_MODE_PHOTO){ set_flg(task3_param.flag_id, FLG_PHOTO_FAST_SLICE_ENC_CMD_STOP); } #endif /* check stopped */ wai_flg(&flag, task2_param.flag_id, FLG_PHOTO_FAST_SLICE_ENC_STA_STOPPED, TWF_ORW); #if !PHOTOFAST_FAST_CLOSE wai_flg(&flag, task3_param.flag_id, FLG_PHOTO_FAST_SLICE_ENC_STA_STOPPED, TWF_ORW); #else if(DrvGPIO_GetPhotoMovieModeFromMonitor() == DX_HUNTING_MODE_PHOTO){ wai_flg(&flag, task3_param.flag_id, FLG_PHOTO_FAST_SLICE_ENC_STA_STOPPED, TWF_ORW); } #endif DBG_DUMP("slice encode finished\n"); lfqueue_destroy(&queue12); #if !PHOTOFAST_FAST_CLOSE lfqueue_destroy(&queue23); #else if(DrvGPIO_GetPhotoMovieModeFromMonitor() == DX_HUNTING_MODE_PHOTO){ lfqueue_destroy(&queue23); } #endif PhotoFast_SliceEncode_Uninit_Flag(&task2_param.flag_id); #if !PHOTOFAST_FAST_CLOSE PhotoFast_SliceEncode_Uninit_Flag(&task3_param.flag_id); #else if(DrvGPIO_GetPhotoMovieModeFromMonitor() == DX_HUNTING_MODE_PHOTO){ PhotoFast_SliceEncode_Uninit_Flag(&task3_param.flag_id); } #endif } INT32 PhotoFast_SliceEncode2_Open( const HD_PATH_ID vproc_path_id, const UINT32 max_cnt ) { INT32 ret = E_OK; FLGPTN flag = 0; if(lfqueue_init(&queue12)){ DBG_ERR("init lfqueue12 failed\n"); goto EXIT; } if(lfqueue_init(&queue23)){ DBG_ERR("init lfqueue23 failed\n"); goto EXIT; } /*************************************************************************************** * task2 ***************************************************************************************/ memset(&task2_param, 0, sizeof(PhotoFast_SliceEncode_Task_Param)); memset(&cb2_param, 0, sizeof(PhotoFast_SliceEncode_CB2_Param)); if(PhotoFast_SliceEncode_Init_Flag(&(task2_param.flag_id), "slice_enc_flag2") != E_OK){ goto EXIT; } task2_param.callback = PhotoFast_SliceEncode_CB2; task2_param.user_data = &cb2_param; task2_param.run = 0; task2_param.is_running = 0; task2_param.task_id = vos_task_create(_PhotoFast_SliceEncode_Worker, &task2_param, "slice_enc_tsk2", 12, 8192); if(!task2_param.task_id){ DBG_ERR("create task2 failed!\n"); ret = E_SYS; goto EXIT; } cb2_param.max_cnt = max_cnt; cb2_param.cnt = 0; cb2_param.queue12 = &queue12; cb2_param.queue23 = &queue23; cb2_param.vproc_path_id = vproc_path_id; DBG_DUMP("resume task2\n"); task2_param.run = 1; vos_task_resume(task2_param.task_id); /*************************************************************************************** * task3 ***************************************************************************************/ memset(&task3_param, 0, sizeof(PhotoFast_SliceEncode_Task_Param)); memset(&cb3_param, 0, sizeof(PhotoFast_SliceEncode_CB3_Param)); if(PhotoFast_SliceEncode_Init_Flag(&(task3_param.flag_id), "slice_enc_flag3") != E_OK){ goto EXIT; } task3_param.callback = PhotoFast_SliceEncode_CB3; task3_param.user_data = &cb3_param; task3_param.run = 0; task3_param.is_running = 0; task3_param.task_id = vos_task_create(_PhotoFast_SliceEncode_Worker, &task3_param, "slice_enc_tsk3", 12, 4096); if(!task3_param.task_id){ DBG_ERR("create task3 failed!\n"); ret = E_SYS; goto EXIT; } cb3_param.max_cnt = max_cnt; cb3_param.cnt = 0; cb3_param.queue23 = &queue23; DBG_DUMP("resume task3\n"); task3_param.run = 1; vos_task_resume(task3_param.task_id); /* start cmd */ set_flg(task2_param.flag_id, FLG_PHOTO_FAST_SLICE_ENC_CMD_START); set_flg(task3_param.flag_id, FLG_PHOTO_FAST_SLICE_ENC_CMD_START); /* check started */ wai_flg(&flag, task2_param.flag_id, FLG_PHOTO_FAST_SLICE_ENC_STA_STARTED, TWF_ORW); wai_flg(&flag, task3_param.flag_id, FLG_PHOTO_FAST_SLICE_ENC_STA_STARTED, TWF_ORW); EXIT: if(ret != E_OK) DBG_ERR("cb2 filaed!\n"); return NVTEVT_CONSUME; } #endif