Files
SDK_RK3288/hardware/rockchip/camera/CameraHal/CameraIspSOCAdapter.cpp
2015-12-31 16:32:45 +08:00

408 lines
16 KiB
C++

#include "CameraIspAdapter.h"
namespace android{
/*
* zyh neon optimize
*/
CameraIspSOCAdapter::CameraIspSOCAdapter(int cameraId):CameraIspAdapter(cameraId)
{
}
CameraIspSOCAdapter::~CameraIspSOCAdapter()
{
}
void CameraIspSOCAdapter::setupPreview(int width_sensor,int height_sensor,int preview_w,int preview_h,int zoom_value)
{
unsigned int max_w = 0,max_h = 0, bufNum = 0, bufSize = 0;
CamEngineWindow_t dcWin;
dcWin.width = width_sensor*2;
dcWin.height = height_sensor;
dcWin.hOffset = 0;
dcWin.vOffset = 0;
//
rk_cam_total_info *pCamInfo = gCamInfos[mCamId].pcam_total_info;
if(((pCamInfo->mHardInfo.mSensorInfo.mPhy.info.cif.fmt == CamSys_Fmt_Raw_10b)
|| (pCamInfo->mHardInfo.mSensorInfo.mPhy.info.cif.fmt == CamSys_Fmt_Raw_12b))
&& (m_camDevice->getBusWidth() == ISI_BUSWIDTH_12BIT)){
if(pCamInfo->mHardInfo.mSensorInfo.mPhy.info.cif.cifio == CamSys_SensorBit0_CifBit0)
mIs10bit0To0 = true;
else
mIs10bit0To0 = false;
}else{
mIs10bit0To0 = false;
LOGE("%s:erro:board xml format is %d,sensor driver bus width is %d",__FUNCTION__,pCamInfo->mHardInfo.mSensorInfo.mPhy.info.cif.fmt,m_camDevice->getBusWidth());
}
m_camDevice->previewSetup_ex( dcWin, width_sensor*2, height_sensor,
CAMERIC_MI_DATAMODE_RAW12,CAMERIC_MI_DATASTORAGE_INTERLEAVED,(bool_t)false);
getSensorMaxRes(max_w,max_h);
bufSize = max_w*max_h*2*2;
bufNum = CONFIG_CAMERA_ISP_BUF_REQ_CNT;
m_camDevice->setIspBufferInfo(bufNum, bufSize);
}
//for soc camera test
int writeframe = 0;
extern "C" void arm_isp_yuyv_12bit_to_8bit (int src_w, int src_h,char *srcbuf,uint32_t ycSequence,bool is0bitto0bit){
int *srcint;
int i = 0;
unsigned int y_size = 0;
int *dst_buf,*debug_buf,*dst_y,*dst_uv;
unsigned int tmp = 0;
//for test
y_size = src_w*src_h;
srcint = ( int*)srcbuf;
dst_buf = ( int*)srcbuf;
debug_buf = ( int*)srcbuf;
#ifdef HAVE_ARM_NEON
/*for(i=0;i<16;i++) {
LOGE("before:0x%x,",*(debug_buf+i));
}*/
if(ycSequence == ISI_YCSEQ_CBYCRY){
int n = y_size;
if(!is0bitto0bit){
#if defined(TARGET_RK3368)
asm volatile (
" pld [%[src], %[src_stride], lsl #2] \n\t"
" cmp %[n], #8 \n\t"
" blt 5f \n\t"
"0: @ 16 pixel swap \n\t"
" vld2.32 {q0,q1} , [%[src]]! @ q0 = dat0 q1 = dat1 \n\t"
" vshr.u32 q0,q0,#8 @ now q0 -> y1 00 v0 00 \n\t"
" vshr.u32 q1,q1,#8 @ now q1 -> y0 00 u0 00 \n\t"
" vswp q0, q1 @ now q0 = q1 q1 = q0 \n\t"
" vuzp.u8 q0,q4 @ now d0 = y0u0.. d8 = 00.. \n\t"
" vuzp.u8 q1,q5 @ now d2 = y1v0.. d10 = 00.. \n\t"
" vst2.16 {d0,d2},[%[dst_buf]]!@ now q0 -> dst \n\t"
" sub %[n], %[n], #8 \n\t"
" cmp %[n], #8 \n\t"
" bge 0b \n\t"
"5: @ end \n\t"
: [dst_buf] "+r" (dst_buf),[src] "+r" (srcint), [n] "+r" (n) ,[tmp] "+r" (is0bitto0bit)
: [src_stride] "r" (y_size)
: "cc", "memory", "q0", "q1", "q2","q3"
);
#else
asm volatile (
" pld [%[src], %[src_stride], lsl #2] \n\t"
" cmp %[n], #8 \n\t"
" blt 5f \n\t"
"0: @ 16 pixel swap \n\t"
" vld2.32 {q0,q1} , [%[src]]! @ q0 = dat0 q1 = dat1 \n\t"
" vshr.u32 q0,q0,#6 @ now q0 -> y1 00 v0 00 \n\t"
" vshr.u32 q1,q1,#6 @ now q1 -> y0 00 u0 00 \n\t"
" vswp q0, q1 @ now q0 = q1 q1 = q0 \n\t"
" vuzp.u8 q0,q4 @ now d0 = y0u0.. d8 = 00.. \n\t"
" vuzp.u8 q1,q5 @ now d2 = y1v0.. d10 = 00.. \n\t"
" vst2.16 {d0,d2},[%[dst_buf]]!@ now q0 -> dst \n\t"
" sub %[n], %[n], #8 \n\t"
" cmp %[n], #8 \n\t"
" bge 0b \n\t"
"5: @ end \n\t"
: [dst_buf] "+r" (dst_buf),[src] "+r" (srcint), [n] "+r" (n) ,[tmp] "+r" (is0bitto0bit)
: [src_stride] "r" (y_size)
: "cc", "memory", "q0", "q1", "q2","q3"
);
#endif
}else{
asm volatile (
" pld [%[src], %[src_stride], lsl #2] \n\t"
" cmp %[n], #8 \n\t"
" blt 5f \n\t"
"0: @ 16 pixel swap \n\t"
" vld2.32 {q0,q1} , [%[src]]! @ q0 = dat0 q1 = dat1 \n\t"
" vshr.u32 q0,q0,#4 @ now q0 -> y1 00 v0 00 \n\t"
" vshr.u32 q1,q1,#4 @ now q1 -> y0 00 u0 00 \n\t"
" vswp q0, q1 @ now q0 = q1 q1 = q0 \n\t"
" vuzp.u8 q0,q4 @ now d0 = y0u0.. d8 = 00.. \n\t"
" vuzp.u8 q1,q5 @ now d2 = y1v0.. d10 = 00.. \n\t"
" vst2.16 {d0,d2},[%[dst_buf]]!@ now q0 -> dst \n\t"
" sub %[n], %[n], #8 \n\t"
" cmp %[n], #8 \n\t"
" bge 0b \n\t"
"5: @ end \n\t"
: [dst_buf] "+r" (dst_buf),[src] "+r" (srcint), [n] "+r" (n) ,[tmp] "+r" (is0bitto0bit)
: [src_stride] "r" (y_size)
: "cc", "memory", "q0", "q1", "q2","q3"
);
}
y_size = src_w * src_h;
srcint = ( int*)srcbuf;
dst_y = ( int*)(srcint+(y_size>>1));
dst_uv = ( int*)(dst_y+(y_size>>2));
for(i=0;i<(src_h);i++) {
int tmp_w = src_w,tmp = i % 2;
asm volatile (
" pld [%[src], %[src_stride], lsl #2] \n\t"
" cmp %[n], #16 \n\t"
" blt 5f \n\t"
"0: @ 16 pixel swap \n\t"
" vld2.8 {q0,q1} , [%[src]]! @ q0 = y0y1 q1 = u0v0 \n\t"
" vst1.16 {q0},[%[dst_y]]! @ now q0 -> dst \n\t"
" cmp %[tmp], #1 \n\t"
" bge 1f \n\t"
" vst1.16 {q1},[%[dst_uv]]! @ now q0 -> dst \n\t"
"1: @ get uv only when even row \n\t"
" sub %[n], %[n], #16 \n\t"
" cmp %[n], #16 \n\t"
" bge 0b \n\t"
"5: @ end \n\t"
: [dst_y] "+r" (dst_y),[dst_uv] "+r" (dst_uv),[src] "+r" (srcint), [n] "+r" (tmp_w) , [tmp] "+r" (tmp)
: [src_stride] "r" (src_w)
: "cc", "memory", "q0", "q1", "q2","q3"
);
}
/*y_size = src_w * src_h;
srcint = ( int*)srcbuf;
dst_y = ( int*)(srcint+(y_size>>1));
dst_uv = ( int*)(dst_y+(y_size>>2));
for(i=0;i<(y_size>>1);i++) {
*srcint++ = *dst_y++;
}*/
#if 0
//write file
srcint = ( int*)srcbuf;
if(writeframe++ == 10){
FILE* fp =NULL;
char filename[40];
filename[0] = 0x00;
sprintf(filename, "/data/raw8_%dx%d.raw",src_w,src_h);
fp = fopen(filename, "wb+");
if (fp > 0) {
fwrite((char*)srcint, 1,src_w*src_h,fp);
// fwrite((char*)uv_addr_vir, 1,width*height*3/2,fp); //yuv422
fclose(fp);
LOGD("Write success yuv data to %s",filename);
} else {
LOGE("Create %s failed(%d, %s)",filename,fp, strerror(errno));
}
}
#endif
}
#else
if(ycSequence == ISI_YCSEQ_CBYCRY){
#if defined(TARGET_RK3368)
for(i=0;i<(y_size>>1);i++) {
//dst : YUYV
*dst_buf++= (((*(srcint+1) >> 8) & 0x000000ff ) << 0)|
((((*(srcint+1) >> 24) & 0x000000ff)) << 8) |
(((*(srcint) >> 8) & 0x000000ff) << 16) |
((((*(srcint) >> 24) & 0x000000ff)) << 24);
srcint += 2;
}
#else
for(i=0;i<(y_size>>1);i++) {
//dst : YUYV
*dst_buf++= (((*(srcint+1) >> 6) & 0x000000ff ) << 0)| /* Y0 */
((((*(srcint+1) >> 22) & 0x000000ff)) << 8) | /* U*/
(((*(srcint) >> 6) & 0x000000ff) << 16) | /*Y1*/
((((*(srcint) >> 22) & 0x000000ff)) << 24); /*V*/
srcint += 2;
}
#endif
}
char *dstbuf1 = srcbuf+src_w*src_h*2;
arm_yuyv_to_nv12(src_w, src_h,srcbuf, dstbuf1);
#endif
}
void CameraIspSOCAdapter::bufferCb( MediaBuffer_t* pMediaBuffer )
{
static int writeoneframe = 0;
unsigned long y_addr,uv_addr;
void *y_addr_vir = NULL,*uv_addr_vir = NULL ;
int width = 0,height = 0;
int fmt = 0;
long phy_addr;
Mutex::Autolock lock(mLock);
// get & check buffer meta data
PicBufMetaData_t *pPicBufMetaData = (PicBufMetaData_t *)(pMediaBuffer->pMetaData);
HalHandle_t tmpHandle = m_camDevice->getHalHandle();
//
if(pPicBufMetaData->Type == PIC_BUF_TYPE_RAW16){
//get sensor fmt
//convert to yuyv 8 bit
fmt = V4L2_PIX_FMT_NV12;
y_addr = (unsigned long)(pPicBufMetaData->Data.raw.pBuffer );
width = pPicBufMetaData->Data.raw.PicWidthPixel >> 1;
height = pPicBufMetaData->Data.raw.PicHeightPixel;
HalMapMemory( tmpHandle, y_addr, 100, HAL_MAPMEM_READWRITE, &y_addr_vir );
m_camDevice->getYCSequence();
arm_isp_yuyv_12bit_to_8bit(width,height,(char*)y_addr_vir,m_camDevice->getYCSequence(),mIs10bit0To0);
y_addr += width*height*2;
if(gCamInfos[mCamId].pcam_total_info->mIsIommuEnabled)
phy_addr = -1; //fd mode can't get offset,so must be copied when pic taken,ugly now
else
phy_addr = y_addr;
y_addr_vir= (void*)((unsigned long)y_addr_vir + width*height*2);
}else{
LOGE("not support this type(%dx%d) ,just support yuv20 now",width,height);
return;
}
if ( pMediaBuffer->pNext != NULL )
{
MediaBufLockBuffer( (MediaBuffer_t*)pMediaBuffer->pNext );
}
#if 1
//need to send face detection ?
if(mRefEventNotifier->isNeedSendToFaceDetect()){
MediaBufLockBuffer( pMediaBuffer );
//new frames
FramInfo_s *tmpFrame=(FramInfo_s *)malloc(sizeof(FramInfo_s));
if(!tmpFrame){
MediaBufUnlockBuffer( pMediaBuffer );
return;
}
//add to vector
tmpFrame->frame_index = (long)tmpFrame;
tmpFrame->phy_addr = (long)phy_addr;
tmpFrame->frame_width = width;
tmpFrame->frame_height= height;
tmpFrame->vir_addr = (long)y_addr_vir;
tmpFrame->frame_fmt = fmt;
tmpFrame->used_flag = 4;
tmpFrame->zoom_value = mZoomVal;
{
Mutex::Autolock lock(mFrameArrayLock);
mFrameInfoArray.add((void*)tmpFrame,(void*)pMediaBuffer);
}
mRefEventNotifier->notifyNewFaceDecFrame(tmpFrame);
}
//need to display ?
if(mRefDisplayAdapter->isNeedSendToDisplay()){
MediaBufLockBuffer( pMediaBuffer );
//new frames
FramInfo_s *tmpFrame=(FramInfo_s *)malloc(sizeof(FramInfo_s));
if(!tmpFrame){
MediaBufUnlockBuffer( pMediaBuffer );
return;
}
//add to vector
tmpFrame->frame_index = (long)tmpFrame;
tmpFrame->phy_addr = (long)(phy_addr);
tmpFrame->frame_width = width;
tmpFrame->frame_height= height;
tmpFrame->vir_addr = (long)y_addr_vir;
tmpFrame->frame_fmt = fmt;
tmpFrame->zoom_value = mZoomVal;
tmpFrame->used_flag = 0;
{
Mutex::Autolock lock(mFrameArrayLock);
mFrameInfoArray.add((void*)tmpFrame,(void*)pMediaBuffer);
mDispFrameLeak++;
}
mRefDisplayAdapter->notifyNewFrame(tmpFrame);
}
//video enc ?
if(mRefEventNotifier->isNeedSendToVideo()){
MediaBufLockBuffer( pMediaBuffer );
//new frames
FramInfo_s *tmpFrame=(FramInfo_s *)malloc(sizeof(FramInfo_s));
if(!tmpFrame){
MediaBufUnlockBuffer( pMediaBuffer );
return;
}
//add to vector
tmpFrame->frame_index = (long)tmpFrame;
tmpFrame->phy_addr = (long)(phy_addr);
tmpFrame->frame_width = width;
tmpFrame->frame_height= height;
tmpFrame->vir_addr = (long)y_addr_vir;
tmpFrame->frame_fmt = fmt;
tmpFrame->zoom_value = mZoomVal;
tmpFrame->used_flag = 1;
{
Mutex::Autolock lock(mFrameArrayLock);
mFrameInfoArray.add((void*)tmpFrame,(void*)pMediaBuffer);
mVideoEncFrameLeak++;
}
mRefEventNotifier->notifyNewVideoFrame(tmpFrame);
}
//picture ?
if(mRefEventNotifier->isNeedSendToPicture()){
MediaBufLockBuffer( pMediaBuffer );
//new frames
FramInfo_s *tmpFrame=(FramInfo_s *)malloc(sizeof(FramInfo_s));
if(!tmpFrame){
MediaBufUnlockBuffer( pMediaBuffer );
return;
}
//add to vector
//fmt = V4L2_PIX_FMT_NV12;
tmpFrame->frame_index = (long)tmpFrame;
tmpFrame->phy_addr = (long)(phy_addr);
tmpFrame->frame_width = width;
tmpFrame->frame_height= height;
tmpFrame->vir_addr = (long)y_addr_vir;
tmpFrame->frame_fmt = fmt;
tmpFrame->zoom_value = mZoomVal;
tmpFrame->used_flag = 2;
tmpFrame->res = &mImgAllFovReq;
{
Mutex::Autolock lock(mFrameArrayLock);
mFrameInfoArray.add((void*)tmpFrame,(void*)pMediaBuffer);
mPicEncFrameLeak++;
}
mRefEventNotifier->notifyNewPicFrame(tmpFrame);
}
//preview data callback ?
if(mRefEventNotifier->isNeedSendToDataCB()){
MediaBufLockBuffer( pMediaBuffer );
//new frames
FramInfo_s *tmpFrame=(FramInfo_s *)malloc(sizeof(FramInfo_s));
if(!tmpFrame){
MediaBufUnlockBuffer( pMediaBuffer );
return;
}
//add to vector
tmpFrame->frame_index = (long)tmpFrame;
tmpFrame->phy_addr = (long)(phy_addr);
tmpFrame->frame_width = width;
tmpFrame->frame_height= height;
tmpFrame->vir_addr = (long)y_addr_vir;
tmpFrame->frame_fmt = fmt;
tmpFrame->zoom_value = mZoomVal;
tmpFrame->used_flag = 3;
{
Mutex::Autolock lock(mFrameArrayLock);
mFrameInfoArray.add((void*)tmpFrame,(void*)pMediaBuffer);
mPreviewCBFrameLeak++;
}
mRefEventNotifier->notifyNewPreviewCbFrame(tmpFrame);
}
#endif
}
}