| /* |
| ** Copyright (c) 2011-2012 The Linux Foundation. All rights reserved. |
| ** |
| ** Licensed under the Apache License, Version 2.0 (the "License"); |
| ** you may not use this file except in compliance with the License. |
| ** You may obtain a copy of the License at |
| ** |
| ** http://www.apache.org/licenses/LICENSE-2.0 |
| ** |
| ** Unless required by applicable law or agreed to in writing, software |
| ** distributed under the License is distributed on an "AS IS" BASIS, |
| ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| ** See the License for the specific language governing permissions and |
| ** limitations under the License. |
| */ |
| |
| /*#error uncomment this for compiler test!*/ |
| #define ALOG_NIDEBUG 0 |
| |
| #define LOG_TAG "QCameraHWI" |
| #include <utils/Log.h> |
| #include <utils/threads.h> |
| #include <cutils/properties.h> |
| #include <fcntl.h> |
| #include <sys/mman.h> |
| #include <string.h> |
| #include <dlfcn.h> |
| |
| #include "QCameraHAL.h" |
| #include "QCameraHWI.h" |
| |
| /* QCameraHardwareInterface class implementation goes here*/ |
| /* following code implement the contol logic of this class*/ |
| |
| namespace android { |
| static void HAL_event_cb(mm_camera_event_t *evt, void *user_data) |
| { |
| QCameraHardwareInterface *obj = (QCameraHardwareInterface *)user_data; |
| if (obj) { |
| obj->processEvent(evt); |
| } else { |
| ALOGE("%s: NULL user_data", __func__); |
| } |
| } |
| |
| int32_t QCameraHardwareInterface::createRecord() |
| { |
| int32_t ret = MM_CAMERA_OK; |
| ALOGV("%s : BEGIN",__func__); |
| |
| /* |
| * Creating Instance of record stream. |
| */ |
| ALOGV("Mymode Record = %d",myMode); |
| mStreamRecord = QCameraStream_record::createInstance(mCameraId, |
| myMode); |
| |
| if (!mStreamRecord) { |
| ALOGE("%s: error - can't creat record stream!", __func__); |
| return BAD_VALUE; |
| } |
| |
| /* Store HAL object in record stream Object */ |
| mStreamRecord->setHALCameraControl(this); |
| |
| /*Init Channel */ |
| ret = mStreamRecord->init(); |
| if (MM_CAMERA_OK != ret){ |
| ALOGE("%s: error - can't init Record channel!", __func__); |
| return BAD_VALUE; |
| } |
| ALOGV("%s : END",__func__); |
| return ret; |
| } |
| |
| int32_t QCameraHardwareInterface::createSnapshot() |
| { |
| int32_t ret = MM_CAMERA_OK; |
| ALOGV("%s : BEGIN",__func__); |
| |
| /* |
| * Creating Instance of Snapshot stream. |
| */ |
| ALOGV("Mymode Snap = %d",myMode); |
| mStreamSnap = QCameraStream_Snapshot::createInstance(mCameraId, |
| myMode); |
| if (!mStreamSnap) { |
| ALOGE("%s: error - can't creat snapshot stream!", __func__); |
| return BAD_VALUE; |
| } |
| |
| /* Store HAL object in Snapshot stream Object */ |
| mStreamSnap->setHALCameraControl(this); |
| |
| /*Init Channel */ |
| ret = mStreamSnap->init(); |
| if (MM_CAMERA_OK != ret){ |
| ALOGE("%s: error - can't init Snapshot channel!", __func__); |
| return BAD_VALUE; |
| } |
| ALOGV("%s : END",__func__); |
| return ret; |
| } |
| |
| int32_t QCameraHardwareInterface::createPreview() |
| { |
| int32_t ret = MM_CAMERA_OK; |
| ALOGV("%s : BEGIN",__func__); |
| |
| ALOGV("Mymode Preview = %d",myMode); |
| mStreamDisplay = QCameraStream_preview::createInstance(mCameraId, |
| myMode); |
| if (!mStreamDisplay) { |
| ALOGE("%s: error - can't creat preview stream!", __func__); |
| return BAD_VALUE; |
| } |
| |
| mStreamDisplay->setHALCameraControl(this); |
| |
| /*now init all the buffers and send to steam object*/ |
| ret = mStreamDisplay->init(); |
| if (MM_CAMERA_OK != ret){ |
| ALOGE("%s: error - can't init Preview channel!", __func__); |
| return BAD_VALUE; |
| } |
| ALOGV("%s : END",__func__); |
| return ret; |
| } |
| |
| /* constructor */ |
| QCameraHardwareInterface:: |
| QCameraHardwareInterface(int cameraId, int mode) |
| : mCameraId(cameraId), |
| mParameters(), |
| mMsgEnabled(0), |
| mNotifyCb(0), |
| mDataCb(0), |
| mDataCbTimestamp(0), |
| mCallbackCookie(0), |
| //mPreviewHeap(0), |
| mStreamDisplay (NULL), mStreamRecord(NULL), mStreamSnap(NULL), |
| mFps(0), |
| mDebugFps(0), |
| mMaxZoom(0), |
| mCurrentZoom(0), |
| mSupportedPictureSizesCount(15), |
| mDumpFrmCnt(0), mDumpSkipCnt(0), |
| mPictureSizeCount(15), |
| mPreviewSizeCount(13), |
| mVideoSizeCount(0), |
| mAutoFocusRunning(false), |
| mNeedToUnlockCaf(false), |
| mHasAutoFocusSupport(false), |
| mInitialized(false), |
| mIs3DModeOn(0), |
| mSmoothZoomRunning(false), |
| mParamStringInitialized(false), |
| mFaceDetectOn(0), |
| mDisEnabled(0), |
| mZoomSupported(false), |
| mFullLiveshotEnabled(false), |
| mRecordingHint(false), |
| mAppRecordingHint(false), |
| mStatsOn(0), mCurrentHisto(-1), mSendData(false), mStatHeap(NULL), |
| mZslLookBackMode(0), |
| mZslLookBackValue(0), |
| mZslEmptyQueueFlag(false), |
| mPictureSizes(NULL), |
| mVideoSizes(NULL), |
| mCameraState(CAMERA_STATE_UNINITED), |
| mPostPreviewHeap(NULL), |
| mHdrMode(HDR_BRACKETING_OFF), |
| mStreamLiveSnap(NULL), |
| mExifTableNumEntries(0), |
| mDenoiseValue(0), |
| mSnapshotFormat(0), |
| mStartRecording(0), |
| mZslInterval(1), |
| mNoDisplayMode(0), |
| mBrightness(0), |
| mContrast(0), |
| mEffects(0), |
| mBestShotMode(0), |
| mHJR(0), |
| mSkinToneEnhancement(0), |
| mRotation(0), |
| mFocusMode(AF_MODE_MAX), |
| mPreviewFormat(CAMERA_YUV_420_NV21), |
| mRestartPreview(false), |
| mReleasedRecordingFrame(false), |
| mStateLiveshot(false), |
| isCameraOpen(false), |
| mPauseFramedispatch(false) |
| { |
| ALOGV("QCameraHardwareInterface: E"); |
| int32_t result = MM_CAMERA_E_GENERAL; |
| char value[PROPERTY_VALUE_MAX]; |
| |
| pthread_mutex_init(&mAsyncCmdMutex, NULL); |
| pthread_cond_init(&mAsyncCmdWait, NULL); |
| mFlashCond = false; |
| |
| property_get("persist.debug.sf.showfps", value, "0"); |
| mDebugFps = atoi(value); |
| mPreviewState = QCAMERA_HAL_PREVIEW_STOPPED; |
| mPreviewWindow = NULL; |
| property_get("camera.hal.fps", value, "0"); |
| mFps = atoi(value); |
| |
| ALOGV("Init mPreviewState = %d", mPreviewState); |
| |
| property_get("persist.camera.hal.multitouchaf", value, "0"); |
| mMultiTouch = atoi(value); |
| |
| property_get("persist.camera.full.liveshot", value, "0"); |
| mFullLiveshotEnabled = atoi(value); |
| |
| property_get("persist.camera.hal.dis", value, "0"); |
| mDisEnabled = atoi(value); |
| |
| /* Open camera stack! */ |
| result=cam_ops_open(mCameraId, MM_CAMERA_OP_MODE_NOTUSED); |
| if (result == MM_CAMERA_OK) { |
| int i; |
| mm_camera_event_type_t evt; |
| for (i = 0; i < MM_CAMERA_EVT_TYPE_MAX; i++) { |
| evt = (mm_camera_event_type_t) i; |
| if (cam_evt_is_event_supported(mCameraId, evt)){ |
| cam_evt_register_event_notify(mCameraId, |
| HAL_event_cb, (void *)this, evt); |
| } |
| } |
| } |
| ALOGV("Cam open returned %d",result); |
| if(MM_CAMERA_OK != result) { |
| ALOGE("startCamera: cam_ops_open failed: id = %d", mCameraId); |
| return; |
| } |
| |
| loadTables(); |
| /* Setup Picture Size and Preview size tables */ |
| setPictureSizeTable(); |
| ALOGV("%s: Picture table size: %d", __func__, mPictureSizeCount); |
| ALOGV("%s: Picture table: ", __func__); |
| for(unsigned int i=0; i < mPictureSizeCount;i++) { |
| ALOGV(" %d %d", mPictureSizes[i].width, mPictureSizes[i].height); |
| } |
| |
| setPreviewSizeTable(); |
| ALOGV("%s: Preview table size: %d", __func__, mPreviewSizeCount); |
| ALOGV("%s: Preview table: ", __func__); |
| for(unsigned int i=0; i < mPreviewSizeCount;i++) { |
| ALOGV(" %d %d", mPreviewSizes[i].width, mPreviewSizes[i].height); |
| } |
| |
| setVideoSizeTable(); |
| ALOGV("%s: Video table size: %d", __func__, mVideoSizeCount); |
| ALOGV("%s: Video table: ", __func__); |
| for(unsigned int i=0; i < mVideoSizeCount;i++) { |
| ALOGV(" %d %d", mVideoSizes[i].width, mVideoSizes[i].height); |
| } |
| |
| isCameraOpen = true; |
| /* set my mode - update myMode member variable due to difference in |
| enum definition between upper and lower layer*/ |
| setMyMode(mode); |
| initDefaultParameters(); |
| |
| //Create Stream Objects |
| //Preview |
| result = createPreview(); |
| if(result != MM_CAMERA_OK) { |
| ALOGE("%s X: Failed to create Preview Object",__func__); |
| return; |
| } |
| |
| //Record |
| result = createRecord(); |
| if(result != MM_CAMERA_OK) { |
| ALOGE("%s X: Failed to create Record Object",__func__); |
| return; |
| } |
| |
| //Snapshot |
| result = createSnapshot(); |
| if(result != MM_CAMERA_OK) { |
| ALOGE("%s X: Failed to create Record Object",__func__); |
| return; |
| } |
| mCameraState = CAMERA_STATE_READY; |
| libdnr = dlopen("libmorpho_noise_reduction.so", RTLD_NOW); |
| if (libdnr) { |
| ALOGV("Open MM camera DL libmorpho_noise_reduction loaded at %p & %p ", libdnr); |
| *(void **)&LINK_morpho_DNR_ProcessFrame = dlsym(libdnr, "LINK_mm_camera_morpho_noise_reduction"); |
| } |
| else |
| ALOGE("failed to open libmorpho_noise_reduction"); |
| |
| ALOGV("QCameraHardwareInterface: X"); |
| } |
| |
| QCameraHardwareInterface::~QCameraHardwareInterface() |
| { |
| ALOGV("~QCameraHardwareInterface: E"); |
| int result; |
| |
| switch(mPreviewState) { |
| case QCAMERA_HAL_PREVIEW_STOPPED: |
| break; |
| case QCAMERA_HAL_PREVIEW_START: |
| break; |
| case QCAMERA_HAL_PREVIEW_STARTED: |
| stopPreview(); |
| break; |
| case QCAMERA_HAL_RECORDING_STARTED: |
| stopRecordingInternal(); |
| stopPreview(); |
| break; |
| case QCAMERA_HAL_TAKE_PICTURE: |
| cancelPictureInternal(); |
| break; |
| default: |
| break; |
| } |
| mPreviewState = QCAMERA_HAL_PREVIEW_STOPPED; |
| |
| if (isCameraOpen) { |
| freePictureTable(); |
| freeVideoSizeTable(); |
| if(mStatHeap != NULL) { |
| mStatHeap.clear( ); |
| mStatHeap = NULL; |
| } |
| } |
| /* Join the threads, complete operations and then delete |
| the instances. */ |
| cam_ops_close(mCameraId); |
| if(mStreamDisplay){ |
| QCameraStream_preview::deleteInstance (mStreamDisplay); |
| mStreamDisplay = NULL; |
| } |
| if(mStreamRecord) { |
| QCameraStream_record::deleteInstance (mStreamRecord); |
| mStreamRecord = NULL; |
| } |
| if(mStreamSnap) { |
| QCameraStream_Snapshot::deleteInstance (mStreamSnap); |
| mStreamSnap = NULL; |
| } |
| if (libdnr != NULL) { |
| dlclose(libdnr); |
| libdnr = NULL; |
| ALOGV("closed libmorpho_noise_reduction.so"); |
| } |
| |
| if (mStreamLiveSnap){ |
| QCameraStream_Snapshot::deleteInstance (mStreamLiveSnap); |
| mStreamLiveSnap = NULL; |
| } |
| |
| pthread_mutex_destroy(&mAsyncCmdMutex); |
| pthread_cond_destroy(&mAsyncCmdWait); |
| isCameraOpen = false; |
| |
| ALOGV("~QCameraHardwareInterface: X"); |
| } |
| |
| bool QCameraHardwareInterface::isCameraReady() |
| { |
| ALOGV("isCameraReady mCameraState %d", mCameraState); |
| return (mCameraState == CAMERA_STATE_READY); |
| } |
| |
| void QCameraHardwareInterface::release() |
| { |
| ALOGV("release: E"); |
| Mutex::Autolock l(&mLock); |
| |
| switch(mPreviewState) { |
| case QCAMERA_HAL_PREVIEW_STOPPED: |
| break; |
| case QCAMERA_HAL_PREVIEW_START: |
| break; |
| case QCAMERA_HAL_PREVIEW_STARTED: |
| stopPreviewInternal(); |
| break; |
| case QCAMERA_HAL_RECORDING_STARTED: |
| stopRecordingInternal(); |
| stopPreviewInternal(); |
| break; |
| case QCAMERA_HAL_TAKE_PICTURE: |
| cancelPictureInternal(); |
| break; |
| default: |
| break; |
| } |
| #if 0 |
| if (isRecordingRunning()) { |
| stopRecordingInternal(); |
| ALOGI("release: stopRecordingInternal done."); |
| } |
| if (isPreviewRunning()) { |
| stopPreview(); //stopPreviewInternal(); |
| ALOGI("release: stopPreviewInternal done."); |
| } |
| if (isSnapshotRunning()) { |
| cancelPictureInternal(); |
| ALOGI("release: cancelPictureInternal done."); |
| } |
| if (mCameraState == CAMERA_STATE_ERROR) { |
| //TBD: If Error occurs then tear down |
| ALOGI("release: Tear down."); |
| } |
| #endif |
| mPreviewState = QCAMERA_HAL_PREVIEW_STOPPED; |
| ALOGV("release: X"); |
| } |
| |
| void QCameraHardwareInterface::setCallbacks( |
| camera_notify_callback notify_cb, |
| camera_data_callback data_cb, |
| camera_data_timestamp_callback data_cb_timestamp, |
| camera_request_memory get_memory, |
| void *user) |
| { |
| ALOGV("setCallbacks: E"); |
| Mutex::Autolock lock(mLock); |
| mNotifyCb = notify_cb; |
| mDataCb = data_cb; |
| mDataCbTimestamp = data_cb_timestamp; |
| mGetMemory = get_memory; |
| mCallbackCookie = user; |
| ALOGV("setCallbacks: X"); |
| } |
| |
| void QCameraHardwareInterface::enableMsgType(int32_t msgType) |
| { |
| ALOGV("enableMsgType: E, msgType =0x%x", msgType); |
| Mutex::Autolock lock(mLock); |
| mMsgEnabled |= msgType; |
| ALOGV("enableMsgType: X, msgType =0x%x, mMsgEnabled=0x%x", msgType, mMsgEnabled); |
| } |
| |
| void QCameraHardwareInterface::disableMsgType(int32_t msgType) |
| { |
| ALOGV("disableMsgType: E"); |
| Mutex::Autolock lock(mLock); |
| mMsgEnabled &= ~msgType; |
| ALOGV("disableMsgType: X, msgType =0x%x, mMsgEnabled=0x%x", msgType, mMsgEnabled); |
| } |
| |
| int QCameraHardwareInterface::msgTypeEnabled(int32_t msgType) |
| { |
| ALOGV("msgTypeEnabled: E"); |
| Mutex::Autolock lock(mLock); |
| return (mMsgEnabled & msgType); |
| ALOGV("msgTypeEnabled: X"); |
| } |
| #if 0 |
| status_t QCameraHardwareInterface::dump(int fd, const Vector<String16>& args) const |
| { |
| ALOGI("dump: E"); |
| const size_t SIZE = 256; |
| char buffer[SIZE]; |
| String8 result; |
| AutoMutex lock(&mLock); |
| write(fd, result.string(), result.size()); |
| ALOGI("dump: E"); |
| return NO_ERROR; |
| } |
| #endif |
| |
| int QCameraHardwareInterface::dump(int fd) |
| { |
| ALOGE("%s: not supported yet", __func__); |
| return -1; |
| } |
| |
| status_t QCameraHardwareInterface::sendCommand(int32_t command, int32_t arg1, |
| int32_t arg2) |
| { |
| ALOGV("sendCommand: E"); |
| status_t rc = NO_ERROR; |
| Mutex::Autolock l(&mLock); |
| |
| switch (command) { |
| case CAMERA_CMD_START_FACE_DETECTION: |
| if(supportsFaceDetection() == false){ |
| ALOGE("Face detection support is not available"); |
| return NO_ERROR; |
| } |
| setFaceDetection("on"); |
| return runFaceDetection(); |
| case CAMERA_CMD_STOP_FACE_DETECTION: |
| if(supportsFaceDetection() == false){ |
| ALOGE("Face detection support is not available"); |
| return NO_ERROR; |
| } |
| setFaceDetection("off"); |
| return runFaceDetection(); |
| |
| #if 0 |
| case CAMERA_CMD_HISTOGRAM_ON: |
| ALOGE("histogram set to on"); |
| rc = setHistogram(1); |
| break; |
| case CAMERA_CMD_HISTOGRAM_OFF: |
| ALOGE("histogram set to off"); |
| rc = setHistogram(0); |
| break; |
| case CAMERA_CMD_HISTOGRAM_SEND_DATA: |
| ALOGE("histogram send data"); |
| mSendData = true; |
| rc = NO_ERROR; |
| break; |
| case CAMERA_CMD_SEND_META_DATA: |
| mMetaDataWaitLock.lock(); |
| if(mFaceDetectOn == true) { |
| mSendMetaData = true; |
| } |
| mMetaDataWaitLock.unlock(); |
| return NO_ERROR; |
| #endif |
| #if 0 /* To Do: will enable it later */ |
| case CAMERA_CMD_START_SMOOTH_ZOOM : |
| ALOGV("HAL sendcmd start smooth zoom %d %d", arg1 , arg2); |
| /*TO DO: get MaxZoom from parameter*/ |
| int MaxZoom = 100; |
| |
| switch(mCameraState ) { |
| case CAMERA_STATE_PREVIEW: |
| case CAMERA_STATE_RECORD_CMD_SENT: |
| case CAMERA_STATE_RECORD: |
| mTargetSmoothZoom = arg1; |
| mCurrentZoom = mParameters.getInt("zoom"); |
| mSmoothZoomStep = (mCurrentZoom > mTargetSmoothZoom)? -1: 1; |
| if(mCurrentZoom == mTargetSmoothZoom) { |
| ALOGV("Smoothzoom target zoom value is same as " |
| "current zoom value, return..."); |
| mNotifyCallback(CAMERA_MSG_ZOOM, |
| mCurrentZoom, 1, mCallbackCookie); |
| } else if(mCurrentZoom < 0 || mCurrentZoom > MaxZoom || |
| mTargetSmoothZoom < 0 || mTargetSmoothZoom > MaxZoom) { |
| ALOGE(" ERROR : beyond supported zoom values, break.."); |
| mNotifyCallback(CAMERA_MSG_ZOOM, |
| mCurrentZoom, 0, mCallbackCookie); |
| } else { |
| mSmoothZoomRunning = true; |
| mCurrentZoom += mSmoothZoomStep; |
| if ((mSmoothZoomStep < 0 && mCurrentZoom < mTargetSmoothZoom)|| |
| (mSmoothZoomStep > 0 && mCurrentZoom > mTargetSmoothZoom )) { |
| mCurrentZoom = mTargetSmoothZoom; |
| } |
| mParameters.set("zoom", mCurrentZoom); |
| setZoom(mParameters); |
| } |
| break; |
| default: |
| ALOGV(" No preview, no smoothzoom "); |
| break; |
| } |
| rc = NO_ERROR; |
| break; |
| |
| case CAMERA_CMD_STOP_SMOOTH_ZOOM: |
| if(mSmoothZoomRunning) { |
| mSmoothZoomRunning = false; |
| /*To Do: send cmd to stop zooming*/ |
| } |
| ALOGV("HAL sendcmd stop smooth zoom"); |
| rc = NO_ERROR; |
| break; |
| #endif |
| default: |
| break; |
| } |
| ALOGV("sendCommand: X"); |
| return rc; |
| } |
| |
| void QCameraHardwareInterface::setMyMode(int mode) |
| { |
| ALOGV("setMyMode: E"); |
| //if (mode & CAMERA_SUPPORT_MODE_3D) { |
| // myMode = CAMERA_MODE_3D; |
| //}else { |
| /* default mode is 2D */ |
| myMode = CAMERA_MODE_2D; |
| //} |
| |
| //if (mode & CAMERA_SUPPORT_MODE_ZSL) { |
| // myMode = (camera_mode_t)(myMode |CAMERA_ZSL_MODE); |
| //}else { |
| myMode = (camera_mode_t) (myMode | CAMERA_NONZSL_MODE); |
| //} |
| ALOGV("setMyMode: Set mode to %d (passed mode: %d)", myMode, mode); |
| ALOGV("setMyMode: X"); |
| } |
| /* static factory function */ |
| QCameraHardwareInterface *QCameraHardwareInterface::createInstance(int cameraId, int mode) |
| { |
| ALOGV("createInstance: E"); |
| QCameraHardwareInterface *cam = new QCameraHardwareInterface(cameraId, mode); |
| if (cam ) { |
| if (cam->mCameraState != CAMERA_STATE_READY) { |
| ALOGE("createInstance: Failed"); |
| delete cam; |
| cam = NULL; |
| } |
| } |
| |
| if (cam) { |
| //sp<CameraHardwareInterface> hardware(cam); |
| ALOGV("createInstance: X"); |
| return cam; |
| } else { |
| return NULL; |
| } |
| } |
| /* external plug in function */ |
| extern "C" void * |
| QCameraHAL_openCameraHardware(int cameraId, int mode) |
| { |
| ALOGV("QCameraHAL_openCameraHardware: E"); |
| return (void *) QCameraHardwareInterface::createInstance(cameraId, mode); |
| } |
| |
| bool QCameraHardwareInterface::isPreviewRunning() { |
| ALOGV("isPreviewRunning: E"); |
| bool ret = false; |
| ALOGV("isPreviewRunning: camera state:%d", mCameraState); |
| |
| if((mCameraState == CAMERA_STATE_PREVIEW) || |
| (mCameraState == CAMERA_STATE_PREVIEW_START_CMD_SENT) || |
| (mCameraState == CAMERA_STATE_RECORD) || |
| (mCameraState == CAMERA_STATE_RECORD_START_CMD_SENT) || |
| (mCameraState == CAMERA_STATE_ZSL) || |
| (mCameraState == CAMERA_STATE_ZSL_START_CMD_SENT)){ |
| return true; |
| } |
| ALOGV("isPreviewRunning: X"); |
| return ret; |
| } |
| |
| bool QCameraHardwareInterface::isRecordingRunning() { |
| ALOGV("isRecordingRunning: E"); |
| bool ret = false; |
| if(QCAMERA_HAL_RECORDING_STARTED == mPreviewState) |
| ret = true; |
| //if((mCameraState == CAMERA_STATE_RECORD) || |
| // (mCameraState == CAMERA_STATE_RECORD_START_CMD_SENT)) { |
| // return true; |
| //} |
| ALOGV("isRecordingRunning: X"); |
| return ret; |
| } |
| |
| bool QCameraHardwareInterface::isSnapshotRunning() { |
| ALOGV("isSnapshotRunning: E"); |
| bool ret = false; |
| //if((mCameraState == CAMERA_STATE_SNAP_CMD_ACKED) || |
| // (mCameraState == CAMERA_STATE_SNAP_START_CMD_SENT)) { |
| // return true; |
| //} |
| switch(mPreviewState) { |
| case QCAMERA_HAL_PREVIEW_STOPPED: |
| case QCAMERA_HAL_PREVIEW_START: |
| case QCAMERA_HAL_PREVIEW_STARTED: |
| case QCAMERA_HAL_RECORDING_STARTED: |
| default: |
| break; |
| case QCAMERA_HAL_TAKE_PICTURE: |
| ret = true; |
| break; |
| } |
| ALOGV("isSnapshotRunning: X"); |
| return ret; |
| } |
| |
| bool QCameraHardwareInterface::isZSLMode() { |
| return (myMode & CAMERA_ZSL_MODE); |
| } |
| |
| int QCameraHardwareInterface::getHDRMode() { |
| return mHdrMode; |
| } |
| |
| void QCameraHardwareInterface::debugShowPreviewFPS() const |
| { |
| static int mFrameCount; |
| static int mLastFrameCount = 0; |
| static nsecs_t mLastFpsTime = 0; |
| static float mFps = 0; |
| mFrameCount++; |
| nsecs_t now = systemTime(); |
| nsecs_t diff = now - mLastFpsTime; |
| if (diff > ms2ns(250)) { |
| mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff; |
| ALOGV("Preview Frames Per Second: %.4f", mFps); |
| mLastFpsTime = now; |
| mLastFrameCount = mFrameCount; |
| } |
| } |
| |
| void QCameraHardwareInterface:: |
| processPreviewChannelEvent(mm_camera_ch_event_type_t channelEvent, app_notify_cb_t *app_cb) { |
| ALOGV("processPreviewChannelEvent: E"); |
| switch(channelEvent) { |
| case MM_CAMERA_CH_EVT_STREAMING_ON: |
| mCameraState = |
| isZSLMode() ? CAMERA_STATE_ZSL : CAMERA_STATE_PREVIEW; |
| break; |
| case MM_CAMERA_CH_EVT_STREAMING_OFF: |
| mCameraState = CAMERA_STATE_READY; |
| break; |
| case MM_CAMERA_CH_EVT_DATA_DELIVERY_DONE: |
| break; |
| default: |
| break; |
| } |
| ALOGV("processPreviewChannelEvent: X"); |
| return; |
| } |
| |
| void QCameraHardwareInterface::processRecordChannelEvent( |
| mm_camera_ch_event_type_t channelEvent, app_notify_cb_t *app_cb) { |
| ALOGV("processRecordChannelEvent: E"); |
| switch(channelEvent) { |
| case MM_CAMERA_CH_EVT_STREAMING_ON: |
| mCameraState = CAMERA_STATE_RECORD; |
| break; |
| case MM_CAMERA_CH_EVT_STREAMING_OFF: |
| mCameraState = CAMERA_STATE_PREVIEW; |
| break; |
| case MM_CAMERA_CH_EVT_DATA_DELIVERY_DONE: |
| break; |
| default: |
| break; |
| } |
| ALOGV("processRecordChannelEvent: X"); |
| return; |
| } |
| |
| void QCameraHardwareInterface:: |
| processSnapshotChannelEvent(mm_camera_ch_event_type_t channelEvent, app_notify_cb_t *app_cb) { |
| ALOGV("processSnapshotChannelEvent: E evt=%d state=%d", channelEvent, |
| mCameraState); |
| switch(channelEvent) { |
| case MM_CAMERA_CH_EVT_STREAMING_ON: |
| if (!mStateLiveshot) { |
| mCameraState = |
| isZSLMode() ? CAMERA_STATE_ZSL : CAMERA_STATE_SNAP_CMD_ACKED; |
| } |
| break; |
| case MM_CAMERA_CH_EVT_STREAMING_OFF: |
| if (!mStateLiveshot) { |
| mCameraState = CAMERA_STATE_READY; |
| } |
| break; |
| case MM_CAMERA_CH_EVT_DATA_DELIVERY_DONE: |
| break; |
| case MM_CAMERA_CH_EVT_DATA_REQUEST_MORE: |
| if (isZSLMode()) { |
| /* ZSL Mode: In ZSL Burst Mode, users may request for number of |
| snapshots larger than internal size of ZSL queue. So we'll need |
| process the remaining frames as they become available. |
| In such case, we'll get this event */ |
| if(NULL != mStreamSnap) |
| mStreamSnap->takePictureZSL(); |
| } |
| break; |
| default: |
| break; |
| } |
| ALOGV("processSnapshotChannelEvent: X"); |
| return; |
| } |
| |
| void QCameraHardwareInterface::processChannelEvent( |
| mm_camera_ch_event_t *event, app_notify_cb_t *app_cb) |
| { |
| ALOGV("processChannelEvent: E"); |
| Mutex::Autolock lock(mLock); |
| switch(event->ch) { |
| case MM_CAMERA_CH_PREVIEW: |
| processPreviewChannelEvent(event->evt, app_cb); |
| break; |
| case MM_CAMERA_CH_VIDEO: |
| processRecordChannelEvent(event->evt, app_cb); |
| break; |
| case MM_CAMERA_CH_SNAPSHOT: |
| processSnapshotChannelEvent(event->evt, app_cb); |
| break; |
| default: |
| break; |
| } |
| ALOGV("processChannelEvent: X"); |
| return; |
| } |
| |
| void QCameraHardwareInterface::processCtrlEvent(mm_camera_ctrl_event_t *event, app_notify_cb_t *app_cb) |
| { |
| ALOGV("processCtrlEvent: %d, E",event->evt); |
| Mutex::Autolock lock(mLock); |
| switch(event->evt) |
| { |
| case MM_CAMERA_CTRL_EVT_ZOOM_DONE: |
| zoomEvent(&event->status, app_cb); |
| break; |
| case MM_CAMERA_CTRL_EVT_AUTO_FOCUS_DONE: |
| autoFocusEvent(&event->status, app_cb); |
| break; |
| case MM_CAMERA_CTRL_EVT_AUTO_FOCUS_MOVE: |
| autoFocusMoveEvent(&event->status, app_cb); |
| break; |
| case MM_CAMERA_CTRL_EVT_PREP_SNAPSHOT: |
| break; |
| case MM_CAMERA_CTRL_EVT_WDN_DONE: |
| wdenoiseEvent(event->status, (void *)(event->cookie)); |
| break; |
| case MM_CAMERA_CTRL_EVT_HDR_DONE: |
| hdrEvent(event->status, (void *)(event->cookie)); |
| break; |
| case MM_CAMERA_CTRL_EVT_ERROR: |
| app_cb->notifyCb = mNotifyCb; |
| app_cb->argm_notify.msg_type = CAMERA_MSG_ERROR; |
| app_cb->argm_notify.ext1 = CAMERA_ERROR_UNKNOWN; |
| app_cb->argm_notify.cookie = mCallbackCookie; |
| break; |
| case MM_CAMERA_CTRL_EVT_SNAPSHOT_CONFIG_DONE: |
| ALOGV("%s: MM_CAMERA_CTRL_EVT_SNAPSHOT_CONFIG_DONE", __func__); |
| app_cb->notifyCb = mNotifyCb; |
| app_cb->argm_notify.msg_type = CAMERA_MSG_SHUTTER; |
| app_cb->argm_notify.ext1 = 0; |
| app_cb->argm_notify.ext2 = true; |
| app_cb->argm_notify.cookie = mCallbackCookie; |
| mShutterSoundPlayed = true; |
| default: |
| break; |
| } |
| ALOGV("processCtrlEvent: X"); |
| return; |
| } |
| |
| void QCameraHardwareInterface::processStatsEvent( |
| mm_camera_stats_event_t *event, app_notify_cb_t *app_cb) |
| { |
| ALOGV("processStatsEvent: E"); |
| if (!isPreviewRunning( )) { |
| ALOGE("preview is not running"); |
| return; |
| } |
| |
| switch (event->event_id) { |
| |
| case MM_CAMERA_STATS_EVT_HISTO: |
| { |
| #if 0 |
| ALOGE("HAL process Histo: mMsgEnabled=0x%x, mStatsOn=%d, mSendData=%d, mDataCb=%p ", |
| (mMsgEnabled & CAMERA_MSG_STATS_DATA), mStatsOn, mSendData, mDataCb); |
| int msgEnabled = mMsgEnabled; |
| /*get stats buffer based on index*/ |
| camera_preview_histogram_info* hist_info = |
| (camera_preview_histogram_info*) mHistServer.camera_memory[event->e.stats_histo.index]->data; |
| |
| if(mStatsOn == QCAMERA_PARM_ENABLE && mSendData && |
| mDataCb && (msgEnabled & CAMERA_MSG_STATS_DATA) ) { |
| uint32_t *dest; |
| mSendData = false; |
| mCurrentHisto = (mCurrentHisto + 1) % 3; |
| // The first element of the array will contain the maximum hist value provided by driver. |
| *(uint32_t *)((unsigned int)(mStatsMapped[mCurrentHisto]->data)) = hist_info->max_value; |
| memcpy((uint32_t *)((unsigned int)mStatsMapped[mCurrentHisto]->data + sizeof(int32_t)), |
| (uint32_t *)hist_info->buffer,(sizeof(int32_t) * 256)); |
| |
| app_cb->dataCb = mDataCb; |
| app_cb->argm_data_cb.msg_type = CAMERA_MSG_STATS_DATA; |
| app_cb->argm_data_cb.data = mStatsMapped[mCurrentHisto]; |
| app_cb->argm_data_cb.index = 0; |
| app_cb->argm_data_cb.metadata = NULL; |
| app_cb->argm_data_cb.cookie = mCallbackCookie; |
| } |
| #endif |
| break; |
| |
| } |
| default: |
| break; |
| } |
| ALOGV("receiveCameraStats X"); |
| } |
| |
| void QCameraHardwareInterface::processInfoEvent( |
| mm_camera_info_event_t *event, app_notify_cb_t *app_cb) { |
| ALOGV("processInfoEvent: %d, E",event->event_id); |
| //Mutex::Autolock lock(eventLock); |
| switch(event->event_id) |
| { |
| case MM_CAMERA_INFO_EVT_ROI: |
| roiEvent(event->e.roi, app_cb); |
| break; |
| default: |
| break; |
| } |
| ALOGV("processInfoEvent: X"); |
| return; |
| } |
| |
| void QCameraHardwareInterface::processEvent(mm_camera_event_t *event) |
| { |
| app_notify_cb_t app_cb; |
| ALOGV("processEvent: type :%d E",event->event_type); |
| if(mPreviewState == QCAMERA_HAL_PREVIEW_STOPPED){ |
| ALOGV("Stop recording issued. Return from process Event"); |
| return; |
| } |
| memset(&app_cb, 0, sizeof(app_notify_cb_t)); |
| switch(event->event_type) |
| { |
| case MM_CAMERA_EVT_TYPE_CH: |
| processChannelEvent(&event->e.ch, &app_cb); |
| break; |
| case MM_CAMERA_EVT_TYPE_CTRL: |
| processCtrlEvent(&event->e.ctrl, &app_cb); |
| break; |
| case MM_CAMERA_EVT_TYPE_STATS: |
| processStatsEvent(&event->e.stats, &app_cb); |
| break; |
| case MM_CAMERA_EVT_TYPE_INFO: |
| processInfoEvent(&event->e.info, &app_cb); |
| break; |
| default: |
| break; |
| } |
| ALOGV(" App_cb Notify %p, datacb=%p", app_cb.notifyCb, app_cb.dataCb); |
| if (app_cb.notifyCb) { |
| app_cb.notifyCb(app_cb.argm_notify.msg_type, |
| app_cb.argm_notify.ext1, app_cb.argm_notify.ext2, |
| app_cb.argm_notify.cookie); |
| } |
| if (app_cb.dataCb) { |
| app_cb.dataCb(app_cb.argm_data_cb.msg_type, |
| app_cb.argm_data_cb.data, app_cb.argm_data_cb.index, |
| app_cb.argm_data_cb.metadata, app_cb.argm_data_cb.cookie); |
| } |
| ALOGV("processEvent: X"); |
| return; |
| } |
| |
| bool QCameraHardwareInterface::preview_parm_config (cam_ctrl_dimension_t* dim, |
| QCameraParameters& parm) |
| { |
| ALOGV("preview_parm_config: E"); |
| bool matching = true; |
| int display_width = 0; /* width of display */ |
| int display_height = 0; /* height of display */ |
| uint16_t video_width = 0; /* width of the video */ |
| uint16_t video_height = 0; /* height of the video */ |
| |
| /* First check if the preview resolution is the same, if not, change it*/ |
| parm.getPreviewSize(&display_width, &display_height); |
| if (display_width && display_height) { |
| matching = (display_width == dim->display_width) && |
| (display_height == dim->display_height); |
| |
| if (!matching) { |
| dim->display_width = display_width; |
| dim->display_height = display_height; |
| } |
| } |
| else |
| matching = false; |
| |
| cam_format_t value = getPreviewFormat(); |
| |
| if(value != NOT_FOUND && value != dim->prev_format ) { |
| //Setting to Parameter requested by the Upper layer |
| dim->prev_format = value; |
| } else if (value == NOT_FOUND) { |
| //Setting to default Format. |
| dim->prev_format = CAMERA_YUV_420_NV21; |
| } |
| mPreviewFormat = dim->prev_format; |
| |
| dim->prev_padding_format = getPreviewPadding( ); |
| |
| dim->enc_format = CAMERA_YUV_420_NV12; |
| dim->orig_video_width = mDimension.orig_video_width; |
| dim->orig_video_height = mDimension.orig_video_height; |
| dim->video_width = mDimension.video_width; |
| dim->video_height = mDimension.video_height; |
| dim->video_chroma_width = mDimension.video_width; |
| dim->video_chroma_height = mDimension.video_height; |
| /* Reset the Main image and thumbnail formats here, |
| * since they might have been changed when video size |
| * livesnapshot was taken. */ |
| if (mSnapshotFormat == 1) |
| dim->main_img_format = CAMERA_YUV_422_NV61; |
| else |
| dim->main_img_format = CAMERA_YUV_420_NV21; |
| dim->thumb_format = CAMERA_YUV_420_NV21; |
| ALOGV("preview_parm_config: X"); |
| return matching; |
| } |
| |
| status_t QCameraHardwareInterface::startPreview() |
| { |
| status_t retVal = NO_ERROR; |
| |
| ALOGV("%s: mPreviewState =%d", __func__, mPreviewState); |
| Mutex::Autolock lock(mLock); |
| |
| if(mPauseFramedispatch){ |
| //In ZSL case after snapshot we need to restart |
| //if stop preview not issued. |
| stopPreviewInternal(); |
| mPreviewState = QCAMERA_HAL_PREVIEW_STOPPED; |
| mPauseFramedispatch = false; |
| } |
| |
| switch(mPreviewState) { |
| case QCAMERA_HAL_PREVIEW_STOPPED: |
| case QCAMERA_HAL_TAKE_PICTURE: |
| mPreviewState = QCAMERA_HAL_PREVIEW_START; |
| ALOGV("%s: HAL::startPreview begin", __func__); |
| |
| if(QCAMERA_HAL_PREVIEW_START == mPreviewState && |
| (mPreviewWindow || isNoDisplayMode())) { |
| ALOGD("%s: start preview now", __func__); |
| retVal = startPreview2(); |
| if(retVal == NO_ERROR) |
| mPreviewState = QCAMERA_HAL_PREVIEW_STARTED; |
| } else { |
| ALOGV("%s: received startPreview, but preview window = null", __func__); |
| } |
| break; |
| case QCAMERA_HAL_PREVIEW_START: |
| case QCAMERA_HAL_PREVIEW_STARTED: |
| break; |
| case QCAMERA_HAL_RECORDING_STARTED: |
| ALOGV("%s: cannot start preview in recording state", __func__); |
| break; |
| default: |
| ALOGE("%s: unknow state %d received", __func__, mPreviewState); |
| retVal = UNKNOWN_ERROR; |
| break; |
| } |
| return retVal; |
| } |
| |
| status_t QCameraHardwareInterface::startPreview2() |
| { |
| ALOGV("startPreview2: E"); |
| status_t ret = NO_ERROR; |
| |
| cam_ctrl_dimension_t dim; |
| mm_camera_dimension_t maxDim; |
| bool initPreview = false; |
| |
| mPauseFramedispatch = false; |
| if (mPreviewState == QCAMERA_HAL_PREVIEW_STARTED) { //isPreviewRunning()){ |
| ALOGE("%s:Preview already started mCameraState = %d!", __func__, mCameraState); |
| ALOGV("%s: X", __func__); |
| return NO_ERROR; |
| } |
| |
| const char *str = mParameters.get(QCameraParameters::KEY_SCENE_MODE); |
| |
| if (mRecordingHint || mFlashCond || !strcmp(str, "hdr")) { |
| ALOGI("%s:Setting non-ZSL mode",__func__); |
| mParameters.set(QCameraParameters::KEY_CAMERA_MODE, 0); |
| myMode = (camera_mode_t)(myMode & ~CAMERA_ZSL_MODE); |
| mParameters.setPreviewFrameRateMode("frame-rate-auto"); |
| setPreviewFrameRateMode(mParameters); |
| } else { |
| ALOGI("%s:Setting ZSL mode",__func__); |
| mParameters.set(QCameraParameters::KEY_CAMERA_MODE, 1); |
| myMode = (camera_mode_t)(myMode | CAMERA_ZSL_MODE); |
| mParameters.setPreviewFrameRateMode("frame-rate-auto"); |
| setPreviewFrameRateMode(mParameters); |
| |
| } |
| |
| /* get existing preview information, by qury mm_camera*/ |
| memset(&dim, 0, sizeof(cam_ctrl_dimension_t)); |
| ret = cam_config_get_parm(mCameraId, MM_CAMERA_PARM_DIMENSION,&dim); |
| |
| if (MM_CAMERA_OK != ret) { |
| ALOGE("%s: error - can't get preview dimension!", __func__); |
| ALOGV("%s: X", __func__); |
| return BAD_VALUE; |
| } |
| |
| /* config the parmeters and see if we need to re-init the stream*/ |
| initPreview = preview_parm_config (&dim, mParameters); |
| |
| if (mRecordingHint && mFullLiveshotEnabled) { |
| #if 0 |
| /* Camcorder mode and Full resolution liveshot enabled |
| * TBD lookup table for correct aspect ratio matching size */ |
| memset(&maxDim, 0, sizeof(mm_camera_dimension_t)); |
| getMaxPictureDimension(&maxDim); |
| if (!maxDim.width || !maxDim.height) { |
| maxDim.width = DEFAULT_LIVESHOT_WIDTH; |
| maxDim.height = DEFAULT_LIVESHOT_HEIGHT; |
| } |
| /* TODO Remove this hack after adding code to get live shot dimension */ |
| if (!mCameraId) { |
| maxDim.width = DEFAULT_LIVESHOT_WIDTH; |
| maxDim.height = DEFAULT_LIVESHOT_HEIGHT; |
| } |
| dim.picture_width = maxDim.width; |
| dim.picture_height = maxDim.height; |
| mParameters.setPictureSize(dim.picture_width, dim.picture_height); |
| ALOGI("%s Setting Liveshot dimension as %d x %d", __func__, |
| maxDim.width, maxDim.height); |
| #endif |
| int mPictureWidth, mPictureHeight; |
| bool matching; |
| /* First check if the picture resolution is the same, if not, change it*/ |
| getPictureSize(&mPictureWidth, &mPictureHeight); |
| |
| matching = (mPictureWidth == dim.picture_width) && |
| (mPictureHeight == dim.picture_height); |
| |
| if (!matching) { |
| dim.picture_width = mPictureWidth; |
| dim.picture_height = mPictureHeight; |
| //For FullSize snapshot Main image Buffer is used as Thumanail. |
| dim.ui_thumbnail_height = mPictureWidth; |
| dim.ui_thumbnail_width = mPictureHeight; |
| } |
| ALOGI("%s: Fullsize Liveshaot Picture size to set: %d x %d", __func__, |
| dim.picture_width, dim.picture_height); |
| mParameters.setPictureSize(dim.picture_width, dim.picture_height); |
| } |
| |
| ret = cam_config_set_parm(mCameraId, MM_CAMERA_PARM_DIMENSION,&dim); |
| if (MM_CAMERA_OK != ret) { |
| ALOGE("%s X: error - can't config preview parms!", __func__); |
| return BAD_VALUE; |
| } |
| |
| mStreamDisplay->setMode(myMode & CAMERA_ZSL_MODE); |
| mStreamSnap->setMode(myMode & CAMERA_ZSL_MODE); |
| mStreamRecord->setMode(myMode & CAMERA_ZSL_MODE); |
| ALOGV("%s: myMode = %d", __func__, myMode); |
| |
| ALOGV("%s: setPreviewWindow", __func__); |
| mStreamDisplay->setPreviewWindow(mPreviewWindow); |
| ret = cam_config_set_parm(mCameraId, MM_CAMERA_PARM_INFORM_STARTPRVIEW, NULL); |
| if(ret<0) |
| { |
| ALOGE("%s: Failed to Check MM_CAMERA_PARM_INFORM_STARTPRVIEW, rc %d", __func__, ret); |
| } |
| |
| if(isZSLMode()) { |
| /* Start preview streaming */ |
| ret = mStreamDisplay->start(); |
| if (MM_CAMERA_OK != ret){ |
| ALOGE("%s: X -error - can't start nonZSL stream!", __func__); |
| return BAD_VALUE; |
| } |
| |
| /* Start ZSL stream */ |
| ret = mStreamSnap->start(); |
| if (MM_CAMERA_OK != ret){ |
| ALOGE("%s: error - can't start Snapshot stream!", __func__); |
| mStreamDisplay->stop(); |
| return BAD_VALUE; |
| } |
| }else{ |
| ret = mStreamDisplay->start(); |
| } |
| |
| /*call QCameraStream_noneZSL::start() */ |
| if (MM_CAMERA_OK != ret){ |
| ALOGE("%s: X error - can't start stream!", __func__); |
| return BAD_VALUE; |
| } |
| if(MM_CAMERA_OK == ret) |
| mCameraState = CAMERA_STATE_PREVIEW_START_CMD_SENT; |
| else |
| mCameraState = CAMERA_STATE_ERROR; |
| |
| if(mPostPreviewHeap != NULL) { |
| mPostPreviewHeap.clear(); |
| mPostPreviewHeap = NULL; |
| } |
| |
| mRestartPreview = false; |
| |
| ALOGV("startPreview: X"); |
| return ret; |
| } |
| |
| void QCameraHardwareInterface::stopPreview() |
| { |
| ALOGV("%s: stopPreview: E", __func__); |
| Mutex::Autolock lock(mLock); |
| mm_camera_util_profile("HAL: stopPreview(): E"); |
| mFaceDetectOn = false; |
| |
| // reset recording hint to the value passed from Apps |
| const char * str = mParameters.get(QCameraParameters::KEY_RECORDING_HINT); |
| if((str != NULL) && !strcmp(str, "true")){ |
| mRecordingHint = true; |
| } else { |
| mRecordingHint = false; |
| } |
| |
| const char * str_fd = mParameters.get(QCameraParameters::KEY_FACE_DETECTION); |
| if((str_fd != NULL) && !strcmp(str_fd, "on")){ |
| if(supportsFaceDetection() == false){ |
| ALOGE("Face detection support is not available"); |
| } |
| setFaceDetection("off"); |
| runFaceDetection(); |
| } |
| |
| switch(mPreviewState) { |
| case QCAMERA_HAL_PREVIEW_START: |
| //mPreviewWindow = NULL; |
| mPreviewState = QCAMERA_HAL_PREVIEW_STOPPED; |
| break; |
| case QCAMERA_HAL_PREVIEW_STARTED: |
| stopPreviewInternal(); |
| mPreviewState = QCAMERA_HAL_PREVIEW_STOPPED; |
| break; |
| case QCAMERA_HAL_RECORDING_STARTED: |
| stopRecordingInternal(); |
| stopPreviewInternal(); |
| mPreviewState = QCAMERA_HAL_PREVIEW_STOPPED; |
| break; |
| case QCAMERA_HAL_TAKE_PICTURE: |
| case QCAMERA_HAL_PREVIEW_STOPPED: |
| default: |
| break; |
| } |
| ALOGV("stopPreview: X, mPreviewState = %d", mPreviewState); |
| } |
| |
| #if 0 //mzhu |
| void QCameraHardwareInterface::stopPreviewZSL() |
| { |
| ALOGI("stopPreviewZSL: E"); |
| |
| if(!mStreamDisplay || !mStreamSnap) { |
| ALOGE("mStreamDisplay/mStreamSnap is null"); |
| return; |
| } |
| ALOGI("stopPreview: X, mPreviewState = %d", mPreviewState); |
| } |
| #endif |
| void QCameraHardwareInterface::stopPreviewInternal() |
| { |
| ALOGV("stopPreviewInternal: E"); |
| status_t ret = NO_ERROR; |
| |
| if(!mStreamDisplay) { |
| ALOGE("mStreamDisplay is null"); |
| return; |
| } |
| |
| if(isZSLMode()) { |
| /* take care snapshot object for ZSL mode */ |
| mStreamSnap->stop(); |
| } |
| mStreamDisplay->stop(); |
| |
| mPauseFramedispatch = false; |
| mCameraState = CAMERA_STATE_PREVIEW_STOP_CMD_SENT; |
| ALOGV("stopPreviewInternal: X"); |
| } |
| |
| int QCameraHardwareInterface::previewEnabled() |
| { |
| ALOGV("previewEnabled: E"); |
| Mutex::Autolock lock(mLock); |
| ALOGV("%s: mCameraState = %d", __func__, mCameraState); |
| if (mPauseFramedispatch) { |
| return false; |
| } |
| switch(mPreviewState) { |
| case QCAMERA_HAL_PREVIEW_STOPPED: |
| case QCAMERA_HAL_TAKE_PICTURE: |
| default: |
| return false; |
| break; |
| case QCAMERA_HAL_PREVIEW_START: |
| case QCAMERA_HAL_PREVIEW_STARTED: |
| case QCAMERA_HAL_RECORDING_STARTED: |
| return true; |
| break; |
| } |
| return false; |
| } |
| |
| status_t QCameraHardwareInterface::startRecording() |
| { |
| ALOGV("startRecording: E"); |
| status_t ret = NO_ERROR; |
| Mutex::Autolock lock(mLock); |
| |
| switch(mPreviewState) { |
| case QCAMERA_HAL_PREVIEW_STOPPED: |
| ALOGE("%s: preview has not been started", __func__); |
| ret = UNKNOWN_ERROR; |
| break; |
| case QCAMERA_HAL_PREVIEW_START: |
| ALOGE("%s: no preview native window", __func__); |
| ret = UNKNOWN_ERROR; |
| break; |
| case QCAMERA_HAL_PREVIEW_STARTED: |
| //remember recordinghint value set by app |
| mAppRecordingHint = mRecordingHint; |
| pausePreviewForVideo(); |
| ret = mStreamRecord->start(); |
| if (MM_CAMERA_OK != ret){ |
| ALOGE("%s: error - mStreamRecord->start!", __func__); |
| ret = BAD_VALUE; |
| break; |
| } |
| if(MM_CAMERA_OK == ret) |
| mCameraState = CAMERA_STATE_RECORD_START_CMD_SENT; |
| else |
| mCameraState = CAMERA_STATE_ERROR; |
| mPreviewState = QCAMERA_HAL_RECORDING_STARTED; |
| break; |
| case QCAMERA_HAL_RECORDING_STARTED: |
| ALOGV("%s: ", __func__); |
| break; |
| case QCAMERA_HAL_TAKE_PICTURE: |
| default: |
| ret = BAD_VALUE; |
| break; |
| } |
| ALOGV("startRecording: X"); |
| return ret; |
| } |
| |
| void QCameraHardwareInterface::stopRecording() |
| { |
| ALOGV("stopRecording: E"); |
| Mutex::Autolock lock(mLock); |
| switch(mPreviewState) { |
| case QCAMERA_HAL_PREVIEW_STOPPED: |
| case QCAMERA_HAL_PREVIEW_START: |
| case QCAMERA_HAL_PREVIEW_STARTED: |
| break; |
| case QCAMERA_HAL_RECORDING_STARTED: |
| mRecordingHint = mAppRecordingHint; |
| stopRecordingInternal(); |
| mPreviewState = QCAMERA_HAL_PREVIEW_STARTED; |
| break; |
| case QCAMERA_HAL_TAKE_PICTURE: |
| default: |
| break; |
| } |
| ALOGV("stopRecording: X"); |
| |
| } |
| void QCameraHardwareInterface::stopRecordingInternal() |
| { |
| ALOGV("stopRecordingInternal: E"); |
| status_t ret = NO_ERROR; |
| |
| if(!mStreamRecord) { |
| ALOGE("mStreamRecord is null"); |
| return; |
| } |
| |
| if(mStateLiveshot && mStreamLiveSnap != NULL) { |
| mStreamLiveSnap->stop(); |
| mStateLiveshot = false; |
| } |
| /* |
| * call QCameraStream_record::stop() |
| * Unregister Callback, action stop |
| */ |
| mStreamRecord->stop(); |
| mCameraState = CAMERA_STATE_PREVIEW; //TODO : Apurva : Hacked for 2nd time Recording |
| mPreviewState = QCAMERA_HAL_PREVIEW_STARTED; |
| ALOGV("stopRecordingInternal: X"); |
| return; |
| } |
| |
| int QCameraHardwareInterface::recordingEnabled() |
| { |
| int ret = 0; |
| Mutex::Autolock lock(mLock); |
| ALOGV("%s: E", __func__); |
| switch(mPreviewState) { |
| case QCAMERA_HAL_PREVIEW_STOPPED: |
| case QCAMERA_HAL_PREVIEW_START: |
| case QCAMERA_HAL_PREVIEW_STARTED: |
| break; |
| case QCAMERA_HAL_RECORDING_STARTED: |
| ret = 1; |
| break; |
| case QCAMERA_HAL_TAKE_PICTURE: |
| default: |
| break; |
| } |
| ALOGV("%s: X, ret = %d", __func__, ret); |
| return ret; //isRecordingRunning(); |
| } |
| |
| /** |
| * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME. |
| */ |
| void QCameraHardwareInterface::releaseRecordingFrame(const void *opaque) |
| { |
| ALOGV("%s : BEGIN",__func__); |
| if(mStreamRecord == NULL) { |
| ALOGE("Record stream Not Initialized"); |
| return; |
| } |
| mStreamRecord->releaseRecordingFrame(opaque); |
| ALOGV("%s : END",__func__); |
| return; |
| } |
| |
| status_t QCameraHardwareInterface::autoFocusMoveEvent(cam_ctrl_status_t *status, app_notify_cb_t *app_cb) |
| { |
| ALOGV("autoFocusMoveEvent: E"); |
| int ret = NO_ERROR; |
| |
| isp3a_af_mode_t afMode = getAutoFocusMode(mParameters); |
| |
| if (afMode == AF_MODE_CAF && mNotifyCb && ( mMsgEnabled & CAMERA_MSG_FOCUS_MOVE)){ |
| ALOGV("%s:Issuing AF Move callback to service",__func__); |
| |
| app_cb->notifyCb = mNotifyCb; |
| app_cb->argm_notify.msg_type = CAMERA_MSG_FOCUS_MOVE; |
| app_cb->argm_notify.ext2 = 0; |
| app_cb->argm_notify.cookie = mCallbackCookie; |
| |
| ALOGV("Auto focus state =%d", *status); |
| if(*status == 1) { |
| app_cb->argm_notify.ext1 = true; |
| }else if(*status == 0){ |
| app_cb->argm_notify.ext1 = false; |
| }else{ |
| app_cb->notifyCb = NULL; |
| ALOGE("%s:Unknown AF Move Status received (%d) received",__func__,*status); |
| } |
| } |
| ALOGV("autoFocusMoveEvent: X"); |
| return ret; |
| } |
| |
| status_t QCameraHardwareInterface::autoFocusEvent(cam_ctrl_status_t *status, app_notify_cb_t *app_cb) |
| { |
| ALOGV("autoFocusEvent: E"); |
| int ret = NO_ERROR; |
| /************************************************************ |
| BEGIN MUTEX CODE |
| *************************************************************/ |
| |
| ALOGV("%s:%d: Trying to acquire AF bit lock",__func__,__LINE__); |
| mAutofocusLock.lock(); |
| ALOGV("%s:%d: Acquired AF bit lock",__func__,__LINE__); |
| |
| if(mAutoFocusRunning==false) { |
| ALOGV("%s:AF not running, discarding stale event",__func__); |
| mAutofocusLock.unlock(); |
| return ret; |
| } |
| /* If autofocus call has been made during CAF, CAF will be locked. |
| * We specifically need to call cancelAutoFocus to unlock CAF. |
| * In that sense, AF is still running.*/ |
| isp3a_af_mode_t afMode = getAutoFocusMode(mParameters); |
| if (afMode == AF_MODE_CAF) |
| mNeedToUnlockCaf = true; |
| mAutoFocusRunning = false; |
| mAutofocusLock.unlock(); |
| |
| /************************************************************ |
| END MUTEX CODE |
| *************************************************************/ |
| if(status==NULL) { |
| ALOGE("%s:NULL ptr received for status",__func__); |
| return BAD_VALUE; |
| } |
| |
| /* update focus distances after autofocus is done */ |
| if((*status != CAM_CTRL_FAILED) && updateFocusDistances() != NO_ERROR) { |
| ALOGE("%s: updateFocusDistances failed for %d", __FUNCTION__, mFocusMode); |
| } |
| |
| /*(Do?) we need to make sure that the call back is the |
| last possible step in the execution flow since the same |
| context might be used if a fail triggers another round |
| of AF then the mAutoFocusRunning flag and other state |
| variables' validity will be under question*/ |
| |
| if (mNotifyCb && ( mMsgEnabled & CAMERA_MSG_FOCUS)){ |
| ALOGV("%s:Issuing AF callback to service",__func__); |
| |
| /* "Accepted" status is not appropriate it should be used for |
| initial cmd, event reporting should only give use SUCCESS/FAIL |
| */ |
| |
| app_cb->notifyCb = mNotifyCb; |
| app_cb->argm_notify.msg_type = CAMERA_MSG_FOCUS; |
| app_cb->argm_notify.ext2 = 0; |
| app_cb->argm_notify.cookie = mCallbackCookie; |
| |
| ALOGV("Auto focus state =%d", *status); |
| if(*status==CAM_CTRL_SUCCESS) { |
| app_cb->argm_notify.ext1 = true; |
| } |
| else if(*status==CAM_CTRL_FAILED){ |
| app_cb->argm_notify.ext1 = false; |
| } |
| else{ |
| app_cb->notifyCb = NULL; |
| ALOGE("%s:Unknown AF status (%d) received",__func__,*status); |
| } |
| |
| }/*(mNotifyCb && ( mMsgEnabled & CAMERA_MSG_FOCUS))*/ |
| else{ |
| ALOGE("%s:Call back not enabled",__func__); |
| } |
| |
| ALOGV("autoFocusEvent: X"); |
| return ret; |
| |
| } |
| |
| status_t QCameraHardwareInterface::cancelPicture() |
| { |
| ALOGV("cancelPicture: E"); |
| status_t ret = MM_CAMERA_OK; |
| Mutex::Autolock lock(mLock); |
| |
| switch(mPreviewState) { |
| case QCAMERA_HAL_PREVIEW_STOPPED: |
| case QCAMERA_HAL_PREVIEW_START: |
| case QCAMERA_HAL_PREVIEW_STARTED: |
| break; |
| case QCAMERA_HAL_RECORDING_STARTED: |
| if(mStateLiveshot && (mStreamLiveSnap != NULL)) { |
| mStreamLiveSnap->stop(); |
| mStateLiveshot = false; |
| } |
| break; |
| case QCAMERA_HAL_TAKE_PICTURE: |
| ret = cancelPictureInternal(); |
| break; |
| default: |
| break; |
| } |
| ALOGV("cancelPicture: X"); |
| return ret; |
| } |
| |
| status_t QCameraHardwareInterface::cancelPictureInternal() |
| { |
| ALOGV("cancelPictureInternal: E"); |
| status_t ret = MM_CAMERA_OK; |
| if(mCameraState != CAMERA_STATE_READY) { |
| if(mStreamSnap) { |
| mStreamSnap->stop(); |
| mCameraState = CAMERA_STATE_SNAP_STOP_CMD_SENT; |
| } |
| } else { |
| ALOGE("%s: Cannot process cancel picture as snapshot is already done",__func__); |
| } |
| ALOGV("cancelPictureInternal: X"); |
| return ret; |
| } |
| |
| void QCameraHardwareInterface::pausePreviewForSnapshot() |
| { |
| stopPreviewInternal( ); |
| } |
| status_t QCameraHardwareInterface::resumePreviewAfterSnapshot() |
| { |
| status_t ret = NO_ERROR; |
| ret = mStreamDisplay->start(); |
| return ret; |
| } |
| |
| void liveshot_callback(mm_camera_ch_data_buf_t *recvd_frame, |
| void *user_data) |
| { |
| QCameraHardwareInterface *pme = (QCameraHardwareInterface *)user_data; |
| cam_ctrl_dimension_t dim; |
| int mJpegMaxSize; |
| int mNuberOfVFEOutputs = 0; |
| status_t ret; |
| ALOGV("%s: E", __func__); |
| |
| if (!pme->mStateLiveshot) { |
| ALOGE("%s: Returning Buffer. Picture Cancelled", __func__); |
| return; |
| } |
| |
| ALOGV("Live Snapshot Enabled"); |
| if (pme->mStreamLiveSnap){ |
| ALOGE("%s:Deleting old Snapshot stream instance",__func__); |
| QCameraStream_Snapshot::deleteInstance (pme->mStreamLiveSnap); |
| pme->mStreamLiveSnap = NULL; |
| } |
| |
| pme->mStreamLiveSnap = (QCameraStream_Snapshot*)QCameraStream_Snapshot::createInstance(pme->mCameraId, |
| pme->myMode); |
| |
| if (!pme->mStreamLiveSnap) { |
| ALOGE("%s: error - can't creat snapshot stream!", __func__); |
| cam_evt_buf_done(pme->mCameraId, recvd_frame); |
| return ; |
| } |
| pme->mStreamLiveSnap->setModeLiveSnapshot(true); |
| pme->mStreamLiveSnap->setHALCameraControl(pme); |
| |
| ret = ((QCameraStream_Snapshot*)(pme->mStreamLiveSnap))->takePictureLiveshot(recvd_frame); |
| if (MM_CAMERA_OK != ret) { |
| ALOGE("%s: Error : returned from takePictureLiveshot",__func__); |
| return; |
| } |
| pme->setCAFLockCancel(); |
| ALOGV("%s: X", __func__); |
| |
| } |
| |
| status_t QCameraHardwareInterface::takePicture() |
| { |
| ALOGV("takePicture: E"); |
| status_t ret = MM_CAMERA_OK; |
| int mNuberOfVFEOutputs = 0; |
| Mutex::Autolock lock(mLock); |
| bool hdr; |
| int frm_num = 1, rc = 0; |
| int exp[MAX_HDR_EXP_FRAME_NUM]; |
| |
| if(QCAMERA_HAL_RECORDING_STARTED != mPreviewState){ |
| isp3a_af_mode_t afMode = getAutoFocusMode(mParameters); |
| if (!mFlashCond) |
| { |
| mFlashCond = getFlashCondition(); |
| } |
| ALOGV("%s: Flash Contidion %d", __func__, mFlashCond); |
| if(mFlashCond) { |
| mRestartPreview = true; |
| pausePreviewForZSL(); |
| } |
| mFlashCond = false; |
| } |
| |
| rc = cam_config_set_parm(mCameraId, MM_CAMERA_PARM_LG_CAF_LOCK, NULL); |
| if(rc<0) |
| { |
| ALOGE("%s: Failed to Check MM_CAMERA_PARM_LG_CAF_LOCK, rc %d", __func__, rc); |
| } |
| hdr = getHdrInfoAndSetExp(MAX_HDR_EXP_FRAME_NUM, &frm_num, exp); |
| mStreamSnap->resetSnapshotCounters(); |
| mStreamSnap->InitHdrInfoForSnapshot(hdr, frm_num, exp); |
| switch(mPreviewState) { |
| case QCAMERA_HAL_PREVIEW_STARTED: |
| //set the fullsize liveshot to false |
| mFullLiveshotEnabled = false; |
| setFullLiveshot(); |
| mStreamSnap->setFullSizeLiveshot(false); |
| if (isZSLMode()) { |
| if (mStreamSnap != NULL) { |
| pausePreviewForZSL(); |
| ret = mStreamSnap->takePictureZSL(); |
| if (ret != MM_CAMERA_OK) { |
| ALOGE("%s: Error taking ZSL snapshot!", __func__); |
| ret = BAD_VALUE; |
| } |
| } |
| else { |
| ALOGE("%s: ZSL stream not active! Failure!!", __func__); |
| ret = BAD_VALUE; |
| } |
| return ret; |
| } |
| /*prepare snapshot, e.g LED*/ |
| takePicturePrepareHardware( ); |
| /* There's an issue where we have a glimpse of corrupted data between |
| a time we stop a preview and display the postview. It happens because |
| when we call stopPreview we deallocate the preview buffers hence overlay |
| displays garbage value till we enqueue postview buffer to be displayed. |
| Hence for temporary fix, we'll do memcopy of the last frame displayed and |
| queue it to overlay*/ |
| // mzhu storePreviewFrameForPostview(); |
| |
| /* stop preview */ |
| pausePreviewForSnapshot(); |
| |
| /* call Snapshot start() :*/ |
| ret = mStreamSnap->start(); |
| if (MM_CAMERA_OK != ret){ |
| /* mzhu: fix me, restore preview */ |
| ALOGE("%s: error - can't start Snapshot stream!", __func__); |
| return BAD_VALUE; |
| } |
| |
| if(MM_CAMERA_OK == ret) |
| mCameraState = CAMERA_STATE_SNAP_START_CMD_SENT; |
| else |
| mCameraState = CAMERA_STATE_ERROR; |
| mPreviewState = QCAMERA_HAL_TAKE_PICTURE; |
| break; |
| case QCAMERA_HAL_TAKE_PICTURE: |
| break; |
| case QCAMERA_HAL_PREVIEW_STOPPED: |
| case QCAMERA_HAL_PREVIEW_START: |
| ret = UNKNOWN_ERROR; |
| break; |
| case QCAMERA_HAL_RECORDING_STARTED: |
| if(mStateLiveshot) { |
| ALOGE("takePicture : Duplicate TakePicture Call"); |
| return ret; |
| } |
| if (canTakeFullSizeLiveshot()) { |
| ALOGV(" Calling takeFullSizeLiveshot"); |
| takeFullSizeLiveshot(); |
| }else{ |
| ret = cam_config_get_parm(mCameraId, MM_CAMERA_PARM_VFE_OUTPUT_ENABLE, |
| &mNuberOfVFEOutputs); |
| if (ret != MM_CAMERA_OK) { |
| ALOGE("get parm MM_CAMERA_PARM_VFE_OUTPUT_ENABLE failed"); |
| ret = BAD_VALUE; |
| } |
| if (mNuberOfVFEOutputs == 1){ |
| (void) cam_evt_register_buf_notify(mCameraId, MM_CAMERA_CH_PREVIEW, |
| liveshot_callback, |
| MM_CAMERA_REG_BUF_CB_COUNT, |
| 1, |
| this); |
| } else { |
| (void) cam_evt_register_buf_notify(mCameraId, MM_CAMERA_CH_VIDEO, |
| liveshot_callback, |
| MM_CAMERA_REG_BUF_CB_COUNT, |
| 1, |
| this); |
| } |
| } |
| mStateLiveshot = true; |
| break; |
| default: |
| ret = UNKNOWN_ERROR; |
| break; |
| } |
| ALOGV("takePicture: X"); |
| return ret; |
| } |
| |
| bool QCameraHardwareInterface::canTakeFullSizeLiveshot() { |
| bool ret; |
| if (mFullLiveshotEnabled && !isLowPowerCamcorder()) { |
| /* Full size liveshot enabled. */ |
| |
| /* If Picture size is same as video size, switch to Video size |
| * live snapshot */ |
| if ((mDimension.picture_width == mVideoWidth) && |
| (mDimension.picture_height == mVideoHeight)) { |
| return false; |
| } |
| |
| if (mDisEnabled) { |
| /* If DIS is enabled and Picture size is |
| * less than (video size + 10% DIS Margin) |
| * then fall back to Video size liveshot. */ |
| if ((mDimension.picture_width < |
| (int)(mVideoWidth * 1.1)) || |
| (mDimension.picture_height < |
| (int)(mVideoHeight * 1.1))) { |
| ret = false; |
| } else { |
| /* Go with Full size live snapshot. */ |
| ret = true; |
| } |
| } else { |
| /* DIS Disabled. Go with Full size live snapshot */ |
| ret = true; |
| } |
| } else { |
| /* Full size liveshot disabled. Fallback to Video size liveshot. */ |
| ret = false; |
| } |
| |
| return ret; |
| } |
| |
| status_t QCameraHardwareInterface::takeFullSizeLiveshot() |
| { |
| status_t ret = NO_ERROR; |
| if (mStreamLiveSnap){ |
| ALOGV("%s:Deleting old Snapshot stream instance",__func__); |
| QCameraStream_Snapshot::deleteInstance (mStreamLiveSnap); |
| mStreamLiveSnap = NULL; |
| } |
| mStreamLiveSnap = QCameraStream_Snapshot::createInstance(mCameraId, myMode); |
| |
| if (!mStreamLiveSnap) { |
| ALOGE("%s: error - can't creat snapshot stream!", __func__); |
| /* mzhu: fix me, restore preview */ |
| return BAD_VALUE; |
| } |
| |
| /* Store HAL object in snapshot stream Object */ |
| mStreamLiveSnap->setHALCameraControl(this); |
| |
| mStreamLiveSnap->setFullSizeLiveshot(true); |
| |
| /* Call snapshot init*/ |
| ret = mStreamLiveSnap->init(); |
| if (MM_CAMERA_OK != ret){ |
| ALOGE("%s: error - can't init Snapshot stream!", __func__); |
| return BAD_VALUE; |
| } |
| |
| /* call Snapshot start() :*/ |
| mStreamLiveSnap->resetSnapshotCounters( ); |
| ret = mStreamLiveSnap->start(); |
| if (MM_CAMERA_OK != ret){ |
| /* mzhu: fix me, restore preview */ |
| ALOGE("%s: error - can't start Snapshot stream!", __func__); |
| return BAD_VALUE; |
| } |
| return ret; |
| } |
| |
| status_t QCameraHardwareInterface::takeLiveSnapshot() |
| { |
| status_t ret = NO_ERROR; |
| ALOGV("takeLiveSnapshot: E"); |
| mStreamRecord->takeLiveSnapshot(); |
| ALOGV("takeLiveSnapshot: X"); |
| return ret; |
| } |
| |
| status_t QCameraHardwareInterface::autoFocus() |
| { |
| ALOGV("autoFocus: E"); |
| status_t ret = NO_ERROR; |
| mFlashCond = getFlashCondition(); |
| ALOGV("autoFocus: mFlashCond = %d", mFlashCond); |
| Mutex::Autolock lock(mLock); |
| ALOGV("autoFocus: Got lock"); |
| bool status = true; |
| isp3a_af_mode_t afMode = getAutoFocusMode(mParameters); |
| |
| if(mAutoFocusRunning==true){ |
| ALOGV("%s:AF already running should not have got this call",__func__); |
| return NO_ERROR; |
| } |
| |
| if (afMode == AF_MODE_MAX) { |
| /* This should never happen. We cannot send a |
| * callback notifying error from this place because |
| * the CameraService has called this function after |
| * acquiring the lock. So if we try to issue a callback |
| * from this place, the callback will try to acquire |
| * the same lock in CameraService and it will result |
| * in deadlock. So, let the call go in to the lower |
| * layer. The lower layer will anyway return error if |
| * the autofocus is not supported or if the focus |
| * value is invalid. |
| * Just print out the error. */ |
| ALOGE("%s:Invalid AF mode (%d)", __func__, afMode); |
| } |
| |
| ALOGV("%s:AF start (mode %d)", __func__, afMode); |
| if(MM_CAMERA_OK != cam_ops_action(mCameraId, true, |
| MM_CAMERA_OPS_FOCUS, &afMode)) { |
| ALOGE("%s: AF command failed err:%d error %s", |
| __func__, errno, strerror(errno)); |
| return UNKNOWN_ERROR; |
| } |
| |
| mAutoFocusRunning = true; |
| ALOGV("autoFocus: X"); |
| return ret; |
| } |
| |
| status_t QCameraHardwareInterface::cancelAutoFocus() |
| { |
| ALOGV("cancelAutoFocus: E"); |
| status_t ret = NO_ERROR; |
| Mutex::Autolock lock(mLock); |
| |
| /************************************************************** |
| BEGIN MUTEX CODE |
| *************************************************************/ |
| |
| mAutofocusLock.lock(); |
| if(mAutoFocusRunning || mNeedToUnlockCaf) { |
| mNeedToUnlockCaf = false; |
| mAutoFocusRunning = false; |
| mAutofocusLock.unlock(); |
| |
| }else/*(!mAutoFocusRunning)*/{ |
| |
| mAutofocusLock.unlock(); |
| ALOGV("%s:Af not running",__func__); |
| return NO_ERROR; |
| } |
| /************************************************************** |
| END MUTEX CODE |
| *************************************************************/ |
| |
| |
| if(MM_CAMERA_OK!=cam_ops_action(mCameraId,false,MM_CAMERA_OPS_FOCUS,NULL )) { |
| ALOGE("%s: AF command failed err:%d error %s",__func__, errno,strerror(errno)); |
| } |
| |
| ALOGV("cancelAutoFocus: X"); |
| return NO_ERROR; |
| } |
| |
| #if 0 //mzhu |
| /*========================================================================== |
| * FUNCTION - prepareSnapshotAndWait - |
| * |
| * DESCRIPTION: invoke preparesnapshot and wait for it done |
| it can be called within takepicture, so no need |
| to grab mLock. |
| *=========================================================================*/ |
| void QCameraHardwareInterface::prepareSnapshotAndWait() |
| { |
| ALOGI("prepareSnapshotAndWait: E"); |
| int rc = 0; |
| /*To Do: call mm camera preparesnapshot */ |
| if(!rc ) { |
| mPreparingSnapshot = true; |
| pthread_mutex_lock(&mAsyncCmdMutex); |
| pthread_cond_wait(&mAsyncCmdWait, &mAsyncCmdMutex); |
| pthread_mutex_unlock(&mAsyncCmdMutex); |
| mPreparingSnapshot = false; |
| } |
| ALOGI("prepareSnapshotAndWait: X"); |
| } |
| #endif //mzhu |
| |
| /*========================================================================== |
| * FUNCTION - processprepareSnapshotEvent - |
| * |
| * DESCRIPTION: Process the event of preparesnapshot done msg |
| unblock prepareSnapshotAndWait( ) |
| *=========================================================================*/ |
| void QCameraHardwareInterface::processprepareSnapshotEvent(cam_ctrl_status_t *status) |
| { |
| ALOGV("processprepareSnapshotEvent: E"); |
| pthread_mutex_lock(&mAsyncCmdMutex); |
| pthread_cond_signal(&mAsyncCmdWait); |
| pthread_mutex_unlock(&mAsyncCmdMutex); |
| ALOGV("processprepareSnapshotEvent: X"); |
| } |
| |
| void QCameraHardwareInterface::roiEvent(fd_roi_t roi,app_notify_cb_t *app_cb) |
| { |
| ALOGV("roiEvent: E"); |
| |
| if(mStreamDisplay) mStreamDisplay->notifyROIEvent(roi); |
| #if 0 //TODO: move to preview obj |
| mCallbackLock.lock(); |
| data_callback mcb = mDataCb; |
| void *mdata = mCallbackCookie; |
| int msgEnabled = mMsgEnabled; |
| mCallbackLock.unlock(); |
| |
| mMetaDataWaitLock.lock(); |
| if (mFaceDetectOn == true && mSendMetaData == true) { |
| mSendMetaData = false; |
| int faces_detected = roi.rect_num; |
| int max_faces_detected = MAX_ROI * 4; |
| int array[max_faces_detected + 1]; |
| |
| array[0] = faces_detected * 4; |
| for (int i = 1, j = 0;j < MAX_ROI; j++, i = i + 4) { |
| if (j < faces_detected) { |
| array[i] = roi.faces[j].x; |
| array[i+1] = roi.faces[j].y; |
| array[i+2] = roi.faces[j].dx; |
| array[i+3] = roi.faces[j].dy; |
| } else { |
| array[i] = -1; |
| array[i+1] = -1; |
| array[i+2] = -1; |
| array[i+3] = -1; |
| } |
| } |
| if(mMetaDataHeap != NULL){ |
| ALOGV("mMetaDataHEap is non-NULL"); |
| memcpy((uint32_t *)mMetaDataHeap->mHeap->base(), (uint32_t *)array, (sizeof(int)*(MAX_ROI*4+1))); |
| mMetaDataWaitLock.unlock(); |
| |
| if (mcb != NULL && (msgEnabled & CAMERA_MSG_META_DATA)) { |
| mcb(CAMERA_MSG_META_DATA, mMetaDataHeap->mBuffers[0], mdata); |
| } |
| } else { |
| mMetaDataWaitLock.unlock(); |
| ALOGE("runPreviewThread mMetaDataHeap is NULL"); |
| } |
| } else { |
| mMetaDataWaitLock.unlock(); |
| } |
| #endif // mzhu |
| ALOGV("roiEvent: X"); |
| } |
| |
| |
| void QCameraHardwareInterface::handleZoomEventForSnapshot(void) |
| { |
| mm_camera_ch_crop_t v4l2_crop; |
| |
| |
| ALOGV("%s: E", __func__); |
| |
| memset(&v4l2_crop,0,sizeof(v4l2_crop)); |
| v4l2_crop.ch_type=MM_CAMERA_CH_SNAPSHOT; |
| |
| ALOGV("%s: Fetching crop info", __func__); |
| cam_config_get_parm(mCameraId,MM_CAMERA_PARM_CROP,&v4l2_crop); |
| |
| ALOGV("%s: Crop info received for main: %d, %d, %d, %d ", __func__, |
| v4l2_crop.snapshot.main_crop.left, |
| v4l2_crop.snapshot.main_crop.top, |
| v4l2_crop.snapshot.main_crop.width, |
| v4l2_crop.snapshot.main_crop.height); |
| ALOGV("%s: Crop info received for thumbnail: %d, %d, %d, %d ",__func__, |
| v4l2_crop.snapshot.thumbnail_crop.left, |
| v4l2_crop.snapshot.thumbnail_crop.top, |
| v4l2_crop.snapshot.thumbnail_crop.width, |
| v4l2_crop.snapshot.thumbnail_crop.height); |
| |
| if(mStreamSnap) { |
| ALOGV("%s: Setting crop info for snapshot", __func__); |
| memcpy(&(mStreamSnap->mCrop), &v4l2_crop, sizeof(v4l2_crop)); |
| } |
| if(mFullLiveshotEnabled && mStreamLiveSnap){ |
| ALOGV("%s: Setting crop info for snapshot", __func__); |
| memcpy(&(mStreamLiveSnap->mCrop), &v4l2_crop, sizeof(v4l2_crop)); |
| } |
| ALOGV("%s: X", __func__); |
| } |
| |
| void QCameraHardwareInterface::handleZoomEventForPreview(app_notify_cb_t *app_cb) |
| { |
| mm_camera_ch_crop_t v4l2_crop; |
| |
| ALOGV("%s: E", __func__); |
| |
| /*regular zooming or smooth zoom stopped*/ |
| if (!mSmoothZoomRunning && mPreviewWindow) { |
| memset(&v4l2_crop, 0, sizeof(v4l2_crop)); |
| v4l2_crop.ch_type = MM_CAMERA_CH_PREVIEW; |
| |
| ALOGV("%s: Fetching crop info", __func__); |
| cam_config_get_parm(mCameraId,MM_CAMERA_PARM_CROP,&v4l2_crop); |
| |
| ALOGV("%s: Crop info received: %d, %d, %d, %d ", __func__, |
| v4l2_crop.crop.left, |
| v4l2_crop.crop.top, |
| v4l2_crop.crop.width, |
| v4l2_crop.crop.height); |
| |
| mPreviewWindow->set_crop(mPreviewWindow, |
| v4l2_crop.crop.left, |
| v4l2_crop.crop.top, |
| v4l2_crop.crop.left + v4l2_crop.crop.width, |
| v4l2_crop.crop.top + v4l2_crop.crop.height); |
| ALOGV("%s: Done setting crop", __func__); |
| ALOGV("%s: Currrent zoom :%d",__func__, mCurrentZoom); |
| } |
| |
| ALOGV("%s: X", __func__); |
| } |
| |
| void QCameraHardwareInterface::zoomEvent(cam_ctrl_status_t *status, app_notify_cb_t *app_cb) |
| { |
| ALOGV("zoomEvent: state:%d E",mPreviewState); |
| switch (mPreviewState) { |
| case QCAMERA_HAL_PREVIEW_STOPPED: |
| break; |
| case QCAMERA_HAL_PREVIEW_START: |
| break; |
| case QCAMERA_HAL_PREVIEW_STARTED: |
| handleZoomEventForPreview(app_cb); |
| if (isZSLMode()) |
| handleZoomEventForSnapshot(); |
| break; |
| case QCAMERA_HAL_RECORDING_STARTED: |
| handleZoomEventForPreview(app_cb); |
| if (mFullLiveshotEnabled) |
| handleZoomEventForSnapshot(); |
| break; |
| case QCAMERA_HAL_TAKE_PICTURE: |
| if(isZSLMode()) |
| handleZoomEventForPreview(app_cb); |
| handleZoomEventForSnapshot(); |
| break; |
| default: |
| break; |
| } |
| ALOGV("zoomEvent: X"); |
| } |
| |
| void QCameraHardwareInterface::dumpFrameToFile(const void * data, uint32_t size, char* name, char* ext, int index) |
| { |
| #if 0 |
| char buf[32], value[PROPERTY_VALUE_MAX]; |
| int file_fd, enabled = 0; |
| static int i = 0 ; |
| property_get("persist.camera.dumpimage", value, "0"); |
| enabled = atoi(value); |
| |
| if ( data != NULL && enabled) { |
| char * str; |
| snprintf(buf, sizeof(buf), "/data/%s_%d.%s", name, index, ext); |
| ALOGE("%s size =%d", buf, size); |
| file_fd = open(buf, O_RDWR | O_CREAT, 0777); |
| write(file_fd, data, size); |
| close(file_fd); |
| i++; |
| } |
| #endif |
| } |
| |
| void QCameraHardwareInterface::dumpFrameToFile(struct msm_frame* newFrame, |
| HAL_cam_dump_frm_type_t frm_type) |
| { |
| #if 0 |
| int32_t enabled = 0; |
| int frm_num; |
| uint32_t skip_mode; |
| char value[PROPERTY_VALUE_MAX]; |
| char buf[32]; |
| int main_422 = 1; |
| property_get("persist.camera.dumpimg", value, "0"); |
| enabled = atoi(value); |
| |
| ALOGV(" newFrame =%p, frm_type = %d", newFrame, frm_type); |
| if(enabled & HAL_DUMP_FRM_MASK_ALL) { |
| if((enabled & frm_type) && newFrame) { |
| frm_num = ((enabled & 0xffff0000) >> 16); |
| if(frm_num == 0) frm_num = 10; /*default 10 frames*/ |
| if(frm_num > 256) frm_num = 256; /*256 buffers cycle around*/ |
| skip_mode = ((enabled & 0x0000ff00) >> 8); |
| if(skip_mode == 0) skip_mode = 1; /*no -skip */ |
| |
| if( mDumpSkipCnt % skip_mode == 0) { |
| if (mDumpFrmCnt >= 0 && mDumpFrmCnt <= frm_num) { |
| int w, h; |
| int file_fd; |
| switch (frm_type) { |
| case HAL_DUMP_FRM_PREVIEW: |
| w = mDimension.display_width; |
| h = mDimension.display_height; |
| snprintf(buf, sizeof(buf), "/data/%dp_%dx%d.yuv", mDumpFrmCnt, w, h); |
| file_fd = open(buf, O_RDWR | O_CREAT, 0777); |
| break; |
| case HAL_DUMP_FRM_VIDEO: |
| w = mVideoWidth; |
| h = mVideoHeight; |
| snprintf(buf, sizeof(buf),"/data/%dv_%dx%d.yuv", mDumpFrmCnt, w, h); |
| file_fd = open(buf, O_RDWR | O_CREAT, 0777); |
| break; |
| case HAL_DUMP_FRM_MAIN: |
| w = mDimension.picture_width; |
| h = mDimension.picture_height; |
| snprintf(buf, sizeof(buf), "/data/%dm_%dx%d.yuv", mDumpFrmCnt, w, h); |
| file_fd = open(buf, O_RDWR | O_CREAT, 0777); |
| if (mDimension.main_img_format == CAMERA_YUV_422_NV16 || |
| mDimension.main_img_format == CAMERA_YUV_422_NV61) |
| main_422 = 2; |
| break; |
| case HAL_DUMP_FRM_THUMBNAIL: |
| w = mDimension.ui_thumbnail_width; |
| h = mDimension.ui_thumbnail_height; |
| snprintf(buf, sizeof(buf),"/data/%dt_%dx%d.yuv", mDumpFrmCnt, w, h); |
| file_fd = open(buf, O_RDWR | O_CREAT, 0777); |
| break; |
| default: |
| w = h = 0; |
| file_fd = -1; |
| break; |
| } |
| |
| if (file_fd < 0) { |
| ALOGE("%s: cannot open file:type=%d\n", __func__, frm_type); |
| } else { |
| ALOGV("%s: %d %d", __func__, newFrame->y_off, newFrame->cbcr_off); |
| write(file_fd, (const void *)(newFrame->buffer+newFrame->y_off), w * h); |
| write(file_fd, (const void *) |
| (newFrame->buffer + newFrame->cbcr_off), w * h / 2 * main_422); |
| close(file_fd); |
| ALOGV("dump %s", buf); |
| } |
| } else if(frm_num == 256){ |
| mDumpFrmCnt = 0; |
| } |
| mDumpFrmCnt++; |
| } |
| mDumpSkipCnt++; |
| } |
| } else { |
| mDumpFrmCnt = 0; |
| } |
| #endif |
| } |
| |
| status_t QCameraHardwareInterface::setPreviewWindow(preview_stream_ops_t* window) |
| { |
| status_t retVal = NO_ERROR; |
| ALOGV(" %s: E mPreviewState = %d, mStreamDisplay = %p", __FUNCTION__, mPreviewState, mStreamDisplay); |
| if( window == NULL) { |
| ALOGE("%s:Received Setting NULL preview window", __func__); |
| } |
| Mutex::Autolock lock(mLock); |
| switch(mPreviewState) { |
| case QCAMERA_HAL_PREVIEW_START: |
| mPreviewWindow = window; |
| if(mPreviewWindow) { |
| /* we have valid surface now, start preview */ |
| retVal = startPreview2(); |
| if(retVal == NO_ERROR) |
| mPreviewState = QCAMERA_HAL_PREVIEW_STARTED; |
| ALOGV("%s: startPreview2 done, mPreviewState = %d", __func__, mPreviewState); |
| } else |
| ALOGE("%s: null window received, mPreviewState = %d", __func__, mPreviewState); |
| break; |
| case QCAMERA_HAL_PREVIEW_STARTED: |
| /* new window comes */ |
| ALOGE("%s: bug, cannot handle new window in started state", __func__); |
| //retVal = UNKNOWN_ERROR; |
| break; |
| case QCAMERA_HAL_PREVIEW_STOPPED: |
| case QCAMERA_HAL_TAKE_PICTURE: |
| mPreviewWindow = window; |
| ALOGE("%s: mPreviewWindow = 0x%p, mStreamDisplay = 0x%p", |
| __func__, mPreviewWindow, mStreamDisplay); |
| if(mStreamDisplay) |
| retVal = mStreamDisplay->setPreviewWindow(window); |
| break; |
| default: |
| ALOGE("%s: bug, cannot handle new window in state %d", __func__, mPreviewState); |
| retVal = UNKNOWN_ERROR; |
| break; |
| } |
| ALOGV(" %s : X, mPreviewState = %d", __FUNCTION__, mPreviewState); |
| return retVal; |
| } |
| |
| int QCameraHardwareInterface::storeMetaDataInBuffers(int enable) |
| { |
| /* this is a dummy func now. fix me later */ |
| mStoreMetaDataInFrame = enable; |
| return 0; |
| } |
| |
| status_t QCameraHardwareInterface::sendMappingBuf(int ext_mode, int idx, int fd, |
| uint32_t size, int cameraid, |
| mm_camera_socket_msg_type msg_type) |
| { |
| cam_sock_packet_t packet; |
| memset(&packet, 0, sizeof(cam_sock_packet_t)); |
| packet.msg_type = msg_type; |
| packet.payload.frame_fd_map.ext_mode = ext_mode; |
| packet.payload.frame_fd_map.frame_idx = idx; |
| packet.payload.frame_fd_map.fd = fd; |
| packet.payload.frame_fd_map.size = size; |
| |
| if ( cam_ops_sendmsg(cameraid, &packet, sizeof(cam_sock_packet_t), packet.payload.frame_fd_map.fd) <= 0 ) { |
| ALOGE("%s: sending frame mapping buf msg Failed", __func__); |
| return FAILED_TRANSACTION; |
| } |
| return NO_ERROR; |
| } |
| |
| status_t QCameraHardwareInterface::sendUnMappingBuf(int ext_mode, int idx, int cameraid, |
| mm_camera_socket_msg_type msg_type) |
| { |
| cam_sock_packet_t packet; |
| memset(&packet, 0, sizeof(cam_sock_packet_t)); |
| packet.msg_type = msg_type; |
| packet.payload.frame_fd_unmap.ext_mode = ext_mode; |
| packet.payload.frame_fd_unmap.frame_idx = idx; |
| if ( cam_ops_sendmsg(cameraid, &packet, sizeof(cam_sock_packet_t), 0) <= 0 ) { |
| ALOGE("%s: sending frame unmapping buf msg Failed", __func__); |
| return FAILED_TRANSACTION; |
| } |
| return NO_ERROR; |
| } |
| |
| int QCameraHardwareInterface::allocate_ion_memory(QCameraHalHeap_t *p_camera_memory, int cnt, int ion_type) |
| { |
| int rc = 0; |
| struct ion_handle_data handle_data; |
| |
| p_camera_memory->main_ion_fd[cnt] = open("/dev/ion", O_RDONLY); |
| if (p_camera_memory->main_ion_fd[cnt] < 0) { |
| ALOGE("Ion dev open failed\n"); |
| ALOGE("Error is %s\n", strerror(errno)); |
| goto ION_OPEN_FAILED; |
| } |
| p_camera_memory->alloc[cnt].len = p_camera_memory->size; |
| /* to make it page size aligned */ |
| p_camera_memory->alloc[cnt].len = (p_camera_memory->alloc[cnt].len + 4095) & (~4095); |
| p_camera_memory->alloc[cnt].align = 4096; |
| p_camera_memory->alloc[cnt].flags = ION_FLAG_CACHED; |
| p_camera_memory->alloc[cnt].heap_mask = ion_type; |
| |
| rc = ioctl(p_camera_memory->main_ion_fd[cnt], ION_IOC_ALLOC, &p_camera_memory->alloc[cnt]); |
| if (rc < 0) { |
| ALOGE("ION allocation failed\n"); |
| goto ION_ALLOC_FAILED; |
| } |
| |
| p_camera_memory->ion_info_fd[cnt].handle = p_camera_memory->alloc[cnt].handle; |
| rc = ioctl(p_camera_memory->main_ion_fd[cnt], ION_IOC_SHARE, &p_camera_memory->ion_info_fd[cnt]); |
| if (rc < 0) { |
| ALOGE("ION map failed %s\n", strerror(errno)); |
| goto ION_MAP_FAILED; |
| } |
| p_camera_memory->fd[cnt] = p_camera_memory->ion_info_fd[cnt].fd; |
| return 0; |
| |
| ION_MAP_FAILED: |
| handle_data.handle = p_camera_memory->ion_info_fd[cnt].handle; |
| ioctl(p_camera_memory->main_ion_fd[cnt], ION_IOC_FREE, &handle_data); |
| ION_ALLOC_FAILED: |
| close(p_camera_memory->main_ion_fd[cnt]); |
| p_camera_memory->main_ion_fd[cnt] = -1; |
| ION_OPEN_FAILED: |
| return -1; |
| } |
| |
| int QCameraHardwareInterface::deallocate_ion_memory(QCameraHalHeap_t *p_camera_memory, int cnt) |
| { |
| struct ion_handle_data handle_data; |
| int rc = 0; |
| |
| if (p_camera_memory->main_ion_fd[cnt] > 0) { |
| handle_data.handle = p_camera_memory->ion_info_fd[cnt].handle; |
| ioctl(p_camera_memory->main_ion_fd[cnt], ION_IOC_FREE, &handle_data); |
| close(p_camera_memory->main_ion_fd[cnt]); |
| p_camera_memory->main_ion_fd[cnt] = -1; |
| } |
| return rc; |
| } |
| |
| int QCameraHardwareInterface::allocate_ion_memory(QCameraStatHeap_t *p_camera_memory, int cnt, int ion_type) |
| { |
| int rc = 0; |
| struct ion_handle_data handle_data; |
| |
| p_camera_memory->main_ion_fd[cnt] = open("/dev/ion", O_RDONLY); |
| if (p_camera_memory->main_ion_fd[cnt] < 0) { |
| ALOGE("Ion dev open failed\n"); |
| ALOGE("Error is %s\n", strerror(errno)); |
| goto ION_OPEN_FAILED; |
| } |
| p_camera_memory->alloc[cnt].len = p_camera_memory->size; |
| /* to make it page size aligned */ |
| p_camera_memory->alloc[cnt].len = (p_camera_memory->alloc[cnt].len + 4095) & (~4095); |
| p_camera_memory->alloc[cnt].align = 4096; |
| p_camera_memory->alloc[cnt].flags = ION_FLAG_CACHED; |
| p_camera_memory->alloc[cnt].heap_mask = (0x1 << ion_type | 0x1 << ION_IOMMU_HEAP_ID); |
| |
| rc = ioctl(p_camera_memory->main_ion_fd[cnt], ION_IOC_ALLOC, &p_camera_memory->alloc[cnt]); |
| if (rc < 0) { |
| ALOGE("ION allocation failed\n"); |
| goto ION_ALLOC_FAILED; |
| } |
| |
| p_camera_memory->ion_info_fd[cnt].handle = p_camera_memory->alloc[cnt].handle; |
| rc = ioctl(p_camera_memory->main_ion_fd[cnt], ION_IOC_SHARE, &p_camera_memory->ion_info_fd[cnt]); |
| if (rc < 0) { |
| ALOGE("ION map failed %s\n", strerror(errno)); |
| goto ION_MAP_FAILED; |
| } |
| p_camera_memory->fd[cnt] = p_camera_memory->ion_info_fd[cnt].fd; |
| return 0; |
| |
| ION_MAP_FAILED: |
| handle_data.handle = p_camera_memory->ion_info_fd[cnt].handle; |
| ioctl(p_camera_memory->main_ion_fd[cnt], ION_IOC_FREE, &handle_data); |
| ION_ALLOC_FAILED: |
| close(p_camera_memory->main_ion_fd[cnt]); |
| p_camera_memory->main_ion_fd[cnt] = -1; |
| ION_OPEN_FAILED: |
| return -1; |
| } |
| |
| int QCameraHardwareInterface::cache_ops(int ion_fd, |
| struct ion_flush_data *cache_data, int type) |
| { |
| int rc = 0; |
| struct ion_custom_data data; |
| data.cmd = type; |
| data.arg = (unsigned long)cache_data; |
| |
| rc = ioctl(ion_fd, ION_IOC_CUSTOM, &data); |
| if (rc < 0) |
| ALOGE("%s: Cache Invalidate failed\n", __func__); |
| else |
| ALOGV("%s: Cache OPs type(%d) success", __func__); |
| |
| return rc; |
| } |
| |
| int QCameraHardwareInterface::deallocate_ion_memory(QCameraStatHeap_t *p_camera_memory, int cnt) |
| { |
| struct ion_handle_data handle_data; |
| int rc = 0; |
| |
| if (p_camera_memory->main_ion_fd[cnt] > 0) { |
| handle_data.handle = p_camera_memory->ion_info_fd[cnt].handle; |
| ioctl(p_camera_memory->main_ion_fd[cnt], ION_IOC_FREE, &handle_data); |
| close(p_camera_memory->main_ion_fd[cnt]); |
| p_camera_memory->main_ion_fd[cnt] = -1; |
| } |
| return rc; |
| } |
| |
| int QCameraHardwareInterface::initHeapMem( QCameraHalHeap_t *heap, |
| int num_of_buf, |
| int buf_len, |
| int y_off, |
| int cbcr_off, |
| int pmem_type, |
| mm_cameara_stream_buf_t *StreamBuf, |
| mm_camera_buf_def_t *buf_def, |
| uint8_t num_planes, |
| uint32_t *planes |
| ) |
| { |
| int rc = 0; |
| int i; |
| int path; |
| int ion_fd; |
| struct msm_frame *frame; |
| struct ion_flush_data cache_inv_data; |
| ALOGV("Init Heap =%p. stream_buf =%p, pmem_type =%d, num_of_buf=%d. buf_len=%d, cbcr_off=%d", |
| heap, StreamBuf, pmem_type, num_of_buf, buf_len, cbcr_off); |
| if(num_of_buf > MM_CAMERA_MAX_NUM_FRAMES || heap == NULL || |
| mGetMemory == NULL ) { |
| ALOGE("Init Heap error"); |
| rc = -1; |
| return rc; |
| } |
| memset(heap, 0, sizeof(QCameraHalHeap_t)); |
| for (i=0; i<MM_CAMERA_MAX_NUM_FRAMES;i++) { |
| heap->main_ion_fd[i] = -1; |
| heap->fd[i] = -1; |
| } |
| heap->buffer_count = num_of_buf; |
| heap->size = buf_len; |
| heap->y_offset = y_off; |
| heap->cbcr_offset = cbcr_off; |
| |
| if (StreamBuf != NULL) { |
| StreamBuf->num = num_of_buf; |
| StreamBuf->frame_len = buf_len; |
| switch (pmem_type) { |
| case MSM_PMEM_MAINIMG: |
| case MSM_PMEM_RAW_MAINIMG: |
| path = OUTPUT_TYPE_S; |
| break; |
| |
| case MSM_PMEM_THUMBNAIL: |
| path = OUTPUT_TYPE_T; |
| break; |
| |
| default: |
| rc = -1; |
| return rc; |
| } |
| } |
| |
| |
| for(i = 0; i < num_of_buf; i++) { |
| #ifdef USE_ION |
| if (isZSLMode()) |
| rc = allocate_ion_memory(heap, i, ((0x1 << CAMERA_ZSL_ION_HEAP_ID) | |
| (0x1 << CAMERA_ZSL_ION_FALLBACK_HEAP_ID))); |
| else |
| rc = allocate_ion_memory(heap, i, ((0x1 << CAMERA_ION_HEAP_ID) | |
| (0x1 << CAMERA_ION_FALLBACK_HEAP_ID))); |
| |
| if (rc < 0) { |
| ALOGE("%s: ION allocation failed\n", __func__); |
| break; |
| } |
| #else |
| if (pmem_type == MSM_PMEM_MAX) |
| heap->fd[i] = -1; |
| else { |
| heap->fd[i] = open("/dev/pmem_adsp", O_RDWR|O_SYNC); |
| if ( heap->fd[i] <= 0) { |
| rc = -1; |
| ALOGE("Open fail: heap->fd[%d] =%d", i, heap->fd[i]); |
| break; |
| } |
| } |
| #endif |
| heap->camera_memory[i] = mGetMemory( heap->fd[i], buf_len, 1, (void *)this); |
| |
| if (heap->camera_memory[i] == NULL ) { |
| ALOGE("Getmem fail %d: ", i); |
| rc = -1; |
| break; |
| } |
| |
| memset(&cache_inv_data, 0, sizeof(struct ion_flush_data)); |
| cache_inv_data.vaddr = (void*) heap->camera_memory[i]->data; |
| cache_inv_data.fd = heap->ion_info_fd[i].fd; |
| cache_inv_data.handle = heap->ion_info_fd[i].handle; |
| cache_inv_data.length = heap->alloc[i].len; |
| ion_fd = heap->main_ion_fd[i]; |
| if(ion_fd > 0) { |
| if(cache_ops(ion_fd, &cache_inv_data, ION_IOC_CLEAN_INV_CACHES) < 0) |
| ALOGE("%s: Cache Invalidate failed\n", __func__); |
| else { |
| ALOGV("%s: Successful cache invalidate\n", __func__); |
| } |
| } |
| |
| if (StreamBuf != NULL) { |
| frame = &(StreamBuf->frame[i]); |
| memset(frame, 0, sizeof(struct msm_frame)); |
| frame->fd = heap->fd[i]; |
| frame->phy_offset = 0; |
| frame->buffer = (uint32_t) heap->camera_memory[i]->data; |
| frame->path = path; |
| frame->cbcr_off = planes[0]+heap->cbcr_offset; |
| frame->y_off = heap->y_offset; |
| frame->fd_data = heap->ion_info_fd[i]; |
| frame->ion_alloc = heap->alloc[i]; |
| frame->ion_dev_fd = heap->main_ion_fd[i]; |
| ALOGV("%s: Buffer idx: %d addr: %x fd: %d phy_offset: %d" |
| "cbcr_off: %d y_off: %d frame_len: %d", __func__, |
| i, (unsigned int)frame->buffer, frame->fd, |
| frame->phy_offset, cbcr_off, y_off, frame->ion_alloc.len); |
| |
| buf_def->buf.mp[i].frame = *frame; |
| buf_def->buf.mp[i].frame_offset = 0; |
| buf_def->buf.mp[i].num_planes = num_planes; |
| /* Plane 0 needs to be set seperately. Set other planes |
| * in a loop. */ |
| buf_def->buf.mp[i].planes[0].length = planes[0]; |
| buf_def->buf.mp[i].planes[0].m.userptr = frame->fd; |
| buf_def->buf.mp[i].planes[0].data_offset = y_off; |
| buf_def->buf.mp[i].planes[0].reserved[0] = |
| buf_def->buf.mp[i].frame_offset; |
| for (int j = 1; j < num_planes; j++) { |
| buf_def->buf.mp[i].planes[j].length = planes[j]; |
| buf_def->buf.mp[i].planes[j].m.userptr = frame->fd; |
| buf_def->buf.mp[i].planes[j].data_offset = cbcr_off; |
| buf_def->buf.mp[i].planes[j].reserved[0] = |
| buf_def->buf.mp[i].planes[j-1].reserved[0] + |
| buf_def->buf.mp[i].planes[j-1].length; |
| } |
| } else { |
| } |
| |
| ALOGV("heap->fd[%d] =%d, camera_memory=%p", i, heap->fd[i], heap->camera_memory[i]); |
| heap->local_flag[i] = 1; |
| } |
| if( rc < 0) { |
| releaseHeapMem(heap); |
| } |
| return rc; |
| } |
| |
| int QCameraHardwareInterface::releaseHeapMem( QCameraHalHeap_t *heap) |
| { |
| int rc = 0; |
| ALOGV("Release %p", heap); |
| if (heap != NULL) { |
| |
| for (int i = 0; i < heap->buffer_count; i++) { |
| if(heap->camera_memory[i] != NULL) { |
| heap->camera_memory[i]->release( heap->camera_memory[i] ); |
| heap->camera_memory[i] = NULL; |
| } else if (heap->fd[i] <= 0) { |
| ALOGE("impossible: amera_memory[%d] = %p, fd = %d", |
| i, heap->camera_memory[i], heap->fd[i]); |
| } |
| |
| if(heap->fd[i] > 0) { |
| close(heap->fd[i]); |
| heap->fd[i] = -1; |
| } |
| #ifdef USE_ION |
| deallocate_ion_memory(heap, i); |
| #endif |
| } |
| heap->buffer_count = 0; |
| heap->size = 0; |
| heap->y_offset = 0; |
| heap->cbcr_offset = 0; |
| } |
| return rc; |
| } |
| |
| preview_format_info_t QCameraHardwareInterface::getPreviewFormatInfo( ) |
| { |
| return mPreviewFormatInfo; |
| } |
| |
| void QCameraHardwareInterface::wdenoiseEvent(cam_ctrl_status_t status, void *cookie) |
| { |
| ALOGV("wdnEvent: preview state:%d E",mPreviewState); |
| if (mStreamSnap != NULL) { |
| ALOGV("notifyWDNEvent to snapshot stream"); |
| mStreamSnap->notifyWDenoiseEvent(status, cookie); |
| } |
| } |
| |
| bool QCameraHardwareInterface::isWDenoiseEnabled() |
| { |
| return mDenoiseValue; |
| } |
| |
| void QCameraHardwareInterface::takePicturePrepareHardware() |
| { |
| ALOGV("%s: E", __func__); |
| |
| /* Prepare snapshot*/ |
| cam_ops_action(mCameraId, |
| true, |
| MM_CAMERA_OPS_PREPARE_SNAPSHOT, |
| this); |
| ALOGV("%s: X", __func__); |
| } |
| |
| bool QCameraHardwareInterface::isNoDisplayMode() |
| { |
| return (mNoDisplayMode != 0); |
| } |
| |
| void QCameraHardwareInterface::pausePreviewForZSL() |
| { |
| ALOGV("%s: mRestartPreview %d", __func__, mRestartPreview); |
| if(mRestartPreview) { |
| ALOGE("%s: Restarting Preview",__func__); |
| stopPreviewInternal(); |
| mPreviewState = QCAMERA_HAL_PREVIEW_STOPPED; |
| startPreview2(); |
| mPreviewState = QCAMERA_HAL_PREVIEW_STARTED; |
| } |
| } |
| |
| void QCameraHardwareInterface::pausePreviewForVideo() |
| { |
| status_t ret = NO_ERROR; |
| bool restart = false; |
| cam_ctrl_dimension_t dim; |
| |
| /* get existing preview information, by qury mm_camera*/ |
| memset(&dim, 0, sizeof(cam_ctrl_dimension_t)); |
| ret = cam_config_get_parm(mCameraId, MM_CAMERA_PARM_DIMENSION,&dim); |
| |
| if (MM_CAMERA_OK != ret) { |
| ALOGE("%s: X error- can't get preview dimension!", __func__); |
| return; |
| } |
| |
| if (mRestartPreview) { |
| mRestartPreview = false; |
| ALOGV("%s: Restarting Preview. Video Size changed",__func__); |
| restart |= false; |
| } |
| if (mRecordingHint == false) { |
| ALOGV("%s: Restarting Preview. Hint not set",__func__); |
| restart |= true; |
| } |
| |
| if(dim.video_width != mVideoWidth || dim.video_height != mVideoHeight){ |
| ALOGV("%s: Restarting Preview. New Video Size set",__func__); |
| restart |= true; |
| } |
| |
| //VFE output1 shouldn't be greater than VFE output2. |
| if( (mPreviewWidth > mVideoWidth) || (mPreviewHeight > mVideoHeight)) { |
| //Set preview sizes as record sizes. |
| ALOGV("Preview size %dx%d is greater than record size %dx%d,\ |
| resetting preview size to record size",mPreviewWidth, |
| mPreviewHeight, mVideoWidth, mVideoHeight); |
| mPreviewWidth = mVideoWidth; |
| mPreviewHeight = mVideoHeight; |
| mParameters.setPreviewSize(mPreviewWidth, mPreviewHeight); |
| restart |= true; |
| } |
| if (restart) { |
| stopPreviewInternal(); |
| mPreviewState = QCAMERA_HAL_PREVIEW_STOPPED; |
| |
| // Set recording hint to true |
| mRecordingHint = true; |
| setRecordingHintValue(mRecordingHint); |
| |
| mDimension.display_width = mPreviewWidth; |
| mDimension.display_height= mPreviewHeight; |
| mDimension.orig_video_width = mVideoWidth; |
| mDimension.orig_video_height = mVideoHeight; |
| mDimension.video_width = mVideoWidth; |
| mDimension.video_height = mVideoHeight; |
| |
| // start preview again |
| mPreviewState = QCAMERA_HAL_PREVIEW_START; |
| if (startPreview2() == NO_ERROR){ |
| mPreviewState = QCAMERA_HAL_PREVIEW_STARTED; |
| }else{ |
| ALOGE("%s: Restart for Video Failed",__func__); |
| } |
| } |
| } |
| |
| /**/ |
| bool QCameraHardwareInterface::getHdrInfoAndSetExp( int max_num_frm, int *num_frame, int *exp) |
| { |
| bool rc = false; |
| |
| if (mHdrMode == HDR_MODE && num_frame != NULL && exp != NULL && |
| mRecordingHint != true && |
| mPreviewState != QCAMERA_HAL_RECORDING_STARTED ) { |
| int ret = 0; |
| *num_frame = 1; |
| exp_bracketing_t temp; |
| memset(&temp, 0, sizeof(exp_bracketing_t)); |
| ret = cam_config_get_parm(mCameraId, MM_CAMERA_PARM_HDR, (void *)&temp ); |
| if (ret == NO_ERROR && max_num_frm > 0) { |
| /*set as AE Bracketing mode*/ |
| temp.hdr_enable = false; |
| temp.mode = HDR_MODE; |
| temp.total_hal_frames = temp.total_frames; |
| ret = native_set_parms(MM_CAMERA_PARM_HDR, |
| sizeof(exp_bracketing_t), (void *)&temp); |
| if (ret) { |
| char *val, *exp_value, *prev_value; |
| int i; |
| exp_value = (char *) temp.values; |
| i = 0; |
| val = strtok_r(exp_value,",", &prev_value); |
| while (val != NULL ){ |
| exp[i++] = atoi(val); |
| if(i >= max_num_frm ) |
| break; |
| val = strtok_r(NULL, ",", &prev_value); |
| } |
| *num_frame =temp.total_frames; |
| rc = true; |
| } |
| } else { |
| temp.total_frames = 1; |
| } |
| /* Application waits until this many snapshots before restarting preview */ |
| mParameters.set("num-snaps-per-shutter", 2); |
| } |
| return rc; |
| } |
| |
| void QCameraHardwareInterface::hdrEvent(cam_ctrl_status_t status, void *cookie) |
| { |
| QCameraStream * snapStream = (QCameraStream *)cookie; |
| ALOGV("HdrEvent: preview state: E"); |
| if (snapStream != NULL && mStreamSnap != NULL) { |
| ALOGV("HdrEvent to snapshot stream"); |
| snapStream->notifyHdrEvent(status, cookie); |
| } |
| } |
| |
| }; // namespace android |