JPEG软编码比较耗时,可能满足不了帧率的需求,RK平台自带JPEG硬编码,支持NV12和RGB565格式编码为MJPEG ,下面是封装后的函数实现
int hw_jpeg_encode_nv12(long input_phy_addr,long output_phy_addr,uint8* input_vir_addr,uint8* output_vir_addr,int width,int height,int picfmt,int quality,int thumbquality )
{
JpegEncInInfo JpegInInfo;
JpegEncOutInfo JpegOutInfo;
RkExifInfo exifInfo;
RkGPSInfo gpsInfo;
JpegEncType encodetype;
int jpeg_w,jpeg_h,err;
int jpegbuf_size,jpeg_buf_w,jpeg_buf_h;;
vpu_display_mem_pool *pool;
if (create_vpu_memory_pool_allocator(&pool, 10, 200*200*2) < 0) {
LOGE("Create vpu memory pool for post process failed\n");
pool = NULL;
} else {
LOG1("============ create_vpu_memory_pool_allocator 10*80kB ==========");
}
memset(&JpegInInfo,0x00,sizeof(JpegEncInInfo));
memset(&JpegOutInfo,0x00,sizeof(JpegEncOutInfo));
memset(&exifInfo,0x00,sizeof(exifInfo));
jpeg_w = width;
jpeg_h = height;
if(picfmt ==V4L2_PIX_FMT_RGB565){
encodetype = HWJPEGENC_RGB565;
jpegbuf_size = jpeg_w * jpeg_h *2;
}else{
encodetype = JPEGENC_YUV420_SP;
jpeg_buf_w = jpeg_w;
jpeg_buf_h = jpeg_h;
if(jpeg_buf_w%16)
jpeg_buf_w += 8;
if(jpeg_buf_h%16)
jpeg_buf_h += 8;
jpegbuf_size = jpeg_buf_w*jpeg_buf_h*3/2;
}
if (jpegbuf_size & 0xfff) {
jpegbuf_size = (jpegbuf_size & 0xfffff000) + 0x1000;
}
JpegInInfo.rotateDegree = DEGREE_0;
JpegInInfo.frameHeader = 1;
JpegInInfo.yuvaddrfor180 = (int)NULL;
JpegInInfo.type = encodetype;
JpegInInfo.y_rgb_addr = input_phy_addr;
JpegInInfo.uv_addr = input_phy_addr + jpeg_w*jpeg_h;
//JpegInInfo.y_vir_addr = input_vir_addr;
//JpegInInfo.uv_vir_addr = input_vir_addr + jpeg_w*jpeg_h;
JpegInInfo.inputW = jpeg_w;
JpegInInfo.inputH = jpeg_h;
JpegInInfo.pool = pool;
JpegInInfo.qLvl = quality/10;
if (JpegInInfo.qLvl < 5) {
JpegInInfo.qLvl = 5;
}
JpegInInfo.thumbqLvl = thumbquality /10;
if (JpegInInfo.thumbqLvl < 5) {
JpegInInfo.thumbqLvl = 5;
}
if(JpegInInfo.thumbqLvl >10) {
JpegInInfo.thumbqLvl = 9;
}
#if 1
JpegInInfo.doThumbNail = 0; //insert thumbnail at APP0 extension
JpegInInfo.thumbData = NULL; //if thumbData is NULL, do scale, the type above can not be 420_P or 422_UYVY
JpegInInfo.thumbDataLen = -1;
JpegInInfo.thumbW = 0;//thumbwidth;
JpegInInfo.thumbH = 0;//thumbheight;
JpegInInfo.y_vir_addr = 0;
JpegInInfo.uv_vir_addr = 0;
#else
JpegInInfo.doThumbNail = 1; //insert thumbnail at APP0 extension
JpegInInfo.thumbData = NULL; //if thumbData is NULL, do scale, the type above can not be 420_P or 422_UYVY
JpegInInfo.thumbDataLen = -1;
JpegInInfo.thumbW = 128;
JpegInInfo.thumbH = 160;
JpegInInfo.y_vir_addr = (unsigned char*)input_vir_addr;
JpegInInfo.uv_vir_addr = (unsigned char*)input_vir_addr+jpeg_w*jpeg_h;
#endif
#if 1
static char ExifMaker[32];
static char ExifModel[32];
static char ExifSelfDefine[640];
/*fill in jpeg exif tag*/
strncpy((char *)ExifMaker, "lvjiong",sizeof(ExifMaker) - 1);
ExifMaker[sizeof(ExifMaker) - 1] = '\0';
exifInfo.maker = ExifMaker;
exifInfo.makerchars = strlen(ExifMaker)+1;
strncpy((char *)ExifModel, "rk3399",sizeof(ExifModel) - 1);
ExifModel[sizeof(ExifModel) - 1] = '\0';
exifInfo.modelstr = ExifModel;
exifInfo.modelchars = strlen(ExifModel)+1;
//degree 0:1
//degree 90(clockwise):6
//degree 180:3
//degree 270:8
exifInfo.Orientation = 1;
// Date time
time_t rawtime;
struct tm *timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
strftime((char *)exifInfo.DateTime, 20, "%Y:%m:%d %H:%M:%S", timeinfo);
exifInfo.ExposureTime.num = 100;//lvjiong
exifInfo.ExposureTime.denom = 10000;
exifInfo.ApertureFNumber.num = 0x118;
exifInfo.ApertureFNumber.denom = 0x64;
exifInfo.ISOSpeedRatings = 10;//lvjiong
exifInfo.CompressedBitsPerPixel.num = 0x4;
exifInfo.CompressedBitsPerPixel.denom = 0x1;
exifInfo.ShutterSpeedValue.num = 0x452;
exifInfo.ShutterSpeedValue.denom = 0x100;
exifInfo.ApertureValue.num = 0x2f8;
exifInfo.ApertureValue.denom = 0x100;
exifInfo.ExposureBiasValue.num = 0;
exifInfo.ExposureBiasValue.denom = 0x100;
exifInfo.MaxApertureValue.num = 0x02f8;
exifInfo.MaxApertureValue.denom = 0x100;
exifInfo.MeteringMode = 02;
exifInfo.Flash = 0;//lvjiong
exifInfo.FocalLength.num = 0;//lvjiong
exifInfo.FocalLength.denom = 0x1;
exifInfo.FocalPlaneXResolution.num = 0x8383;
exifInfo.FocalPlaneXResolution.denom = 0x67;
exifInfo.FocalPlaneYResolution.num = 0x7878;
exifInfo.FocalPlaneYResolution.denom = 0x76;
exifInfo.SensingMethod = 2;
exifInfo.FileSource = 3;
exifInfo.CustomRendered = 1;
exifInfo.ExposureMode = 0;
exifInfo.WhiteBalance = 100;//lvjiong
exifInfo.DigitalZoomRatio.num = width;//lvjiong
exifInfo.DigitalZoomRatio.denom = width;//lvjiong
exifInfo.SceneCaptureType = 0x01;
/* snprintf(ExifSelfDefine,sizeof(ExifSelfDefine)-1,"XMLVersion=%s Rg_Proj=%0.5f s=%0.5f s_max1=%0.5f s_max2=%0.5f Bg1=%0.5f Rg1=%0.5f Bg2=%0.5f Rg2=%0.5f "
"colortemperature=%s ExpPriorIn=%0.2f ExpPriorOut=%0.2f region=%d ",params.cameraparam.XMLVersion,params.cameraparam.f_RgProj,\
params.cameraparam.f_s,params.cameraparam.f_s_Max1,params.cameraparam.f_s_Max2,params.cameraparam.f_Bg1,params.cameraparam.f_Rg1,params.cameraparam.f_Bg2,\
params.cameraparam.f_Rg2,params.cameraparam.illuName[params.cameraparam.illuIdx],params.cameraparam.expPriorIn,params.cameraparam.expPriorOut,\
params.cameraparam.region);
int i;
char str[64];
for(i=0; i<params.cameraparam.count; i++)
{
snprintf(str,sizeof(str)-1, "illuName[%d]=%s ",i,params.cameraparam.illuName[i]);
strncat(ExifSelfDefine, str, sizeof(ExifSelfDefine)-strlen(ExifSelfDefine)-1);
snprintf(str,sizeof(str)-1, "likehood[%d]=%0.2f ",i,params.cameraparam.likehood[i]);
strncat(ExifSelfDefine, str, sizeof(ExifSelfDefine)-strlen(ExifSelfDefine)-1);
snprintf(str,sizeof(str)-1, "wight[%d]=%0.2f ",i,params.cameraparam.wight[i]);
strncat(ExifSelfDefine, str, sizeof(ExifSelfDefine)-strlen(ExifSelfDefine)-1);
}
exifInfo.makernote = ExifSelfDefine;
exifInfo.makernotechars = strlen(ExifSelfDefine)+1; */
#endif
//Jpegfillexifinfo(&exifInfo,mPictureInfo);
JpegInInfo.exifInfo =&exifInfo;
JpegInInfo.gpsInfo = NULL;
JpegOutInfo.outBufPhyAddr = output_phy_addr;
JpegOutInfo.outBufVirAddr = output_vir_addr;
JpegOutInfo.outBuflen = jpegbuf_size;
JpegOutInfo.jpegFileLen = 0x00;
JpegOutInfo.cacheflush= /*jpegEncFlushBufferCb*/NULL;
/* LOGE("input_phy_addr %d,JpegOutInfo.outBufPhyAddr:%x,JpegOutInfo.outBufVirAddr:%p,jpegbuf_size:%d",input_phy_addr,JpegOutInfo.outBufPhyAddr,JpegOutInfo.outBufVirAddr,jpegbuf_size);
LOGE("\nJpegInInfo.y_rgb_addr=0x%x\n"
"JpegInInfo.uv_addr=0x%x\n"
"JpegInInfo.inputW=0x%x\n"
"JpegInInfo.inputH=0x%x\n"
"JpegInInfo.pool=0x%x\n"
"JpegInInfo.qLvl=0x%x\n"
"\n"
"JpegOutInfo.outBufPhyAddr=0x%x\n"
"JpegOutInfo.outBufVirAddr=0x%x\n"
"JpegOutInfo.outBuflen=0x%x\n",
JpegInInfo.y_rgb_addr,
JpegInInfo.uv_addr,
JpegInInfo.inputW,
JpegInInfo.inputH,
JpegInInfo.pool,
JpegInInfo.qLvl,
JpegOutInfo.outBufPhyAddr,
JpegOutInfo.outBufVirAddr,
JpegOutInfo.outBuflen); */
err = hw_jpeg_encode(&JpegInInfo, &JpegOutInfo);
if ((err < 0) || (JpegOutInfo.jpegFileLen <=0x00))
LOGE("%s(%d): hw_jpeg_encode Failed, err: %d JpegOutInfo.jpegFileLen:0x%x\n",__FUNCTION__,__LINE__,
err, JpegOutInfo.jpegFileLen);
if (pool) {
release_vpu_memory_pool_allocator(pool);
pool = NULL;
}
return JpegOutInfo.jpegFileLen;
}
调用方法
long shared_buf_phy, shared_buf_vir;//存放编码后jpeg数据,使用时直接引用虚拟地址即可
int index = -1;
//phy_addr,y_addr_vir 为ISP输出的相机数据存放的物理地址和虚拟地址
this->mSharedBufProvider->createBuffer(CONFIG_CAMERA_SHARED_BUF_CNT,SENSOR_WIDTH*SENSOR_HEIGHT*2,JPEGBUFFER,false);
index = this->mSharedBufProvider->getOneAvailableBuffer(&shared_buf_phy,&shared_buf_vir);
#if defined(RK_DRM_GRALLOC) // should use fd
shared_buf_phy = this->mSharedBufProvider->getBufShareFd(index);
#endif
outlen = hw_jpeg_encode_nv12(phy_addr,shared_buf_phy,(uint8*)y_addr_vir,(uint8*)shared_buf_vir,width,height,V4L2_PIX_FMT_NV12,80,80);