#include "CameraDebug.h" #if DBG_V4L2_CAMERA #define LOG_NDEBUG 0 #endif #define LOG_TAG "V4L2CameraDevice" #include #include #include #ifdef USE_MP_CONVERT #include #endif #include "V4L2CameraDevice2.h" #include "CallbackNotifier.h" #include "PreviewWindow.h" #include "CameraHardware2.h" #include #include #include "math.h" //#include "memory/memoryAdapter.h" //#include "memory/sc_interface.h" #ifdef USE_SUNXI_CAMERA_H #include #else //#include #endif #ifdef USE_CSI_VIN_DRIVER #include #endif #define CHECK_NO_ERROR(a) \ if (a != NO_ERROR) { \ if (mCameraFd != NULL) { \ ALOGE("Camaera[%d]CHECK_NO_ERROR",mCameraId); \ close(mCameraFd); \ mCameraFd = NULL; \ } \ return EINVAL; \ } #define RAW_DATA_INTERFACE 104 #define RAW_DATA_SYSTEM 105 #define RAW_DATA_FORMAT 106 #define RAW_DATA_PIXELFORMAT 107 #define RAW_DATA_ROW 108 #define RAW_DATA_COLUMN 109 #define RAW_DATA_CH0_INDEX 110 #define RAW_DATA_CH1_INDEX 111 #define RAW_DATA_CH2_INDEX 112 #define RAW_DATA_CH3_INDEX 113 #define RAW_DATA_CH0_STATUS 114 #define RAW_DATA_CH1_STATUS 115 #define RAW_DATA_CH2_STATUS 116 #define RAW_DATA_CH3_STATUS 117 extern void PreviewCnr(unsigned int snr_level, unsigned int gain, int width, int height, char *src, char *dst); extern void ColorDenoise(unsigned char *dst_plane, unsigned char *src_plane, int width, int height, int threshold); extern int Sharpen(unsigned char * image, int min_val, int level, int width, int height); namespace android { // defined in HALCameraFactory.cpp extern void getCallingProcessName(char *name); static int SceneNotifyCallback(int cmd, void* data, int* ret,void* user) { V4L2CameraDevice* dev = (V4L2CameraDevice*)user; switch(cmd) { case SCENE_NOTIFY_CMD_GET_AE_STATE: ALOGV("SCENE_NOTIFY_CMD_GET_AE_STATE"); *ret = dev->getAeStat((struct isp_stat_buf *)data); break; case SCENE_NOTIFY_CMD_GET_HIST_STATE: ALOGV("SCENE_NOTIFY_CMD_GET_HIST_STATE"); *ret = dev->getHistStat((struct isp_stat_buf * )data); break; case SCENE_NOTIFY_CMD_SET_3A_LOCK: ALOGV("SCENE_NOTIFY_CMD_SET_3A_LOCK: %ld",(long)data); *ret = dev->set3ALock((long)data); break; case SCENE_NOTIFY_CMD_SET_HDR_SETTING: ALOGV("SENE_NOTIFY_CMD_SET_HDR_SETTING"); *ret = dev->setHDRMode(data); break; case SCENE_NOTIFY_CMD_GET_HDR_FRAME_COUNT: //*ret = dev->getHDRFrameCnt((int*)data); int cnt; cnt = dev->getHDRFrameCnt(); *(int *)data = cnt; *ret = 0; ALOGD("SCENE_NOTIFY_CMD_GET_HDR_FRAME_COUNT: %ld",cnt); break; default: break; } return 0; } static void calculateCrop(Rect * rect, int new_zoom, int max_zoom, int width, int height) { if (max_zoom == 0) { rect->left = 0; rect->top = 0; rect->right = width -1; rect->bottom = height -1; } else { int new_ratio = (new_zoom * 2 * 100 / max_zoom + 100); rect->left = (width - (width * 100) / new_ratio)/2; rect->top = (height - (height * 100) / new_ratio)/2; rect->right = rect->left + (width * 100) / new_ratio -1; rect->bottom = rect->top + (height * 100) / new_ratio - 1; } // ALOGD("crop: [%d, %d, %d, %d]", rect->left, rect->top, rect->right, rect->bottom); } static void YUYVToNV12(const void* yuyv, void *nv12, int width, int height) { uint8_t* Y = (uint8_t*)nv12; uint8_t* UV = (uint8_t*)Y + width * height; for(int i = 0; i < height; i += 2) { for (int j = 0; j < width; j++) { *(uint8_t*)((uint8_t*)Y + i * width + j) = *(uint8_t*)((uint8_t*)yuyv + i * width * 2 + j * 2); *(uint8_t*)((uint8_t*)Y + (i + 1) * width + j) = *(uint8_t*)((uint8_t*)yuyv + (i + 1) * width * 2 + j * 2); *(uint8_t*)((uint8_t*)UV + ((i * width) >> 1) + j) = *(uint8_t*)((uint8_t*)yuyv + i * width * 2 + j * 2 + 1); } } } static void YUYVToNV21(const void* yuyv, void *nv21, int width, int height) { uint8_t* Y = (uint8_t*)nv21; uint8_t* VU = (uint8_t*)Y + width * height; for(int i = 0; i < height; i += 2) { for (int j = 0; j < width; j++) { *(uint8_t*)((uint8_t*)Y + i * width + j) = *(uint8_t*)((uint8_t*)yuyv + i * width * 2 + j * 2); *(uint8_t*)((uint8_t*)Y + (i + 1) * width + j) = *(uint8_t*)((uint8_t*)yuyv + (i + 1) * width * 2 + j * 2); if (j % 2) { if (j < width - 1) { *(uint8_t*)((uint8_t*)VU + ((i * width) >> 1) + j) = *(uint8_t*)((uint8_t*)yuyv + i * width * 2 + (j + 1) * 2 + 1); } } else { if (j > 1) { *(uint8_t*)((uint8_t*)VU + ((i * width) >> 1) + j) = *(uint8_t*)((uint8_t*)yuyv + i * width * 2 + (j - 1) * 2 + 1); } } } } } #ifdef USE_MP_CONVERT void V4L2CameraDevice::YUYVToYUV420C(const void* yuyv, void *yuv420, int width, int height) { g2d_blt blit_para; int err; blit_para.src_image.addr[0] = (unsigned long)yuyv; blit_para.src_image.addr[1] = (unsigned long)yuyv + width * height; blit_para.src_image.w = width; /* src buffer width in pixel units */ blit_para.src_image.h = height; /* src buffer height in pixel units */ blit_para.src_image.format = G2D_FMT_IYUV422; blit_para.src_image.pixel_seq = G2D_SEQ_NORMAL; /* not use now */ blit_para.src_rect.x = 0; /* src rect->x in pixel */ blit_para.src_rect.y = 0; /* src rect->y in pixel */ blit_para.src_rect.w = width; /* src rect->w in pixel */ blit_para.src_rect.h = height; /* src rect->h in pixel */ blit_para.dst_image.addr[0] = (unsigned long)yuv420; blit_para.dst_image.addr[1] = (unsigned long)yuv420 + width * height; blit_para.dst_image.w = width; /* dst buffer width in pixel units */ blit_para.dst_image.h = height; /* dst buffer height in pixel units */ blit_para.dst_image.format = G2D_FMT_PYUV420UVC; blit_para.dst_image.pixel_seq = (mVideoFormat == V4L2_PIX_FMT_NV12) ? G2D_SEQ_NORMAL : G2D_SEQ_VUVU; /* not use now */ blit_para.dst_x = 0; /* dst rect->x in pixel */ blit_para.dst_y = 0; /* dst rect->y in pixel */ blit_para.color = 0xff; /* fix me*/ blit_para.alpha = 0xff; /* globe alpha */ blit_para.flag = G2D_BLT_NONE; // G2D_BLT_FLIP_HORIZONTAL; err = ioctl(mG2DHandle, G2D_CMD_BITBLT, (unsigned long)&blit_para); if(err < 0) { ALOGD("ioctl, G2D_CMD_BITBLT failed"); return; } } void V4L2CameraDevice::NV21ToYV12(const void* nv21, void *yv12, int width, int height) { g2d_blt blit_para; int err; int u, v; if (mVideoFormat == V4L2_PIX_FMT_NV21) { u = 1; v = 2; } else { u = 2; v = 1; } blit_para.src_image.addr[0] = (unsigned long)nv21; blit_para.src_image.addr[1] = (unsigned long)nv21 + width * height; blit_para.src_image.w = width; /* src buffer width in pixel units */ blit_para.src_image.h = height; /* src buffer height in pixel units */ blit_para.src_image.format = G2D_FMT_PYUV420UVC; blit_para.src_image.pixel_seq = G2D_SEQ_NORMAL;//G2D_SEQ_VUVU; /* */ blit_para.src_rect.x = 0; /* src rect->x in pixel */ blit_para.src_rect.y = 0; /* src rect->y in pixel */ blit_para.src_rect.w = width; /* src rect->w in pixel */ blit_para.src_rect.h = height; /* src rect->h in pixel */ blit_para.dst_image.addr[0] = (unsigned long)yv12; // y blit_para.dst_image.addr[u] = (unsigned long)yv12 + width * height; // v blit_para.dst_image.addr[v] = (unsigned long)yv12 + width * height * 5 / 4; // u blit_para.dst_image.w = width; /* dst buffer width in pixel units */ blit_para.dst_image.h = height; /* dst buffer height in pixel units */ blit_para.dst_image.format = G2D_FMT_PYUV420; blit_para.dst_image.pixel_seq = G2D_SEQ_NORMAL; /* not use now */ blit_para.dst_x = 0; /* dst rect->x in pixel */ blit_para.dst_y = 0; /* dst rect->y in pixel */ blit_para.color = 0xff; /* fix me*/ blit_para.alpha = 0xff; /* globe alpha */ blit_para.flag = G2D_BLT_NONE; err = ioctl(mG2DHandle , G2D_CMD_BITBLT, (unsigned long)&blit_para); if(err < 0) { ALOGD("NV21ToYV12 ioctl, G2D_CMD_BITBLT failed"); return; } } #endif DBG_TIME_AVG_BEGIN(TAG_CONTINUOUS_PICTURE); void V4L2CameraDevice::showformat(int format,char *str) { switch(format){ case V4L2_PIX_FMT_YUYV: ALOGD("Camera[%d] The %s foramt is V4L2_PIX_FMT_YUYV",mCameraId,str); break; case V4L2_PIX_FMT_MJPEG: ALOGD("Camera[%d] The %s foramt is V4L2_PIX_FMT_MJPEG",mCameraId,str); break; case V4L2_PIX_FMT_YVU420: ALOGD("Camera[%d] The %s foramt is V4L2_PIX_FMT_YVU420",mCameraId,str); break; case V4L2_PIX_FMT_NV12: ALOGD("Camera[%d] The %s foramt is V4L2_PIX_FMT_NV12",mCameraId,str); break; case V4L2_PIX_FMT_NV21: ALOGD("Camera[%d] The %s foramt is V4L2_PIX_FMT_NV21",mCameraId,str); break; case V4L2_PIX_FMT_H264: ALOGD("Camera[%d] The %s foramt is V4L2_PIX_FMT_H264",mCameraId,str); break; default: ALOGD("Camera[%d] The %s format can't be showed",mCameraId,str); } } V4L2CameraDevice::V4L2CameraDevice(CameraHardware* camera_hal, PreviewWindow * preview_window, CallbackNotifier * cb) : mCameraHardware(camera_hal), mPreviewWindow(preview_window), mCallbackNotifier(cb), mCameraDeviceState(STATE_CONSTRUCTED), mCaptureThreadState(CAPTURE_STATE_NULL), mPreviewThreadState(PREVIEW_STATE_NULL), mCameraFd(0), mCameraId(0), mCameraType(CAMERA_TYPE_CSI), mTakePictureState(TAKE_PICTURE_NULL), mIsPicCopy(false), mFrameWidth(0), mFrameHeight(0), mThumbWidth(0), mThumbHeight(0), mCurFrameTimestamp(0), mBufferCnt(NB_BUFFER), mUseHwEncoder(false), mNewZoom(0), mLastZoom(-1), mMaxZoom(0xffffffff), mCaptureFormat(V4L2_PIX_FMT_NV21), mVideoFormat(V4L2_PIX_FMT_NV21), mFrameRate(30), mStartSmartTimeout(false) #ifdef USE_MP_CONVERT ,mG2DHandle(0) #endif ,mCurrentV4l2buf(NULL) ,mCanBeDisconnected(false) ,mContinuousPictureStarted(false) ,mContinuousPictureCnt(0) ,mContinuousPictureMax(0) ,mContinuousPictureStartTime(0) ,mContinuousPictureLast(0) ,mContinuousPictureAfter(0) ,mSmartPictureDone(true) ,mFaceDectectLast(0) ,mFaceDectectAfter(0) ,mPreviewLast(0) ,mPreviewAfter(0) ,mVideoHint(false) ,mCurAvailBufferCnt(0) ,mStatisicsIndex(0) ,mNeedHalfFrameRate(false) ,mIsThumbUsedForVideo(false) ,mVideoWidth(640) ,mVideoHeight(480) ,mSceneMode(NULL) ,mFlashMode(V4L2_FLASH_LED_MODE_NONE) ,mZoomRatio(100) ,mExposureBias(0) ,mMemOpsS(NULL) ,releaseIndex(-1) #ifdef CAMERA_MANAGER_ENABLE ,mCameraManager(NULL) #endif ,nPlanes(0) #ifdef USE_DEINTERLACE_HW ,mDiProcess(NULL) ,mPreFrameIndex(-1) ,mPrePreFrameIndex(-1) ,mEnableYUV422(-1) #endif ,mAWIspApi(NULL) ,mIspId(-1) #ifdef CAMERA_DECODE ,mCameraDecoder(NULL) #endif ,mPicCnt(0) ,mOrgTime(0) ,mDebugLogCnt(0) { ALOGV("V4L2CameraDevice construct"); memset(&mMapMem,0,sizeof(mMapMem)); memset(&mVideoBuffer,0,sizeof(mVideoBuffer)); memset(&mHalCameraInfo, 0, sizeof(mHalCameraInfo)); memset(&mRectCrop, 0, sizeof(Rect)); memset(&mTakePictureFlag,0,sizeof(mTakePictureFlag)); memset(&mPicBuffer,0,sizeof(mPicBuffer)); #ifdef USE_DEINTERLACE_HW memset(&mDiOutPutBuffer, 0, sizeof(bufferManagerQD_t)); for(int i = 0; i < NB_BUFFER; i++) { memset(&mV4l2DiBuf[i], 0, sizeof(V4L2BUF_t)); } #endif mMemOpsS = MemCamAdapterGetOpsS(); mMemOpsS->open_cam(); // init preview buffer queue OSAL_QueueCreate(&mQueueBufferPreview, NB_BUFFER); OSAL_QueueCreate(&mQueueBufferPicture, 2); pthread_mutex_init(&mCaptureMutex, NULL); pthread_cond_init(&mCaptureCond, NULL); mCaptureThreadState = CAPTURE_STATE_PAUSED; pthread_mutex_init(&mPreviewMutex, NULL); pthread_cond_init(&mPreviewCond, NULL); pthread_mutex_init(&mPreviewSyncMutex, NULL); pthread_cond_init(&mPreviewSyncCond, NULL); mPreviewThreadState = PREVIEW_STATE_STARTED; pthread_mutex_init(&mPictureMutex, NULL); pthread_cond_init(&mPictureCond, NULL); pthread_mutex_init(&mConnectMutex, NULL); pthread_cond_init(&mConnectCond, NULL); pthread_mutex_init(&mContinuousPictureMutex, NULL); pthread_cond_init(&mContinuousPictureCond, NULL); pthread_mutex_init(&mSmartPictureMutex, NULL); pthread_cond_init(&mSmartPictureCond, NULL); // init capture thread mCaptureThread = new DoCaptureThread(this); mCaptureThread->startThread(); // init preview thread mPreviewThread = new DoPreviewThread(this); mPreviewThread->startThread(); // init picture thread mPictureThread = new DoPictureThread(this); mPictureThread->startThread(); // init continuous picture thread //disnable // mContinuousPictureThread = new DoContinuousPictureThread(this); // mContinuousPictureThread->startThread(); // mSmartPictureThread = new DoSmartPictureThread(this); // mSmartPictureThread->startThread(); } V4L2CameraDevice::~V4L2CameraDevice() { ALOGD("Camera[%d]V4L2CameraDevice disconstruct",mCameraId); if (mCaptureThread != NULL) { mCaptureThread->stopThread(); pthread_cond_signal(&mCaptureCond); mCaptureThread.clear(); mCaptureThread = 0; } if (mPreviewThread != NULL) { mPreviewThread->stopThread(); pthread_cond_signal(&mPreviewCond); mPreviewThread.clear(); mPreviewThread = 0; } if (mPictureThread != NULL) { mPictureThread->stopThread(); pthread_cond_signal(&mPictureCond); mPictureThread.clear(); mPictureThread = 0; } if (mContinuousPictureThread != NULL) { mContinuousPictureThread->stopThread(); pthread_cond_signal(&mContinuousPictureCond); mContinuousPictureThread.clear(); mContinuousPictureThread = 0; } if (mSmartPictureThread != NULL) { mSmartPictureThread->stopThread(); pthread_cond_signal(&mSmartPictureCond); mSmartPictureThread.clear(); mSmartPictureThread = 0; } if (mMemOpsS != NULL) { mMemOpsS->close_cam(); } pthread_mutex_destroy(&mCaptureMutex); pthread_cond_destroy(&mCaptureCond); pthread_mutex_destroy(&mPreviewMutex); pthread_cond_destroy(&mPreviewCond); pthread_mutex_destroy(&mPictureMutex); pthread_cond_destroy(&mPictureCond); pthread_mutex_destroy(&mConnectMutex); pthread_cond_destroy(&mConnectCond); pthread_mutex_destroy(&mContinuousPictureMutex); pthread_cond_destroy(&mContinuousPictureCond); pthread_mutex_destroy(&mSmartPictureMutex); pthread_cond_destroy(&mSmartPictureCond); OSAL_QueueTerminate(&mQueueBufferPreview); OSAL_QueueTerminate(&mQueueBufferPicture); } /**************************************************************************** * V4L2CameraDevice interface implementation. ***************************************************************************/ status_t V4L2CameraDevice::connectDevice(HALCameraInfo * halInfo) { Mutex::Autolock locker(&mObjectLock); if (isConnected()) { ALOGW("%s: camera device is already connected.", __FUNCTION__); return NO_ERROR; } memcpy((void*)&mHalCameraInfo, (void*)halInfo, sizeof(HALCameraInfo)); ALOGD("Camera[%d]F:%s,L:%d" ,mHalCameraInfo.device_id,__FUNCTION__, __LINE__); // open v4l2 camera device int ret = openCameraDev(halInfo); if (ret != OK) { ALOGE("Camera[%d]open Camera failed! F:%s, L:%d",mCameraId, __FUNCTION__, __LINE__); return ret; } if (mCameraType == CAMERA_TYPE_CSI) { mSensor_Type = V4L2_SENSOR_TYPE_YUV; switch((v4l2_sensor_type)getSensorType()) { case V4L2_SENSOR_TYPE_YUV: ALOGD("Camera[%d]the sensor is YUV sensor",mCameraId); mSensor_Type = V4L2_SENSOR_TYPE_YUV; break; case V4L2_SENSOR_TYPE_RAW: ALOGD("Camera[%d]the sensor is RAW sensor",mCameraId); mSensor_Type = V4L2_SENSOR_TYPE_RAW; mAWIspApi = new AWIspApi(); break; default: ALOGE("Camera[%d]get the sensor type failed",mCameraId); goto END_ERROR; } //struct isp_exif_attribute exif_attri; //getExifInfo(&exif_attri); //mCameraHardware->setExifInfo(exif_attri); } #ifdef USE_MP_CONVERT if (mCameraType == CAMERA_TYPE_UVC) { // open MP driver mG2DHandle = open("/dev/g2d", O_RDWR, 0); if (mG2DHandle < 0) { ALOGE("Camera[%d]open /dev/g2d failed",mCameraId); goto END_ERROR; } ALOGD("Camera[%d]open /dev/g2d OK",mCameraId); } #endif ret = mMemOpsS->open_cam(); if (ret < 0) { ALOGE("Camera[%d]ion_alloc_open failed",mCameraId); goto END_ERROR; } ALOGD("Camera[%d]ion_alloc_open ok",mCameraId); #ifdef USE_DEINTERLACE_HW if (mCameraType == CAMERA_TYPE_TVIN_NTSC || mCameraType == CAMERA_TYPE_TVIN_PAL || mCameraType == CAMERA_TYPE_TVIN_YPBPR) { mDiProcess = new DiProcess(); if (mDiProcess == NULL) { ALOGD("new Diprocess failed"); goto END_ERROR; } ALOGD("new Diprocess OK"); ret = mDiProcess->init(); if (ret != NO_ERROR) { ALOGD("Diprocess init failed"); goto END_ERROR; } } for(int i = 0; i < NB_BUFFER; i++) { memset(&mV4l2DiBuf[i], 0, sizeof(V4L2BUF_t)); } #endif /* There is a device to connect to. */ mCameraDeviceState = STATE_CONNECTED; return NO_ERROR; END_ERROR: if (mCameraFd != NULL) { close(mCameraFd); mCameraFd = NULL; } #ifdef USE_MP_CONVERT if(mG2DHandle != NULL) { close(mG2DHandle); mG2DHandle = NULL; } #endif #ifdef USE_DEINTERLACE_HW if (mDiProcess != NULL) { delete mDiProcess; mDiProcess = NULL; } #endif if (mAWIspApi != NULL) { delete mAWIspApi; mAWIspApi = NULL; } return UNKNOWN_ERROR; } status_t V4L2CameraDevice::disconnectDevice() { ALOGD("Camera[%d] %s enter",mCameraId,__FUNCTION__); Mutex::Autolock locker(&mObjectLock); if (!isConnected()) { ALOGW("Camera[%d]%s: camera device is already disconnected.", mCameraId,__FUNCTION__); return NO_ERROR; } if (isStarted()) { ALOGE("Camera[%d]%s: Cannot disconnect from the started device.",mCameraId, __FUNCTION__); return -EINVAL; } // close v4l2 camera device closeCameraDev(); #ifdef USE_MP_CONVERT if(mG2DHandle != NULL) { close(mG2DHandle); mG2DHandle = NULL; } #endif #ifdef USE_DEINTERLACE_HW if (mDiProcess != NULL) { delete mDiProcess; mDiProcess = NULL; } #endif mMemOpsS->close_cam(); /* There is no device to disconnect from. */ mCameraDeviceState = STATE_CONSTRUCTED; #ifdef USE_ISP if (mAWIspApi != NULL) { delete mAWIspApi; mAWIspApi = NULL; } #endif return NO_ERROR; } status_t V4L2CameraDevice::startDevice(int width, int height, uint32_t pix_fmt, bool video_hint) { ALOGD("Camera[%d]%s, wxh: %dx%d, fmt: %d",mCameraId, __FUNCTION__, width, height, pix_fmt); Mutex::Autolock locker(&mObjectLock); if (!isConnected()) { ALOGE("Camera[%d] %s: camera device is not connected.",mCameraId, __FUNCTION__); return EINVAL; } if (isStarted()) { ALOGD("Camera[%d] %s: camera device is already started.", mCameraId,__FUNCTION__); return EINVAL; } // VE encoder need this format mVideoFormat = pix_fmt; #ifdef USE_DEINTERLACE_HW if ((mCameraType == CAMERA_TYPE_TVIN_NTSC || mCameraType == CAMERA_TYPE_TVIN_PAL || mCameraType == CAMERA_TYPE_TVIN_YPBPR) && (width == 720) && (mEnableYUV422 > 0)) { if ((mCameraManager == NULL) || ((mCameraManager != NULL) && !mCameraManager->isOviewEnable())) { mVideoFormat = V4L2_PIX_FMT_NV61; mCaptureFormat = V4L2_PIX_FMT_NV61; ALOGD("F:%s, L:%d, CaptureFormat set to V4L2_PIX_FMT_NV61", __FUNCTION__, __LINE__); } } else if ((mCameraType == CAMERA_TYPE_TVIN_NTSC || mCameraType == CAMERA_TYPE_TVIN_PAL || mCameraType == CAMERA_TYPE_TVIN_YPBPR)){ mCaptureFormat = pix_fmt; } #endif mCurrentV4l2buf = NULL; mVideoHint = video_hint; mCanBeDisconnected = false; #ifdef USE_DEINTERLACE_HW mPreFrameIndex = -1; mPrePreFrameIndex = -1; #endif // set capture mode and fps // CHECK_NO_ERROR(v4l2setCaptureParams()); // do not check this error v4l2setCaptureParams(); // set v4l2 device parameters, it maybe change the value of mFrameWidth and mFrameHeight. CHECK_NO_ERROR(v4l2SetVideoParams(width, height, mVideoFormat)); // v4l2 request buffers int buf_cnt = (mTakePictureState == TAKE_PICTURE_NORMAL) ? 1 : NB_BUFFER; CHECK_NO_ERROR(v4l2ReqBufs(&buf_cnt)); mBufferCnt = buf_cnt; mCurAvailBufferCnt = mBufferCnt; // v4l2 query buffers CHECK_NO_ERROR(v4l2QueryBuf()); #ifdef CAMERA_MANAGER_ENABLE if((mCameraManager != NULL) && mCameraManager->isOviewEnable()) { mCameraManager->setFrameSize(mHalCameraInfo.device_id,mFrameWidth,mFrameHeight); ALOGD("Camera[%d]CameraManager F:%s,L:%d",mCameraId,__FUNCTION__,__LINE__); } #endif // stream on the v4l2 device CHECK_NO_ERROR(v4l2StartStreaming()); if ((mCameraType == CAMERA_TYPE_CSI) && (mSensor_Type == V4L2_SENSOR_TYPE_RAW)) { mIspId = -1; mIspId = mAWIspApi->awIspGetIspId(mHalCameraInfo.device_id); if (mIspId >= 0) { mAWIspApi->awIspStart(mIspId); } } mContinuousPictureAfter = 1000000 / 10; mFaceDectectAfter = 1000000 / 15; mPreviewAfter = 1000000 / 24; set3ALock(0); #ifdef CAMERA_DECODE if (mCaptureFormat == V4L2_PIX_FMT_MJPEG) { mCameraDecoder = new CameraDecoder; mCameraDecoder->DecorderOpen(PIXEL_FORMAT_NV21, VIDEO_CODEC_FORMAT_MJPEG, mFrameRate, mFrameWidth, mFrameHeight); } else if (mCaptureFormat == V4L2_PIX_FMT_H264) { mCameraDecoder = new CameraDecoder; mCameraDecoder->DecorderOpen(PIXEL_FORMAT_NV21, VIDEO_CODEC_FORMAT_H264, mFrameRate, mFrameWidth, mFrameHeight); } #endif mCameraDeviceState = STATE_STARTED; ALOGD("Camera[%d] %s end",mCameraId,__FUNCTION__); return NO_ERROR; } status_t V4L2CameraDevice::stopDevice() { ALOGD("Camera[%d] %s enter",mCameraId,__FUNCTION__); pthread_mutex_lock(&mConnectMutex); if (!mCanBeDisconnected) { ALOGW("Camera[%d]wait until capture thread pause or exit",mCameraId); pthread_cond_wait(&mConnectCond, &mConnectMutex); } pthread_mutex_unlock(&mConnectMutex); Mutex::Autolock locker(&mObjectLock); if (!isStarted()) { ALOGW("Camera[%d]%s: camera device is not started.",mCameraId, __FUNCTION__); return NO_ERROR; } // v4l2 device stop stream v4l2StopStreaming(); if ((mCameraType == CAMERA_TYPE_CSI) && (mSensor_Type == V4L2_SENSOR_TYPE_RAW) && (mIspId >= 0)) { mAWIspApi->awIspStop(mIspId); } // v4l2 device unmap buffers v4l2UnmapBuf(); for(int i = 0; i < NB_BUFFER; i++) { memset(&mV4l2buf[i], 0, sizeof(V4L2BUF_t)); } mCameraDeviceState = STATE_CONNECTED; mLastZoom = -1; mCurrentV4l2buf = NULL; int buf_cnt = 0; CHECK_NO_ERROR(v4l2ReqBufs(&buf_cnt)); #ifdef AW_ADAS_MODULE mCurV4l2Buf = NULL; #endif #ifdef CAMERA_DECODE if ((mCaptureFormat == V4L2_PIX_FMT_MJPEG) || (mCaptureFormat == V4L2_PIX_FMT_H264)) { mCameraDecoder->DecorderClose(); delete mCameraDecoder; mCameraDecoder = NULL; } #endif #ifdef USE_DEINTERLACE_HW mPreFrameIndex = -1; mPrePreFrameIndex = -1; mEnableYUV422 = -1; #endif ALOGD("Camera[%d] %s end",mCameraId,__FUNCTION__); return NO_ERROR; } status_t V4L2CameraDevice::startDeliveringFrames() { ALOGD("Camera[%d] %s enter",mCameraId,__FUNCTION__); pthread_mutex_lock(&mCaptureMutex); if (mCaptureThreadState == CAPTURE_STATE_NULL) { ALOGE("Camera[%d]error state of capture thread, %s",mCameraId, __FUNCTION__); pthread_mutex_unlock(&mCaptureMutex); return EINVAL; } if (mCaptureThreadState == CAPTURE_STATE_STARTED) { ALOGW("Camera[%d]capture thread has already started",mCameraId); pthread_mutex_unlock(&mCaptureMutex); return NO_ERROR; } // singal to start capture thread mCaptureThreadState = CAPTURE_STATE_STARTED; pthread_cond_signal(&mCaptureCond); pthread_mutex_unlock(&mCaptureMutex); pthread_mutex_lock(&mPreviewSyncMutex); mPreviewThreadState = PREVIEW_STATE_STARTED; ALOGD("Camera[%d]set mPreviewThreadState to %d\n",mCameraId,mPreviewThreadState); pthread_cond_signal(&mPreviewSyncCond); pthread_mutex_unlock(&mPreviewSyncMutex); return NO_ERROR; } status_t V4L2CameraDevice::stopDeliveringFrames() { ALOGD("Camera[%d] %s enter",mCameraId,__FUNCTION__); pthread_mutex_lock(&mCaptureMutex); if (mCaptureThreadState == CAPTURE_STATE_NULL) { ALOGE("Camera[%d]error state of capture thread, %s", mCameraId,__FUNCTION__); pthread_mutex_unlock(&mCaptureMutex); return EINVAL; } if (mCaptureThreadState == CAPTURE_STATE_PAUSED) { ALOGW("Camera[%d]capture thread has already paused",mCameraId); pthread_mutex_unlock(&mCaptureMutex); return NO_ERROR; } mCaptureThreadState = CAPTURE_STATE_PAUSED; pthread_mutex_unlock(&mCaptureMutex); return NO_ERROR; } /**************************************************************************** * Worker thread management. ***************************************************************************/ int V4L2CameraDevice::v4l2WaitCameraReady() { fd_set fds; struct timeval tv; int r; int availBufferCntBak = 0; FD_ZERO(&fds); FD_SET(mCameraFd, &fds); /* Timeout */ tv.tv_sec = 2; tv.tv_usec = 0; availBufferCntBak = mCurAvailBufferCnt; r = select(mCameraFd + 1, &fds, NULL, NULL, &tv); if (r == -1) { ALOGE("Camera[%d] bufferCntBak=%d,curBufferCnt=%d,select err=%s", mCameraId,mCurAvailBufferCnt,availBufferCntBak,strerror(errno)); return -1; } else if (r == 0) { ALOGE("Camera[%d] bufferCntBak=%d,curBufferCnt=%d,select timeout", mCameraId,mCurAvailBufferCnt,availBufferCntBak); return -1; } return 0; } void V4L2CameraDevice::singalDisconnect() { pthread_mutex_lock(&mConnectMutex); mCanBeDisconnected = true; pthread_cond_signal(&mConnectCond); pthread_mutex_unlock(&mConnectMutex); } int V4L2CameraDevice::testFrameRate() { mPicCnt++; if (mPicCnt >= 1500) { timeval cur_time; gettimeofday(&cur_time, NULL); const uint64_t now_time = cur_time.tv_sec * 1000000LL + cur_time.tv_usec; int framerate = mPicCnt * 1000 / ((now_time - mOrgTime) / 1000); if (framerate) { if (mCameraType == CAMERA_TYPE_UVC) { ALOGD("Camera[%d]CAMERA_TYPE_UVC framerate = %dfps@%dx%d",mCameraId, framerate, mFrameWidth, mFrameHeight); } else if (mCameraType == CAMERA_TYPE_CSI) { ALOGD("Camera[%d]CAMERA_TYPE_CSI framerate = %dfps@%dx%d",mCameraId, framerate, mFrameWidth, mFrameHeight); } else { ALOGD("Camera[%d]other type framerate = %dfps@%dx%d",mCameraId, framerate, mFrameWidth, mFrameHeight); } } mOrgTime = now_time; mPicCnt = 0; } return 0; } bool V4L2CameraDevice::captureThread() { pthread_mutex_lock(&mCaptureMutex); // stop capture if (mCaptureThreadState == CAPTURE_STATE_PAUSED) { singalDisconnect(); // wait for signal of starting to capture a frame ALOGD("Camera[%d] capture thread paused",mCameraId); pthread_cond_wait(&mCaptureCond, &mCaptureMutex); } // thread exit if (mCaptureThreadState == CAPTURE_STATE_EXIT) { singalDisconnect(); ALOGD("Camaera[%d] capture thread exit",mCameraId); pthread_mutex_unlock(&mCaptureMutex); return false; } pthread_mutex_unlock(&mCaptureMutex); int ret = v4l2WaitCameraReady(); //ALOGD("FUNC:%s, CamID=%d, mCurAvailBufferCnt =%d", __FUNCTION__, mHalCameraInfo.device_id,mCurAvailBufferCnt); pthread_mutex_lock(&mCaptureMutex); // stop capture or thread exit if (mCaptureThreadState == CAPTURE_STATE_PAUSED || mCaptureThreadState == CAPTURE_STATE_EXIT) { singalDisconnect(); ALOGW("Camera[%d]should stop capture now",mCameraId); pthread_mutex_unlock(&mCaptureMutex); return __LINE__; } if (ret != 0) { ALOGW("Camera[%d] wait v4l2 buffer time out",mCameraId); ALOGW("Camera[%d] mCurAvailBufferCnt has %d",mCameraId, mCurAvailBufferCnt); pthread_mutex_unlock(&mCaptureMutex); recoveryPreviewFrame(); return __LINE__; } // get one video frame struct v4l2_buffer buf; memset(&buf, 0, sizeof(v4l2_buffer)); ret = getPreviewFrame(&buf); if (ret != OK) { pthread_mutex_unlock(&mCaptureMutex); usleep(10000); return ret; } //modify for cts by clx mCurAvailBufferCnt--; if (mCurAvailBufferCnt <= 2) { mNeedHalfFrameRate = true; mStatisicsIndex = 0; } else if (mNeedHalfFrameRate) { mStatisicsIndex++; if (mStatisicsIndex >= STATISICS_CNT) { mNeedHalfFrameRate = false; } } // deal with this frame #ifdef __CEDARX_FRAMEWORK_1__ mCurFrameTimestamp = (int64_t)((int64_t)buf.timestamp.tv_usec + (((int64_t)buf.timestamp.tv_sec) * 1000000)); #elif defined __CEDARX_FRAMEWORK_2__ mCurFrameTimestamp = (int64_t)systemTime(); #endif //get picture flag mTakePictureFlag.dwval = buf.reserved; if (mLastZoom != mNewZoom) { float widthRate = (float)mFrameWidth / (float)mVideoWidth; float heightRate = (float)mFrameHeight / (float)mVideoHeight; if (mIsThumbUsedForVideo && (widthRate > 4.0) && (heightRate > 4.0)) { calculateCrop(&mRectCrop, mNewZoom, mMaxZoom, mFrameWidth/2, mFrameHeight/2); // for cts, to do } else { // the main frame crop calculateCrop(&mRectCrop, mNewZoom, mMaxZoom, mFrameWidth, mFrameHeight); } mCameraHardware->setNewCrop(&mRectCrop); // the sub-frame crop if (mHalCameraInfo.fast_picture_mode) { calculateCrop(&mThumbRectCrop, mNewZoom, mMaxZoom, mThumbWidth, mThumbHeight); } mLastZoom = mNewZoom; mZoomRatio = (mNewZoom * 2 * 100 / mMaxZoom + 100); ALOGV("CROP: [%d, %d, %d, %d]", mRectCrop.left, mRectCrop.top, mRectCrop.right, mRectCrop.bottom); ALOGV("thumb CROP: [%d, %d, %d, %d]", mThumbRectCrop.left, mThumbRectCrop.top, mThumbRectCrop.right, mThumbRectCrop.bottom); } #ifdef CAMERA_DECODE if ((mCaptureFormat == V4L2_PIX_FMT_MJPEG) || (mCaptureFormat == V4L2_PIX_FMT_H264)) { mCameraDecoder->DecorderEnter(mMapMem.mem[buf.index], (void*)mVideoBuffer.buf_vir_addr[buf.index], buf.bytesused, (int64_t)mCurFrameTimestamp/1000); } #endif if (mVideoFormat != V4L2_PIX_FMT_YUYV && mCaptureFormat == V4L2_PIX_FMT_YUYV) { #ifdef USE_MP_CONVERT YUYVToYUV420C((void*)buf.m.offset, (void*)(mVideoBuffer.buf_phy_addr[buf.index] | 0x40000000), mFrameWidth, mFrameHeight); #else YUYVToNV21(mMapMem.mem[buf.index], (void*)mVideoBuffer.buf_vir_addr[buf.index], mFrameWidth, mFrameHeight); #endif } // V4L2BUF_t for preview and HW encoder V4L2BUF_t v4l2_buf; if (mVideoFormat != V4L2_PIX_FMT_YUYV && mCaptureFormat == V4L2_PIX_FMT_YUYV) { v4l2_buf.addrPhyY = mVideoBuffer.buf_phy_addr[buf.index]; v4l2_buf.addrVirY = mVideoBuffer.buf_vir_addr[buf.index]; v4l2_buf.nShareBufFd = mVideoBuffer.nShareBufFd[buf.index]; } #ifdef CAMERA_DECODE else if(mVideoFormat != V4L2_PIX_FMT_YUYV &&(( mCaptureFormat == V4L2_PIX_FMT_MJPEG)|| (mCaptureFormat == V4L2_PIX_FMT_H264))) { v4l2_buf.addrPhyY = mVideoBuffer.buf_phy_addr[buf.index];//- 0x20000000; v4l2_buf.addrVirY = mVideoBuffer.buf_vir_addr[buf.index]; v4l2_buf.width = mFrameWidth;//mVideoInfo.nWidth; v4l2_buf.height = mFrameHeight;//mVideoInfo.nHeight; v4l2_buf.nShareBufFd = mVideoBuffer.nShareBufFd[buf.index]; } #endif else { v4l2_buf.addrPhyY = buf.m.offset - BUFFER_PHY_OFFSET; if (mCameraType == CAMERA_TYPE_CSI) { v4l2_buf.addrPhyY = buf.m.planes[0].m.mem_offset- BUFFER_PHY_OFFSET; } v4l2_buf.addrVirY = (unsigned long)mMapMem.mem[buf.index]; v4l2_buf.nShareBufFd = mMapMem.nShareBufFd[buf.index]; //ALOGD("Camera[%d]v4l2_buf.nShareBufFd=0x%x,index:%d",mCameraId,v4l2_buf.nShareBufFd,buf.index); } v4l2_buf.index = buf.index; v4l2_buf.timeStamp = mCurFrameTimestamp; v4l2_buf.width = mFrameWidth; v4l2_buf.height = mFrameHeight; v4l2_buf.crop_rect.left = mRectCrop.left; v4l2_buf.crop_rect.top = mRectCrop.top; v4l2_buf.crop_rect.width = mRectCrop.right - mRectCrop.left + 1; v4l2_buf.crop_rect.height = mRectCrop.bottom - mRectCrop.top + 1; v4l2_buf.format = mVideoFormat; v4l2_buf.refCnt = 1; mMemOpsS->flush_cache_cam((void*)v4l2_buf.addrVirY, ALIGN_16B(mFrameWidth) * mFrameHeight * 3 >> 1); #ifdef USE_DEINTERLACE_HW if (mCameraType == CAMERA_TYPE_TVIN_NTSC || mCameraType == CAMERA_TYPE_TVIN_PAL || mCameraType == CAMERA_TYPE_TVIN_YPBPR) { v4l2_buf.refMutex.lock(); v4l2_buf.refCnt++; v4l2_buf.refMutex.unlock(); memcpy(&mV4l2DiBuf[v4l2_buf.index], &v4l2_buf, sizeof(V4L2BUF_t)); if ((mPrePreFrameIndex >= 0) && (mPreFrameIndex >= 0) && (mDiProcess != NULL)) { if (mCaptureFormat == V4L2_PIX_FMT_NV61) { mDiProcess->diProcess((unsigned char*)mV4l2DiBuf[mPrePreFrameIndex].addrPhyY, (unsigned char*)mV4l2DiBuf[mPreFrameIndex].addrPhyY, (unsigned char *)v4l2_buf.addrPhyY, mFrameWidth, mFrameHeight, mCaptureFormat, (unsigned char *)mDiOutPutBuffer.buf_phy_addr[buf.index + NB_BUFFER], mFrameWidth, mFrameHeight, mCaptureFormat, 0); mMemOpsS->flush_cache_cam((void*)mDiOutPutBuffer.buf_vir_addr[buf.index + NB_BUFFER], ALIGN_16B(mFrameWidth) * mFrameHeight * 2); } else { mDiProcess->diProcess((unsigned char*)mV4l2DiBuf[mPrePreFrameIndex].addrPhyY, (unsigned char*)mV4l2DiBuf[mPreFrameIndex].addrPhyY, (unsigned char *)v4l2_buf.addrPhyY, mFrameWidth, mFrameHeight, mCaptureFormat, (unsigned char *)mDiOutPutBuffer.buf_phy_addr[buf.index], mFrameWidth, mFrameHeight, mCaptureFormat, 0); } mDiProcess->diProcess((unsigned char*)mV4l2DiBuf[mPrePreFrameIndex].addrPhyY, (unsigned char*)mV4l2DiBuf[mPreFrameIndex].addrPhyY, (unsigned char *)v4l2_buf.addrPhyY, mFrameWidth, mFrameHeight, mCaptureFormat, (unsigned char *)mDiOutPutBuffer.buf_phy_addr[buf.index], mFrameWidth, mFrameHeight, mCaptureFormat, 1); v4l2_buf.addrPhyY = mDiOutPutBuffer.buf_phy_addr[buf.index]; v4l2_buf.addrVirY = mDiOutPutBuffer.buf_vir_addr[buf.index]; if (mCaptureFormat == V4L2_PIX_FMT_NV61) { mMemOpsS->flush_cache_cam((void*)mDiOutPutBuffer.buf_vir_addr[buf.index], ALIGN_16B(mFrameWidth) * mFrameHeight * 2); } else { mMemOpsS->flush_cache_cam((void*)mDiOutPutBuffer.buf_vir_addr[buf.index], ALIGN_16B(mFrameWidth) * mFrameHeight * 3 >> 1); } } mPrePreFrameIndex = mPreFrameIndex; mPreFrameIndex = buf.index; } #endif #if DBG_BUFFER_SAVE ALOGD("Debug to save yuv data! Size:%dx%d",mFrameWidth,mFrameHeight); unsigned int length = 0; length = GPU_BUFFER_ALIGN(ALIGN_16B(mFrameWidth)*mFrameHeight*3/2); saveframe("/data/camera/capture.bin",(void *)v4l2_buf.addrVirY, length, 1); saveSize(mFrameWidth,mFrameHeight); #endif if (mHalCameraInfo.fast_picture_mode) { v4l2_buf.isThumbAvailable = 1; v4l2_buf.thumbUsedForPreview = 1; v4l2_buf.thumbUsedForPhoto = 0; if(mIsThumbUsedForVideo == true) { v4l2_buf.thumbUsedForVideo = 1; } else { v4l2_buf.thumbUsedForVideo = 0; } v4l2_buf.thumbAddrPhyY = v4l2_buf.addrPhyY + ALIGN_4K(ALIGN_16B(mFrameWidth) * mFrameHeight * 3 / 2); // to do v4l2_buf.thumbAddrVirY = v4l2_buf.addrVirY + ALIGN_4K(ALIGN_16B(mFrameWidth) * mFrameHeight * 3 / 2); // to do v4l2_buf.thumbWidth = mThumbWidth; v4l2_buf.thumbHeight = mThumbHeight; v4l2_buf.thumb_crop_rect.left = mThumbRectCrop.left; v4l2_buf.thumb_crop_rect.top = mThumbRectCrop.top; v4l2_buf.thumb_crop_rect.width = mThumbRectCrop.right - mThumbRectCrop.left; v4l2_buf.thumb_crop_rect.height = mThumbRectCrop.bottom - mThumbRectCrop.top; v4l2_buf.thumbFormat = mVideoFormat; } else { v4l2_buf.isThumbAvailable = 0; } //memcpy(&mV4l2buf[v4l2_buf.index], &v4l2_buf, sizeof(V4L2BUF_t)); #ifdef CAMERA_MANAGER_ENABLE if((mCameraManager != NULL) && mCameraManager->isOviewEnable()) { mCameraManager->queueCameraBuf(mHalCameraInfo.device_id,&v4l2_buf); if (mTakePictureState == TAKE_PICTURE_FAST || mTakePictureState == TAKE_PICTURE_RECORD || mTakePictureState == TAKE_PICTURE_NORMAL) { ALOGD("Camera[%d]F:%s, L:%d, need take pic!",mCameraId, __FUNCTION__, __LINE__); if(mHalCameraInfo.device_id == mCameraManager->mStartCameraID) { mCameraManager->mTakePicState = true; ALOGD("Camera[%d]F:%s, L:%d, set mCameraManager mTakePicState = true!", mCameraId,__FUNCTION__, __LINE__); } } //ALOGV("CameraDebug,F:%s,L:%d,id:%d,fd:%d +++++++++++",__FUNCTION__,__LINE__,mHalCameraInfo.device_id,mCameraFd); memcpy(&mV4l2buf[v4l2_buf.index], &v4l2_buf, sizeof(V4L2BUF_t)); goto DEC_REF; } #endif memcpy(&mV4l2buf[v4l2_buf.index], &v4l2_buf, sizeof(V4L2BUF_t)); if ((!mVideoHint) && (mTakePictureState != TAKE_PICTURE_NORMAL)) { // face detection only use when picture mode mCurrentV4l2buf = &mV4l2buf[v4l2_buf.index]; } if (mTakePictureState == TAKE_PICTURE_NORMAL) { //copy picture buffer unsigned long phy_addr = mPicBuffer.addrPhyY; unsigned long vir_addr = mPicBuffer.addrVirY; int share_fd = mPicBuffer.nShareBufFd; int frame_size = GPU_BUFFER_ALIGN(ALIGN_16B(mFrameWidth)*mFrameHeight*3/2); if (frame_size > MAX_PICTURE_SIZE) { ALOGE("Camera[%d]picture buffer size(%d) is smaller than the frame buffer size(%d)",mCameraId, MAX_PICTURE_SIZE, frame_size); pthread_mutex_unlock(&mCaptureMutex); return false; } //copy picture buffer memcpy((void*)&mPicBuffer, &v4l2_buf, sizeof(V4L2BUF_t)); mPicBuffer.addrPhyY = phy_addr; mPicBuffer.addrVirY = vir_addr; mPicBuffer.nShareBufFd = share_fd; mMemOpsS->flush_cache_cam((void*)v4l2_buf.addrVirY, frame_size); memcpy((void*)mPicBuffer.addrVirY, (void*)v4l2_buf.addrVirY, frame_size); mMemOpsS->flush_cache_cam((void*)mPicBuffer.addrVirY, frame_size); //get Exif info for driver struct isp_exif_attribute exif_attri; getExifInfo(&exif_attri); mCallbackNotifier->setExifInfo(exif_attri,mZoomRatio,mExposureBias); mCameraHardware->setExifInfo(exif_attri); // enqueue picture buffer ret = OSAL_Queue(&mQueueBufferPicture, &mPicBuffer); if (ret != 0) { ALOGW("Camera[%d]picture queue full",mCameraId); pthread_cond_signal(&mPictureCond); goto DEC_REF; } mIsPicCopy = true; mCaptureThreadState = CAPTURE_STATE_PAUSED; mTakePictureState = TAKE_PICTURE_NULL; pthread_cond_signal(&mPictureCond); goto DEC_REF; } else { // add reference count mV4l2buf[v4l2_buf.index].refMutex.lock(); mV4l2buf[v4l2_buf.index].refCnt++; mV4l2buf[v4l2_buf.index].refMutex.unlock(); //mV4l2buf[v4l2_buf.index].nShareBufFd = mMapMem.nShareBufFd[v4l2_buf.index]; ret = OSAL_Queue(&mQueueBufferPreview, &mV4l2buf[v4l2_buf.index]); if (ret != 0) { ALOGW("Camera[%d]preview queue full",mCameraId); goto DEC_REF; } // signal a new frame for preview pthread_cond_signal(&mPreviewCond); if (mTakePictureState == TAKE_PICTURE_SCENE_MODE) { int ret; int frame_size = mFrameWidth * mFrameHeight * 3 >> 1; if(mSceneMode == NULL) { pthread_mutex_unlock(&mCaptureMutex); return false; } if(mSceneMode->GetCurrentSceneMode() != SCENE_FACTORY_MODE_HDR && mSceneMode->GetCurrentSceneMode() != SCENE_FACTORY_MODE_NIGHT) goto DEC_REF; #ifdef USE_ION_MEM_ALLOCATOR mMemOpsS->flush_cache_cam((void*)v4l2_buf.addrVirY, frame_size); #elif USE_SUNXI_MEM_ALLOCATOR sunxi_flush_cache((void*)v4l2_buf.addrVirY, frame_size); #endif ret = mSceneMode->GetCurrentFrameData((void *)v4l2_buf.addrVirY); //capture target frames finish if(ret == SCENE_CAPTURE_DONE || ret == SCENE_CAPTURE_FAIL){ ret = OSAL_Queue(&mQueueBufferPicture, &mV4l2buf[v4l2_buf.index]); if (ret != 0) { ALOGW("Camera[%d]picture queue full....",mCameraId); //?? no test ?? pthread_cond_signal(&mPictureCond); goto DEC_REF; } mV4l2buf[v4l2_buf.index].refMutex.lock(); mV4l2buf[v4l2_buf.index].refCnt++; mV4l2buf[v4l2_buf.index].refMutex.unlock(); mTakePictureState = TAKE_PICTURE_NULL; //stop take picture mIsPicCopy = false; pthread_cond_signal(&mPictureCond); } } if (mTakePictureState == TAKE_PICTURE_FAST || mTakePictureState == TAKE_PICTURE_RECORD) { //ALOGD("xxxxxxxxxxxxxxxxxxxx buf.reserved: %x", buf.reserved); if (mHalCameraInfo.fast_picture_mode) { //ALOGD("af_sharp: %d, hdr_cnt:%d, flash_ok: %d, capture_ok: %d.", mTakePictureFlag.bits.af_sharp, \ //get Exif info for driver struct isp_exif_attribute exif_attri; static int flash_fire = 0; getExifInfo(&exif_attri); if(mTakePictureState == TAKE_PICTURE_FAST){ //in order to get the right flash status ,it must check the status here. //beause the flash and the flag is asynchronous,it means current flash //mode is on while flash_fire set at least one time. if(exif_attri.flash_fire == 1) flash_fire = 1; //the current frame buffer is no the target frame,it can't be used for jpg encode static int count = 0; if (mFlashMode == V4L2_FLASH_LED_MODE_NONE && \ mTakePictureFlag.bits.capture_ok == 0) { ALOGV("mTakePictureFlag.bits.capture_ok:%d\n",mTakePictureFlag.bits.capture_ok); if(count++ > 20) { count = 0; setTakePictureCtrl(V4L2_TAKE_PICTURE_NORM); } goto DEC_REF; } else { count = 0; } //when flash mode,the target frame buffer flag is 1 if (mFlashMode != V4L2_FLASH_LED_MODE_NONE && \ mTakePictureFlag.bits.flash_ok == 0 ) goto DEC_REF; exif_attri.flash_fire = flash_fire; flash_fire = 0; } mCallbackNotifier->setExifInfo(exif_attri,mZoomRatio,mExposureBias); mCameraHardware->setExifInfo(exif_attri); int SnrValue = getSnrValue(); int Gain = ((SnrValue >> V4L2_GAIN_SHIFT)&0xff); int SharpLevel = (SnrValue >> V4L2_SHARP_LEVEL_SHIFT) &0xfff; int SharpMin = (SnrValue >> V4L2_SHARP_MIN_SHIFT)&0x3f; int NdfTh = ((SnrValue >> V4L2_NDF_SHIFT) &0x1f) ; ALOGD("Gain = %d, SharpLevel = %d, SharpMin = %d, NdfTh = %d!", Gain, SharpLevel, SharpMin, NdfTh); if (NdfTh > 1) { unsigned char *p_addr =(unsigned char *)malloc((ALIGN_16B(mFrameWidth)*mFrameHeight)>>1); ColorDenoise(p_addr, (unsigned char *)v4l2_buf.addrVirY+ALIGN_16B(mFrameWidth)*mFrameHeight, mFrameWidth, mFrameHeight >> 1, NdfTh + Gain / 24);//6); memcpy((unsigned char *)v4l2_buf.addrVirY+ALIGN_16B(mFrameWidth)*mFrameHeight,p_addr,((ALIGN_16B(mFrameWidth)*mFrameHeight)>>1)); free(p_addr); } if (SharpLevel > 0) { Sharpen((unsigned char *)v4l2_buf.addrVirY, SharpMin,SharpLevel, mFrameWidth,mFrameHeight); } } else{ struct isp_exif_attribute exif_attri; getExifInfo(&exif_attri); mCallbackNotifier->setExifInfo(exif_attri,mZoomRatio,mExposureBias); mCameraHardware->setExifInfo(exif_attri); } #ifdef TAKE_PIC_USE_COPY //copy picture buffer unsigned long phy_addr = mPicBuffer.addrPhyY; unsigned long vir_addr = mPicBuffer.addrVirY; int share_fd = mPicBuffer.nShareBufFd; int frame_size = GPU_BUFFER_ALIGN(ALIGN_16B(mFrameWidth) * mFrameHeight * 3 / 2); if (frame_size > MAX_PICTURE_SIZE) { ALOGD("picture buffer size(%d) is smaller than the frame buffer size(%d)", MAX_PICTURE_SIZE, frame_size); } else { //copy picture buffer memcpy((void*)&mPicBuffer, &v4l2_buf, sizeof(V4L2BUF_t)); mPicBuffer.addrPhyY = phy_addr; mPicBuffer.addrVirY = vir_addr; mPicBuffer.nShareBufFd = share_fd; mMemOpsS->flush_cache_cam((void*)v4l2_buf.addrVirY, frame_size); memcpy((void*)mPicBuffer.addrVirY, (void*)v4l2_buf.addrVirY, frame_size); mMemOpsS->flush_cache_cam((void*)mPicBuffer.addrVirY, frame_size); // enqueue picture buffer ret = OSAL_Queue(&mQueueBufferPicture, &mPicBuffer); if (ret != 0) { LOGW("picture queue full"); pthread_cond_signal(&mPictureCond); goto DEC_REF; } mIsPicCopy = true; mTakePictureState = TAKE_PICTURE_NULL; pthread_cond_signal(&mPictureCond); } #else // enqueue picture buffer ret = OSAL_Queue(&mQueueBufferPicture, &mV4l2buf[v4l2_buf.index]); if (ret != 0) { LOGW("picture queue full"); pthread_cond_signal(&mPictureCond); goto DEC_REF; } // add reference count mV4l2buf[v4l2_buf.index].refMutex.lock(); mV4l2buf[v4l2_buf.index].refCnt++; mV4l2buf[v4l2_buf.index].refMutex.unlock(); mTakePictureState = TAKE_PICTURE_NULL; mIsPicCopy = false; pthread_cond_signal(&mPictureCond); #endif } if (mTakePictureState == TAKE_PICTURE_SMART) { //get Exif info for driver if (mHalCameraInfo.fast_picture_mode) if (mTakePictureFlag.bits.fast_capture_ok == 0) { goto DEC_REF;} struct isp_exif_attribute exif_attri; getExifInfo(&exif_attri); mCallbackNotifier->setExifInfo(exif_attri,mZoomRatio,mExposureBias); mCameraHardware->setExifInfo(exif_attri); // enqueue picture buffer ret = OSAL_Queue(&mQueueBufferPicture, &mV4l2buf[v4l2_buf.index]); if (ret != 0) { LOGW("picture queue full"); pthread_cond_signal(&mSmartPictureCond); goto DEC_REF; } // add reference count mV4l2buf[v4l2_buf.index].refMutex.lock(); mV4l2buf[v4l2_buf.index].refCnt++; mV4l2buf[v4l2_buf.index].refMutex.unlock(); //mTakePictureState = TAKE_PICTURE_NULL; mIsPicCopy = false; pthread_cond_signal(&mSmartPictureCond); } if ((mTakePictureState == TAKE_PICTURE_CONTINUOUS || mTakePictureState == TAKE_PICTURE_CONTINUOUS_FAST) && isContinuousPictureTime()) { if (mTakePictureFlag.bits.fast_capture_ok == 0) goto DEC_REF; // enqueue picture buffer ret = OSAL_Queue(&mQueueBufferPicture, &mV4l2buf[v4l2_buf.index]); if (ret != 0) { // ALOGV("continuous picture queue full"); pthread_cond_signal(&mContinuousPictureCond); goto DEC_REF; } //get Exif info for driver struct isp_exif_attribute exif_attri; getExifInfo(&exif_attri); mCallbackNotifier->setExifInfo(exif_attri,mZoomRatio,mExposureBias); mCameraHardware->setExifInfo(exif_attri); // add reference count mV4l2buf[v4l2_buf.index].refMutex.lock(); mV4l2buf[v4l2_buf.index].refCnt++; mV4l2buf[v4l2_buf.index].refMutex.unlock(); mIsPicCopy = false; pthread_cond_signal(&mContinuousPictureCond); } } DEC_REF: pthread_mutex_unlock(&mCaptureMutex); #ifdef USE_DEINTERLACE_HW if ((mCameraType == CAMERA_TYPE_TVIN_NTSC || mCameraType == CAMERA_TYPE_TVIN_PAL || mCameraType == CAMERA_TYPE_TVIN_YPBPR) && (mPrePreFrameIndex >= 0) && (mDiProcess != NULL)) { releasePreviewFrame(mPrePreFrameIndex); } #endif releasePreviewFrame(v4l2_buf.index); return true; } bool V4L2CameraDevice::previewThread() { int releasebufferindex = -1; V4L2BUF_t * pbuf = (V4L2BUF_t *)OSAL_Dequeue(&mQueueBufferPreview); if (pbuf == NULL) { ALOGV("Camera[%d]preview queue no buffer, sleep...",mCameraId); pthread_mutex_lock(&mPreviewMutex); pthread_cond_wait(&mPreviewCond, &mPreviewMutex); pthread_mutex_unlock(&mPreviewMutex); return true; } //nsecs_t beforePrevew = (int64_t)systemTime(); pthread_mutex_lock(&mPreviewSyncMutex); if(mPreviewThreadState == PREVIEW_STATE_PAUSED){ ALOGV("Camera[%d]preview thread paused",mCameraId); pthread_cond_wait(&mPreviewSyncCond, &mPreviewSyncMutex); } Mutex::Autolock locker(&mObjectLock); if (pbuf->addrVirY == 0) { ALOGV("Camera[%d]preview buffer have been released...",mCameraId); pthread_mutex_unlock(&mPreviewSyncMutex); return true; } if (mCameraType == CAMERA_TYPE_UVC) { mCallbackNotifier->onNextFrameAvailable((void*)pbuf, mUseHwEncoder, NOT_NEED_RELEASE_INDEX); } else { mCallbackNotifier->onNextFrameAvailable((void*)pbuf, mUseHwEncoder, NEED_RELEASE_INDEX); } releasePreviewFrame(pbuf->index); pthread_mutex_unlock(&mPreviewSyncMutex); return true; } void V4L2CameraDevice::stopPreviewThread() { ALOGD("Camera[%d]stop preview thread!\n",mCameraId); pthread_mutex_lock(&mPreviewSyncMutex); pthread_cond_signal(&mPreviewSyncCond); ALOGD("Camera[%d]stop preview mPreviewSyncCond!\n",mCameraId); if(mPreviewThreadState == PREVIEW_STATE_STARTED) { mPreviewThreadState = PREVIEW_STATE_PAUSED; ALOGD("Camera[%d]set mPreviewThreadState to %d\n",mCameraId,mPreviewThreadState); } pthread_mutex_unlock(&mPreviewSyncMutex); } // singal picture bool V4L2CameraDevice::pictureThread() { V4L2BUF_t * pbuf = (V4L2BUF_t *)OSAL_Dequeue(&mQueueBufferPicture); if (pbuf == NULL) { ALOGV("Camera[%d]picture queue no buffer, sleep...",mCameraId); pthread_mutex_lock(&mPictureMutex); pthread_cond_wait(&mPictureCond, &mPictureMutex); pthread_mutex_unlock(&mPictureMutex); return true; } DBG_TIME_BEGIN("taking picture", 0); // notify picture cb mCameraHardware->notifyPictureMsg((void*)pbuf); if(mSceneMode != NULL){ if(mSceneMode->GetCurrentSceneMode() == SCENE_FACTORY_MODE_HDR){ int ret; ret = mSceneMode->PostScenePicture((void*) pbuf->addrVirY); stopSceneModePicture(); } else if(mSceneMode->GetCurrentSceneMode() == SCENE_FACTORY_MODE_NIGHT){ int ret; ret = mSceneMode->PostScenePicture((void*) pbuf->addrVirY); stopSceneModePicture(); } } mCallbackNotifier->takePicture((void*)pbuf,(void*)mMemOpsS); char str[128]; sprintf(str, "hw picture size: %dx%d", pbuf->width, pbuf->height); DBG_TIME_DIFF(str); if((mCameraManager != NULL) && (mCameraManager->isOviewEnable()) && (mHalCameraInfo.device_id == mCameraManager->mStartCameraID)) { ALOGD("Camera[%d]F:%s, L:%d, mCameraManager take pic ok!",mCameraId, __FUNCTION__, __LINE__); } else { if (!mIsPicCopy) { releasePreviewFrame(pbuf->index); } } DBG_TIME_END("Take picture", 0); return true; } // blink picture bool V4L2CameraDevice::smartPictureThread() { V4L2BUF_t * pbuf = (V4L2BUF_t *)OSAL_Dequeue(&mQueueBufferPicture); if (pbuf == NULL) { pthread_mutex_lock(&mSmartPictureMutex); pthread_cond_wait(&mSmartPictureCond, &mSmartPictureMutex); pthread_mutex_unlock(&mSmartPictureMutex); return true; } // apk stop smart pictures if (mSmartPictureDone) { mTakePictureState = TAKE_PICTURE_NULL; if (!mIsPicCopy) { releasePreviewFrame(pbuf->index); } return true; } #if 0 ALOGD("!! mCameraHardware->mBlinkPictureResult %d state %d", mCameraHardware->mBlinkPictureResult, mCameraHardware->mBlinkDetectionState); if ((mCameraHardware->mBlinkPictureResult == true) && (mCameraHardware->mBlinkDetectionState == FACE_DETECTION_PREPARED)) { DBG_TIME_BEGIN("taking blink picture", 0); // notify picture cb mCameraHardware->notifyPictureMsg((void*)pbuf); DBG_TIME_DIFF("notifyPictureMsg"); mCallbackNotifier->takePicture((void*)pbuf,(void*)mMemOpsS); stopSmartPicture(); mTakePictureState = TAKE_PICTURE_NULL; } #endif #if 0 ALOGD("!!! mCameraHardware->mSmilePictureResult %d, state %d", mCameraHardware->mSmilePictureResult, mCameraHardware->mSmileDetectionState); if ((mCameraHardware->mSmilePictureResult == true) && (mCameraHardware->mSmileDetectionState == FACE_DETECTION_PREPARED)) { DBG_TIME_BEGIN("taking smile picture", 0); // notify picture cb mCameraHardware->notifyPictureMsg((void*)pbuf); DBG_TIME_DIFF("notifyPictureMsg"); mCallbackNotifier->takePicture((void*)pbuf,(void*)mMemOpsS); stopSmartPicture(); mTakePictureState = TAKE_PICTURE_NULL; } #endif #if 0 if (mStartSmartTimeout == false) { if ((systemTime() / 1000000 - mStartSmartTimeMs) > 5000) // 5s timeout { mStartSmartTimeout = true; ALOGV("taking smile picture time out!!!"); DBG_TIME_BEGIN("taking smile picture time out!!!", 0); // notify picture cb mCameraHardware->notifyPictureMsg((void*)pbuf); DBG_TIME_DIFF("notifyPictureMsg"); mCallbackNotifier->takePicture((void*)pbuf,(void*)mMemOpsS); stopSmartPicture(); mTakePictureState = TAKE_PICTURE_NULL; } } #endif char str[128]; sprintf(str, "hw picture size: %dx%d", pbuf->width, pbuf->height); DBG_TIME_DIFF(str); if (!mIsPicCopy) { releasePreviewFrame(pbuf->index); } DBG_TIME_END("Take smart picture", 0); return true; } void V4L2CameraDevice::startSmartPicture() { F_LOG; mSmartPictureDone = false; mStartSmartTimeout = false; mStartSmartTimeMs = systemTime() / 1000000; DBG_TIME_AVG_INIT(TAG_SMART_PICTURE); } void V4L2CameraDevice::stopSmartPicture() { F_LOG; if (mSmartPictureDone) { ALOGD("Smart picture has already stopped"); return; } mStartSmartTimeout = true; mSmartPictureDone = true; DBG_TIME_AVG_END(TAG_SMART_PICTURE, "picture enc"); } status_t V4L2CameraDevice::openSceneMode(const char* scenemode) { F_LOG; int ret; int mode = 0; //HDR sence if (!strcmp(scenemode, CameraParameters::SCENE_MODE_HDR)){ mode = SCENE_FACTORY_MODE_HDR; } if(!strcmp(scenemode, CameraParameters::SCENE_MODE_NIGHT)){ mode = SCENE_FACTORY_MODE_NIGHT; } mSceneMode = mSceneModeFactory.CreateSceneMode(mode); if(mSceneMode == NULL){ ALOGD("SceneModeFactory CreateSceneMode failed"); mSceneModeFactory.DestorySceneMode(NULL); return -1; } mSceneMode->SetCallBack(SceneNotifyCallback,(void*)this); ret = mSceneMode->InitSceneMode(mFrameWidth,mFrameHeight); if(ret == -1){ ALOGD("SceneMode Init faided"); return -1; } return 0; } void V4L2CameraDevice::closeSceneMode() { F_LOG; if(mSceneMode != NULL){ mSceneMode->ReleaseSceneMode(); mSceneModeFactory.DestorySceneMode(mSceneMode); mSceneMode = NULL; //when close scene mode, it must restore the flash status setFlashMode(mFlashMode); } } void V4L2CameraDevice::startSceneModePicture(int scenemode) { F_LOG mSceneMode->StartScenePicture(); } void V4L2CameraDevice::stopSceneModePicture() { F_LOG mSceneMode->StopScenePicture(); } // continuous picture bool V4L2CameraDevice::continuousPictureThread() { V4L2BUF_t * pbuf = (V4L2BUF_t *)OSAL_Dequeue(&mQueueBufferPicture); if (pbuf == NULL) { ALOGV("continuousPictureThread queue no buffer, sleep..."); pthread_mutex_lock(&mContinuousPictureMutex); pthread_cond_wait(&mContinuousPictureCond, &mContinuousPictureMutex); pthread_mutex_unlock(&mContinuousPictureMutex); return true; } Mutex::Autolock locker(&mObjectLock); if (mMapMem.mem[pbuf->index] == NULL || pbuf->addrPhyY == 0) { ALOGV("picture buffer have been released..."); return true; } DBG_TIME_AVG_AREA_IN(TAG_CONTINUOUS_PICTURE); // reach the max number of pictures if (mContinuousPictureCnt >= mContinuousPictureMax) { mTakePictureState = TAKE_PICTURE_NULL; stopContinuousPicture(); releasePreviewFrame(pbuf->index); return true; } // apk stop continuous pictures if (!mContinuousPictureStarted) { mTakePictureState = TAKE_PICTURE_NULL; releasePreviewFrame(pbuf->index); return true; } bool ret = mCallbackNotifier->takePicture((void*)pbuf,(void*)mMemOpsS, true); if (ret) { mContinuousPictureCnt++; DBG_TIME_AVG_AREA_OUT(TAG_CONTINUOUS_PICTURE); } else { // LOGW("do not encoder jpeg"); } releasePreviewFrame(pbuf->index); return true; } void V4L2CameraDevice::startContinuousPicture() { F_LOG; mContinuousPictureCnt = 0; mContinuousPictureStarted = true; mContinuousPictureStartTime = systemTime(SYSTEM_TIME_MONOTONIC); DBG_TIME_AVG_INIT(TAG_CONTINUOUS_PICTURE); } void V4L2CameraDevice::stopContinuousPicture() { F_LOG; if (!mContinuousPictureStarted) { ALOGD("Continuous picture has already stopped"); return; } mContinuousPictureStarted = false; nsecs_t time = (systemTime(SYSTEM_TIME_MONOTONIC) - mContinuousPictureStartTime)/1000000; ALOGD("Continuous picture cnt: %d, use time %lld(ms)", mContinuousPictureCnt, time); if (time != 0) { ALOGD("Continuous picture %f(fps)", (float)mContinuousPictureCnt/(float)time * 1000); } DBG_TIME_AVG_END(TAG_CONTINUOUS_PICTURE, "picture enc"); } void V4L2CameraDevice::setContinuousPictureCnt(int cnt) { F_LOG; mContinuousPictureMax = cnt; } bool V4L2CameraDevice::isContinuousPictureTime() { if (mTakePictureState == TAKE_PICTURE_CONTINUOUS_FAST) { return true; } timeval cur_time; gettimeofday(&cur_time, NULL); const uint64_t cur_mks = cur_time.tv_sec * 1000000LL + cur_time.tv_usec; if ((cur_mks - mContinuousPictureLast) >= mContinuousPictureAfter) { mContinuousPictureLast = cur_mks; return true; } return false; } bool V4L2CameraDevice::isPreviewTime() { if (mVideoHint != true) { return true; } timeval cur_time; gettimeofday(&cur_time, NULL); const uint64_t cur_mks = cur_time.tv_sec * 1000000LL + cur_time.tv_usec; if ((cur_mks - mPreviewLast) >= mPreviewAfter) { mPreviewLast = cur_mks; return true; } return false; } void V4L2CameraDevice::waitFaceDectectTime() { timeval cur_time; gettimeofday(&cur_time, NULL); const uint64_t cur_mks = cur_time.tv_sec * 1000000LL + cur_time.tv_usec; if ((cur_mks - mFaceDectectLast) >= mFaceDectectAfter) { mFaceDectectLast = cur_mks; } else { usleep(mFaceDectectAfter - (cur_mks - mFaceDectectLast)); gettimeofday(&cur_time, NULL); mFaceDectectLast = cur_time.tv_sec * 1000000LL + cur_time.tv_usec; } } int V4L2CameraDevice::getCurrentFaceFrame(void* frame, int* width, int* height) { if (frame == NULL) { ALOGD("getCurrentFrame: error in null pointer"); return -1; } pthread_mutex_lock(&mCaptureMutex); // stop capture if (mCaptureThreadState != CAPTURE_STATE_STARTED) { LOGW("capture thread dose not started"); pthread_mutex_unlock(&mCaptureMutex); return -1; } pthread_mutex_unlock(&mCaptureMutex); #ifdef WATI_FACEDETECT waitFaceDectectTime(); #endif Mutex::Autolock locker(&mObjectLock); if (mCurrentV4l2buf == NULL || mCurrentV4l2buf->addrVirY == 0) { LOGW("frame buffer not ready"); return -1; } //ALOGV("getCurrentFaceFrame: %dx%d", mCurrentV4l2buf->width, mCurrentV4l2buf->height); if ((mCurrentV4l2buf->isThumbAvailable == 1) && (mCurrentV4l2buf->thumbUsedForPreview == 1)) { mMemOpsS->flush_cache_cam((char *)mCurrentV4l2buf->addrVirY + (ALIGN_16B(mCurrentV4l2buf->width) * mCurrentV4l2buf->height * 3 / 2), ALIGN_16B(mCurrentV4l2buf->thumbWidth) * mCurrentV4l2buf->thumbHeight); memcpy(frame, (char*)mCurrentV4l2buf->addrVirY + ALIGN_4K((ALIGN_16B(mCurrentV4l2buf->width) * mCurrentV4l2buf->height * 3 / 2)), ALIGN_16B(mCurrentV4l2buf->thumbWidth) * mCurrentV4l2buf->thumbHeight); *width = mCurrentV4l2buf->thumbWidth; *height = mCurrentV4l2buf->thumbHeight; } else { mMemOpsS->flush_cache_cam((void*)mCurrentV4l2buf->addrVirY, mCurrentV4l2buf->width * mCurrentV4l2buf->height); memcpy(frame, (void*)mCurrentV4l2buf->addrVirY, mCurrentV4l2buf->width * mCurrentV4l2buf->height); *width = mCurrentV4l2buf->width; *height = mCurrentV4l2buf->height; } //ALOGV("getCurrentFaceFrame: %dx%d", *width, *height); return 0; } int V4L2CameraDevice::getTVINSystemType(int fd) { struct v4l2_format format; struct v4l2_format format_set; struct v4l2_frmsizeenum frmsize; enum v4l2_buf_type type; int i = 0; int temp_height = 0; memset(&format, 0, sizeof(struct v4l2_format)); memset(&format_set, 0, sizeof(struct v4l2_format)); memset(&frmsize, 0, sizeof(struct v4l2_frmsizeenum)); frmsize.pixel_format = V4L2_PIX_FMT_NV21; frmsize.index = 0; while ((!ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsize))&&(i < 20)) { ALOGV("i = %d\n", i); ALOGV("framesize width = %d, height = %d\n",frmsize.discrete.width, frmsize.discrete.height); i++; frmsize.index++; } memset(&format, 0, sizeof(struct v4l2_format)); format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; i = 0; while (ioctl(fd, VIDIOC_G_FMT, &format) &&(i++ < 20)) { ALOGV("get tvin signal failed.\n"); return -1; } memcpy(&format_set,&format,sizeof(struct v4l2_format)); ALOGV("---width= [%d], height =[%d],system=%d,i=%d\n",format.fmt.pix.width, format.fmt.pix.height,format.fmt.raw_data[RAW_DATA_SYSTEM],i); format_set.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; format_set.fmt.pix.pixelformat = V4L2_PIX_FMT_NV21; format_set.fmt.pix.width= format.fmt.pix.width; format_set.fmt.pix.height= format.fmt.pix.height; if (ioctl(fd, VIDIOC_S_FMT, &format_set) == -1) { ALOGV("set tvin image format failed\n"); return -1 ; } if((format.fmt.raw_data[RAW_DATA_SYSTEM]==0)) { ALOGD("------------get tvin ntsc\n"); return TVD_NTSC; } else if((format.fmt.raw_data[RAW_DATA_SYSTEM]==1)) { ALOGD("------------get tvin pal\n"); return TVD_PAL ; } else if((format.fmt.raw_data[RAW_DATA_SYSTEM]==2)||(format.fmt.raw_data[RAW_DATA_SYSTEM]==3)) { ALOGD("---------get tvin ypbpr\n"); return TVD_YPBPR; } ALOGD("---------get no type \n"); return 0; } // ----------------------------------------------------------------------------- // extended interfaces here <***** star *****> // ----------------------------------------------------------------------------- int V4L2CameraDevice::openCameraDev(HALCameraInfo * halInfo) { int ret = -1; struct v4l2_input inp; struct v4l2_capability cap; if (halInfo == NULL) { ALOGD("error HAL camera info"); return -1; } // open V4L2 device ALOGD("Camera[%d] openCameraDev enter",halInfo->device_id); mCameraFd = open(halInfo->device_name, O_RDWR | O_NONBLOCK, 0); if (mCameraFd == -1) { ALOGE("ERROR opening %s: %s", halInfo->device_name, strerror(errno)); return -1; } mCameraId = halInfo->device_id; // check v4l2 device capabilities ret = ioctl (mCameraFd, VIDIOC_QUERYCAP, &cap); if (ret < 0) { ALOGE("Camera[%d] Error opening device: unable to query device.",mCameraId); goto END_ERROR; } if (!strcmp((char *)cap.driver, "uvcvideo")) { mCameraType = CAMERA_TYPE_UVC; halInfo->is_uvc = true; ALOGD("Camera[%d] mCameraType = CAMERA_TYPE_UVC",mCameraId); } else if (!strcmp((char *)cap.driver, "sunxi-tvd" )) { int tvinType; tvinType = getTVINSystemType(mCameraFd); if(tvinType == TVD_PAL ) { mCameraType = CAMERA_TYPE_TVIN_PAL; ALOGD("Camera[%d] mCameraType = CAMERA_TYPE_TVIN_PAL",mCameraId); } else if(tvinType == TVD_NTSC ) { mCameraType = CAMERA_TYPE_TVIN_NTSC; ALOGD("Camera[%d] mCameraType = CAMERA_TYPE_TVIN_NTSC",mCameraId); } else if(tvinType == TVD_YPBPR ) { mCameraType = CAMERA_TYPE_TVIN_YPBPR; ALOGD("Camera[%d] mCameraType = CAMERA_TYPE_TVIN_YPBPR",mCameraId); } else { mCameraType = CAMERA_TYPE_TVIN_NTSC; ALOGD("Camera[%d] Default mCameraType = CAMERA_TYPE_TVIN_NTSC",mCameraId); } } else { mCameraType = CAMERA_TYPE_CSI; ALOGD("Camera[%d] mCameraType = CAMERA_TYPE_CSI",mCameraId); } if (mCameraType != CAMERA_TYPE_CSI) { if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) { ALOGD("Camera[%d] Error opening device: video capture not supported.",mCameraId); goto END_ERROR; } if ((cap.capabilities & V4L2_CAP_STREAMING) == 0) { ALOGD("Camera[%d] Capture device does not support streaming i/o",mCameraId); goto END_ERROR; } } if (mCameraType == CAMERA_TYPE_CSI) { // uvc do not need to set input inp.index = 0;//halInfo->device_id; if (-1 == ioctl (mCameraFd, VIDIOC_S_INPUT, &inp)) { ALOGD("Camera[%d] VIDIOC_S_INPUT error!",mCameraId); goto END_ERROR; } halInfo->facing = CAMERA_FACING_FRONT; //mIsThumbUsedForVideo = true; } if (mCameraType == CAMERA_TYPE_UVC) { // try to support this format: NV21, YUYV // we do not support mjpeg camera now if (tryFmt(V4L2_PIX_FMT_NV21) == OK) { mCaptureFormat = V4L2_PIX_FMT_NV21; ALOGD("Camera[%d] capture format: V4L2_PIX_FMT_NV21",mCameraId); } else if(tryFmt(V4L2_PIX_FMT_H264) == OK) { mCaptureFormat = V4L2_PIX_FMT_H264; ALOGD("Camera[%d] capture format: V4L2_PIX_FMT_H264",mCameraId); } else if(tryFmt(V4L2_PIX_FMT_MJPEG) == OK) { mCaptureFormat = V4L2_PIX_FMT_MJPEG; // maybe usb camera ALOGD("Camera[%d] capture format: V4L2_PIX_FMT_MJPEG",mCameraId); } else if(tryFmt(V4L2_PIX_FMT_YUYV) == OK) { mCaptureFormat = V4L2_PIX_FMT_YUYV; // maybe usb camera ALOGD("Camera[%d] capture format: V4L2_PIX_FMT_YUYV",mCameraId); } else { ALOGD("Camera[%d] driver should surpport NV21/NV12 or YUYV format, but it not!",mCameraId); goto END_ERROR; } } ALOGD("openCameraDev[%d] name:%s succesfully",mCameraId,halInfo->device_name); return OK; END_ERROR: if (mCameraFd != NULL) { close(mCameraFd); mCameraFd = NULL; } return -1; } void V4L2CameraDevice::closeCameraDev() { ALOGD("Camera[%d] closeCameraDev",mCameraId); if (mCameraFd != NULL) { close(mCameraFd); mCameraFd = NULL; } } int V4L2CameraDevice::v4l2SetVideoParams(int width, int height, uint32_t pix_fmt) { int ret = UNKNOWN_ERROR; struct v4l2_format format; ALOGD("Camera[%d] %s, line: %d, w: %d, h: %d, pfmt: %d",mCameraId, __FUNCTION__, __LINE__, width, height, pix_fmt); memset(&format, 0, sizeof(format)); if (mCameraType == CAMERA_TYPE_CSI) { format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; format.fmt.pix_mp.width = width; format.fmt.pix_mp.height = height; format.fmt.pix_mp.field = V4L2_FIELD_NONE; format.fmt.pix_mp.pixelformat = pix_fmt; } else { int i = 0; if(mCameraType == CAMERA_TYPE_TVIN_PAL || mCameraType == CAMERA_TYPE_TVIN_NTSC) { format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; while (ioctl(mCameraFd, VIDIOC_G_FMT, &format) &&(i++ < 20)) { ALOGD("+++get tvin signal failed.\n"); return -1; } } format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; format.fmt.pix.width = width; format.fmt.pix.height = height; if (mCaptureFormat == V4L2_PIX_FMT_YUYV) { format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; } else if(mCaptureFormat == V4L2_PIX_FMT_MJPEG) { format.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; } else if(mCaptureFormat == V4L2_PIX_FMT_H264) { format.fmt.pix.pixelformat = V4L2_PIX_FMT_H264; } else { format.fmt.pix.pixelformat = pix_fmt; } format.fmt.pix.field = V4L2_FIELD_NONE; } ret = ioctl(mCameraFd, VIDIOC_S_FMT, &format); if (ret < 0) { ALOGE("Camera[%d] VIDIOC_S_FMT Failed: %s", mCameraId,strerror(errno)); return ret; } if (mCameraType == CAMERA_TYPE_CSI) { ret = ioctl(mCameraFd, VIDIOC_G_FMT, &format); if (ret < 0) { ALOGE("Camera[%d] VIDIOC_G_FMT Failed: %s", mCameraId,strerror(errno)); return ret; } else { nPlanes = format.fmt.pix_mp.num_planes; ALOGD("Camera[%d] VIDIOC_G_FMT resolution = %d*%d num_planes = %d\n",mCameraId,format.fmt.pix_mp.width, format.fmt.pix_mp.height,format.fmt.pix_mp.num_planes); } mFrameWidth = format.fmt.pix_mp.width; mFrameHeight = format.fmt.pix_mp.height; } else { mFrameWidth = format.fmt.pix.width; mFrameHeight = format.fmt.pix.height; } return OK; } int V4L2CameraDevice::v4l2ReqBufs(int * buf_cnt) { int ret = UNKNOWN_ERROR; struct v4l2_requestbuffers rb; ALOGD("Camera[%d] v4l2ReqBufs count: %d", mCameraId,*buf_cnt); memset(&rb, 0, sizeof(rb)); rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (mCameraType == CAMERA_TYPE_CSI) { rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; } if(mCameraType == CAMERA_TYPE_CSI || mCameraType == CAMERA_TYPE_VFE) { rb.memory = V4L2_MEMORY_USERPTR; } else { rb.memory = V4L2_MEMORY_MMAP; } rb.count = *buf_cnt; ret = ioctl(mCameraFd, VIDIOC_REQBUFS, &rb); if (ret < 0) { ALOGE("Camera[%d]Init: VIDIOC_REQBUFS failed: %s",mCameraId, strerror(errno)); return ret; } *buf_cnt = rb.count; ALOGD("Camera[%d] v4l2ReqBufs count: %d,memory type:%d succesfully",mCameraId, *buf_cnt,rb.memory); return OK; } int V4L2CameraDevice::v4l2QueryBuf() { int ret = UNKNOWN_ERROR; struct v4l2_buffer buf; ALOGD("Camera[%d] v4l2QueryBuf cnt:%d enter",mCameraId,mBufferCnt); for (int i = 0; i < mBufferCnt; i++) { memset (&buf, 0, sizeof (struct v4l2_buffer)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (mCameraType == CAMERA_TYPE_CSI) { struct v4l2_plane planes[VIDEO_MAX_PLANES]; memset(planes, 0, VIDEO_MAX_PLANES*sizeof(struct v4l2_plane)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; buf.length = nPlanes; buf.m.planes = planes; if (NULL == buf.m.planes) { ALOGE("Camera[%d] v4l2QueryBuf calloc failed!",mCameraId); } } if(mCameraType == CAMERA_TYPE_CSI || mCameraType == CAMERA_TYPE_VFE) { buf.memory = V4L2_MEMORY_USERPTR; } else { buf.memory = V4L2_MEMORY_MMAP; } buf.index = i; ret = ioctl (mCameraFd, VIDIOC_QUERYBUF, &buf); if (ret < 0) { ALOGE("Camera[%d] v4l2QueryBuf Unable to query buffer (%s)", mCameraId,strerror(errno)); return ret; } switch (buf.memory) { case V4L2_MEMORY_MMAP: mMapMem.mem[i] = mmap (0, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, mCameraFd, buf.m.offset); mMapMem.length = buf.length; if (mMapMem.mem[i] == MAP_FAILED){ ALOGE("Camera[%d] Unable to map buffer (%s)", mCameraId,strerror(errno)); for(int j = 0;j < i;j++){ munmap(mMapMem.mem[j], mMapMem.length); } return -1; } ALOGD("Camera[%d] mem[%d]: %lx, len: %x, offset: %x",mCameraId, i, (unsigned long)mMapMem.mem[i], buf.length, buf.m.offset); break; case V4L2_MEMORY_USERPTR: mMapMem.length = GPU_BUFFER_ALIGN(ALIGN_16B(mFrameWidth)*mFrameHeight*3/2);/*buf.length;*/ mMapMem.mem[i] = mMemOpsS->palloc_cam(mMapMem.length,&mMapMem.nShareBufFd[i]); mMapMem.length = buf.length; if (mMapMem.mem[i] == NULL){ ALOGE("Camera[%d] v4l2QueryBuf buffer allocate ERROR(%s)",mCameraId, strerror(errno)); return -1; } if(mCameraType == CAMERA_TYPE_CSI) { mMapMem.length = buf.m.planes[0].length; buf.m.planes[0].m.userptr = (unsigned long)mMapMem.mem[i]; buf.m.planes[0].length = mMapMem.length; } else { buf.m.userptr = (unsigned long)mMapMem.mem[i]; } ALOGD("Camera[%d] v4l2QueryBuf mem[%d]:0x%lx,len:%d,fd:%d,w*h:%d,%d", mCameraId,i, (unsigned long)mMapMem.mem[i], mMapMem.length, mMapMem.nShareBufFd[i],mFrameWidth,mFrameHeight); break; default: break; } // start with all buffers in queue ret = ioctl(mCameraFd, VIDIOC_QBUF, &buf); if (ret < 0) { ALOGE("Camera[%d] v4l2QueryBuf VIDIOC_QBUF Failed",mCameraId); return ret; } if (mCameraType == CAMERA_TYPE_UVC ) // star to do { int buffer_len = mFrameWidth * mFrameHeight * 3 / 2; mVideoBuffer.buf_vir_addr[i] = (unsigned long)mMemOpsS->palloc_cam(buffer_len,&mVideoBuffer.nShareBufFd[i]); mVideoBuffer.buf_phy_addr[i] = (unsigned long)mMemOpsS->cpu_get_phyaddr_cam((void*)mVideoBuffer.buf_vir_addr[i]); ALOGD("Camera[%d] video buffer: index: %d, vir: %x, phy: %x, len: %x",mCameraId, i, mVideoBuffer.buf_vir_addr[i], mVideoBuffer.buf_phy_addr[i], buffer_len); memset((void*)mVideoBuffer.buf_vir_addr[i], 0x10, mFrameWidth * mFrameHeight); memset((char *)mVideoBuffer.buf_vir_addr[i] + mFrameWidth * mFrameHeight, 0x80, mFrameWidth * mFrameHeight / 2); } #ifdef USE_DEINTERLACE_HW if (mCameraType == CAMERA_TYPE_TVIN_NTSC || mCameraType == CAMERA_TYPE_TVIN_PAL || mCameraType == CAMERA_TYPE_TVIN_YPBPR) { if (mCaptureFormat == V4L2_PIX_FMT_NV61) { int buffer_size = ALIGN_16B(mFrameWidth) * mFrameHeight * 2; mDiOutPutBuffer.buf_vir_addr[i] = (unsigned long)mMemOpsS->palloc_cam(buffer_size, &mDiOutPutBuffer.nShareBufFd[i]); mDiOutPutBuffer.buf_phy_addr[i] = (unsigned long)mMemOpsS->cpu_get_phyaddr_cam((void*)mDiOutPutBuffer.buf_vir_addr[i]); ALOGV("DiOutPutbuffer: index: %d, vir: %x, phy: %x, len: %x, V4L2_PIX_FMT_NV61", i, mDiOutPutBuffer.buf_vir_addr[i], mDiOutPutBuffer.buf_phy_addr[i], buffer_size); memset((void*)mDiOutPutBuffer.buf_vir_addr[i], 0x10, ALIGN_16B(mFrameWidth) * mFrameHeight); memset((void*)(mDiOutPutBuffer.buf_vir_addr[i] + ALIGN_16B(mFrameWidth) * mFrameHeight), 0x80, mFrameWidth * mFrameHeight); mDiOutPutBuffer.buf_vir_addr[i + NB_BUFFER] = (unsigned long)mMemOpsS->palloc_cam(buffer_size, &mDiOutPutBuffer.nShareBufFd[i + NB_BUFFER]); mDiOutPutBuffer.buf_phy_addr[i + NB_BUFFER] = (unsigned long)mMemOpsS->cpu_get_phyaddr_cam( (void*)mDiOutPutBuffer.buf_vir_addr[i + NB_BUFFER]); ALOGV("DiOutPutbuffer: index: %d, vir: %x, phy: %x, len: %x, V4L2_PIX_FMT_NV61", i + NB_BUFFER, mDiOutPutBuffer.buf_vir_addr[i + NB_BUFFER], mDiOutPutBuffer.buf_phy_addr[i + NB_BUFFER], buffer_size); memset((void*)mDiOutPutBuffer.buf_vir_addr[i + NB_BUFFER], 0x10, ALIGN_16B(mFrameWidth) * mFrameHeight); memset((void*)(mDiOutPutBuffer.buf_vir_addr[i + NB_BUFFER] + ALIGN_16B(mFrameWidth) * mFrameHeight), 0x80, mFrameWidth * mFrameHeight); }else { int buffer_size = ALIGN_16B(mFrameWidth) * mFrameHeight * 3 >> 1; mDiOutPutBuffer.buf_vir_addr[i] = (unsigned long)mMemOpsS->palloc_cam(buffer_size, &mDiOutPutBuffer.nShareBufFd[i]); mDiOutPutBuffer.buf_phy_addr[i] = (unsigned long)mMemOpsS->cpu_get_phyaddr_cam((void*)mDiOutPutBuffer.buf_vir_addr[i]); ALOGV("DiOutPutbuffer: index: %d, vir: %x, phy: %x, len: %x", i, mDiOutPutBuffer.buf_vir_addr[i], mDiOutPutBuffer.buf_phy_addr[i], buffer_size); memset((void*)mDiOutPutBuffer.buf_vir_addr[i], 0x10, ALIGN_16B(mFrameWidth) * mFrameHeight); memset((void*)(mDiOutPutBuffer.buf_vir_addr[i] + ALIGN_16B(mFrameWidth) * mFrameHeight), 0x80, mFrameWidth * mFrameHeight / 2); } } #endif } mPicBuffer.addrVirY = (unsigned long)mMemOpsS->palloc_cam(MAX_PICTURE_SIZE, &mPicBuffer.nShareBufFd); mPicBuffer.addrPhyY = (unsigned long)mMemOpsS->cpu_get_phyaddr_cam((void*)mPicBuffer.addrVirY); return OK; } int V4L2CameraDevice::v4l2StartStreaming() { ALOGD("Camera[%d] v4l2StartStreaming enter",mCameraId); int ret = UNKNOWN_ERROR; enum v4l2_buf_type type; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (mCameraType == CAMERA_TYPE_CSI) { type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; } ret = ioctl (mCameraFd, VIDIOC_STREAMON, &type); if (ret < 0) { ALOGE("Camera[%d] StartStreaming: Unable to start capture: %s", mCameraId,strerror(errno)); return ret; } return OK; } int V4L2CameraDevice::v4l2StopStreaming() { ALOGD("Camera[%d] v4l2StopStreaming enter",mCameraId); int ret = UNKNOWN_ERROR; enum v4l2_buf_type type; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (mCameraType == CAMERA_TYPE_CSI) { type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; } ret = ioctl (mCameraFd, VIDIOC_STREAMOFF, &type); if (ret < 0) { ALOGE("Camera[%d] StopStreaming: Unable to stop capture: %s", mCameraId,strerror(errno)); return ret; } ALOGD("Camera[%d] V4L2Camera::v4l2StopStreaming OK",mCameraId); return OK; } int V4L2CameraDevice::v4l2UnmapBuf() { ALOGD("Camera[%d] %s enter",mCameraId,__FUNCTION__); int ret = UNKNOWN_ERROR; for (int i = 0; i < mBufferCnt; i++) { ret = munmap(mMapMem.mem[i], mMapMem.length); if (ret < 0) { ALOGE("Camera[%d] v4l2UnmapBuf Unmap failed",mCameraId); return ret; } mMapMem.mem[i] = NULL; if (mVideoBuffer.buf_vir_addr[i] != 0) { mMemOpsS->pfree_cam((void*)mVideoBuffer.buf_vir_addr[i]); mVideoBuffer.buf_phy_addr[i] = 0; } #ifdef USE_DEINTERLACE_HW if (mDiOutPutBuffer.buf_vir_addr[i] != 0) { mMemOpsS->pfree_cam((void*)mDiOutPutBuffer.buf_vir_addr[i]); mDiOutPutBuffer.buf_phy_addr[i] = 0; mDiOutPutBuffer.buf_vir_addr[i] = 0; } if (mDiOutPutBuffer.buf_vir_addr[i + NB_BUFFER] != 0) { mMemOpsS->pfree_cam((void*)mDiOutPutBuffer.buf_vir_addr[i + NB_BUFFER]); mDiOutPutBuffer.buf_phy_addr[i + NB_BUFFER] = 0; mDiOutPutBuffer.buf_vir_addr[i + NB_BUFFER] = 0; } #endif } mVideoBuffer.buf_unused = NB_BUFFER; mVideoBuffer.read_id = 0; mVideoBuffer.write_id = 0; if (mPicBuffer.addrVirY != 0) { mMemOpsS->pfree_cam((void*)mPicBuffer.addrVirY); mPicBuffer.addrVirY = 0; } ALOGD("Camera[%d] %s end",mCameraId,__FUNCTION__); return OK; } void V4L2CameraDevice::releasePreviewFrame(int index) { int ret = UNKNOWN_ERROR; struct v4l2_buffer buf; if (index == NOT_NEED_RELEASE_INDEX) { ALOGV("Camera[%d] type:%d, index:%x", mCameraId, mCameraType, index); return; } pthread_mutex_lock(&mCaptureMutex); // Decrease buffer reference count first. mV4l2buf[index].refMutex.lock(); mV4l2buf[index].refCnt--; mV4l2buf[index].refMutex.unlock(); // If the reference count is equal 0, release it. if (mV4l2buf[index].refCnt == 0) { memset(&buf, 0, sizeof(v4l2_buffer)); #ifdef USE_CSI_VIN_DRIVER struct v4l2_plane planes[VIDEO_MAX_PLANES]; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; buf.memory = V4L2_MEMORY_USERPTR; buf.length = nPlanes; buf.m.planes = planes; buf.m.planes[0].m.userptr = (unsigned long)mMapMem.mem[index]; buf.m.planes[0].length = mMapMem.length; #else buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.m.userptr = (unsigned long)mMapMem.mem[index]; //the buffer virtual address buf.length = mMapMem.length; //the buffer size #endif buf.index = index; ALOGV("Camera[%d]Qbuf:%d, addr:%x, len:%d", mCameraId,buf.index, mMapMem.mem[index],buf.length); ret = ioctl(mCameraFd, VIDIOC_QBUF, &buf); if (ret != 0) { ALOGE("Camera[%d]releasePreviewFrame: VIDIOC_QBUF Failed: index = %d, ret = %d, addr:%x, len:%d, %s",mCameraId, buf.index, ret, (unsigned int)mMapMem.mem[index],buf.length,strerror(errno)); } else { mCurAvailBufferCnt++; } } pthread_mutex_unlock(&mCaptureMutex); } void V4L2CameraDevice::recoveryPreviewFrame() { int ret = UNKNOWN_ERROR; struct v4l2_buffer buf; pthread_mutex_lock(&mCaptureMutex); for(int i=0; i1000000000) //if(mV4l2buf[i].refCnt>0) { //LOGW("release buff: %d",i); memset(&buf, 0, sizeof(v4l2_buffer)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (mCameraType == CAMERA_TYPE_CSI) { struct v4l2_plane planes[VIDEO_MAX_PLANES]; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; buf.length = nPlanes; buf.m.planes = planes; } if(mCameraType == CAMERA_TYPE_UVC || mCameraType == CAMERA_TYPE_TVIN_NTSC || mCameraType == CAMERA_TYPE_TVIN_PAL || mCameraType == CAMERA_TYPE_TVIN_YPBPR) { buf.memory = V4L2_MEMORY_MMAP; } else { buf.memory = V4L2_MEMORY_USERPTR; } buf.index = i; ret = ioctl(mCameraFd, VIDIOC_QBUF, &buf); ALOGD("Camera[%d]RecoveryPreviewFrame idx: %d",mCameraId,i); if (ret != 0) { ALOGE("Camera[%d] recoveryPreviewFrame: VIDIOC_QBUF Failed: index = %d, ret = %d, %s",mCameraId, buf.index, ret, strerror(errno)); } else { mV4l2buf[i].refCnt =0; mCurAvailBufferCnt++; } } } pthread_mutex_unlock(&mCaptureMutex); } int V4L2CameraDevice::getPreviewFrame(v4l2_buffer *buf) { int ret = UNKNOWN_ERROR; if (mCameraType == CAMERA_TYPE_CSI) { struct v4l2_plane planes[VIDEO_MAX_PLANES]; buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; buf->memory = V4L2_MEMORY_USERPTR; buf->length = nPlanes; buf->m.planes =planes; } else { buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if(mCameraType == CAMERA_TYPE_UVC || mCameraType == CAMERA_TYPE_TVIN_NTSC || mCameraType == CAMERA_TYPE_TVIN_PAL || mCameraType == CAMERA_TYPE_TVIN_YPBPR) { buf->memory = V4L2_MEMORY_MMAP; } else { buf->memory = V4L2_MEMORY_USERPTR; } } ret = ioctl(mCameraFd, VIDIOC_DQBUF, buf); if (ret < 0) { if (mDebugLogCnt == 0 || mDebugLogCnt >= 1500) { ALOGW("Camera[%d]GetPreviewFrame: VIDIOC_DQBUF Failed, %s, mCurAvailBufferCnt %d",mCameraId, strerror(errno), mCurAvailBufferCnt); if (mDebugLogCnt >= 1500) { mDebugLogCnt = 0; } } mDebugLogCnt++; return __LINE__; // can not return false } mDebugLogCnt = 0; testFrameRate(); return OK; } int V4L2CameraDevice::tryFmt(int format) { struct v4l2_fmtdesc fmtdesc; ALOGD("Camera[%d] %s enter",mCameraId,__FUNCTION__); fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (mCameraType == CAMERA_TYPE_CSI) { fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; } for(int i = 0; i < 12; i++) { fmtdesc.index = i; if (-1 == ioctl (mCameraFd, VIDIOC_ENUM_FMT, &fmtdesc)) { break; } ALOGD("Camera[%d]tryFmt index = %d, name = %s, v4l2 pixel format = %x\n",mCameraId, i, fmtdesc.description, fmtdesc.pixelformat); if (fmtdesc.pixelformat == format) { return OK; } } return -1; } int V4L2CameraDevice::tryFmtSize(int * width, int * height) { ALOGD("Camera[%d] %s enter",mCameraId,__FUNCTION__); int ret = -1; struct v4l2_format fmt; ALOGD("Camera[%d]Before tryFmtSize: w: %d, h: %d", mCameraId,*width, *height); memset(&fmt, 0, sizeof(fmt)); if (mCameraType == CAMERA_TYPE_CSI) { fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; fmt.fmt.pix_mp.pixelformat = mVideoFormat; fmt.fmt.pix_mp.width = *width; fmt.fmt.pix_mp.height = *height; fmt.fmt.pix_mp.field = V4L2_FIELD_NONE; fmt.fmt.pix_mp.pixelformat = mVideoFormat; } else { fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = *width; fmt.fmt.pix.height = *height; if(mCaptureFormat == V4L2_PIX_FMT_MJPEG) { fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; } else if (mCaptureFormat == V4L2_PIX_FMT_YUYV) { fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; } else if (mCaptureFormat == V4L2_PIX_FMT_H264) { fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_H264; } else { fmt.fmt.pix.pixelformat = mVideoFormat; } fmt.fmt.pix.field = V4L2_FIELD_NONE; } ret = ioctl(mCameraFd, VIDIOC_TRY_FMT, &fmt); if (ret < 0) { ALOGE("Camera[%d]VIDIOC_TRY_FMT Failed: %s", mCameraId,strerror(errno)); return ret; } // driver surpport this size if (mCameraType == CAMERA_TYPE_CSI) { *width = fmt.fmt.pix_mp.width; *height = fmt.fmt.pix_mp.height; } else { *width = fmt.fmt.pix.width; *height = fmt.fmt.pix.height; } ALOGD("Camera[%d]After tryFmtSize: w: %d, h: %d",mCameraId, *width, *height); return 0; } int V4L2CameraDevice::setFrameRate(int rate) { ALOGD("Camera[%d] %s rate:%d enter",mCameraId,__FUNCTION__,rate); mFrameRate = rate; return OK; } int V4L2CameraDevice::getFrameRate() { ALOGD("Camera[%d] %s enter",mCameraId,__FUNCTION__); int ret = -1; struct v4l2_streamparm parms; parms.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (mCameraType == CAMERA_TYPE_CSI) { parms.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; } ret = ioctl (mCameraFd, VIDIOC_G_PARM, &parms); if (ret < 0) { ALOGE("Camera[%d] getFrameRate VIDIOC_G_PARM error, %s",mCameraId, strerror(errno)); return ret; } int numerator = parms.parm.capture.timeperframe.numerator; int denominator = parms.parm.capture.timeperframe.denominator; if (numerator != 0 && denominator != 0) { ALOGD("Camera[id]getFrameRate:%d fps",mCameraId,denominator / numerator); return denominator / numerator; } else { ALOGW("Camera[id] unsupported frame return defualt:25fps",mCameraId); return 25; } } int V4L2CameraDevice::setImageEffect(int effect) { ALOGD("Camera[%d] %s enter",mCameraId,__FUNCTION__); int ret = -1; struct v4l2_control ctrl; ctrl.id = V4L2_CID_COLORFX; ctrl.value = effect; ret = ioctl(mCameraFd, VIDIOC_S_CTRL, &ctrl); if (ret < 0) ALOGE("Camera[%d] setImageEffect failed!",mCameraId); else ALOGD("Camera[%d] setImageEffect ok",mCameraId); return ret; } int V4L2CameraDevice::setWhiteBalance(int wb) { struct v4l2_control ctrl; int ret = -1; ALOGD("Camera[%d] %s enter",mCameraId,__FUNCTION__); ctrl.id = V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE; ctrl.value = wb; ret = ioctl(mCameraFd, VIDIOC_S_CTRL, &ctrl); if (ret < 0) ALOGE("Camera[%d] setWhiteBalance failed, %s",mCameraId, strerror(errno)); else ALOGD("Camera[%d] setWhiteBalance ok",mCameraId); return ret; } int V4L2CameraDevice::setTakePictureCtrl(enum v4l2_take_picture value) { struct v4l2_control ctrl; int ret = -1; ALOGD("Camera[%d] %s:%d enter",mCameraId,__FUNCTION__,value); if (mHalCameraInfo.fast_picture_mode) { ctrl.id = V4L2_CID_TAKE_PICTURE; ctrl.value = value; ret = ioctl(mCameraFd, VIDIOC_S_CTRL, &ctrl); if (ret < 0) ALOGE("Camera[%d] setTakePictureCtrl failed, %s", mCameraId,strerror(errno)); else ALOGD("Camera[%d] setTakePictureCtrl ok",mCameraId); return ret; } return 0; } // ae mode int V4L2CameraDevice::setExposureMode(int mode) { ALOGD("Camera[%d] %s:%d enter",mCameraId,__FUNCTION__,mode); int ret = -1; struct v4l2_control ctrl; ctrl.id = V4L2_CID_EXPOSURE_AUTO; ctrl.value = mode; ret = ioctl(mCameraFd, VIDIOC_S_CTRL, &ctrl); if (ret < 0) ALOGE("Camera[%d]setExposureMode failed, %s",mCameraId, strerror(errno)); else ALOGD("Camera[%d]setExposureMode ok",mCameraId); return ret; } // ae compensation int V4L2CameraDevice::setExposureCompensation(int val) { ALOGD("Camera[%d] %s enter",mCameraId,__FUNCTION__); int ret = -1; struct v4l2_control ctrl; mExposureBias = val; ctrl.id = V4L2_CID_AUTO_EXPOSURE_BIAS; ctrl.value = val + 4; ret = ioctl(mCameraFd, VIDIOC_S_CTRL, &ctrl); if (ret < 0) ALOGE("Camera[%d]setExposureCompensation failed, %s",mCameraId, strerror(errno)); else ALOGD("Camera[%d]setExposureCompensation ok",mCameraId); return ret; } int V4L2CameraDevice::setExposureWind(int num, void *wind) { F_LOG; int ret = -1; return ret; } // flash mode int V4L2CameraDevice::setFlashMode(int mode) { F_LOG; int ret = -1; struct v4l2_control ctrl; mFlashMode = mode; //scene mode must close the flash,eg: HDR,night mode //it ought to do in application,it must do it again here //in order to insure the status in driver. --by henrisk if(mSceneMode != NULL && \ (mSceneMode->GetCurrentSceneMode() == SCENE_FACTORY_MODE_HDR || \ mSceneMode->GetCurrentSceneMode() == SCENE_FACTORY_MODE_NIGHT)) mode = V4L2_FLASH_LED_MODE_NONE; ctrl.id = V4L2_CID_FLASH_LED_MODE; ctrl.value = mode; ret = ioctl(mCameraFd, VIDIOC_S_CTRL, &ctrl); if (ret < 0) ALOGE("setFlashMode failed, %s", strerror(errno)); else ALOGV("setFlashMode ok"); return ret; } // af init int V4L2CameraDevice::setAutoFocusInit() { F_LOG; int ret = -1; struct v4l2_control ctrl; if(mCameraType == CAMERA_TYPE_CSI) { ctrl.id = V4L2_CID_AUTO_FOCUS_INIT; ctrl.value = 0; ret = ioctl(mCameraFd, VIDIOC_S_CTRL, &ctrl); if (ret < 0) ALOGE("setAutoFocusInit failed, %s", strerror(errno)); else ALOGV("setAutoFocusInit ok"); } return ret; } // af release int V4L2CameraDevice::setAutoFocusRelease() { F_LOG; int ret = -1; struct v4l2_control ctrl; ctrl.id = V4L2_CID_AUTO_FOCUS_RELEASE; ret = ioctl(mCameraFd, VIDIOC_S_CTRL, &ctrl); if (ret < 0) ALOGE("setAutoFocusRelease failed, %s", strerror(errno)); else ALOGV("setAutoFocusRelease ok"); return ret; } // af range int V4L2CameraDevice::setAutoFocusRange(int af_range) { F_LOG; int ret = -1; struct v4l2_control ctrl; ctrl.id = V4L2_CID_FOCUS_AUTO; ctrl.value = 1; ret = ioctl(mCameraFd, VIDIOC_S_CTRL, &ctrl); if (ret < 0) ALOGV("setAutoFocusRange id V4L2_CID_FOCUS_AUTO failed, %s", strerror(errno)); else ALOGV("setAutoFocusRange id V4L2_CID_FOCUS_AUTO ok"); ctrl.id = V4L2_CID_AUTO_FOCUS_RANGE; ctrl.value = af_range; ret = ioctl(mCameraFd, VIDIOC_S_CTRL, &ctrl); if (ret < 0) ALOGV("setAutoFocusRange id V4L2_CID_AUTO_FOCUS_RANGE failed, %s", strerror(errno)); else ALOGV("setAutoFocusRange id V4L2_CID_AUTO_FOCUS_RANGE ok"); return ret; } // af wind #ifdef USE_SUNXI_CAMERA_H int V4L2CameraDevice::setAutoFocusWind(int num, void *wind) { F_LOG; int ret = -1; struct v4l2_win_setting set_para; set_para.win_num = num; set_para.coor[0] = *(struct v4l2_win_coordinate*)wind; ret = ioctl(mCameraFd, VIDIOC_AUTO_FOCUS_WIN, &set_para); if (ret < 0) ALOGD("setAutoFocusCtrl failed, %s", strerror(errno)); else ALOGV("setAutoFocusCtrl ok"); return ret; } #else int V4L2CameraDevice::setAutoFocusWind(int num, void *wind) { F_LOG; int ret = -1; #if 0 struct v4l2_control ctrl; ctrl.id = V4L2_CID_AUTO_FOCUS_WIN_NUM; ctrl.value = num; ctrl.user_pt = (unsigned int)wind; ret = ioctl(mCameraFd, VIDIOC_S_CTRL, &ctrl); if (ret < 0) ALOGD("setAutoFocusCtrl failed, %s", strerror(errno)); else ALOGV("setAutoFocusCtrl ok"); #endif return ret; } #endif // af start int V4L2CameraDevice::setAutoFocusStart() { F_LOG; int ret = -1; struct v4l2_control ctrl; ctrl.id = V4L2_CID_AUTO_FOCUS_START; ret = ioctl(mCameraFd, VIDIOC_S_CTRL, &ctrl); if (ret < 0) ALOGD("setAutoFocusStart failed, %s", strerror(errno)); else ALOGV("setAutoFocusStart ok"); return ret; } // af stop int V4L2CameraDevice::setAutoFocusStop() { F_LOG; int ret = -1; struct v4l2_control ctrl; ctrl.id = V4L2_CID_AUTO_FOCUS_STOP; ret = ioctl(mCameraFd, VIDIOC_S_CTRL, &ctrl); if (ret < 0) ALOGD("setAutoFocusStart failed, %s", strerror(errno)); else ALOGV("setAutoFocusStart ok"); return ret; } // get af statue int V4L2CameraDevice::getAutoFocusStatus() { //F_LOG; int ret = -1; struct v4l2_control ctrl; if (mCameraFd == NULL) { return 0xFF000000; } ctrl.id = V4L2_CID_AUTO_FOCUS_STATUS; ret = ioctl(mCameraFd, VIDIOC_G_CTRL, &ctrl); if (ret >= 0) { //ALOGV("getAutoFocusCtrl ok"); } return ret; } int V4L2CameraDevice::getSnrValue() { //F_LOG; int ret = -1; struct v4l2_control ctrl; struct v4l2_queryctrl qc_ctrl; if (mCameraFd == NULL) { return 0xFF000000; } ctrl.id = V4L2_CID_GAIN; qc_ctrl.id = V4L2_CID_GAIN; if (-1 == ioctl (mCameraFd, VIDIOC_QUERYCTRL, &qc_ctrl)) { return 0; } ret = ioctl(mCameraFd, VIDIOC_G_CTRL, &ctrl); return ctrl.value; } int V4L2CameraDevice::getGainValue() //get gain (trait specially, need the last 8 bits) { //F_LOG; int ret = -1; struct v4l2_control ctrl; struct v4l2_queryctrl qc_ctrl; if (mCameraFd == NULL) { return 0xFF000000; } ctrl.id = V4L2_CID_GAIN; qc_ctrl.id = V4L2_CID_GAIN; if (-1 == ioctl (mCameraFd, VIDIOC_QUERYCTRL, &qc_ctrl)) { return 0; } ret = ioctl(mCameraFd, VIDIOC_G_CTRL, &ctrl); ctrl.value = ctrl.value &0xff; return ctrl.value; } int V4L2CameraDevice::getExpValue() //get gain (trait specially, need the last 8 bits) { //F_LOG; int ret = -1; struct v4l2_control ctrl; struct v4l2_queryctrl qc_ctrl; if (mCameraFd == NULL) { return 0xFF000000; } ctrl.id = V4L2_CID_EXPOSURE; qc_ctrl.id = V4L2_CID_EXPOSURE; if (-1 == ioctl (mCameraFd, VIDIOC_QUERYCTRL, &qc_ctrl)) { return 0; } ret = ioctl(mCameraFd, VIDIOC_G_CTRL, &ctrl); return ctrl.value; } #ifdef USE_SUNXI_CAMERA_H int V4L2CameraDevice::setHDRMode(void *hdr_setting) { int ret = -1; struct isp_hdr_ctrl hdr_ctrl; hdr_ctrl.flag = HDR_CTRL_SET; hdr_ctrl.count = 0; hdr_ctrl.hdr_t = *(struct isp_hdr_setting_t*)hdr_setting; if (mCameraFd == NULL) { return 0xFF000000; } ret = ioctl(mCameraFd, VIDIOC_HDR_CTRL, &hdr_ctrl); return ret; } #else int V4L2CameraDevice::setHDRMode(void *hdr_setting) { int ret = -1; #if 0 struct v4l2_control ctrl; struct v4l2_queryctrl qc_ctrl; ctrl.value = 0; ctrl.user_pt = (unsigned int)hdr_setting; if (mCameraFd == NULL) { return 0xFF000000; } ctrl.id = V4L2_CID_HDR; qc_ctrl.id = V4L2_CID_HDR; if (-1 == ioctl (mCameraFd, VIDIOC_QUERYCTRL, &qc_ctrl)) { return 0; } ret = ioctl(mCameraFd, VIDIOC_S_CTRL, &ctrl); #endif return ret; } #endif int V4L2CameraDevice::getAeStat(struct isp_stat_buf *AeBuf) { int ret = -1; if (mCameraFd == NULL) { return 0xFF000000; } //AeBuf->buf = malloc(0xc00); //memset(AeBuf->buf,0,0xc00); //ALOGD("AeBuf->buf == %x\n",AeBuf->buf); if(AeBuf->buf == NULL){ return -1; } ret = ioctl(mCameraFd, VIDIOC_ISP_AE_STAT_REQ, AeBuf); return ret; } int V4L2CameraDevice::getGammaStat(struct isp_stat_buf *GammaBuf) { int ret = -1; #if 1 if (mCameraFd == NULL) { return 0xFF000000; } GammaBuf->buf = malloc(0x200); memset(GammaBuf->buf,0,0x200); ALOGD("GammaBuf->buf == %x\n",GammaBuf->buf); if(GammaBuf->buf == NULL){ return -1; } //ret = ioctl(mCameraFd, VIDIOC_ISP_GAMMA_REQ, GammaBuf); #endif return ret; } int V4L2CameraDevice::getHistStat(struct isp_stat_buf *HistBuf) { int ret = -1; if (mCameraFd == NULL) { return 0xFF000000; } //HistBuf->buf = malloc(0x200); //memset(HistBuf->buf,0,0x200); if(HistBuf->buf == NULL){ return -1; } ret = ioctl(mCameraFd, VIDIOC_ISP_HIST_STAT_REQ, HistBuf); return ret; } int V4L2CameraDevice::setGainValue(int Gain) { F_LOG; int ret = -1; struct v4l2_control ctrl; ctrl.id = V4L2_CID_GAIN; ctrl.value = Gain; ret = ioctl(mCameraFd, VIDIOC_S_CTRL, &ctrl); if (ret < 0) ALOGD("setGain failed, %s", strerror(errno)); else ALOGV("setGain ok"); return ret; } int V4L2CameraDevice::setExpValue(int Exp) { F_LOG; int ret = -1; struct v4l2_control ctrl; ctrl.id = V4L2_CID_EXPOSURE; ctrl.value = Exp; ret = ioctl(mCameraFd, VIDIOC_S_CTRL, &ctrl); if (ret < 0) ALOGD("Set V4L2_CID_EXPOSURE failed, %s", strerror(errno)); else ALOGV("Set V4L2_CID_EXPOSURE ok"); return ret; } int V4L2CameraDevice::set3ALock(int lock) { F_LOG; int ret = -1; struct v4l2_control ctrl; ctrl.id = V4L2_CID_3A_LOCK; ctrl.value = lock; ret = ioctl(mCameraFd, VIDIOC_S_CTRL, &ctrl); if (ret >= 0) ALOGV("set3ALock ok"); return ret; } int V4L2CameraDevice::v4l2setCaptureParams() { ALOGD("Camera[%d] %s enter",mCameraId,__FUNCTION__); int ret = -1; struct v4l2_streamparm params; memset(&(params), 0, sizeof (params)); params.parm.capture.timeperframe.numerator = 1; params.parm.capture.timeperframe.denominator = mFrameRate; params.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; params.parm.capture.reserved[0] = 0;/*when different video have the same sensor source, 1:use sensor current win, 0:find the nearest win*/ params.parm.capture.reserved[1] = 0;/*2:command, 1: wdr, 0: normal*/ if (mCameraType == CAMERA_TYPE_CSI) { params.parm.capture.reserved[0] = 0; params.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; } if (mTakePictureState == TAKE_PICTURE_NORMAL) { params.parm.capture.capturemode = V4L2_MODE_IMAGE; } else { if(mVideoHint == true) { params.parm.capture.capturemode = V4L2_MODE_VIDEO; } else { params.parm.capture.capturemode = V4L2_MODE_PREVIEW; } } ALOGD("Camera[%d]v4l2setCaptureParams rate:%d fps,capture mode:%d", mCameraId,mFrameRate, params.parm.capture.capturemode); ret = ioctl(mCameraFd, VIDIOC_S_PARM, ¶ms); if (ret < 0) ALOGE("Camera[%d]v4l2setCaptureParams failed, %s", mCameraId,strerror(errno)); else ALOGD("Camera[%d]v4l2setCaptureParams ok",mCameraId); return ret; } int V4L2CameraDevice::enumSize(char * pSize, int len) { ALOGD("Camera[%d] %s enter",mCameraId,__FUNCTION__); struct v4l2_frmsizeenum size_enum; size_enum.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (mCameraType == CAMERA_TYPE_CSI) { size_enum.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; } size_enum.pixel_format = mCaptureFormat; if (pSize == NULL) { ALOGE("Camera[%d]error input params",mCameraId); return -1; } char str[16]; memset(str, 0, 16); memset(pSize, 0, len); for(int i = 0; i < 20; i++) { size_enum.index = i; if (-1 == ioctl (mCameraFd, VIDIOC_ENUM_FRAMESIZES, &size_enum)) { break; } // ALOGV("format index = %d, size_enum: %dx%d", i, size_enum.discrete.width, size_enum.discrete.height); sprintf(str, "%dx%d", size_enum.discrete.width, size_enum.discrete.height); if (i != 0) { strcat(pSize, ","); } strcat(pSize, str); } ALOGD("Camera[%d] enumSize:%s end",mCameraId,pSize); return OK; } int V4L2CameraDevice::getFullSize(int * full_w, int * full_h) { ALOGD("Camera[%d] %s enter",mCameraId,__FUNCTION__); struct v4l2_frmsizeenum size_enum; size_enum.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (mCameraType == CAMERA_TYPE_CSI) { size_enum.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; } size_enum.pixel_format = mCaptureFormat; size_enum.index = 0; if (-1 == ioctl (mCameraFd, VIDIOC_ENUM_FRAMESIZES, &size_enum)) { ALOGE("Camera[%d]getFullSize failed",mCameraId); return -1; } *full_w = size_enum.discrete.width; *full_h = size_enum.discrete.height; ALOGD("Camera[%d] getFullSize: %dx%d end",mCameraId, *full_w, *full_h); return OK; } int V4L2CameraDevice::getSuitableThumbScale(int full_w, int full_h) { ALOGD("Camera[%d] %s enter",mCameraId,__FUNCTION__); int scale = 1; if(mIsThumbUsedForVideo == true) { scale = 2; } //TODO: Get the screen size to calculate the scaler factor if (full_w*full_h > 10*1024*1024) //maybe 12m,13m,16m return 2; else if(full_w*full_h > 4.5*1024*1024) //maybe 5m,8m return 2; else return scale; //others #if 0 if ((full_w == 4608) && (full_h == 3456)) { return 4; // 1000x750 } if ((full_w == 3840) && (full_h == 2160)) { return 4; // 1000x750 } if ((full_w == 4000) && (full_h == 3000)) { return 4; // 1000x750 } else if ((full_w == 3264) && (full_h == 2448)) { return 2; // 1632x1224 } else if ((full_w == 2592) && (full_h == 1936)) { return 2; // 1296x968 } else if ((full_w == 1280) && (full_h == 960)) { return 1 * scale; // 1280x960 } else if ((full_w == 1920) && (full_h == 1080)) { return 2; // 960x540 } else if ((full_w == 1280) && (full_h == 720)) { return 1 * scale; // 1280x720 } else if ((full_w == 640) && (full_h == 480)) { return 1; // 640x480 } LOGW("getSuitableThumbScale unknown size: %dx%d", full_w, full_h); return 1; // failed #endif } void V4L2CameraDevice::getThumbSize(int* sub_w, int* sub_h) { ALOGD("Camera[%d] %s:%dx%d enter",mCameraId,__FUNCTION__,mThumbWidth,mThumbHeight); *sub_w= mThumbWidth; *sub_h= mThumbHeight; } int V4L2CameraDevice::getSensorType() { F_LOG; int ret = -1; struct v4l2_control ctrl; struct v4l2_queryctrl qc_ctrl; if (mCameraFd == NULL) { return 0xFF000000; } ctrl.id = V4L2_CID_SENSOR_TYPE; qc_ctrl.id = V4L2_CID_SENSOR_TYPE; if (-1 == ioctl (mCameraFd, VIDIOC_QUERYCTRL, &qc_ctrl)) { ALOGD("query sensor type ctrl failed"); return -1; } ret = ioctl(mCameraFd, VIDIOC_G_CTRL, &ctrl); return ctrl.value; } int V4L2CameraDevice::getExifInfo(struct isp_exif_attribute *exif_attri) { int ret = -1; if (mCameraFd == NULL) { return 0xFF000000; } ret = ioctl(mCameraFd, VIDIOC_ISP_EXIF_REQ, exif_attri); if(exif_attri->focal_length < -1) { exif_attri->focal_length = 100; } return ret; } int V4L2CameraDevice::getCameraType() { return mCameraType; } #ifdef CAMERA_MANAGER_ENABLE void V4L2CameraDevice::setCameraManager(CameraManager * manager) { ALOGD("Camera[%d]setCameraManager manager=0x%x",mCameraId,manager); mCameraManager = manager; } void V4L2CameraDevice::startPreview_d() { //ALOGD("CameraDebug,F:%s,L:%d,id:%d,En:%d",__FUNCTION__,__LINE__,mHalCameraInfo.device_id,mCameraManager->isOviewEnable()); ALOGD("Camera[%d] %s enter",mCameraId,__FUNCTION__); if((mCameraManager != NULL) && (mCameraManager->isOviewEnable()) && (mHalCameraInfo.device_id == mCameraManager->mStartCameraID)) { mCameraManager->startPreview(); ALOGD("Camera[%d]F:%s,L:%d",mCameraId,__FUNCTION__,__LINE__); } } void V4L2CameraDevice::stopPreview_d() { ALOGD("Camera[%d] %s enter",mCameraId,__FUNCTION__); if((mCameraManager != NULL) && (mCameraManager->isOviewEnable()) && (mHalCameraInfo.device_id == mCameraManager->mStartCameraID)) { mCameraManager->stopPreview(); ALOGD("Camera[%d]F:%s,L:%d",mCameraId,__FUNCTION__,__LINE__); } } void V4L2CameraDevice::releaseCamera_d() { ALOGD("Camera[%d] %s enter",mCameraId,__FUNCTION__); if((mCameraManager != NULL) && (mCameraManager->isOviewEnable()) && (mHalCameraInfo.device_id == mCameraManager->mStartCameraID)) { mCameraManager->releaseCamera(); ALOGD("Camera[%d]F:%s,L:%d",mCameraId,__FUNCTION__,__LINE__); } } void V4L2CameraDevice::takePicInputBuffer(V4L2BUF_t *pic_buffer) { int ret; ret = OSAL_Queue(&mQueueBufferPicture, pic_buffer); if (ret != 0) { ALOGW("Camera[%d]Rec queue full",mCameraId); return; } struct isp_exif_attribute exif_attri; getExifInfo(&exif_attri); mCallbackNotifier->setExifInfo(exif_attri, mZoomRatio, mExposureBias); mCameraHardware->setExifInfo(exif_attri); mTakePictureState = TAKE_PICTURE_NULL; pthread_cond_signal(&mPictureCond); } #endif }; /* namespace android */