/*
* 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