nt9856x/rtos/code/application/source/cardv/SrcCode/UIApp/PhotoFast/PhotoFastSliceEncode.c

2123 lines
67 KiB
C
Executable File

#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 <kwrap/cmdsys.h>
#define VDO_YUV_BUFSIZE(w, h, pxlfmt) ALIGN_CEIL_4(((w) * (h) * HD_VIDEO_PXLFMT_BPP(pxlfmt)) / 8)
/**********************************************************************************
* independent thumbnail
*********************************************************************************/
#define PHOTO_THUMB_PATH "A:\\Thumb\\"
#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
#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 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(video_frame.dim.h / src_info->slice_num, 2);
src_info->last_slice_height = src_info->height - src_info->slice_height * (src_info->slice_num - 1);
}
else{
src_info->slice_height = video_frame.dim.h;
src_info->last_slice_height = src_info->slice_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_height = ((dim.h * 3) / 10);
UINT32 reserved_buffer = VDO_YUV_BUFSIZE(dim.w, reserved_buffer_height, pxl_fmt);
UINT32 max_buffer_size = VDO_YUV_BUFSIZE(dim.w, dim.h, 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)
{
if((cap_size_h % slice_num) != 0){
DBG_ERR("Height(%lu) should be %lu aligned!, please check photo size of PhotoMapping\r\n", cap_size_h, slice_num);
return E_SYS;
}
info->width = cap_size_w;
info->height = cap_size_h;
info->slice_num = slice_num;
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!\n");
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)
{
UINT32 cap_size_w = GetPhotoSizeWidth(SysGetFlag(FL_PHOTO_SIZE));
UINT32 cap_size_h = GetPhotoSizeHeight(SysGetFlag(FL_PHOTO_SIZE));
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){
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);
slice_num = cap_size_h / lines + (cap_size_h % lines ? 1 : 0);
if(cap_size_h % slice_num){
// cap_size_h = ALIGN_FLOOR(cap_size_h, slice_num);
cap_size_h -= (cap_size_h % slice_num);
// DBG_WRN("fix photo height to %u to meet alignment requirement slice_num=%lu\n", cap_size_h, slice_num);
}
}
return PhotoFast_SliceEncode_Get_Dst_Slice_Info(info, cap_size_w, cap_size_h, slice_num);
}
static HD_DIM PhotoFast_SliceEncode_Get_Encode_Max_Size()
{
PhotoFast_SliceSize_Info info;
if(PhotoFast_SliceEncode_Get_Curr_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 = 4;
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_Curr_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);
goto EXIT;
}
vproc_out_pxlfmt = vproc_out.pxlfmt;
}
if ((ret = hd_videoenc_init()) != HD_OK){
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 ; i<PHOTO_ENC_JPG_TYPE_MAX_ID ; i++)
{
PhotoFast_SliceEncode_Info* info = PhotoFast_SliceEncode_Get_Info(i);
switch(i)
{
case PHOTO_ENC_JPG_PRIMARY:
{
PhotoFast_SliceSize_Info max_info;
info->enc_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_Curr_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;
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;
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 ; i<PHOTO_ENC_JPG_TYPE_MAX_ID ; i++)
{
PhotoFast_SliceEncode_Info* info = PhotoFast_SliceEncode_Get_Info(i);
if(path_id == 0 || path_id != info->enc_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 ((ret = hd_common_mem_alloc(name, &info->pa, (void **)&va_ptr, info->blk_size, ddr_id)) != HD_OK) {
DBG_ERR("hd_common_mem_alloc failed(%d)\r\n", ret);
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_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)) ? (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_slice_height;
vf_gfx_scale_param->dst_img.blk = dst_buffer_info.blk;
vf_gfx_scale_param->quality = HD_GFX_SCALE_QUALITY_BILINEAR;
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]
);
return E_OK;
}
#if PHOTOFAST_SLICE_ENC_DBG_PRIMARY_YUV
static INT32 PhotoFast_SliceEncode_Dump_Frame(const HD_VIDEO_FRAME video_frame)
{
char fileName[128] = {0};
FST_FILE fp = NULL;
UINT32 size;
UINT32 va;
size = VDO_YUV_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;
}
sprintf(fileName, "A:\\frame_%lux%lu_fmt%lx.dat", video_frame.dim.w, video_frame.dim.h, 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_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_BILINEAR;
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;
dest_size.w = CFG_SCREENNAIL_W;
dest_size.h = CFG_SCREENNAIL_H;
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;
}
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, -1); // -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, -1); // -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_SYS;
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, -1); // -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, -1); // -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_SYS;
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 UINT32 PhotoFast_GetScreenNailSize(void)
{
UINT32 uiImageSize, ScreenNailSize;
UINT32 BitStreamSize;
ScreenNailSize = CFG_SCREENNAIL_SIZE;
uiImageSize = UI_GetData(FL_PHOTO_SIZE);
if (uiImageSize < ScreenNailSize) {
BitStreamSize = CFG_SCREENNAIL_W * CFG_SCREENNAIL_H / 2;
} 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
)
{
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 */
const UINT8 slice_idx_of_date_stamp = dst_slice_info.slice_num > 2 ? dst_slice_info.slice_num - 2 : 0;
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<dst_slice_info.slice_num ; slice_idx++)
{
PHOTOFAST_SLICE_ENC_DUMP("\r\n");
PhotoFast_SliceEncode_Init_VF_GFX_Slice(
&vf_gfx_scale_param,
video_frame,
yuv_buffer_info,
src_slice_info,
dst_slice_info,
slice_idx);
if(vf_gfx_scale(&vf_gfx_scale_param, 1) != HD_OK){
goto EXIT;
}
// /* attach the date stamp to a slice */
if(slice_idx == slice_idx_of_date_stamp){
HD_VIDEO_FRAME slice_img;
memcpy(&slice_img, &vf_gfx_scale_param.dst_img, sizeof(HD_VIDEO_FRAME));
if(slice_idx_of_date_stamp == (dst_slice_info.slice_num - 1)){
slice_img.dim.h = dst_slice_info.last_slice_height;
slice_img.ph[0] = dst_slice_info.last_slice_height;
slice_img.ph[1] = dst_slice_info.last_slice_height;
}
PhotoFastCapDateImprint_GenYuvData(&slice_img);
}
vf_gfx_scale_param.dst_img.count = 0;
vf_gfx_scale_param.dst_img.timestamp = hd_gettime_us();
if(dst_slice_info.slice_num > 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, -1); // -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, -1); // -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_DOWN_STEP){
quality_new = 1;
restart = TRUE;
}
else if(quality_old > CFG_PHOTOFAST_SLICE_ENC_QUALITY_DOWN_STEP){
quality_new = quality_old - CFG_PHOTOFAST_SLICE_ENC_QUALITY_DOWN_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;
}
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;
// 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;
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);
goto EXIT;
}
vproc_out_pxlfmt = vproc_out.pxlfmt;
/*******************************************************************
* Calculate dst slice info
******************************************************************/
if(PhotoFast_SliceEncode_Get_Curr_Dst_Slice_Info(&dst_slice_info) != 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);
#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;
}
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;
}
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() ;
if(PhotoFast_SliceEncode_Alloc_Buffer(&slice_encode_primary_info->bs_buf_mem_info, "slice_enc_primary") != E_OK){
goto EXIT;
}
/* 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) != 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 */
PhotoFast_SliceEncode_Encode_Set_In(slice_encode_screennail_info->enc_path_id, vproc_out_pxlfmt, (HD_DIM) {CFG_SCREENNAIL_W, CFG_SCREENNAIL_H});
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;
}
#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);
fastboot_wait_done(BOOT_INIT_FILENAMINGOK);
PhotoFast_WriteFile(
dst_jpg_file.addr,
dst_jpg_file.size,
NAMERULE_FMT_JPG,
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;
} 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 task1_param = {0};
static PhotoFast_SliceEncode_Task_Param task2_param = {0};
static PhotoFast_SliceEncode_Task_Param task3_param = {0};
//static PhotoFast_SliceEncode_CB1_Param cb1_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)
{
PhotoFast_SliceEncode_Queue12_Param* queue_ele_out = NULL;
queue_ele_out = (PhotoFast_SliceEncode_Queue12_Param*) malloc(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_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;
// PHOTO_VID_IN vid_in = PHOTO_VID_IN_1;
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;
// PHOTO_CAP_CBMSG_FP PhotoCapMsgCb = (PHOTO_CAP_CBMSG_FP)Photo_CaptureCB;
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);
goto EXIT;
}
vproc_out_pxlfmt = vproc_out.pxlfmt;
/*******************************************************************
* Calculate dst slice info
******************************************************************/
if(PhotoFast_SliceEncode_Get_Curr_Dst_Slice_Info(&dst_slice_info) != E_OK){
return NVTEVT_CONSUME;
}
/* 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;
}
DBG_DUMP("process frame\n");
/*******************************************************************
* Calculate src slice info
******************************************************************/
PhotoFast_SliceEncode_Get_Src_Slice_Info(&dst_slice_info, &src_slice_info, queue_ele_in->frame);
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(&slice_encode_primary_info->bs_buf_mem_info, "slice_enc_primary") != 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;
}
/*******************************************************************
* 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;
}
/*******************************************************************
* 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(&queue_ele_in->frame, src_slice_info, dst_slice_info, &enc_accum_size) != E_OK){
goto EXIT;
}
slice_encode_primary_info->bs_buf_mem_info.used_size = enc_accum_size;
/*******************************************************************
* Screennail & Thumbnail Encode
******************************************************************/
/* screennail encode */
PhotoFast_SliceEncode_Encode_Set_In(slice_encode_screennail_info->enc_path_id, vproc_out_pxlfmt, (HD_DIM) {CFG_SCREENNAIL_W, CFG_SCREENNAIL_H});
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;
}
/* 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 };
DBG_WRN(" EXIF\r\n");
/* 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);
// 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));
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;
while (lfqueue_enq(param->queue23, (void*) queue_ele_out) == -1)
{
DBG_ERR("ENQ Full ?\r\n");
}
/* 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++;
if(param->cnt >= param->max_cnt)
break;
} 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);
}
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;
// PHOTO_CAP_CBMSG_FP PhotoCapMsgCb = (PHOTO_CAP_CBMSG_FP)Photo_CaptureCB;
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;
}
/*******************************************************************
* Output jpg file
******************************************************************/
extern INT32 PhotoFast_WriteFile(UINT32 Addr, UINT32 Size, UINT32 Fmt, UINT32 uiPathId);
fastboot_wait_done(BOOT_INIT_FILESYSOK);
fastboot_wait_done(BOOT_INIT_FILENAMINGOK);
PhotoFast_WriteFile(
(UINT32)queue_ele_in->jpg_combined_addr,
queue_ele_in->jpg_combined_size,
NAMERULE_FMT_JPG,
0);
{
extern CHAR* PhotoFast_GetLastWriteFilePath(void);
char* file_path = PhotoFast_GetLastWriteFilePath();
char tmp[256] = {'\0'};
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");
DBG_DUMP("PHOTO THUMB %s\n", tmp);
FST_FILE fp = FileSys_OpenFile(tmp, FST_OPEN_ALWAYS | FST_OPEN_WRITE);
FileSys_WriteFile(fp, (UINT8*)queue_ele_in->jpg_thumb_addr, &queue_ele_in->jpg_thumb_size, 0, NULL);
FileSys_CloseFile(fp);
}
/* 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(task1_param.flag_id, FLG_PHOTO_FAST_SLICE_ENC_CMD_STOP);
set_flg(task2_param.flag_id, FLG_PHOTO_FAST_SLICE_ENC_CMD_STOP);
set_flg(task3_param.flag_id, FLG_PHOTO_FAST_SLICE_ENC_CMD_STOP);
/* check stopped */
// wai_flg(&flag, task1_param.flag_id, FLG_PHOTO_FAST_SLICE_ENC_STA_STOPPED, TWF_ORW);
wai_flg(&flag, task2_param.flag_id, FLG_PHOTO_FAST_SLICE_ENC_STA_STOPPED, TWF_ORW);
wai_flg(&flag, task3_param.flag_id, FLG_PHOTO_FAST_SLICE_ENC_STA_STOPPED, TWF_ORW);
DBG_DUMP("slice encode finished\n");
lfqueue_destroy(&queue12);
lfqueue_destroy(&queue23);
// PhotoFast_SliceEncode_Uninit_Flag(&task1_param.flag_id);
PhotoFast_SliceEncode_Uninit_Flag(&task2_param.flag_id);
PhotoFast_SliceEncode_Uninit_Flag(&task3_param.flag_id);
}
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;
}
/***************************************************************************************
* task1
***************************************************************************************/
// memset(&task1_param, 0, sizeof(PhotoFast_SliceEncode_Task_Param));
// memset(&cb1_param, 0, sizeof(PhotoFast_SliceEncode_CB1_Param));
//
//
// if(PhotoFast_SliceEncode_Init_Flag(&(task1_param.flag_id), "slice_enc_flag1") != E_OK){
// goto EXIT;
// }
//
// task1_param.callback = PhotoFast_SliceEncode_CB1;
// task1_param.user_data = &cb1_param;
// task1_param.run = 0;
// task1_param.is_running = 0;
// task1_param.task_id = vos_task_create(_PhotoFast_SliceEncode_Worker, &task1_param, "slice_enc_tsk1", 9, 2048);
// if(!task1_param.task_id){
// DBG_ERR("create task1 failed!\n");
// ret = E_SYS;
// goto EXIT;
// }
//
// cb1_param.max_cnt = max_cnt;
// cb1_param.cnt = 0;
// cb1_param.queue12 = &queue12;
//
// cb1_param.period = 1000 / max_cnt; /* average ms in one second */
//// cb1_param.period = 1000;
//
// DBG_DUMP("resume task1\n");
// task1_param.run = 1;
// vos_task_resume(task1_param.task_id);
/***************************************************************************************
* 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(task1_param.flag_id, FLG_PHOTO_FAST_SLICE_ENC_CMD_START);
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, task1_param.flag_id, FLG_PHOTO_FAST_SLICE_ENC_STA_STARTED, TWF_ORW);
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