| /* |
| * 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. |
| * |
| */ |
| |
| #include "CameraHal.h" |
| #include "OMXCameraAdapter.h" |
| #include "ErrorUtils.h" |
| |
| |
| namespace Ti { |
| namespace Camera { |
| |
| status_t OMXCameraAdapter::setParametersCapture(const android::CameraParameters ¶ms, |
| BaseCameraAdapter::AdapterState state) |
| { |
| status_t ret = NO_ERROR; |
| const char *str = NULL; |
| int w, h; |
| OMX_COLOR_FORMATTYPE pixFormat; |
| CodingMode codingMode = mCodingMode; |
| const char *valstr = NULL; |
| int varint = 0; |
| OMX_TI_STEREOFRAMELAYOUTTYPE capFrmLayout; |
| bool inCaptureState = false; |
| |
| LOG_FUNCTION_NAME; |
| |
| OMXCameraPortParameters *cap; |
| cap = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex]; |
| |
| capFrmLayout = cap->mFrameLayoutType; |
| setParamS3D(mCameraAdapterParameters.mImagePortIndex, |
| params.get(TICameraParameters::KEY_S3D_CAP_FRAME_LAYOUT)); |
| if (capFrmLayout != cap->mFrameLayoutType) { |
| mPendingCaptureSettings |= SetFormat; |
| } |
| |
| 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, android::CameraParameters::PIXEL_FORMAT_YUV422I) == 0) { |
| CAMHAL_LOGDA("CbYCrY format selected"); |
| pixFormat = OMX_COLOR_FormatCbYCrY; |
| mPictureFormatFromClient = android::CameraParameters::PIXEL_FORMAT_YUV422I; |
| } else if(strcmp(valstr, android::CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) { |
| CAMHAL_LOGDA("YUV420SP format selected"); |
| pixFormat = OMX_COLOR_FormatYUV420SemiPlanar; |
| mPictureFormatFromClient = android::CameraParameters::PIXEL_FORMAT_YUV420SP; |
| } else if(strcmp(valstr, android::CameraParameters::PIXEL_FORMAT_RGB565) == 0) { |
| CAMHAL_LOGDA("RGB565 format selected"); |
| pixFormat = OMX_COLOR_Format16bitRGB565; |
| mPictureFormatFromClient = android::CameraParameters::PIXEL_FORMAT_RGB565; |
| } else if (strcmp(valstr, android::CameraParameters::PIXEL_FORMAT_JPEG) == 0) { |
| CAMHAL_LOGDA("JPEG format selected"); |
| pixFormat = OMX_COLOR_FormatUnused; |
| codingMode = CodingJPEG; |
| mPictureFormatFromClient = android::CameraParameters::PIXEL_FORMAT_JPEG; |
| } else if (strcmp(valstr, TICameraParameters::PIXEL_FORMAT_JPS) == 0) { |
| CAMHAL_LOGDA("JPS format selected"); |
| pixFormat = OMX_COLOR_FormatUnused; |
| codingMode = CodingJPS; |
| mPictureFormatFromClient = TICameraParameters::PIXEL_FORMAT_JPS; |
| } else if (strcmp(valstr, TICameraParameters::PIXEL_FORMAT_MPO) == 0) { |
| CAMHAL_LOGDA("MPO format selected"); |
| pixFormat = OMX_COLOR_FormatUnused; |
| codingMode = CodingMPO; |
| mPictureFormatFromClient = TICameraParameters::PIXEL_FORMAT_MPO; |
| } else if (strcmp(valstr, android::CameraParameters::PIXEL_FORMAT_BAYER_RGGB) == 0) { |
| CAMHAL_LOGDA("RAW Picture format selected"); |
| pixFormat = OMX_COLOR_FormatRawBayer10bit; |
| mPictureFormatFromClient = android::CameraParameters::PIXEL_FORMAT_BAYER_RGGB; |
| } else { |
| CAMHAL_LOGEA("Invalid format, JPEG format selected as default"); |
| pixFormat = OMX_COLOR_FormatUnused; |
| codingMode = CodingJPEG; |
| mPictureFormatFromClient = NULL; |
| } |
| } else { |
| CAMHAL_LOGEA("Picture format is NULL, defaulting to JPEG"); |
| pixFormat = OMX_COLOR_FormatUnused; |
| codingMode = CodingJPEG; |
| mPictureFormatFromClient = NULL; |
| } |
| |
| #ifdef CAMERAHAL_USE_RAW_IMAGE_SAVING |
| mRawCapture = false; |
| mYuvCapture = false; |
| |
| valstr = params.get(TICameraParameters::KEY_CAP_MODE); |
| if ( (!valstr || strcmp(valstr, TICameraParameters::HIGH_QUALITY_MODE) == 0) && |
| access(kRawImagesOutputDirPath, F_OK) != -1 ) { |
| mRawCapture = true; |
| } |
| |
| if (mRawCapture && (access(kYuvImagesOutputDirPath, F_OK) != -1)) { |
| pixFormat = OMX_COLOR_FormatCbYCrY; |
| mYuvCapture = true; |
| } |
| #endif |
| // 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) == 0 || |
| strcmp(valstr, (const char *) TICameraParameters::VIDEO_MODE_HQ) == 0 ) ) && |
| (pixFormat == OMX_COLOR_FormatUnused) ) { |
| CAMHAL_LOGDA("Capturing in video mode...selecting yuv422i"); |
| pixFormat = OMX_COLOR_FormatCbYCrY; |
| } |
| |
| if (pixFormat != cap->mColorFormat || codingMode != mCodingMode) { |
| mPendingCaptureSettings |= SetFormat; |
| cap->mColorFormat = pixFormat; |
| mCodingMode = codingMode; |
| } |
| |
| #ifdef OMAP_ENHANCEMENT |
| str = params.get(TICameraParameters::KEY_TEMP_BRACKETING); |
| if ( ( str != NULL ) && |
| ( strcmp(str, android::CameraParameters::TRUE) == 0 ) ) { |
| |
| if ( !mBracketingSet ) { |
| mPendingCaptureSettings |= SetBurstExpBracket; |
| } |
| |
| mBracketingSet = true; |
| } else { |
| |
| if ( mBracketingSet ) { |
| mPendingCaptureSettings |= SetBurstExpBracket; |
| } |
| |
| mBracketingSet = false; |
| } |
| |
| if ( (str = params.get(TICameraParameters::KEY_EXP_BRACKETING_RANGE)) != NULL ) { |
| parseExpRange(str, mExposureBracketingValues, NULL, |
| mExposureGainBracketingModes, |
| EXP_BRACKET_RANGE, mExposureBracketingValidEntries); |
| if (mCapMode == OMXCameraAdapter::CP_CAM) { |
| mExposureBracketMode = OMX_BracketVectorShot; |
| } else { |
| mExposureBracketMode = OMX_BracketExposureRelativeInEV; |
| } |
| mPendingCaptureSettings |= SetBurstExpBracket; |
| } else if ( (str = params.get(TICameraParameters::KEY_EXP_GAIN_BRACKETING_RANGE)) != NULL) { |
| parseExpRange(str, mExposureBracketingValues, mExposureGainBracketingValues, |
| mExposureGainBracketingModes, |
| EXP_BRACKET_RANGE, mExposureBracketingValidEntries); |
| if (mCapMode == OMXCameraAdapter::CP_CAM) { |
| mExposureBracketMode = OMX_BracketVectorShot; |
| } else { |
| mExposureBracketMode = OMX_BracketExposureGainAbsolute; |
| } |
| mPendingCaptureSettings |= SetBurstExpBracket; |
| } else { |
| // always set queued shot config in CPCAM mode |
| if (mCapMode == OMXCameraAdapter::CP_CAM) { |
| mExposureBracketMode = OMX_BracketVectorShot; |
| mPendingCaptureSettings |= SetBurstExpBracket; |
| } |
| // if bracketing was previously set...we set again before capturing to clear |
| if (mExposureBracketingValidEntries) { |
| mPendingCaptureSettings |= SetBurstExpBracket; |
| mExposureBracketingValidEntries = 0; |
| } |
| } |
| |
| str = params.get(TICameraParameters::KEY_ZOOM_BRACKETING_RANGE); |
| if ( NULL != str ) { |
| parseExpRange(str, mZoomBracketingValues, NULL, NULL, |
| ZOOM_BRACKET_RANGE, mZoomBracketingValidEntries); |
| mCurrentZoomBracketing = 0; |
| mZoomBracketingEnabled = true; |
| } else { |
| if (mZoomBracketingValidEntries) { |
| mZoomBracketingValidEntries = 0; |
| } |
| mZoomBracketingEnabled = false; |
| } |
| #endif |
| |
| // Flush config queue |
| // If TRUE: Flush queue and abort processing before enqueing |
| valstr = params.get(TICameraParameters::KEY_FLUSH_SHOT_CONFIG_QUEUE); |
| if ( NULL != valstr ) { |
| if ( 0 == strcmp(valstr, android::CameraParameters::TRUE) ) { |
| mFlushShotConfigQueue = true; |
| } else if ( 0 == strcmp(valstr, android::CameraParameters::FALSE) ) { |
| mFlushShotConfigQueue = false; |
| } else { |
| CAMHAL_LOGE("Missing flush shot config parameter. Will use current (%s)", |
| mFlushShotConfigQueue ? "true" : "false"); |
| } |
| } |
| |
| if ( params.getInt(android::CameraParameters::KEY_ROTATION) != -1 ) |
| { |
| if (params.getInt(android::CameraParameters::KEY_ROTATION) != (int) mPictureRotation) { |
| mPendingCaptureSettings |= SetRotation; |
| } |
| mPictureRotation = params.getInt(android::CameraParameters::KEY_ROTATION); |
| } |
| 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 ) |
| { |
| 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); |
| #endif |
| |
| #ifdef OMAP_ENHANCEMENT_BURST_CAPTURE |
| varint = params.getInt(TICameraParameters::KEY_BURST); |
| if ( varint >= 1 ) |
| { |
| if (varint != (int) mBurstFrames) { |
| mPendingCaptureSettings |= SetBurstExpBracket; |
| } |
| mBurstFrames = varint; |
| } |
| else |
| { |
| if (mBurstFrames != 1) mPendingCaptureSettings |= SetBurstExpBracket; |
| mBurstFrames = 1; |
| } |
| |
| CAMHAL_LOGVB("Burst Frames set %d", mBurstFrames); |
| #endif |
| |
| varint = params.getInt(android::CameraParameters::KEY_JPEG_QUALITY); |
| if ( varint >= MIN_JPEG_QUALITY && varint <= MAX_JPEG_QUALITY ) { |
| if (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(android::CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH); |
| if ( varint >= 0 ) { |
| if (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(android::CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT); |
| if ( varint >= 0 ) { |
| if (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(android::CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY); |
| if ( varint >= MIN_JPEG_QUALITY && varint <= MAX_JPEG_QUALITY ) { |
| if (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; |
| } |
| |
| cap = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoPortIndex]; |
| cap->mWidth = params.getInt(TICameraParameters::RAW_WIDTH); |
| cap->mHeight = params.getInt(TICameraParameters::RAW_HEIGHT); |
| |
| LOG_FUNCTION_NAME_EXIT; |
| |
| return ret; |
| } |
| |
| status_t OMXCameraAdapter::getPictureBufferSize(CameraFrame &frame, 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]; |
| |
| |
| // If any settings have changed that need to be set with SetParam, |
| // we will need to disable the port to set them |
| if ((mPendingCaptureSettings & ECaptureParamSettings)) { |
| disableImagePort(); |
| if ( NULL != mReleaseImageBuffersCallback ) { |
| mReleaseImageBuffersCallback(mReleaseData); |
| } |
| } |
| |
| if (mPendingCaptureSettings & SetFormat) { |
| ret = setFormat(OMX_CAMERA_PORT_IMAGE_OUT_IMAGE, *imgCaptureData); |
| } |
| |
| if ( ret == NO_ERROR ) |
| { |
| frame.mLength = imgCaptureData->mBufSize; |
| frame.mWidth = imgCaptureData->mWidth; |
| frame.mHeight = imgCaptureData->mHeight; |
| frame.mAlignment = imgCaptureData->mStride; |
| CAMHAL_LOGDB("getPictureBufferSize: width:%u height:%u alignment:%u length:%u", |
| frame.mWidth, frame.mHeight, frame.mAlignment, frame.mLength); |
| } |
| else |
| { |
| CAMHAL_LOGEB("setFormat() failed 0x%x", ret); |
| } |
| } |
| |
| LOG_FUNCTION_NAME_EXIT; |
| |
| return ret; |
| } |
| |
| int OMXCameraAdapter::getBracketingValueMode(const char *a, const char *b) const |
| { |
| BracketingValueMode bvm = BracketingValueAbsolute; |
| |
| if ( (NULL != b) && |
| (NULL != a) && |
| (a < b) && |
| ( (NULL != memchr(a, '+', b - a)) || |
| (NULL != memchr(a, '-', b - a)) ) ) { |
| bvm = BracketingValueRelative; |
| } |
| return bvm; |
| } |
| |
| status_t OMXCameraAdapter::parseExpRange(const char *rangeStr, |
| int *expRange, |
| int *gainRange, |
| int *expGainModes, |
| size_t count, |
| size_t &validEntries) |
| { |
| status_t ret = NO_ERROR; |
| char *end = NULL; |
| const char *startPtr = NULL; |
| size_t i = 0; |
| |
| LOG_FUNCTION_NAME; |
| |
| if ( NULL == rangeStr ){ |
| return -EINVAL; |
| } |
| |
| if ( NULL == expRange ){ |
| return -EINVAL; |
| } |
| |
| if ( NO_ERROR == ret ) { |
| startPtr = rangeStr; |
| do { |
| // Relative Exposure example: "-30,-10, 0, 10, 30" |
| // Absolute Gain ex. (exposure,gain) pairs: "(100,300),(200,300),(400,300),(800,300),(1600,300)" |
| // Relative Gain ex. (exposure,gain) pairs: "(-30,+0),(-10, +0),(+0,+0),(+10,+0),(+30,+0)" |
| // Forced relative Exposure example: "-30F,-10F, 0F, 10F, 30F" |
| // Forced absolute Gain ex. (exposure,gain) pairs: "(100,300)F,(200,300)F,(400,300)F,(800,300)F,(1600,300)F" |
| // Forced relative Gain ex. (exposure,gain) pairs: "(-30,+0)F,(-10, +0)F,(+0,+0)F,(+10,+0)F,(+30,+0)F" |
| |
| // skip '(' and ',' |
| while ((*startPtr == '(') || (*startPtr == ',')) startPtr++; |
| |
| expRange[i] = (int)strtol(startPtr, &end, 10); |
| |
| if (expGainModes) { |
| // if gainRange is given rangeStr should be (exposure, gain) pair |
| if (gainRange) { |
| int bvm_exp = getBracketingValueMode(startPtr, end); |
| startPtr = end + 1; // for the ',' |
| gainRange[i] = (int)strtol(startPtr, &end, 10); |
| |
| if (BracketingValueAbsolute == bvm_exp) { |
| expGainModes[i] = getBracketingValueMode(startPtr, end); |
| } else { |
| expGainModes[i] = bvm_exp; |
| } |
| } else { |
| expGainModes[i] = BracketingValueCompensation; |
| } |
| } |
| startPtr = end; |
| |
| // skip ')' |
| while (*startPtr == ')') startPtr++; |
| |
| // Check for "forced" key |
| if (expGainModes) { |
| while ((*startPtr == 'F') || (*startPtr == 'f')) { |
| if ( BracketingValueAbsolute == expGainModes[i] ) { |
| expGainModes[i] = BracketingValueAbsoluteForced; |
| } else if ( BracketingValueRelative == expGainModes[i] ) { |
| expGainModes[i] = BracketingValueRelativeForced; |
| } else if ( BracketingValueCompensation == expGainModes[i] ) { |
| expGainModes[i] = BracketingValueCompensationForced; |
| } else { |
| CAMHAL_LOGE("Unexpected old mode 0x%x", expGainModes[i]); |
| } |
| startPtr++; |
| } |
| } |
| |
| i++; |
| |
| } while ((startPtr[0] != '\0') && (i < count)); |
| validEntries = i; |
| } |
| |
| LOG_FUNCTION_NAME_EXIT; |
| |
| return ret; |
| } |
| |
| status_t OMXCameraAdapter::doExposureBracketing(int *evValues, |
| int *evValues2, |
| int *evModes2, |
| size_t evCount, |
| size_t frameCount, |
| bool flush, |
| OMX_BRACKETMODETYPE bracketMode) |
| { |
| status_t ret = NO_ERROR; |
| |
| 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 ) { |
| if (bracketMode == OMX_BracketVectorShot) { |
| ret = setVectorShot(evValues, evValues2, evModes2, evCount, frameCount, flush, bracketMode); |
| } else { |
| ret = setExposureBracketing(evValues, evValues2, evCount, frameCount, bracketMode); |
| } |
| } |
| |
| LOG_FUNCTION_NAME_EXIT; |
| |
| return ret; |
| } |
| |
| status_t OMXCameraAdapter::setVectorStop(bool toPreview) |
| { |
| status_t ret = NO_ERROR; |
| OMX_ERRORTYPE eError = OMX_ErrorNone; |
| OMX_TI_CONFIG_VECTSHOTSTOPMETHODTYPE vecShotStop; |
| |
| |
| LOG_FUNCTION_NAME; |
| |
| OMX_INIT_STRUCT_PTR(&vecShotStop, OMX_TI_CONFIG_VECTSHOTSTOPMETHODTYPE); |
| |
| vecShotStop.nPortIndex = mCameraAdapterParameters.mImagePortIndex; |
| if (toPreview) { |
| vecShotStop.eStopMethod = OMX_TI_VECTSHOTSTOPMETHOD_GOTO_PREVIEW; |
| } else { |
| vecShotStop.eStopMethod = OMX_TI_VECTSHOTSTOPMETHOD_WAIT_IN_CAPTURE; |
| } |
| |
| eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, |
| (OMX_INDEXTYPE) OMX_TI_IndexConfigVectShotStopMethod, |
| &vecShotStop); |
| if (OMX_ErrorNone != eError) { |
| CAMHAL_LOGEB("Error while configuring bracket shot 0x%x", eError); |
| } else { |
| CAMHAL_LOGDA("Bracket shot configured successfully"); |
| } |
| |
| LOG_FUNCTION_NAME_EXIT; |
| |
| return (ret | Utils::ErrorUtils::omxToAndroidError(eError)); |
| } |
| |
| status_t OMXCameraAdapter::initVectorShot() |
| { |
| status_t ret = NO_ERROR; |
| OMX_ERRORTYPE eError = OMX_ErrorNone; |
| OMX_CONFIG_CAPTUREMODETYPE expCapMode; |
| OMX_CONFIG_EXTCAPTUREMODETYPE extExpCapMode; |
| |
| LOG_FUNCTION_NAME; |
| |
| if (NO_ERROR == ret) { |
| OMX_INIT_STRUCT_PTR (&expCapMode, OMX_CONFIG_CAPTUREMODETYPE); |
| expCapMode.nPortIndex = mCameraAdapterParameters.mImagePortIndex; |
| |
| expCapMode.bFrameLimited = OMX_FALSE; |
| |
| eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, |
| OMX_IndexConfigCaptureMode, |
| &expCapMode); |
| if (OMX_ErrorNone != eError) { |
| CAMHAL_LOGEB("Error while configuring capture mode 0x%x", eError); |
| goto exit; |
| } else { |
| CAMHAL_LOGDA("Camera capture mode configured successfully"); |
| } |
| } |
| |
| if (NO_ERROR == ret) { |
| OMX_INIT_STRUCT_PTR (&extExpCapMode, OMX_CONFIG_EXTCAPTUREMODETYPE); |
| extExpCapMode.nPortIndex = mCameraAdapterParameters.mImagePortIndex; |
| |
| extExpCapMode.bEnableBracketing = OMX_TRUE; |
| extExpCapMode.tBracketConfigType.eBracketMode = OMX_BracketVectorShot; |
| |
| 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); |
| goto exit; |
| } else { |
| CAMHAL_LOGDA("Extended camera capture mode configured successfully"); |
| } |
| } |
| |
| |
| if (NO_ERROR == ret) { |
| // set vector stop method to stop in capture |
| ret = setVectorStop(false); |
| } |
| |
| exit: |
| LOG_FUNCTION_NAME_EXIT; |
| |
| return (ret | Utils::ErrorUtils::omxToAndroidError(eError)); |
| } |
| |
| status_t OMXCameraAdapter::setVectorShot(int *evValues, |
| int *evValues2, |
| int *evModes2, |
| size_t evCount, |
| size_t frameCount, |
| bool flush, |
| OMX_BRACKETMODETYPE bracketMode) |
| { |
| status_t ret = NO_ERROR; |
| OMX_ERRORTYPE eError = OMX_ErrorNone; |
| OMX_TI_CONFIG_ENQUEUESHOTCONFIGS enqueueShotConfigs; |
| OMX_TI_CONFIG_QUERYAVAILABLESHOTS queryAvailableShots; |
| bool doFlush = flush; |
| |
| LOG_FUNCTION_NAME; |
| |
| OMX_INIT_STRUCT_PTR(&enqueueShotConfigs, OMX_TI_CONFIG_ENQUEUESHOTCONFIGS); |
| OMX_INIT_STRUCT_PTR(&queryAvailableShots, OMX_TI_CONFIG_QUERYAVAILABLESHOTS); |
| |
| queryAvailableShots.nPortIndex = mCameraAdapterParameters.mImagePortIndex; |
| eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp, |
| (OMX_INDEXTYPE) OMX_TI_IndexConfigQueryAvailableShots, |
| &queryAvailableShots); |
| if (OMX_ErrorNone != eError) { |
| CAMHAL_LOGE("Error getting available shots 0x%x", eError); |
| goto exit; |
| } else { |
| CAMHAL_LOGD("AVAILABLE SHOTS: %d", queryAvailableShots.nAvailableShots); |
| if (queryAvailableShots.nAvailableShots < evCount) { |
| // TODO(XXX): Need to implement some logic to handle this error |
| CAMHAL_LOGE("Not enough available shots to fulfill this queue request"); |
| ret = -ENOSPC; |
| goto exit; |
| } |
| } |
| |
| for ( unsigned int confID = 0; confID < evCount; ) { |
| unsigned int i; |
| for ( i = 0 ; (i < ARRAY_SIZE(enqueueShotConfigs.nShotConfig)) && (confID < evCount); i++, confID++ ) { |
| CAMHAL_LOGD("%2u: (%7d,%4d) mode: %d", confID, evValues[confID], evValues2[confID], evModes2[confID]); |
| enqueueShotConfigs.nShotConfig[i].nConfigId = confID; |
| enqueueShotConfigs.nShotConfig[i].nFrames = 1; |
| if ( (BracketingValueCompensation == evModes2[confID]) || |
| (BracketingValueCompensationForced == evModes2[confID]) ) { |
| // EV compensation |
| enqueueShotConfigs.nShotConfig[i].nEC = evValues[confID]; |
| enqueueShotConfigs.nShotConfig[i].nExp = 0; |
| enqueueShotConfigs.nShotConfig[i].nGain = 0; |
| } else { |
| // exposure,gain pair |
| enqueueShotConfigs.nShotConfig[i].nEC = 0; |
| enqueueShotConfigs.nShotConfig[i].nExp = evValues[confID]; |
| enqueueShotConfigs.nShotConfig[i].nGain = evValues2[confID]; |
| } |
| enqueueShotConfigs.nShotConfig[i].eExpGainApplyMethod = OMX_TI_EXPGAINAPPLYMETHOD_ABSOLUTE; |
| switch (evModes2[confID]) { |
| case BracketingValueAbsolute: // (exp,gain) pairs directly program sensor values |
| default : |
| enqueueShotConfigs.nShotConfig[i].eExpGainApplyMethod = OMX_TI_EXPGAINAPPLYMETHOD_ABSOLUTE; |
| break; |
| case BracketingValueRelative: // (exp,gain) pairs relative to AE settings and constraints |
| case BracketingValueCompensation: // EV compensation relative to AE settings and constraints |
| enqueueShotConfigs.nShotConfig[i].eExpGainApplyMethod = OMX_TI_EXPGAINAPPLYMETHOD_RELATIVE; |
| break; |
| case BracketingValueAbsoluteForced: // (exp,gain) pairs directly program sensor values |
| // are forced over constraints due to flicker, etc. |
| enqueueShotConfigs.nShotConfig[i].eExpGainApplyMethod = OMX_TI_EXPGAINAPPLYMETHOD_FORCE_ABSOLUTE; |
| break; |
| case BracketingValueRelativeForced: // (exp, gain) pairs relative to AE settings AND settings |
| case BracketingValueCompensationForced: // EV compensation relative to AE settings and constraints |
| // are forced over constraints due to flicker, etc. |
| enqueueShotConfigs.nShotConfig[i].eExpGainApplyMethod = OMX_TI_EXPGAINAPPLYMETHOD_FORCE_RELATIVE; |
| break; |
| } |
| enqueueShotConfigs.nShotConfig[i].bNoSnapshot = OMX_FALSE; // TODO: Make this configurable |
| } |
| |
| // Repeat last exposure and again |
| if ((confID == evCount) && (evCount > 0) && (frameCount > evCount) && (0 != i)) { |
| enqueueShotConfigs.nShotConfig[i-1].nFrames = frameCount - evCount; |
| } |
| |
| enqueueShotConfigs.nPortIndex = mCameraAdapterParameters.mImagePortIndex; |
| enqueueShotConfigs.bFlushQueue = doFlush ? OMX_TRUE : OMX_FALSE; |
| enqueueShotConfigs.nNumConfigs = i; |
| eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, |
| ( OMX_INDEXTYPE ) OMX_TI_IndexConfigEnqueueShotConfigs, |
| &enqueueShotConfigs); |
| if ( OMX_ErrorNone != eError ) { |
| CAMHAL_LOGEB("Error while configuring enqueue shot 0x%x", eError); |
| goto exit; |
| } else { |
| CAMHAL_LOGDA("Enqueue shot configured successfully"); |
| } |
| // Flush only first time |
| doFlush = false; |
| } |
| |
| // Handle burst capture (no any bracketing) case |
| if (0 == evCount) { |
| CAMHAL_LOGE("Handle burst capture (no any bracketing) case"); |
| enqueueShotConfigs.nShotConfig[0].nConfigId = 0; |
| enqueueShotConfigs.nShotConfig[0].nFrames = frameCount; |
| enqueueShotConfigs.nShotConfig[0].nEC = 0; |
| enqueueShotConfigs.nShotConfig[0].nExp = 0; |
| enqueueShotConfigs.nShotConfig[0].nGain = 0; |
| enqueueShotConfigs.nShotConfig[0].eExpGainApplyMethod = OMX_TI_EXPGAINAPPLYMETHOD_RELATIVE; |
| enqueueShotConfigs.nShotConfig[0].bNoSnapshot = OMX_FALSE; // TODO: Make this configurable |
| enqueueShotConfigs.nNumConfigs = 1; |
| enqueueShotConfigs.nPortIndex = mCameraAdapterParameters.mImagePortIndex; |
| enqueueShotConfigs.bFlushQueue = doFlush ? OMX_TRUE : OMX_FALSE; |
| eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, |
| ( OMX_INDEXTYPE ) OMX_TI_IndexConfigEnqueueShotConfigs, |
| &enqueueShotConfigs); |
| if ( OMX_ErrorNone != eError ) { |
| CAMHAL_LOGEB("Error while configuring enqueue shot 0x%x", eError); |
| goto exit; |
| } else { |
| CAMHAL_LOGDA("Enqueue shot configured successfully"); |
| } |
| } |
| |
| exit: |
| LOG_FUNCTION_NAME_EXIT; |
| |
| return (ret | Utils::ErrorUtils::omxToAndroidError(eError)); |
| } |
| |
| status_t OMXCameraAdapter::setExposureBracketing(int *evValues, |
| int *evValues2, |
| size_t evCount, |
| size_t frameCount, |
| OMX_BRACKETMODETYPE bracketMode) |
| { |
| status_t ret = NO_ERROR; |
| OMX_ERRORTYPE eError = OMX_ErrorNone; |
| OMX_CONFIG_CAPTUREMODETYPE expCapMode; |
| OMX_CONFIG_EXTCAPTUREMODETYPE extExpCapMode; |
| |
| LOG_FUNCTION_NAME; |
| |
| 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 = bracketMode; |
| extExpCapMode.tBracketConfigType.nNbrBracketingValues = evCount - 1; |
| } |
| |
| for ( unsigned int i = 0 ; i < evCount ; i++ ) |
| { |
| if (bracketMode == OMX_BracketExposureGainAbsolute) { |
| extExpCapMode.tBracketConfigType.nBracketValues[i] = evValues[i]; |
| extExpCapMode.tBracketConfigType.nBracketValues2[i] = evValues2[i]; |
| } else { |
| // assuming OMX_BracketExposureRelativeInEV |
| 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 ) |
| { |
| CameraBuffer *buffer = (CameraBuffer *)pBuffHeader->pAppPrivate; |
| currentBufferIdx = buffer->index; |
| |
| 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((CameraBuffer *)imgCaptureData->mBufferHeader[nextBufferIdx]->pAppPrivate, typeOfFrame, 1); |
| returnFrame((CameraBuffer *)imgCaptureData->mBufferHeader[nextBufferIdx]->pAppPrivate, typeOfFrame); |
| } |
| } |
| |
| LOG_FUNCTION_NAME_EXIT; |
| |
| return ret; |
| } |
| |
| status_t OMXCameraAdapter::sendBracketFrames(size_t &framesSent) |
| { |
| status_t ret = NO_ERROR; |
| int currentBufferIdx; |
| OMXCameraPortParameters * imgCaptureData = NULL; |
| |
| LOG_FUNCTION_NAME; |
| |
| imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex]; |
| framesSent = 0; |
| |
| 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); |
| framesSent++; |
| } |
| } 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; |
| } |
| |
| { |
| android::AutoMutex 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 ) |
| { |
| android::AutoMutex 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; |
| mBurstFramesAccum = imgCaptureData->mNumBufs; |
| mLastBracetingBufferIdx = mBracketingBuffersQueuedCount - 1; |
| |
| for ( int i = 0 ; i < imgCaptureData->mNumBufs ; i++ ) |
| { |
| mBracketingBuffersQueued[i] = true; |
| } |
| |
| } |
| } |
| |
| if ( NO_ERROR == ret ) |
| { |
| CachedCaptureParameters* cap_params = cacheCaptureParameters(); |
| ret = startImageCapture(true, cap_params); |
| delete cap_params; |
| { |
| android::AutoMutex 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; |
| |
| ret = stopImageCapture(); |
| |
| android::AutoMutex lock(mBracketingLock); |
| |
| if ( NULL != mBracketingBuffersQueued ) |
| { |
| delete [] mBracketingBuffersQueued; |
| } |
| |
| mBracketingBuffersQueued = NULL; |
| mBracketingEnabled = false; |
| mBracketingBuffersQueuedCount = 0; |
| mLastBracetingBufferIdx = 0; |
| |
| LOG_FUNCTION_NAME_EXIT; |
| |
| return ret; |
| } |
| |
| status_t OMXCameraAdapter::startImageCapture(bool bracketing, CachedCaptureParameters* capParams) |
| { |
| status_t ret = NO_ERROR; |
| OMX_ERRORTYPE eError = OMX_ErrorNone; |
| OMXCameraPortParameters * capData = NULL; |
| OMX_CONFIG_BOOLEANTYPE bOMX; |
| size_t bracketingSent = 0; |
| |
| LOG_FUNCTION_NAME; |
| |
| android::AutoMutex 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 ( !bracketing ) { |
| if ((getNextState() & (CAPTURE_ACTIVE|BRACKETING_ACTIVE)) == 0) { |
| CAMHAL_LOGDA("trying starting capture when already canceled"); |
| return NO_ERROR; |
| } |
| } |
| |
| if (!capParams) { |
| CAMHAL_LOGE("Invalid cached parameters sent!"); |
| return BAD_VALUE; |
| } |
| |
| // Camera framework doesn't expect face callbacks once capture is triggered |
| pauseFaceDetection(true); |
| |
| //During bracketing image capture is already active |
| { |
| android::AutoMutex lock(mBracketingLock); |
| if ( mBracketingEnabled ) |
| { |
| //Stop bracketing, activate normal burst for the remaining images |
| mBracketingEnabled = false; |
| ret = sendBracketFrames(bracketingSent); |
| |
| // Check if we accumulated enough buffers |
| if ( bracketingSent < ( mBracketingRange - 1 ) ) |
| { |
| mCapturedFrames = mBracketingRange + ( ( mBracketingRange - 1 ) - bracketingSent ); |
| } |
| else |
| { |
| mCapturedFrames = mBracketingRange; |
| } |
| mBurstFramesQueued = 0; |
| mBurstFramesAccum = mCapturedFrames; |
| |
| if(ret != NO_ERROR) |
| goto EXIT; |
| else |
| return ret; |
| } |
| } |
| |
| if ( NO_ERROR == ret ) { |
| if (capParams->mPendingCaptureSettings & SetRotation) { |
| mPendingCaptureSettings &= ~SetRotation; |
| ret = setPictureRotation(mPictureRotation); |
| if ( NO_ERROR != ret ) { |
| CAMHAL_LOGEB("Error configuring image rotation %x", ret); |
| } |
| } |
| |
| if (capParams->mPendingCaptureSettings & SetBurstExpBracket) { |
| mPendingCaptureSettings &= ~SetBurstExpBracket; |
| if ( mBracketingSet ) { |
| ret = doExposureBracketing(capParams->mExposureBracketingValues, |
| capParams->mExposureGainBracketingValues, |
| capParams->mExposureGainBracketingModes, |
| 0, |
| 0, |
| capParams->mFlushShotConfigQueue, |
| capParams->mExposureBracketMode); |
| } else { |
| ret = doExposureBracketing(capParams->mExposureBracketingValues, |
| capParams->mExposureGainBracketingValues, |
| capParams->mExposureGainBracketingModes, |
| capParams->mExposureBracketingValidEntries, |
| capParams->mBurstFrames, |
| capParams->mFlushShotConfigQueue, |
| capParams->mExposureBracketMode); |
| } |
| |
| if ( ret != NO_ERROR ) { |
| CAMHAL_LOGEB("setExposureBracketing() failed %d", ret); |
| goto EXIT; |
| } |
| } |
| } |
| |
| #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS |
| CameraHal::PPM("startImageCapture bracketing configs done: ", &mStartCapture); |
| #endif |
| |
| capData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex]; |
| |
| //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 (mPending3Asettings) { |
| apply3Asettings(mParameters3A); |
| } |
| |
| if (ret == NO_ERROR) { |
| int index = 0; |
| int queued = 0; |
| android::AutoMutex lock(mBurstLock); |
| |
| if (capParams->mFlushShotConfigQueue) { |
| // reset shot queue |
| mCapturedFrames = mBurstFrames; |
| mBurstFramesAccum = mBurstFrames; |
| mBurstFramesQueued = 0; |
| for ( int index = 0 ; index < capData->mNumBufs ; index++ ) { |
| if (OMXCameraPortParameters::FILL == capData->mStatus[index]) { |
| mBurstFramesQueued++; |
| } |
| } |
| } else { |
| mCapturedFrames += mBurstFrames; |
| mBurstFramesAccum += mBurstFrames; |
| } |
| CAMHAL_LOGD("mBurstFramesQueued = %d mBurstFramesAccum = %d index = %d " |
| "capData->mNumBufs = %d queued = %d capData->mMaxQueueable = %d", |
| mBurstFramesQueued,mBurstFramesAccum,index, |
| capData->mNumBufs,queued,capData->mMaxQueueable); |
| CAMHAL_LOGD("%d", (mBurstFramesQueued < mBurstFramesAccum) |
| && (index < capData->mNumBufs) |
| && (queued < capData->mMaxQueueable)); |
| while ((mBurstFramesQueued < mBurstFramesAccum) && |
| (index < capData->mNumBufs) && |
| (queued < capData->mMaxQueueable)) { |
| if (capData->mStatus[index] == OMXCameraPortParameters::IDLE) { |
| CAMHAL_LOGDB("Queuing buffer on Capture port - %p", |
| capData->mBufferHeader[index]->pBuffer); |
| capData->mStatus[index] = OMXCameraPortParameters::FILL; |
| eError = OMX_FillThisBuffer(mCameraAdapterParameters.mHandleComp, |
| (OMX_BUFFERHEADERTYPE*)capData->mBufferHeader[index]); |
| GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError); |
| mBurstFramesQueued++; |
| queued++; |
| } else if (OMXCameraPortParameters::FILL == capData->mStatus[index]) { |
| CAMHAL_LOGE("Not queueing index = %d", index); |
| queued++; |
| } |
| index++; |
| } |
| |
| #ifdef CAMERAHAL_USE_RAW_IMAGE_SAVING |
| if (mRawCapture) { |
| capData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoPortIndex]; |
| |
| ///Queue all the buffers on capture port |
| for ( int index = 0 ; index < capData->mNumBufs ; index++ ) { |
| CAMHAL_LOGDB("Queuing buffer on Video port (for RAW capture) - 0x%x", ( unsigned int ) capData->mBufferHeader[index]->pBuffer); |
| capData->mStatus[index] = OMXCameraPortParameters::FILL; |
| eError = OMX_FillThisBuffer(mCameraAdapterParameters.mHandleComp, |
| (OMX_BUFFERHEADERTYPE*)capData->mBufferHeader[index]); |
| |
| GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError); |
| } |
| } |
| #endif |
| |
| 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 ) && ( mCapMode != VIDEO_MODE_HQ ) ) { |
| 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); |
| } |
| } |
| |
| #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS |
| CameraHal::PPM("startImageCapture image buffers queued and capture enabled: ", &mStartCapture); |
| #endif |
| |
| //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; |
| } |
| |
| } |
| |
| #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS |
| CameraHal::PPM("startImageCapture shutter event received: ", &mStartCapture); |
| #endif |
| |
| return (ret | Utils::ErrorUtils::omxToAndroidError(eError)); |
| |
| EXIT: |
| CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError); |
| mWaitingForSnapshot = false; |
| mCaptureSignalled = false; |
| performCleanupAfterError(); |
| LOG_FUNCTION_NAME_EXIT; |
| return (ret | Utils::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; |
| |
| android::AutoMutex 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; |
| } |
| |
| // TODO(XXX): Reprocessing is currently piggy-backing capture commands |
| if (mAdapterState == REPROCESS_STATE) { |
| ret = stopReprocess(); |
| } |
| |
| //Disable the callback first |
| mWaitingForSnapshot = false; |
| |
| // 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); |
| } |
| } else if (CP_CAM == mCapMode) { |
| // Reset shot config queue |
| OMX_TI_CONFIG_ENQUEUESHOTCONFIGS resetShotConfigs; |
| OMX_INIT_STRUCT_PTR(&resetShotConfigs, OMX_TI_CONFIG_ENQUEUESHOTCONFIGS); |
| |
| resetShotConfigs.nPortIndex = mCameraAdapterParameters.mImagePortIndex; |
| resetShotConfigs.bFlushQueue = OMX_TRUE; |
| resetShotConfigs.nNumConfigs = 0; |
| eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, |
| ( OMX_INDEXTYPE ) OMX_TI_IndexConfigEnqueueShotConfigs, |
| &resetShotConfigs); |
| if ( OMX_ErrorNone != eError ) { |
| CAMHAL_LOGEB("Error while reset shot config 0x%x", eError); |
| goto EXIT; |
| } else { |
| CAMHAL_LOGDA("Shot config reset successfully"); |
| } |
| } |
| |
| //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 ) && ( mCapMode != VIDEO_MODE_HQ ) ) { |
| 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; |
| } |
| } |
| |
| CAMHAL_LOGDB("Capture set - 0x%x", eError); |
| |
| mCaptureSignalled = true; //set this to true if we exited because of timeout |
| |
| { |
| android::AutoMutex lock(mFrameCountMutex); |
| mFrameCount = 0; |
| mFirstFrameCondition.broadcast(); |
| } |
| |
| // Stop is always signalled externally in CPCAM mode |
| // We need to make sure we really stop |
| if ((mCapMode == CP_CAM)) { |
| disableReprocess(); |
| disableImagePort(); |
| if ( NULL != mReleaseImageBuffersCallback ) { |
| mReleaseImageBuffersCallback(mReleaseData); |
| } |
| } |
| |
| // Moving code for below commit here as an optimization for continuous capture, |
| // so focus settings don't have to reapplied after each capture |
| // c78fa2a CameraHAL: Always reset focus mode after capture |
| // Workaround when doing many consecutive shots, CAF wasn't getting restarted. |
| mPending3Asettings |= SetFocus; |
| |
| mCapturedFrames = 0; |
| mBurstFramesAccum = 0; |
| mBurstFramesQueued = 0; |
| |
| return (ret | Utils::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); |
| } |
| |
| { |
| android::AutoMutex lock(mFrameCountMutex); |
| mFrameCount = 0; |
| mFirstFrameCondition.broadcast(); |
| } |
| |
| performCleanupAfterError(); |
| LOG_FUNCTION_NAME_EXIT; |
| return (ret | Utils::ErrorUtils::omxToAndroidError(eError)); |
| } |
| |
| status_t OMXCameraAdapter::disableImagePort(){ |
| status_t ret = NO_ERROR; |
| OMX_ERRORTYPE eError = OMX_ErrorNone; |
| OMXCameraPortParameters *imgCaptureData = NULL; |
| OMXCameraPortParameters *imgRawCaptureData = NULL; |
| |
| if (!mCaptureConfigured) { |
| return NO_ERROR; |
| } |
| |
| mCaptureConfigured = false; |
| imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex]; |
| imgRawCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoPortIndex]; // for RAW capture |
| |
| ///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; |
| } |
| |
| deinitInternalBuffers(mCameraAdapterParameters.mImagePortIndex); |
| |
| // since port settings are not persistent after port is disabled... |
| mPendingCaptureSettings |= SetFormat; |
| |
| #ifdef CAMERAHAL_USE_RAW_IMAGE_SAVING |
| |
| if (mRawCapture) { |
| ///Register for Video port Disable event |
| ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp, |
| OMX_EventCmdComplete, |
| OMX_CommandPortDisable, |
| mCameraAdapterParameters.mVideoPortIndex, |
| mStopCaptureSem); |
| ///Disable RawCapture Port |
| eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp, |
| OMX_CommandPortDisable, |
| mCameraAdapterParameters.mVideoPortIndex, |
| NULL); |
| |
| GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError); |
| |
| ///Free all the buffers on RawCapture port |
| if (imgRawCaptureData) { |
| CAMHAL_LOGDB("Freeing buffer on Capture port - %d", imgRawCaptureData->mNumBufs); |
| for ( int index = 0 ; index < imgRawCaptureData->mNumBufs ; index++) { |
| CAMHAL_LOGDB("Freeing buffer on Capture port - 0x%x", ( unsigned int ) imgRawCaptureData->mBufferHeader[index]->pBuffer); |
| eError = OMX_FreeBuffer(mCameraAdapterParameters.mHandleComp, |
| mCameraAdapterParameters.mVideoPortIndex, |
| (OMX_BUFFERHEADERTYPE*)imgRawCaptureData->mBufferHeader[index]); |
| |
| GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError); |
| } |
| } |
| CAMHAL_LOGDA("Waiting for Video port disable"); |
| //Wait for the image port enable event |
| mStopCaptureSem.WaitTimeout(OMX_CMD_TIMEOUT); |
| CAMHAL_LOGDA("Video Port disabled"); |
| } |
| #endif |
| |
| EXIT: |
| return (ret | Utils::ErrorUtils::omxToAndroidError(eError)); |
| } |
| |
| status_t OMXCameraAdapter::initInternalBuffers(OMX_U32 portIndex) |
| { |
| OMX_ERRORTYPE eError = OMX_ErrorNone; |
| int index = 0; |
| OMX_TI_PARAM_USEBUFFERDESCRIPTOR bufferdesc; |
| |
| /* Indicate to Ducati that we're planning to use dynamically-mapped buffers */ |
| OMX_INIT_STRUCT_PTR (&bufferdesc, OMX_TI_PARAM_USEBUFFERDESCRIPTOR); |
| bufferdesc.nPortIndex = portIndex; |
| bufferdesc.bEnabled = OMX_FALSE; |
| bufferdesc.eBufferType = OMX_TI_BufferTypePhysicalPageList; |
| |
| eError = OMX_SetParameter(mCameraAdapterParameters.mHandleComp, |
| (OMX_INDEXTYPE) OMX_TI_IndexUseBufferDescriptor, |
| &bufferdesc); |
| if (eError!=OMX_ErrorNone) { |
| CAMHAL_LOGEB("OMX_SetParameter - %x", eError); |
| return -EINVAL; |
| } |
| |
| CAMHAL_LOGDA("Initializing internal buffers"); |
| do { |
| OMX_TI_PARAM_COMPONENTBUFALLOCTYPE bufferalloc; |
| OMX_TI_PARAM_COMPONENTBUFALLOCTYPE bufferallocset; |
| OMX_INIT_STRUCT_PTR (&bufferalloc, OMX_TI_PARAM_COMPONENTBUFALLOCTYPE); |
| bufferalloc.nPortIndex = portIndex; |
| bufferalloc.nIndex = index; |
| |
| eError = OMX_GetParameter (mCameraAdapterParameters.mHandleComp, |
| (OMX_INDEXTYPE)OMX_TI_IndexParamComponentBufferAllocation, |
| &bufferalloc); |
| if (eError == OMX_ErrorNoMore) { |
| return NO_ERROR; |
| } |
| if (eError != OMX_ErrorNone) { |
| CAMHAL_LOGE("GetParameter failed error = 0x%x", eError); |
| break; |
| } |
| |
| CAMHAL_LOGDB("Requesting buftype %d of size %dx%d", |
| (int)bufferalloc.eBufType, (int)bufferalloc.nAllocWidth, |
| (int)bufferalloc.nAllocLines); |
| |
| bufferalloc.eBufType = OMX_TI_BufferTypeHardwareReserved1D; |
| |
| OMX_INIT_STRUCT_PTR (&bufferallocset, OMX_TI_PARAM_COMPONENTBUFALLOCTYPE); |
| bufferallocset.nPortIndex = portIndex; |
| bufferallocset.nIndex = index; |
| bufferallocset.eBufType = OMX_TI_BufferTypeHardwareReserved1D; |
| bufferallocset.nAllocWidth = bufferalloc.nAllocWidth; |
| bufferallocset.nAllocLines = bufferalloc.nAllocLines; |
| |
| eError = OMX_SetParameter (mCameraAdapterParameters.mHandleComp, |
| (OMX_INDEXTYPE)OMX_TI_IndexParamComponentBufferAllocation, |
| &bufferallocset); |
| if (eError != OMX_ErrorNone) { |
| CAMHAL_LOGE("SetParameter failed, error=%08x", eError); |
| if (eError == OMX_ErrorNoMore) return NO_ERROR; |
| break; |
| } |
| |
| index++; |
| |
| /* 1 is an arbitrary limit */ |
| } while (index < 1); |
| |
| CAMHAL_LOGV("Ducati requested too many (>1) internal buffers"); |
| |
| return -EINVAL; |
| } |
| |
| status_t OMXCameraAdapter::deinitInternalBuffers(OMX_U32 portIndex) |
| { |
| OMX_ERRORTYPE eError = OMX_ErrorNone; |
| OMX_TI_PARAM_USEBUFFERDESCRIPTOR bufferdesc; |
| |
| OMX_INIT_STRUCT_PTR (&bufferdesc, OMX_TI_PARAM_USEBUFFERDESCRIPTOR); |
| bufferdesc.nPortIndex = portIndex; |
| bufferdesc.bEnabled = OMX_FALSE; |
| bufferdesc.eBufferType = OMX_TI_BufferTypeDefault; |
| |
| eError = OMX_SetParameter(mCameraAdapterParameters.mHandleComp, |
| (OMX_INDEXTYPE) OMX_TI_IndexUseBufferDescriptor, |
| &bufferdesc); |
| if (eError!=OMX_ErrorNone) { |
| CAMHAL_LOGEB("OMX_SetParameter - %x", eError); |
| return -EINVAL; |
| } |
| |
| OMX_TI_PARAM_COMPONENTBUFALLOCTYPE bufferalloc; |
| OMX_INIT_STRUCT_PTR (&bufferalloc, OMX_TI_PARAM_COMPONENTBUFALLOCTYPE); |
| bufferalloc.nPortIndex = portIndex; |
| bufferalloc.eBufType = OMX_TI_BufferTypeDefault; |
| bufferalloc.nAllocWidth = 1; |
| bufferalloc.nAllocLines = 1; |
| eError = OMX_SetParameter(mCameraAdapterParameters.mHandleComp, |
| (OMX_INDEXTYPE) OMX_TI_IndexParamComponentBufferAllocation, |
| &bufferalloc); |
| if (eError!=OMX_ErrorNone) { |
| CAMHAL_LOGEB("OMX_SetParameter - %x", eError); |
| return -EINVAL; |
| } |
| |
| return Utils::ErrorUtils::omxToAndroidError(eError); |
| } |
| |
| status_t OMXCameraAdapter::UseBuffersCapture(CameraBuffer * bufArr, int num) |
| { |
| LOG_FUNCTION_NAME; |
| |
| status_t ret = NO_ERROR; |
| OMX_ERRORTYPE eError = OMX_ErrorNone; |
| OMXCameraPortParameters * imgCaptureData = NULL; |
| OMXCameraPortParameters cap; |
| |
| imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex]; |
| |
| if ( 0 != mUseCaptureSem.Count() ) |
| { |
| CAMHAL_LOGEB("Error mUseCaptureSem semaphore count %d", mUseCaptureSem.Count()); |
| return BAD_VALUE; |
| } |
| |
| CAMHAL_ASSERT(num > 0); |
| |
| // if some setting that requires a SetParameter (including |
| // changing buffer types) then we need to disable the port |
| // before being allowed to apply the settings |
| if ((mPendingCaptureSettings & ECaptureParamSettings) || |
| bufArr[0].type != imgCaptureData->mBufferType || |
| imgCaptureData->mNumBufs != num) { |
| if (mCaptureConfigured) { |
| disableImagePort(); |
| if ( NULL != mReleaseImageBuffersCallback ) { |
| mReleaseImageBuffersCallback(mReleaseData); |
| } |
| } |
| |
| imgCaptureData->mBufferType = bufArr[0].type; |
| imgCaptureData->mNumBufs = num; |
| |
| CAMHAL_LOGDB("Params Width = %d", (int)imgCaptureData->mWidth); |
| CAMHAL_LOGDB("Params Height = %d", (int)imgCaptureData->mHeight); |
| |
| 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 & SetQuality) { |
| mPendingCaptureSettings &= ~SetQuality; |
| ret = setImageQuality(mPictureQuality); |
| if ( NO_ERROR != ret) { |
| CAMHAL_LOGEB("Error configuring image quality %x", ret); |
| goto EXIT; |
| } |
| } |
| |
| // Configure DOMX to use either gralloc handles or vptrs |
| { |
| OMX_TI_PARAMUSENATIVEBUFFER domxUseGrallocHandles; |
| OMX_INIT_STRUCT_PTR (&domxUseGrallocHandles, OMX_TI_PARAMUSENATIVEBUFFER); |
| |
| domxUseGrallocHandles.nPortIndex = mCameraAdapterParameters.mImagePortIndex; |
| if (bufArr[0].type == CAMERA_BUFFER_ANW) { |
| CAMHAL_LOGD ("Using ANW Buffers"); |
| initInternalBuffers(mCameraAdapterParameters.mImagePortIndex); |
| domxUseGrallocHandles.bEnable = OMX_TRUE; |
| } else { |
| CAMHAL_LOGD ("Using ION Buffers"); |
| domxUseGrallocHandles.bEnable = OMX_FALSE; |
| } |
| |
| eError = OMX_SetParameter(mCameraAdapterParameters.mHandleComp, |
| (OMX_INDEXTYPE)OMX_TI_IndexUseNativeBuffers, &domxUseGrallocHandles); |
| if (eError!=OMX_ErrorNone) { |
| CAMHAL_LOGEB("OMX_SetParameter - %x", eError); |
| } |
| GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError); |
| } |
| |
| #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS |
| |
| CameraHal::PPM("Takepicture image port configuration: ", &bufArr->ppmStamp); |
| |
| #endif |
| |
| // 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)bufArr[index].opaque, |
| (int)imgCaptureData->mBufSize); |
| |
| eError = OMX_UseBuffer(mCameraAdapterParameters.mHandleComp, |
| &pBufferHdr, |
| mCameraAdapterParameters.mImagePortIndex, |
| 0, |
| imgCaptureData->mBufSize, |
| (OMX_U8*)camera_buffer_get_omx_ptr(&bufArr[index])); |
| |
| CAMHAL_LOGDB("OMX_UseBuffer = 0x%x", eError); |
| GOTO_EXIT_IF(( eError != OMX_ErrorNone ), eError); |
| |
| pBufferHdr->pAppPrivate = (OMX_PTR) &bufArr[index]; |
| bufArr[index].index = 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; |
| imgCaptureData->mStatus[index] = OMXCameraPortParameters::IDLE; |
| } |
| |
| // 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) { |
| ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp, |
| OMX_EventCmdComplete, |
| OMX_CommandPortEnable, |
| mCameraAdapterParameters.mImagePortIndex, |
| NULL); |
| CAMHAL_LOGDA("Timeout expired on port enable"); |
| goto EXIT; |
| } |
| CAMHAL_LOGDA("Port enabled"); |
| |
| #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS |
| |
| CameraHal::PPM("Takepicture image port enabled and buffers registered: ", &bufArr->ppmStamp); |
| |
| #endif |
| |
| if (mNextState != LOADED_REPROCESS_CAPTURE_STATE) { |
| // Enable WB and vector shot extra data for metadata |
| setExtraData(true, mCameraAdapterParameters.mImagePortIndex, OMX_WhiteBalance); |
| setExtraData(true, mCameraAdapterParameters.mImagePortIndex, OMX_TI_LSCTable); |
| } |
| |
| // CPCam mode only supports vector shot |
| // Regular capture is not supported |
| if ( (mCapMode == CP_CAM) && (mNextState != LOADED_REPROCESS_CAPTURE_STATE) ) { |
| initVectorShot(); |
| } |
| |
| mCaptureBuffersAvailable.clear(); |
| for (unsigned int i = 0; i < imgCaptureData->mMaxQueueable; i++ ) { |
| mCaptureBuffersAvailable.add(&mCaptureBuffers[i], 0); |
| } |
| |
| // initial ref count for undeqeueued buffers is 1 since buffer provider |
| // is still holding on to it |
| for (unsigned int i = imgCaptureData->mMaxQueueable; i < imgCaptureData->mNumBufs; i++ ) { |
| mCaptureBuffersAvailable.add(&mCaptureBuffers[i], 1); |
| } |
| } |
| |
| if ( NO_ERROR == ret ) |
| { |
| ret = setupEXIF(); |
| if ( NO_ERROR != ret ) |
| { |
| CAMHAL_LOGEB("Error configuring EXIF Buffer %x", ret); |
| } |
| } |
| |
| // Choose proper single preview mode for cp capture (reproc or hs) |
| if (( NO_ERROR == ret) && (OMXCameraAdapter::CP_CAM == mCapMode)) { |
| OMX_TI_CONFIG_SINGLEPREVIEWMODETYPE singlePrevMode; |
| OMX_INIT_STRUCT_PTR (&singlePrevMode, OMX_TI_CONFIG_SINGLEPREVIEWMODETYPE); |
| if (mNextState == LOADED_CAPTURE_STATE) { |
| singlePrevMode.eMode = OMX_TI_SinglePreviewMode_ImageCaptureHighSpeed; |
| } else if (mNextState == LOADED_REPROCESS_CAPTURE_STATE) { |
| singlePrevMode.eMode = OMX_TI_SinglePreviewMode_Reprocess; |
| } else { |
| CAMHAL_LOGE("Wrong state trying to start a capture in CPCAM mode?"); |
| singlePrevMode.eMode = OMX_TI_SinglePreviewMode_ImageCaptureHighSpeed; |
| } |
| eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, |
| (OMX_INDEXTYPE) OMX_TI_IndexConfigSinglePreviewMode, |
| &singlePrevMode); |
| if ( OMX_ErrorNone != eError ) { |
| CAMHAL_LOGEB("Error while configuring single preview mode 0x%x", eError); |
| ret = Utils::ErrorUtils::omxToAndroidError(eError); |
| } else { |
| CAMHAL_LOGDA("single preview mode configured successfully"); |
| } |
| } |
| |
| #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS |
| |
| CameraHal::PPM("Takepicture extra configs on image port done: ", &bufArr->ppmStamp); |
| |
| #endif |
| |
| mCaptureConfigured = true; |
| |
| #ifdef CAMERAHAL_USE_RAW_IMAGE_SAVING |
| if (mRawCapture) { |
| mCaptureConfigured = false; |
| } |
| #endif |
| |
| return (ret | Utils::ErrorUtils::omxToAndroidError(eError)); |
| |
| EXIT: |
| CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError); |
| setExtraData(false, mCameraAdapterParameters.mImagePortIndex, OMX_WhiteBalance); |
| // TODO: WA: if domx client disables VectShotInfo metadata on the image port, this causes |
| // VectShotInfo to be disabled internally on preview port also. Remove setting in OMXCapture |
| // setExtraData(false, mCameraAdapterParameters.mImagePortIndex, OMX_TI_VectShotInfo); |
| setExtraData(false, mCameraAdapterParameters.mImagePortIndex, OMX_TI_LSCTable); |
| //Release image buffers |
| if ( NULL != mReleaseImageBuffersCallback ) { |
| mReleaseImageBuffersCallback(mReleaseData); |
| } |
| performCleanupAfterError(); |
| LOG_FUNCTION_NAME_EXIT; |
| return (ret | Utils::ErrorUtils::omxToAndroidError(eError)); |
| |
| } |
| status_t OMXCameraAdapter::UseBuffersRawCapture(CameraBuffer *bufArr, int num) |
| { |
| LOG_FUNCTION_NAME |
| status_t ret; |
| OMX_ERRORTYPE eError; |
| OMXCameraPortParameters * imgRawCaptureData = NULL; |
| Utils::Semaphore camSem; |
| OMXCameraPortParameters cap; |
| |
| imgRawCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoPortIndex]; |
| |
| if (mCaptureConfigured) { |
| return NO_ERROR; |
| } |
| |
| camSem.Create(); |
| |
| // mWaitingForSnapshot is true only when we're in the process of capturing |
| if (mWaitingForSnapshot) { |
| ///Register for Video port Disable event |
| ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp, |
| (OMX_EVENTTYPE) OMX_EventCmdComplete, |
| OMX_CommandPortDisable, |
| mCameraAdapterParameters.mVideoPortIndex, |
| camSem); |
| |
| ///Disable Capture Port |
| eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp, |
| OMX_CommandPortDisable, |
| mCameraAdapterParameters.mVideoPortIndex, |
| NULL); |
| |
| CAMHAL_LOGDA("Waiting for port disable"); |
| //Wait for the image port enable event |
| camSem.Wait(); |
| CAMHAL_LOGDA("Port disabled"); |
| } |
| |
| imgRawCaptureData->mNumBufs = num; |
| |
| CAMHAL_LOGDB("RAW Max sensor width = %d", (int)imgRawCaptureData->mWidth); |
| CAMHAL_LOGDB("RAW Max sensor height = %d", (int)imgRawCaptureData->mHeight); |
| |
| ret = setFormat(OMX_CAMERA_PORT_VIDEO_OUT_VIDEO, *imgRawCaptureData); |
| |
| if (ret != NO_ERROR) { |
| CAMHAL_LOGEB("setFormat() failed %d", ret); |
| LOG_FUNCTION_NAME_EXIT |
| return ret; |
| } |
| |
| ///Register for Video port ENABLE event |
| ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp, |
| (OMX_EVENTTYPE) OMX_EventCmdComplete, |
| OMX_CommandPortEnable, |
| mCameraAdapterParameters.mVideoPortIndex, |
| camSem); |
| |
| ///Enable Video Capture Port |
| eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp, |
| OMX_CommandPortEnable, |
| mCameraAdapterParameters.mVideoPortIndex, |
| NULL); |
| |
| mCaptureBuffersLength = (int)imgRawCaptureData->mBufSize; |
| for ( int index = 0 ; index < imgRawCaptureData->mNumBufs ; index++ ) { |
| OMX_BUFFERHEADERTYPE *pBufferHdr; |
| CAMHAL_LOGDB("OMX_UseBuffer rawCapture address: 0x%x, size = %d ", |
| (unsigned int)bufArr[index].opaque, |
| (int)imgRawCaptureData->mBufSize ); |
| |
| eError = OMX_UseBuffer( mCameraAdapterParameters.mHandleComp, |
| &pBufferHdr, |
| mCameraAdapterParameters.mVideoPortIndex, |
| 0, |
| mCaptureBuffersLength, |
| (OMX_U8*)camera_buffer_get_omx_ptr(&bufArr[index])); |
| if (eError != OMX_ErrorNone) { |
| CAMHAL_LOGEB("OMX_UseBuffer = 0x%x", eError); |
| } |
| |
| GOTO_EXIT_IF(( eError != OMX_ErrorNone ), eError); |
| |
| pBufferHdr->pAppPrivate = (OMX_PTR) &bufArr[index]; |
| bufArr[index].index = 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; |
| imgRawCaptureData->mBufferHeader[index] = pBufferHdr; |
| |
| } |
| |
| //Wait for the image port enable event |
| CAMHAL_LOGDA("Waiting for port enable"); |
| camSem.Wait(); |
| CAMHAL_LOGDA("Port enabled"); |
| |
| if (NO_ERROR == ret) { |
| ret = setupEXIF(); |
| if ( NO_ERROR != ret ) { |
| CAMHAL_LOGEB("Error configuring EXIF Buffer %x", ret); |
| } |
| } |
| |
| mCapturedFrames = mBurstFrames; |
| mBurstFramesQueued = 0; |
| mCaptureConfigured = true; |
| |
| EXIT: |
| |
| if (eError != OMX_ErrorNone) { |
| if ( NULL != mErrorNotifier ) |
| { |
| mErrorNotifier->errorNotify(eError); |
| } |
| } |
| |
| LOG_FUNCTION_NAME_EXIT |
| |
| return ret; |
| } |
| |
| } // namespace Camera |
| } // namespace Ti |