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