diff options
Diffstat (limited to 'camera/OMXCameraAdapter/OMXCapture.cpp')
-rw-r--r-- | camera/OMXCameraAdapter/OMXCapture.cpp | 1229 |
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 ¶ms, + 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)); + +} + +}; |