summaryrefslogtreecommitdiffstats
path: root/camera/OMXCameraAdapter/OMXCapture.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'camera/OMXCameraAdapter/OMXCapture.cpp')
-rw-r--r--camera/OMXCameraAdapter/OMXCapture.cpp1229
1 files changed, 1229 insertions, 0 deletions
diff --git a/camera/OMXCameraAdapter/OMXCapture.cpp b/camera/OMXCameraAdapter/OMXCapture.cpp
new file mode 100644
index 0000000..0a622cc
--- /dev/null
+++ b/camera/OMXCameraAdapter/OMXCapture.cpp
@@ -0,0 +1,1229 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * 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.
+ */
+
+/**
+* @file OMXCapture.cpp
+*
+* This file contains functionality for handling image capture.
+*
+*/
+
+#undef LOG_TAG
+
+#define LOG_TAG "CameraHAL"
+
+#include "CameraHal.h"
+#include "OMXCameraAdapter.h"
+#include "ErrorUtils.h"
+
+
+namespace android {
+
+status_t OMXCameraAdapter::setParametersCapture(const CameraParameters &params,
+ BaseCameraAdapter::AdapterState state)
+{
+ status_t ret = NO_ERROR;
+ const char *str = NULL;
+ int w, h;
+ OMX_COLOR_FORMATTYPE pixFormat;
+ const char *valstr = NULL;
+ int varint = 0;
+
+ LOG_FUNCTION_NAME;
+
+ OMXCameraPortParameters *cap;
+ cap = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+
+ params.getPictureSize(&w, &h);
+
+ if ( ( w != ( int ) cap->mWidth ) ||
+ ( h != ( int ) cap->mHeight ) )
+ {
+ mPendingCaptureSettings |= SetFormat;
+ }
+
+ cap->mWidth = w;
+ cap->mHeight = h;
+ //TODO: Support more pixelformats
+ //cap->mStride = 2;
+
+ CAMHAL_LOGVB("Image: cap.mWidth = %d", (int)cap->mWidth);
+ CAMHAL_LOGVB("Image: cap.mHeight = %d", (int)cap->mHeight);
+
+ if ((valstr = params.getPictureFormat()) != NULL) {
+ if (strcmp(valstr, (const char *) CameraParameters::PIXEL_FORMAT_YUV422I) == 0) {
+ CAMHAL_LOGDA("CbYCrY format selected");
+ pixFormat = OMX_COLOR_FormatCbYCrY;
+ mPictureFormatFromClient = CameraParameters::PIXEL_FORMAT_YUV422I;
+ } else if(strcmp(valstr, (const char *) CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) {
+ CAMHAL_LOGDA("YUV420SP format selected");
+ pixFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+ mPictureFormatFromClient = CameraParameters::PIXEL_FORMAT_YUV420SP;
+ } else if(strcmp(valstr, (const char *) CameraParameters::PIXEL_FORMAT_RGB565) == 0) {
+ CAMHAL_LOGDA("RGB565 format selected");
+ pixFormat = OMX_COLOR_Format16bitRGB565;
+ mPictureFormatFromClient = CameraParameters::PIXEL_FORMAT_RGB565;
+ } else if (strcmp(valstr, (const char *) CameraParameters::PIXEL_FORMAT_JPEG) == 0) {
+ CAMHAL_LOGDA("JPEG format selected");
+ pixFormat = OMX_COLOR_FormatUnused;
+ mCodingMode = CodingNone;
+ mPictureFormatFromClient = CameraParameters::PIXEL_FORMAT_JPEG;
+ } else if (strcmp(valstr, (const char *) TICameraParameters::PIXEL_FORMAT_JPS) == 0) {
+ CAMHAL_LOGDA("JPS format selected");
+ pixFormat = OMX_COLOR_FormatUnused;
+ mCodingMode = CodingJPS;
+ mPictureFormatFromClient = TICameraParameters::PIXEL_FORMAT_JPS;
+ } else if (strcmp(valstr, (const char *) TICameraParameters::PIXEL_FORMAT_MPO) == 0) {
+ CAMHAL_LOGDA("MPO format selected");
+ pixFormat = OMX_COLOR_FormatUnused;
+ mCodingMode = CodingMPO;
+ mPictureFormatFromClient = TICameraParameters::PIXEL_FORMAT_MPO;
+ } else if (strcmp(valstr, (const char *) TICameraParameters::PIXEL_FORMAT_RAW) == 0) {
+ CAMHAL_LOGDA("RAW Picture format selected");
+ pixFormat = OMX_COLOR_FormatRawBayer10bit;
+ mPictureFormatFromClient = TICameraParameters::PIXEL_FORMAT_RAW;
+ } else {
+ CAMHAL_LOGEA("Invalid format, JPEG format selected as default");
+ pixFormat = OMX_COLOR_FormatUnused;
+ mPictureFormatFromClient = NULL;
+ }
+ } else {
+ CAMHAL_LOGEA("Picture format is NULL, defaulting to JPEG");
+ pixFormat = OMX_COLOR_FormatUnused;
+ mPictureFormatFromClient = NULL;
+ }
+
+ // JPEG capture is not supported in video mode by OMX Camera
+ // Set capture format to yuv422i...jpeg encode will
+ // be done on A9
+ valstr = params.get(TICameraParameters::KEY_CAP_MODE);
+ if ( (valstr && !strcmp(valstr, (const char *) TICameraParameters::VIDEO_MODE)) &&
+ (pixFormat == OMX_COLOR_FormatUnused) ) {
+ CAMHAL_LOGDA("Capturing in video mode...selecting yuv422i");
+ pixFormat = OMX_COLOR_FormatCbYCrY;
+ }
+
+ if ( pixFormat != cap->mColorFormat )
+ {
+ mPendingCaptureSettings |= SetFormat;
+ cap->mColorFormat = pixFormat;
+ }
+
+#ifdef OMAP_ENHANCEMENT
+
+ str = params.get(TICameraParameters::KEY_EXP_BRACKETING_RANGE);
+ if ( NULL != str ) {
+ parseExpRange(str, mExposureBracketingValues, EXP_BRACKET_RANGE, mExposureBracketingValidEntries);
+ } else {
+ // if bracketing was previously set...we set again before capturing to clear
+ if (mExposureBracketingValidEntries) mPendingCaptureSettings |= SetExpBracket;
+ mExposureBracketingValidEntries = 0;
+ }
+
+#endif
+
+ varint = params.getInt(CameraParameters::KEY_ROTATION);
+ if ( varint != -1 )
+ {
+ if ( ( unsigned int ) varint != mPictureRotation) {
+ mPendingCaptureSettings |= SetRotation;
+ }
+ mPictureRotation = varint;
+ }
+ else
+ {
+ if (mPictureRotation) mPendingCaptureSettings |= SetRotation;
+ mPictureRotation = 0;
+ }
+
+ CAMHAL_LOGVB("Picture Rotation set %d", mPictureRotation);
+
+#ifdef OMAP_ENHANCEMENT
+
+ // Read Sensor Orientation and set it based on perating mode
+
+ varint = params.getInt(TICameraParameters::KEY_SENSOR_ORIENTATION);
+ if (( varint != -1 ) && (mCapMode == OMXCameraAdapter::VIDEO_MODE))
+ {
+ mSensorOrientation = varint;
+ if (mSensorOrientation == 270 ||mSensorOrientation==90)
+ {
+ CAMHAL_LOGEA(" Orientation is 270/90. So setting counter rotation to Ducati");
+ mSensorOrientation +=180;
+ mSensorOrientation%=360;
+ }
+ }
+ else
+ {
+ mSensorOrientation = 0;
+ }
+
+ CAMHAL_LOGVB("Sensor Orientation set : %d", mSensorOrientation);
+
+ varint = params.getInt(TICameraParameters::KEY_BURST);
+ if ( varint >= 1 )
+ {
+ if (varint != mBurstFrames) {
+ mPendingCaptureSettings |= SetExpBracket;
+ }
+ mBurstFrames = varint;
+ }
+ else
+ {
+ if (mBurstFrames != 1) mPendingCaptureSettings |= SetExpBracket;
+ mBurstFrames = 1;
+ }
+
+ CAMHAL_LOGVB("Burst Frames set %d", mBurstFrames);
+
+#endif
+
+ varint = params.getInt(CameraParameters::KEY_JPEG_QUALITY);
+ if ( ( varint >= MIN_JPEG_QUALITY ) &&
+ ( varint <= MAX_JPEG_QUALITY ) )
+ {
+ if ( ( unsigned int ) varint != mPictureQuality) {
+ mPendingCaptureSettings |= SetQuality;
+ }
+ mPictureQuality = varint;
+ }
+ else
+ {
+ if (mPictureQuality != MAX_JPEG_QUALITY) mPendingCaptureSettings |= SetQuality;
+ mPictureQuality = MAX_JPEG_QUALITY;
+ }
+
+ CAMHAL_LOGVB("Picture Quality set %d", mPictureQuality);
+
+ varint = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
+ if ( varint >= 0 )
+ {
+ if ( ( unsigned int ) varint != mThumbWidth) {
+ mPendingCaptureSettings |= SetThumb;
+ }
+ mThumbWidth = varint;
+ }
+ else
+ {
+ if (mThumbWidth != DEFAULT_THUMB_WIDTH) mPendingCaptureSettings |= SetThumb;
+ mThumbWidth = DEFAULT_THUMB_WIDTH;
+ }
+
+
+ CAMHAL_LOGVB("Picture Thumb width set %d", mThumbWidth);
+
+ varint = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
+ if ( varint >= 0 )
+ {
+ if ( ( unsigned int ) varint != mThumbHeight) {
+ mPendingCaptureSettings |= SetThumb;
+ }
+ mThumbHeight = varint;
+ }
+ else
+ {
+ if (mThumbHeight != DEFAULT_THUMB_HEIGHT) mPendingCaptureSettings |= SetThumb;
+ mThumbHeight = DEFAULT_THUMB_HEIGHT;
+ }
+
+
+ CAMHAL_LOGVB("Picture Thumb height set %d", mThumbHeight);
+
+ varint = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
+ if ( ( varint >= MIN_JPEG_QUALITY ) &&
+ ( varint <= MAX_JPEG_QUALITY ) )
+ {
+ if ( ( unsigned int ) varint != mThumbQuality) {
+ mPendingCaptureSettings |= SetThumb;
+ }
+ mThumbQuality = varint;
+ }
+ else
+ {
+ if (mThumbQuality != MAX_JPEG_QUALITY) mPendingCaptureSettings |= SetThumb;
+ mThumbQuality = MAX_JPEG_QUALITY;
+ }
+
+ CAMHAL_LOGDB("Thumbnail Quality set %d", mThumbQuality);
+
+ if (mFirstTimeInit) {
+ mPendingCaptureSettings = ECapturesettingsAll;
+ }
+
+ if (mPendingCaptureSettings) {
+ disableImagePort();
+ if ( NULL != mReleaseImageBuffersCallback ) {
+ mReleaseImageBuffersCallback(mReleaseData);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::getPictureBufferSize(size_t &length, size_t bufferCount)
+{
+ status_t ret = NO_ERROR;
+ OMXCameraPortParameters *imgCaptureData = NULL;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+
+ LOG_FUNCTION_NAME;
+
+ if ( NO_ERROR == ret )
+ {
+ imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+
+ imgCaptureData->mNumBufs = bufferCount;
+
+ // check if image port is already configured...
+ // if it already configured then we don't have to query again
+ if (!mCaptureConfigured) {
+ ret = setFormat(OMX_CAMERA_PORT_IMAGE_OUT_IMAGE, *imgCaptureData);
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ length = imgCaptureData->mBufSize;
+ }
+ else
+ {
+ CAMHAL_LOGEB("setFormat() failed 0x%x", ret);
+ length = 0;
+ }
+ }
+
+ CAMHAL_LOGDB("getPictureBufferSize %d", length);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::parseExpRange(const char *rangeStr,
+ int * expRange,
+ size_t count,
+ size_t &validEntries)
+{
+ status_t ret = NO_ERROR;
+ char *ctx, *expVal;
+ char *tmp = NULL;
+ size_t i = 0;
+
+ LOG_FUNCTION_NAME;
+
+ if ( NULL == rangeStr )
+ {
+ return -EINVAL;
+ }
+
+ if ( NULL == expRange )
+ {
+ return -EINVAL;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ tmp = ( char * ) malloc( strlen(rangeStr) + 1 );
+
+ if ( NULL == tmp )
+ {
+ CAMHAL_LOGEA("No resources for temporary buffer");
+ return -1;
+ }
+ memset(tmp, '\0', strlen(rangeStr) + 1);
+
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ strncpy(tmp, rangeStr, strlen(rangeStr) );
+ expVal = strtok_r( (char *) tmp, CameraHal::PARAMS_DELIMITER, &ctx);
+
+ i = 0;
+ while ( ( NULL != expVal ) && ( i < count ) )
+ {
+ expRange[i] = atoi(expVal);
+ expVal = strtok_r(NULL, CameraHal::PARAMS_DELIMITER, &ctx);
+ i++;
+ }
+ validEntries = i;
+ }
+
+ if ( NULL != tmp )
+ {
+ free(tmp);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::setExposureBracketing(int *evValues,
+ size_t evCount,
+ size_t frameCount)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_CAPTUREMODETYPE expCapMode;
+ OMX_CONFIG_EXTCAPTUREMODETYPE extExpCapMode;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ ret = -EINVAL;
+ }
+
+ if ( NULL == evValues )
+ {
+ CAMHAL_LOGEA("Exposure compensation values pointer is invalid");
+ ret = -EINVAL;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ OMX_INIT_STRUCT_PTR (&expCapMode, OMX_CONFIG_CAPTUREMODETYPE);
+ expCapMode.nPortIndex = mCameraAdapterParameters.mImagePortIndex;
+
+ /// If frameCount>0 but evCount<=0, then this is the case of HQ burst.
+ //Otherwise, it is normal HQ capture
+ ///If frameCount>0 and evCount>0 then this is the cause of HQ Exposure bracketing.
+ if ( 0 == evCount && 0 == frameCount )
+ {
+ expCapMode.bFrameLimited = OMX_FALSE;
+ }
+ else
+ {
+ expCapMode.bFrameLimited = OMX_TRUE;
+ expCapMode.nFrameLimit = frameCount;
+ }
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCaptureMode,
+ &expCapMode);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring capture mode 0x%x", eError);
+ }
+ else
+ {
+ CAMHAL_LOGDA("Camera capture mode configured successfully");
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ OMX_INIT_STRUCT_PTR (&extExpCapMode, OMX_CONFIG_EXTCAPTUREMODETYPE);
+ extExpCapMode.nPortIndex = mCameraAdapterParameters.mImagePortIndex;
+
+ if ( 0 == evCount )
+ {
+ extExpCapMode.bEnableBracketing = OMX_FALSE;
+ }
+ else
+ {
+ extExpCapMode.bEnableBracketing = OMX_TRUE;
+ extExpCapMode.tBracketConfigType.eBracketMode = OMX_BracketExposureRelativeInEV;
+ extExpCapMode.tBracketConfigType.nNbrBracketingValues = evCount - 1;
+ }
+
+ for ( unsigned int i = 0 ; i < evCount ; i++ )
+ {
+ extExpCapMode.tBracketConfigType.nBracketValues[i] = ( evValues[i] * ( 1 << Q16_OFFSET ) ) / 10;
+ }
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_IndexConfigExtCaptureMode,
+ &extExpCapMode);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring extended capture mode 0x%x", eError);
+ }
+ else
+ {
+ CAMHAL_LOGDA("Extended camera capture mode configured successfully");
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::setShutterCallback(bool enabled)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_CALLBACKREQUESTTYPE shutterRequstCallback;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateExecuting != mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component not in executing state");
+ ret = -1;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+
+ OMX_INIT_STRUCT_PTR (&shutterRequstCallback, OMX_CONFIG_CALLBACKREQUESTTYPE);
+ shutterRequstCallback.nPortIndex = OMX_ALL;
+
+ if ( enabled )
+ {
+ shutterRequstCallback.bEnable = OMX_TRUE;
+ shutterRequstCallback.nIndex = ( OMX_INDEXTYPE ) OMX_TI_IndexConfigShutterCallback;
+ CAMHAL_LOGDA("Enabling shutter callback");
+ }
+ else
+ {
+ shutterRequstCallback.bEnable = OMX_FALSE;
+ shutterRequstCallback.nIndex = ( OMX_INDEXTYPE ) OMX_TI_IndexConfigShutterCallback;
+ CAMHAL_LOGDA("Disabling shutter callback");
+ }
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_IndexConfigCallbackRequest,
+ &shutterRequstCallback);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error registering shutter callback 0x%x", eError);
+ ret = -1;
+ }
+ else
+ {
+ CAMHAL_LOGDB("Shutter callback for index 0x%x registered successfully",
+ OMX_TI_IndexConfigShutterCallback);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::doBracketing(OMX_BUFFERHEADERTYPE *pBuffHeader,
+ CameraFrame::FrameType typeOfFrame)
+{
+ status_t ret = NO_ERROR;
+ int currentBufferIdx, nextBufferIdx;
+ OMXCameraPortParameters * imgCaptureData = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+
+ if ( OMX_StateExecuting != mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is not in executing state");
+ ret = -EINVAL;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ currentBufferIdx = ( unsigned int ) pBuffHeader->pAppPrivate;
+
+ if ( currentBufferIdx >= imgCaptureData->mNumBufs)
+ {
+ CAMHAL_LOGEB("Invalid bracketing buffer index 0x%x", currentBufferIdx);
+ ret = -EINVAL;
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ mBracketingBuffersQueued[currentBufferIdx] = false;
+ mBracketingBuffersQueuedCount--;
+
+ if ( 0 >= mBracketingBuffersQueuedCount )
+ {
+ nextBufferIdx = ( currentBufferIdx + 1 ) % imgCaptureData->mNumBufs;
+ mBracketingBuffersQueued[nextBufferIdx] = true;
+ mBracketingBuffersQueuedCount++;
+ mLastBracetingBufferIdx = nextBufferIdx;
+ setFrameRefCount(imgCaptureData->mBufferHeader[nextBufferIdx]->pBuffer, typeOfFrame, 1);
+ returnFrame(imgCaptureData->mBufferHeader[nextBufferIdx]->pBuffer, typeOfFrame);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::sendBracketFrames()
+{
+ status_t ret = NO_ERROR;
+ int currentBufferIdx;
+ OMXCameraPortParameters * imgCaptureData = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+
+ if ( OMX_StateExecuting != mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is not in executing state");
+ ret = -EINVAL;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+
+ currentBufferIdx = mLastBracetingBufferIdx;
+ do
+ {
+ currentBufferIdx++;
+ currentBufferIdx %= imgCaptureData->mNumBufs;
+ if (!mBracketingBuffersQueued[currentBufferIdx] )
+ {
+ CameraFrame cameraFrame;
+ sendCallBacks(cameraFrame,
+ imgCaptureData->mBufferHeader[currentBufferIdx],
+ imgCaptureData->mImageType,
+ imgCaptureData);
+ }
+ } while ( currentBufferIdx != mLastBracetingBufferIdx );
+
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::startBracketing(int range)
+{
+ status_t ret = NO_ERROR;
+ OMXCameraPortParameters * imgCaptureData = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+
+ if ( OMX_StateExecuting != mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is not in executing state");
+ ret = -EINVAL;
+ }
+
+ {
+ Mutex::Autolock lock(mBracketingLock);
+
+ if ( mBracketingEnabled )
+ {
+ return ret;
+ }
+ }
+
+ if ( 0 == imgCaptureData->mNumBufs )
+ {
+ CAMHAL_LOGEB("Image capture buffers set to %d", imgCaptureData->mNumBufs);
+ ret = -EINVAL;
+ }
+
+ if ( mPending3Asettings )
+ apply3Asettings(mParameters3A);
+
+ if ( NO_ERROR == ret )
+ {
+ Mutex::Autolock lock(mBracketingLock);
+
+ mBracketingRange = range;
+ mBracketingBuffersQueued = new bool[imgCaptureData->mNumBufs];
+ if ( NULL == mBracketingBuffersQueued )
+ {
+ CAMHAL_LOGEA("Unable to allocate bracketing management structures");
+ ret = -1;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ mBracketingBuffersQueuedCount = imgCaptureData->mNumBufs;
+ mLastBracetingBufferIdx = mBracketingBuffersQueuedCount - 1;
+
+ for ( int i = 0 ; i < imgCaptureData->mNumBufs ; i++ )
+ {
+ mBracketingBuffersQueued[i] = true;
+ }
+
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+
+ ret = startImageCapture();
+ {
+ Mutex::Autolock lock(mBracketingLock);
+
+ if ( NO_ERROR == ret )
+ {
+ mBracketingEnabled = true;
+ }
+ else
+ {
+ mBracketingEnabled = false;
+ }
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::stopBracketing()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ Mutex::Autolock lock(mBracketingLock);
+
+ if ( NULL != mBracketingBuffersQueued )
+ {
+ delete [] mBracketingBuffersQueued;
+ }
+
+ ret = stopImageCapture();
+
+ mBracketingBuffersQueued = NULL;
+ mBracketingEnabled = false;
+ mBracketingBuffersQueuedCount = 0;
+ mLastBracetingBufferIdx = 0;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::startImageCapture()
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMXCameraPortParameters * capData = NULL;
+ OMX_CONFIG_BOOLEANTYPE bOMX;
+
+ LOG_FUNCTION_NAME;
+
+ Mutex::Autolock lock(mImageCaptureLock);
+
+ if(!mCaptureConfigured)
+ {
+ ///Image capture was cancelled before we could start
+ return NO_ERROR;
+ }
+
+ if ( 0 != mStartCaptureSem.Count() )
+ {
+ CAMHAL_LOGEB("Error mStartCaptureSem semaphore count %d", mStartCaptureSem.Count());
+ return NO_INIT;
+ }
+
+ if ((getNextState() & (CAPTURE_ACTIVE|BRACKETING_ACTIVE)) == 0) {
+ CAMHAL_LOGDA("trying starting capture when already canceled");
+ return NO_ERROR;
+ }
+
+ // Camera framework doesn't expect face callbacks once capture is triggered
+ pauseFaceDetection(true);
+
+ //During bracketing image capture is already active
+ {
+ Mutex::Autolock lock(mBracketingLock);
+ if ( mBracketingEnabled )
+ {
+ //Stop bracketing, activate normal burst for the remaining images
+ mBracketingEnabled = false;
+ mCapturedFrames = mBracketingRange;
+ ret = sendBracketFrames();
+ if(ret != NO_ERROR)
+ goto EXIT;
+ else
+ return ret;
+ }
+ }
+
+ if ( NO_ERROR == ret ) {
+ if (mPendingCaptureSettings & SetRotation) {
+ mPendingCaptureSettings &= ~SetRotation;
+ ret = setPictureRotation(mPictureRotation);
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("Error configuring image rotation %x", ret);
+ }
+ }
+ }
+
+ // need to enable wb data for video snapshot to fill in exif data
+ if ((ret == NO_ERROR) && (mCapMode == VIDEO_MODE)) {
+ // video snapshot uses wb data from snapshot frame
+ ret = setExtraData(true, mCameraAdapterParameters.mPrevPortIndex, OMX_WhiteBalance);
+ }
+
+ //OMX shutter callback events are only available in hq mode
+ if ( (HIGH_QUALITY == mCapMode) || (HIGH_QUALITY_ZSL== mCapMode))
+ {
+
+ if ( NO_ERROR == ret )
+ {
+ ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
+ (OMX_EVENTTYPE) OMX_EventIndexSettingChanged,
+ OMX_ALL,
+ OMX_TI_IndexConfigShutterCallback,
+ mStartCaptureSem);
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ ret = setShutterCallback(true);
+ }
+
+ }
+
+ if ( NO_ERROR == ret ) {
+ capData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+
+ ///Queue all the buffers on capture port
+ for ( int index = 0 ; index < capData->mNumBufs ; index++ ) {
+ CAMHAL_LOGDB("Queuing buffer on Capture port - 0x%x",
+ ( unsigned int ) capData->mBufferHeader[index]->pBuffer);
+ eError = OMX_FillThisBuffer(mCameraAdapterParameters.mHandleComp,
+ (OMX_BUFFERHEADERTYPE*)capData->mBufferHeader[index]);
+
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+ }
+
+ mWaitingForSnapshot = true;
+ mCaptureSignalled = false;
+
+ // Capturing command is not needed when capturing in video mode
+ // Only need to queue buffers on image ports
+ if (mCapMode != VIDEO_MODE) {
+ OMX_INIT_STRUCT_PTR (&bOMX, OMX_CONFIG_BOOLEANTYPE);
+ bOMX.bEnabled = OMX_TRUE;
+
+ /// sending Capturing Command to the component
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCapturing,
+ &bOMX);
+
+ CAMHAL_LOGDB("Capture set - 0x%x", eError);
+
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+ }
+ }
+
+ //OMX shutter callback events are only available in hq mode
+ if ( (HIGH_QUALITY == mCapMode) || (HIGH_QUALITY_ZSL== mCapMode))
+ {
+
+ if ( NO_ERROR == ret )
+ {
+ ret = mStartCaptureSem.WaitTimeout(OMX_CAPTURE_TIMEOUT);
+ }
+
+ //If something bad happened while we wait
+ if (mComponentState != OMX_StateExecuting)
+ {
+ CAMHAL_LOGEA("Invalid State after Image Capture Exitting!!!");
+ goto EXIT;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ CAMHAL_LOGDA("Shutter callback received");
+ notifyShutterSubscribers();
+ }
+ else
+ {
+ ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp,
+ (OMX_EVENTTYPE) OMX_EventIndexSettingChanged,
+ OMX_ALL,
+ OMX_TI_IndexConfigShutterCallback,
+ NULL);
+ CAMHAL_LOGEA("Timeout expired on shutter callback");
+ goto EXIT;
+ }
+
+ }
+
+ return (ret | ErrorUtils::omxToAndroidError(eError));
+
+EXIT:
+ CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
+ setExtraData(false, mCameraAdapterParameters.mPrevPortIndex, OMX_WhiteBalance);
+ mWaitingForSnapshot = false;
+ mCaptureSignalled = false;
+ performCleanupAfterError();
+ LOG_FUNCTION_NAME_EXIT;
+ return (ret | ErrorUtils::omxToAndroidError(eError));
+}
+
+status_t OMXCameraAdapter::stopImageCapture()
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_BOOLEANTYPE bOMX;
+ OMXCameraPortParameters *imgCaptureData = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ Mutex::Autolock lock(mImageCaptureLock);
+
+ if (!mCaptureConfigured) {
+ //Capture is not ongoing, return from here
+ return NO_ERROR;
+ }
+
+ if ( 0 != mStopCaptureSem.Count() ) {
+ CAMHAL_LOGEB("Error mStopCaptureSem semaphore count %d", mStopCaptureSem.Count());
+ goto EXIT;
+ }
+
+ //Disable the callback first
+ mWaitingForSnapshot = false;
+ mSnapshotCount = 0;
+
+ // OMX shutter callback events are only available in hq mode
+ if ((HIGH_QUALITY == mCapMode) || (HIGH_QUALITY_ZSL== mCapMode)) {
+ //Disable the callback first
+ ret = setShutterCallback(false);
+
+ // if anybody is waiting on the shutter callback
+ // signal them and then recreate the semaphore
+ if ( 0 != mStartCaptureSem.Count() ) {
+
+ for (int i = mStartCaptureSem.Count(); i < 0; i++) {
+ ret |= SignalEvent(mCameraAdapterParameters.mHandleComp,
+ (OMX_EVENTTYPE) OMX_EventIndexSettingChanged,
+ OMX_ALL,
+ OMX_TI_IndexConfigShutterCallback,
+ NULL );
+ }
+ mStartCaptureSem.Create(0);
+ }
+ }
+
+ // After capture, face detection should be disabled
+ // and application needs to restart face detection
+ stopFaceDetection();
+
+ //Wait here for the capture to be done, in worst case timeout and proceed with cleanup
+ mCaptureSem.WaitTimeout(OMX_CAPTURE_TIMEOUT);
+
+ //If somethiing bad happened while we wait
+ if (mComponentState == OMX_StateInvalid)
+ {
+ CAMHAL_LOGEA("Invalid State Image Capture Stop Exitting!!!");
+ goto EXIT;
+ }
+
+ // Disable image capture
+ // Capturing command is not needed when capturing in video mode
+ if (mCapMode != VIDEO_MODE) {
+ OMX_INIT_STRUCT_PTR (&bOMX, OMX_CONFIG_BOOLEANTYPE);
+ bOMX.bEnabled = OMX_FALSE;
+ imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCapturing,
+ &bOMX);
+ if ( OMX_ErrorNone != eError ) {
+ CAMHAL_LOGDB("Error during SetConfig- 0x%x", eError);
+ ret = -1;
+ goto EXIT;
+ }
+ }
+
+ // had to enable wb data for video snapshot to fill in exif data
+ // now that we are done...disable
+ if ((ret == NO_ERROR) && (mCapMode == VIDEO_MODE)) {
+ ret = setExtraData(false, mCameraAdapterParameters.mPrevPortIndex, OMX_WhiteBalance);
+ }
+
+ CAMHAL_LOGDB("Capture set - 0x%x", eError);
+
+ mCaptureSignalled = true; //set this to true if we exited because of timeout
+
+ {
+ Mutex::Autolock lock(mFrameCountMutex);
+ mFrameCount = 0;
+ mFirstFrameCondition.broadcast();
+ }
+
+ return (ret | ErrorUtils::omxToAndroidError(eError));
+
+EXIT:
+ CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
+ //Release image buffers
+ if ( NULL != mReleaseImageBuffersCallback ) {
+ mReleaseImageBuffersCallback(mReleaseData);
+ }
+
+ {
+ Mutex::Autolock lock(mFrameCountMutex);
+ mFrameCount = 0;
+ mFirstFrameCondition.broadcast();
+ }
+
+ performCleanupAfterError();
+ LOG_FUNCTION_NAME_EXIT;
+ return (ret | ErrorUtils::omxToAndroidError(eError));
+}
+
+status_t OMXCameraAdapter::disableImagePort(){
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMXCameraPortParameters *imgCaptureData = NULL;
+
+ if (!mCaptureConfigured) {
+ return NO_ERROR;
+ }
+
+ mCaptureConfigured = false;
+ imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+
+ ///Register for Image port Disable event
+ ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortDisable,
+ mCameraAdapterParameters.mImagePortIndex,
+ mStopCaptureSem);
+ ///Disable Capture Port
+ eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp,
+ OMX_CommandPortDisable,
+ mCameraAdapterParameters.mImagePortIndex,
+ NULL);
+
+ ///Free all the buffers on capture port
+ if (imgCaptureData) {
+ CAMHAL_LOGDB("Freeing buffer on Capture port - %d", imgCaptureData->mNumBufs);
+ for ( int index = 0 ; index < imgCaptureData->mNumBufs ; index++) {
+ CAMHAL_LOGDB("Freeing buffer on Capture port - 0x%x",
+ ( unsigned int ) imgCaptureData->mBufferHeader[index]->pBuffer);
+ eError = OMX_FreeBuffer(mCameraAdapterParameters.mHandleComp,
+ mCameraAdapterParameters.mImagePortIndex,
+ (OMX_BUFFERHEADERTYPE*)imgCaptureData->mBufferHeader[index]);
+
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+ }
+ }
+ CAMHAL_LOGDA("Waiting for port disable");
+ //Wait for the image port enable event
+ ret = mStopCaptureSem.WaitTimeout(OMX_CMD_TIMEOUT);
+
+ //If somethiing bad happened while we wait
+ if (mComponentState == OMX_StateInvalid)
+ {
+ CAMHAL_LOGEA("Invalid State after Disable Image Port Exitting!!!");
+ goto EXIT;
+ }
+
+ if ( NO_ERROR == ret ) {
+ CAMHAL_LOGDA("Port disabled");
+ } else {
+ ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortDisable,
+ mCameraAdapterParameters.mImagePortIndex,
+ NULL);
+ CAMHAL_LOGDA("Timeout expired on port disable");
+ goto EXIT;
+ }
+
+ EXIT:
+ return (ret | ErrorUtils::omxToAndroidError(eError));
+}
+
+
+status_t OMXCameraAdapter::UseBuffersCapture(void* bufArr, int num)
+{
+ LOG_FUNCTION_NAME;
+
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMXCameraPortParameters * imgCaptureData = NULL;
+ uint32_t *buffers = (uint32_t*)bufArr;
+ OMXCameraPortParameters cap;
+
+ imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+
+ if ( 0 != mUseCaptureSem.Count() )
+ {
+ CAMHAL_LOGEB("Error mUseCaptureSem semaphore count %d", mUseCaptureSem.Count());
+ return BAD_VALUE;
+ }
+
+ // capture is already configured...we can skip this step
+ if (mCaptureConfigured) {
+
+ if ( NO_ERROR == ret )
+ {
+ ret = setupEXIF();
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("Error configuring EXIF Buffer %x", ret);
+ }
+ }
+
+ mCapturedFrames = mBurstFrames;
+ return NO_ERROR;
+ }
+
+ imgCaptureData->mNumBufs = num;
+
+ //TODO: Support more pixelformats
+
+ CAMHAL_LOGDB("Params Width = %d", (int)imgCaptureData->mWidth);
+ CAMHAL_LOGDB("Params Height = %d", (int)imgCaptureData->mWidth);
+
+ if (mPendingCaptureSettings & SetFormat) {
+ mPendingCaptureSettings &= ~SetFormat;
+ ret = setFormat(OMX_CAMERA_PORT_IMAGE_OUT_IMAGE, *imgCaptureData);
+ if ( ret != NO_ERROR ) {
+ CAMHAL_LOGEB("setFormat() failed %d", ret);
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+ }
+ }
+
+ if (mPendingCaptureSettings & SetThumb) {
+ mPendingCaptureSettings &= ~SetThumb;
+ ret = setThumbnailParams(mThumbWidth, mThumbHeight, mThumbQuality);
+ if ( NO_ERROR != ret) {
+ CAMHAL_LOGEB("Error configuring thumbnail size %x", ret);
+ return ret;
+ }
+ }
+
+ if (mPendingCaptureSettings & SetExpBracket) {
+ mPendingCaptureSettings &= ~SetExpBracket;
+ ret = setExposureBracketing( mExposureBracketingValues,
+ mExposureBracketingValidEntries, mBurstFrames);
+ if ( ret != NO_ERROR ) {
+ CAMHAL_LOGEB("setExposureBracketing() failed %d", ret);
+ goto EXIT;
+ }
+ }
+
+ if (mPendingCaptureSettings & SetQuality) {
+ mPendingCaptureSettings &= ~SetQuality;
+ ret = setImageQuality(mPictureQuality);
+ if ( NO_ERROR != ret) {
+ CAMHAL_LOGEB("Error configuring image quality %x", ret);
+ goto EXIT;
+ }
+ }
+
+ ///Register for Image port ENABLE event
+ ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mImagePortIndex,
+ mUseCaptureSem);
+
+ ///Enable Capture Port
+ eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mImagePortIndex,
+ NULL);
+
+ CAMHAL_LOGDB("OMX_UseBuffer = 0x%x", eError);
+ GOTO_EXIT_IF(( eError != OMX_ErrorNone ), eError);
+
+ for ( int index = 0 ; index < imgCaptureData->mNumBufs ; index++ )
+ {
+ OMX_BUFFERHEADERTYPE *pBufferHdr;
+ CAMHAL_LOGDB("OMX_UseBuffer Capture address: 0x%x, size = %d",
+ (unsigned int)buffers[index],
+ (int)imgCaptureData->mBufSize);
+
+ eError = OMX_UseBuffer(mCameraAdapterParameters.mHandleComp,
+ &pBufferHdr,
+ mCameraAdapterParameters.mImagePortIndex,
+ 0,
+ mCaptureBuffersLength,
+ (OMX_U8*)buffers[index]);
+
+ CAMHAL_LOGDB("OMX_UseBuffer = 0x%x", eError);
+ GOTO_EXIT_IF(( eError != OMX_ErrorNone ), eError);
+
+ pBufferHdr->pAppPrivate = (OMX_PTR) index;
+ pBufferHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ pBufferHdr->nVersion.s.nVersionMajor = 1 ;
+ pBufferHdr->nVersion.s.nVersionMinor = 1 ;
+ pBufferHdr->nVersion.s.nRevision = 0;
+ pBufferHdr->nVersion.s.nStep = 0;
+ imgCaptureData->mBufferHeader[index] = pBufferHdr;
+ }
+
+ //Wait for the image port enable event
+ CAMHAL_LOGDA("Waiting for port enable");
+ ret = mUseCaptureSem.WaitTimeout(OMX_CMD_TIMEOUT);
+
+ //If somethiing bad happened while we wait
+ if (mComponentState == OMX_StateInvalid)
+ {
+ CAMHAL_LOGEA("Invalid State after Enable Image Port Exitting!!!");
+ goto EXIT;
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ CAMHAL_LOGDA("Port enabled");
+ }
+ else
+ {
+ ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mImagePortIndex,
+ NULL);
+ CAMHAL_LOGDA("Timeout expired on port enable");
+ goto EXIT;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ ret = setupEXIF();
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("Error configuring EXIF Buffer %x", ret);
+ }
+ }
+
+ mCapturedFrames = mBurstFrames;
+ mCaptureConfigured = true;
+
+ return (ret | ErrorUtils::omxToAndroidError(eError));
+
+EXIT:
+ CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
+ //Release image buffers
+ if ( NULL != mReleaseImageBuffersCallback ) {
+ mReleaseImageBuffersCallback(mReleaseData);
+ }
+ performCleanupAfterError();
+ LOG_FUNCTION_NAME_EXIT;
+ return (ret | ErrorUtils::omxToAndroidError(eError));
+
+}
+
+};