/*
* 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 OMXReprocess.cpp
*
* This file contains functionality for handling reprocessing operations.
*
*/
#include "CameraHal.h"
#include "OMXCameraAdapter.h"
#include "ErrorUtils.h"
namespace Ti {
namespace Camera {
status_t OMXCameraAdapter::setParametersReprocess(const android::CameraParameters ¶ms,
CameraBuffer* buffers,
BaseCameraAdapter::AdapterState state)
{
status_t ret = NO_ERROR;
int w, h, s;
OMX_COLOR_FORMATTYPE pixFormat;
OMXCameraPortParameters *portData;
const char* valstr;
LOG_FUNCTION_NAME;
if (!buffers) {
CAMHAL_LOGE("invalid buffer array");
return BAD_VALUE;
}
portData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoInPortIndex];
w = buffers[0].width;
h = buffers[0].height;
s = buffers[0].stride;
valstr = buffers[0].format;
if (valstr != NULL) {
if(strcmp(valstr, android::CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) {
CAMHAL_LOGDA("YUV420SP format selected");
pixFormat = OMX_COLOR_FormatYUV420SemiPlanar;
} else if (strcmp(valstr, android::CameraParameters::PIXEL_FORMAT_BAYER_RGGB) == 0) {
CAMHAL_LOGDA("RAW Picture format selected");
pixFormat = OMX_COLOR_FormatRawBayer10bit;
} else if (strcmp(valstr, android::CameraParameters::PIXEL_FORMAT_YUV422I) == 0) {
CAMHAL_LOGDA("YUV422i Picture format selected");
pixFormat = OMX_COLOR_FormatCbYCrY;
} else {
CAMHAL_LOGDA("Format not supported, selecting YUV420SP by default");
pixFormat = OMX_COLOR_FormatYUV420SemiPlanar;
}
} else {
CAMHAL_LOGDA("Format not supported, selecting YUV420SP by default");
pixFormat = OMX_COLOR_FormatYUV420SemiPlanar;
}
if ( (w != (int)portData->mWidth) || (h != (int)portData->mHeight) ||
(s != (int) portData->mStride) || (pixFormat != portData->mColorFormat)) {
portData->mWidth = w;
portData->mHeight = h;
if ( ( OMX_COLOR_FormatRawBayer10bit == pixFormat ) ||
( OMX_COLOR_FormatCbYCrY == pixFormat ) ) {
portData->mStride = w * 2;
} else {
portData->mStride = s;
}
portData->mColorFormat = pixFormat;
mPendingReprocessSettings |= SetFormat;
}
LOG_FUNCTION_NAME_EXIT;
return ret;
}
status_t OMXCameraAdapter::startReprocess()
{
status_t ret = NO_ERROR;
OMX_ERRORTYPE eError = OMX_ErrorNone;
OMXCameraPortParameters * portData = NULL;
LOG_FUNCTION_NAME;
CAMHAL_LOGD ("mReprocConfigured = %d", mReprocConfigured);
if (!mReprocConfigured) {
return NO_ERROR;
}
portData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoInPortIndex];
CAMHAL_LOGD ("mReprocConfigured = %d", mBurstFramesQueued);
if (NO_ERROR == ret) {
android::AutoMutex lock(mBurstLock);
for ( int index = 0 ; index < portData->mMaxQueueable ; index++ ) {
CAMHAL_LOGDB("Queuing buffer on video input port - %p, offset: %d, length: %d",
portData->mBufferHeader[index]->pBuffer,
portData->mBufferHeader[index]->nOffset,
portData->mBufferHeader[index]->nFilledLen);
portData->mStatus[index] = OMXCameraPortParameters::FILL;
eError = OMX_EmptyThisBuffer(mCameraAdapterParameters.mHandleComp,
(OMX_BUFFERHEADERTYPE*)portData->mBufferHeader[index]);
GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
}
}
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
CameraHal::PPM("startReprocess buffers queued on video port: ", &mStartCapture);
#endif
return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
EXIT:
CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
performCleanupAfterError();
LOG_FUNCTION_NAME_EXIT;
return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
}
status_t OMXCameraAdapter::stopReprocess()
{
LOG_FUNCTION_NAME;
status_t ret = NO_ERROR;
OMX_ERRORTYPE eError = OMX_ErrorNone;
OMXCameraPortParameters *portData = NULL;
if (!mReprocConfigured) {
return NO_ERROR;
}
portData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoInPortIndex];
// Disable port - send command and then free all buffers
ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
OMX_EventCmdComplete,
OMX_CommandPortDisable,
mCameraAdapterParameters.mVideoInPortIndex,
mStopReprocSem);
eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp,
OMX_CommandPortDisable,
mCameraAdapterParameters.mVideoInPortIndex,
NULL);
if (portData) {
CAMHAL_LOGDB("Freeing buffers on reproc port - num: %d", portData->mNumBufs);
for (int index = 0 ; index < portData->mNumBufs ; index++) {
CAMHAL_LOGDB("Freeing buffer on reproc port - 0x%x",
( unsigned int ) portData->mBufferHeader[index]->pBuffer);
eError = OMX_FreeBuffer(mCameraAdapterParameters.mHandleComp,
mCameraAdapterParameters.mVideoInPortIndex,
(OMX_BUFFERHEADERTYPE*)portData->mBufferHeader[index]);
GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
}
}
CAMHAL_LOGDA("Waiting for port disable");
ret = mStopReprocSem.WaitTimeout(OMX_CMD_TIMEOUT);
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.mVideoInPortIndex,
NULL);
CAMHAL_LOGDA("Timeout expired on port disable");
goto EXIT;
}
deinitInternalBuffers(mCameraAdapterParameters.mVideoInPortIndex);
mReprocConfigured = false;
EXIT:
CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
LOG_FUNCTION_NAME_EXIT;
return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
}
status_t OMXCameraAdapter::disableReprocess(){
status_t ret = NO_ERROR;
OMX_ERRORTYPE eError = OMX_ErrorNone;
// no-op..for now
EXIT:
return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
}
status_t OMXCameraAdapter::UseBuffersReprocess(CameraBuffer *bufArr, int num)
{
LOG_FUNCTION_NAME;
status_t ret = NO_ERROR;
OMX_ERRORTYPE eError = OMX_ErrorNone;
OMXCameraPortParameters *portData = NULL;
portData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoInPortIndex];
if ( 0 != mUseReprocessSem.Count() ) {
CAMHAL_LOGEB("Error mUseReprocessSem semaphore count %d", mUseReprocessSem.Count());
return BAD_VALUE;
}
CAMHAL_ASSERT(num > 0);
if (mAdapterState == REPROCESS_STATE) {
stopReprocess();
} else if (mAdapterState == CAPTURE_STATE) {
stopImageCapture();
stopReprocess();
}
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
CameraHal::PPM("Reprocess stopping image capture and disabling image port: ", &bufArr->ppmStamp);
#endif
portData->mNumBufs = num;
// Configure
ret = setParametersReprocess(mParams, bufArr, mAdapterState);
if (mReprocConfigured) {
if (mPendingReprocessSettings & ECaptureParamSettings) {
stopReprocess();
} else {
// Tap in port has been already configured.
return NO_ERROR;
}
}
if (mPendingReprocessSettings & SetFormat) {
mPendingReprocessSettings &= ~SetFormat;
ret = setFormat(OMX_CAMERA_PORT_VIDEO_IN_VIDEO, *portData);
if ( ret != NO_ERROR ) {
CAMHAL_LOGEB("setFormat() failed %d", ret);
LOG_FUNCTION_NAME_EXIT;
return ret;
}
}
// Configure DOMX to use either gralloc handles or vptrs
OMX_TI_PARAMUSENATIVEBUFFER domxUseGrallocHandles;
OMX_INIT_STRUCT_PTR (&domxUseGrallocHandles, OMX_TI_PARAMUSENATIVEBUFFER);
domxUseGrallocHandles.nPortIndex = mCameraAdapterParameters.mVideoInPortIndex;
if (bufArr[0].type == CAMERA_BUFFER_ANW) {
CAMHAL_LOGD("Using ANW");
domxUseGrallocHandles.bEnable = OMX_TRUE;
// Need to allocate tiler reservation and state we are going to be using
// pagelist buffers. Assuming this happens when buffers if from anw
initInternalBuffers(mCameraAdapterParameters.mVideoInPortIndex);
} else {
CAMHAL_LOGD("Using ION");
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("Reprocess configuration done: ", &bufArr->ppmStamp);
#endif
// Enable Port
ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
OMX_EventCmdComplete,
OMX_CommandPortEnable,
mCameraAdapterParameters.mVideoInPortIndex,
mUseReprocessSem);
eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp,
OMX_CommandPortEnable,
mCameraAdapterParameters.mVideoInPortIndex,
NULL);
GOTO_EXIT_IF(( eError != OMX_ErrorNone ), eError);
for (int index = 0 ; index < portData->mNumBufs ; index++)
{
OMX_BUFFERHEADERTYPE *pBufferHdr;
CAMHAL_LOGDB("OMX_UseBuffer Capture address: 0x%x, size = %d",
(unsigned int)bufArr[index].opaque,
(int)portData->mBufSize);
eError = OMX_UseBuffer(mCameraAdapterParameters.mHandleComp,
&pBufferHdr,
mCameraAdapterParameters.mVideoInPortIndex,
0,
portData->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;
pBufferHdr->nOffset = bufArr[index].offset;
pBufferHdr->nFilledLen = bufArr[index].actual_size;
portData->mBufferHeader[index] = pBufferHdr;
}
// Wait for port enable event
CAMHAL_LOGDA("Waiting for port enable");
ret = mUseReprocessSem.WaitTimeout(OMX_CMD_TIMEOUT);
// Error out if somethiing bad happened while we wait
if (mComponentState == OMX_StateInvalid) {
CAMHAL_LOGEA("Invalid State while trying to enable port for reprocessing");
goto EXIT;
}
if (ret == NO_ERROR) {
CAMHAL_LOGDA("Port enabled");
} else {
ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp,
OMX_EventCmdComplete,
OMX_CommandPortEnable,
mCameraAdapterParameters.mVideoInPortIndex,
NULL);
CAMHAL_LOGDA("Timeout expired on port enable");
goto EXIT;
}
mReprocConfigured = true;
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
CameraHal::PPM("Reprocess video port enabled and buffers registered: ", &bufArr->ppmStamp);
#endif
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);
}
performCleanupAfterError();
LOG_FUNCTION_NAME_EXIT;
return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
}
} // namespace Camera
} // namespace Ti