1 /* 2 * Copyright (C) Texas Instruments - http://www.ti.com/ 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /** 18 * @file OMXReprocess.cpp 19 * 20 * This file contains functionality for handling reprocessing operations. 21 * 22 */ 23 24 #include "CameraHal.h" 25 #include "OMXCameraAdapter.h" 26 #include "ErrorUtils.h" 27 28 29 namespace Ti { 30 namespace Camera { 31 32 status_t OMXCameraAdapter::setParametersReprocess(const android::CameraParameters ¶ms, 33 CameraBuffer* buffers, 34 BaseCameraAdapter::AdapterState state) 35 { 36 status_t ret = NO_ERROR; 37 int w, h, s; 38 OMX_COLOR_FORMATTYPE pixFormat; 39 OMXCameraPortParameters *portData; 40 const char* valstr; 41 42 LOG_FUNCTION_NAME; 43 44 if (!buffers) { 45 CAMHAL_LOGE("invalid buffer array"); 46 return BAD_VALUE; 47 } 48 49 portData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoInPortIndex]; 50 51 w = buffers[0].width; 52 h = buffers[0].height; 53 s = buffers[0].stride; 54 55 valstr = buffers[0].format; 56 if (valstr != NULL) { 57 if(strcmp(valstr, android::CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) { 58 CAMHAL_LOGDA("YUV420SP format selected"); 59 pixFormat = OMX_COLOR_FormatYUV420SemiPlanar; 60 } else if (strcmp(valstr, android::CameraParameters::PIXEL_FORMAT_BAYER_RGGB) == 0) { 61 CAMHAL_LOGDA("RAW Picture format selected"); 62 pixFormat = OMX_COLOR_FormatRawBayer10bit; 63 } else if (strcmp(valstr, android::CameraParameters::PIXEL_FORMAT_YUV422I) == 0) { 64 CAMHAL_LOGDA("YUV422i Picture format selected"); 65 pixFormat = OMX_COLOR_FormatCbYCrY; 66 } else { 67 CAMHAL_LOGDA("Format not supported, selecting YUV420SP by default"); 68 pixFormat = OMX_COLOR_FormatYUV420SemiPlanar; 69 } 70 } else { 71 CAMHAL_LOGDA("Format not supported, selecting YUV420SP by default"); 72 pixFormat = OMX_COLOR_FormatYUV420SemiPlanar; 73 } 74 75 if ( (w != (int)portData->mWidth) || (h != (int)portData->mHeight) || 76 (s != (int) portData->mStride) || (pixFormat != portData->mColorFormat)) { 77 portData->mWidth = w; 78 portData->mHeight = h; 79 80 if ( ( OMX_COLOR_FormatRawBayer10bit == pixFormat ) || 81 ( OMX_COLOR_FormatCbYCrY == pixFormat ) ) { 82 portData->mStride = w * 2; 83 } else { 84 portData->mStride = s; 85 } 86 87 portData->mColorFormat = pixFormat; 88 89 mPendingReprocessSettings |= SetFormat; 90 } 91 92 LOG_FUNCTION_NAME_EXIT; 93 94 return ret; 95 } 96 97 status_t OMXCameraAdapter::startReprocess() 98 { 99 status_t ret = NO_ERROR; 100 OMX_ERRORTYPE eError = OMX_ErrorNone; 101 OMXCameraPortParameters * portData = NULL; 102 103 LOG_FUNCTION_NAME; 104 CAMHAL_LOGD ("mReprocConfigured = %d", mReprocConfigured); 105 if (!mReprocConfigured) { 106 return NO_ERROR; 107 } 108 109 portData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoInPortIndex]; 110 111 CAMHAL_LOGD ("mReprocConfigured = %d", mBurstFramesQueued); 112 if (NO_ERROR == ret) { 113 android::AutoMutex lock(mBurstLock); 114 115 for ( int index = 0 ; index < portData->mMaxQueueable ; index++ ) { 116 CAMHAL_LOGDB("Queuing buffer on video input port - %p, offset: %d, length: %d", 117 portData->mBufferHeader[index]->pBuffer, 118 portData->mBufferHeader[index]->nOffset, 119 portData->mBufferHeader[index]->nFilledLen); 120 portData->mStatus[index] = OMXCameraPortParameters::FILL; 121 eError = OMX_EmptyThisBuffer(mCameraAdapterParameters.mHandleComp, 122 (OMX_BUFFERHEADERTYPE*)portData->mBufferHeader[index]); 123 GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError); 124 } 125 } 126 127 #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS 128 CameraHal::PPM("startReprocess buffers queued on video port: ", &mStartCapture); 129 #endif 130 131 return (ret | Utils::ErrorUtils::omxToAndroidError(eError)); 132 133 EXIT: 134 CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError); 135 performCleanupAfterError(); 136 LOG_FUNCTION_NAME_EXIT; 137 return (ret | Utils::ErrorUtils::omxToAndroidError(eError)); 138 } 139 140 status_t OMXCameraAdapter::stopReprocess() 141 { 142 LOG_FUNCTION_NAME; 143 144 status_t ret = NO_ERROR; 145 OMX_ERRORTYPE eError = OMX_ErrorNone; 146 OMXCameraPortParameters *portData = NULL; 147 148 if (!mReprocConfigured) { 149 return NO_ERROR; 150 } 151 152 portData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoInPortIndex]; 153 154 // Disable port - send command and then free all buffers 155 ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp, 156 OMX_EventCmdComplete, 157 OMX_CommandPortDisable, 158 mCameraAdapterParameters.mVideoInPortIndex, 159 mStopReprocSem); 160 eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp, 161 OMX_CommandPortDisable, 162 mCameraAdapterParameters.mVideoInPortIndex, 163 NULL); 164 if (portData) { 165 CAMHAL_LOGDB("Freeing buffers on reproc port - num: %d", portData->mNumBufs); 166 for (int index = 0 ; index < portData->mNumBufs ; index++) { 167 CAMHAL_LOGDB("Freeing buffer on reproc port - 0x%x", 168 ( unsigned int ) portData->mBufferHeader[index]->pBuffer); 169 eError = OMX_FreeBuffer(mCameraAdapterParameters.mHandleComp, 170 mCameraAdapterParameters.mVideoInPortIndex, 171 (OMX_BUFFERHEADERTYPE*)portData->mBufferHeader[index]); 172 GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError); 173 } 174 } 175 CAMHAL_LOGDA("Waiting for port disable"); 176 ret = mStopReprocSem.WaitTimeout(OMX_CMD_TIMEOUT); 177 if (mComponentState == OMX_StateInvalid) { 178 CAMHAL_LOGEA("Invalid State after Disable Image Port Exitting!!!"); 179 goto EXIT; 180 } 181 if (NO_ERROR == ret) { 182 CAMHAL_LOGDA("Port disabled"); 183 } else { 184 ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp, 185 OMX_EventCmdComplete, 186 OMX_CommandPortDisable, 187 mCameraAdapterParameters.mVideoInPortIndex, 188 NULL); 189 CAMHAL_LOGDA("Timeout expired on port disable"); 190 goto EXIT; 191 } 192 193 deinitInternalBuffers(mCameraAdapterParameters.mVideoInPortIndex); 194 195 mReprocConfigured = false; 196 197 EXIT: 198 CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError); 199 LOG_FUNCTION_NAME_EXIT; 200 return (ret | Utils::ErrorUtils::omxToAndroidError(eError)); 201 } 202 203 status_t OMXCameraAdapter::disableReprocess(){ 204 status_t ret = NO_ERROR; 205 OMX_ERRORTYPE eError = OMX_ErrorNone; 206 207 // no-op..for now 208 209 EXIT: 210 return (ret | Utils::ErrorUtils::omxToAndroidError(eError)); 211 } 212 213 status_t OMXCameraAdapter::UseBuffersReprocess(CameraBuffer *bufArr, int num) 214 { 215 LOG_FUNCTION_NAME; 216 217 status_t ret = NO_ERROR; 218 OMX_ERRORTYPE eError = OMX_ErrorNone; 219 OMXCameraPortParameters *portData = NULL; 220 221 portData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoInPortIndex]; 222 223 if ( 0 != mUseReprocessSem.Count() ) { 224 CAMHAL_LOGEB("Error mUseReprocessSem semaphore count %d", mUseReprocessSem.Count()); 225 return BAD_VALUE; 226 } 227 228 CAMHAL_ASSERT(num > 0); 229 230 if (mAdapterState == REPROCESS_STATE) { 231 stopReprocess(); 232 } else if (mAdapterState == CAPTURE_STATE) { 233 stopImageCapture(); 234 stopReprocess(); 235 } 236 237 #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS 238 239 CameraHal::PPM("Reprocess stopping image capture and disabling image port: ", &bufArr->ppmStamp); 240 241 #endif 242 243 portData->mNumBufs = num; 244 245 // Configure 246 ret = setParametersReprocess(mParams, bufArr, mAdapterState); 247 248 if (mReprocConfigured) { 249 if (mPendingReprocessSettings & ECaptureParamSettings) { 250 stopReprocess(); 251 } else { 252 // Tap in port has been already configured. 253 return NO_ERROR; 254 } 255 } 256 257 if (mPendingReprocessSettings & SetFormat) { 258 mPendingReprocessSettings &= ~SetFormat; 259 ret = setFormat(OMX_CAMERA_PORT_VIDEO_IN_VIDEO, *portData); 260 if ( ret != NO_ERROR ) { 261 CAMHAL_LOGEB("setFormat() failed %d", ret); 262 LOG_FUNCTION_NAME_EXIT; 263 return ret; 264 } 265 } 266 267 // Configure DOMX to use either gralloc handles or vptrs 268 OMX_TI_PARAMUSENATIVEBUFFER domxUseGrallocHandles; 269 OMX_INIT_STRUCT_PTR (&domxUseGrallocHandles, OMX_TI_PARAMUSENATIVEBUFFER); 270 271 domxUseGrallocHandles.nPortIndex = mCameraAdapterParameters.mVideoInPortIndex; 272 if (bufArr[0].type == CAMERA_BUFFER_ANW) { 273 CAMHAL_LOGD("Using ANW"); 274 domxUseGrallocHandles.bEnable = OMX_TRUE; 275 276 // Need to allocate tiler reservation and state we are going to be using 277 // pagelist buffers. Assuming this happens when buffers if from anw 278 initInternalBuffers(mCameraAdapterParameters.mVideoInPortIndex); 279 } else { 280 CAMHAL_LOGD("Using ION"); 281 domxUseGrallocHandles.bEnable = OMX_FALSE; 282 } 283 eError = OMX_SetParameter(mCameraAdapterParameters.mHandleComp, 284 (OMX_INDEXTYPE)OMX_TI_IndexUseNativeBuffers, &domxUseGrallocHandles); 285 if (eError!=OMX_ErrorNone) { 286 CAMHAL_LOGEB("OMX_SetParameter - %x", eError); 287 } 288 GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError); 289 290 #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS 291 292 CameraHal::PPM("Reprocess configuration done: ", &bufArr->ppmStamp); 293 294 #endif 295 296 // Enable Port 297 ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp, 298 OMX_EventCmdComplete, 299 OMX_CommandPortEnable, 300 mCameraAdapterParameters.mVideoInPortIndex, 301 mUseReprocessSem); 302 eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp, 303 OMX_CommandPortEnable, 304 mCameraAdapterParameters.mVideoInPortIndex, 305 NULL); 306 GOTO_EXIT_IF(( eError != OMX_ErrorNone ), eError); 307 308 for (int index = 0 ; index < portData->mNumBufs ; index++) 309 { 310 OMX_BUFFERHEADERTYPE *pBufferHdr; 311 CAMHAL_LOGDB("OMX_UseBuffer Capture address: 0x%x, size = %d", 312 (unsigned int)bufArr[index].opaque, 313 (int)portData->mBufSize); 314 315 eError = OMX_UseBuffer(mCameraAdapterParameters.mHandleComp, 316 &pBufferHdr, 317 mCameraAdapterParameters.mVideoInPortIndex, 318 0, 319 portData->mBufSize, 320 (OMX_U8*)camera_buffer_get_omx_ptr(&bufArr[index])); 321 322 CAMHAL_LOGDB("OMX_UseBuffer = 0x%x", eError); 323 GOTO_EXIT_IF(( eError != OMX_ErrorNone ), eError); 324 325 pBufferHdr->pAppPrivate = (OMX_PTR) &bufArr[index]; 326 bufArr[index].index = index; 327 pBufferHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); 328 pBufferHdr->nVersion.s.nVersionMajor = 1 ; 329 pBufferHdr->nVersion.s.nVersionMinor = 1 ; 330 pBufferHdr->nVersion.s.nRevision = 0; 331 pBufferHdr->nVersion.s.nStep = 0; 332 pBufferHdr->nOffset = bufArr[index].offset; 333 pBufferHdr->nFilledLen = bufArr[index].actual_size; 334 portData->mBufferHeader[index] = pBufferHdr; 335 } 336 337 // Wait for port enable event 338 CAMHAL_LOGDA("Waiting for port enable"); 339 ret = mUseReprocessSem.WaitTimeout(OMX_CMD_TIMEOUT); 340 341 // Error out if somethiing bad happened while we wait 342 if (mComponentState == OMX_StateInvalid) { 343 CAMHAL_LOGEA("Invalid State while trying to enable port for reprocessing"); 344 goto EXIT; 345 } 346 347 if (ret == NO_ERROR) { 348 CAMHAL_LOGDA("Port enabled"); 349 } else { 350 ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp, 351 OMX_EventCmdComplete, 352 OMX_CommandPortEnable, 353 mCameraAdapterParameters.mVideoInPortIndex, 354 NULL); 355 CAMHAL_LOGDA("Timeout expired on port enable"); 356 goto EXIT; 357 } 358 359 mReprocConfigured = true; 360 361 #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS 362 363 CameraHal::PPM("Reprocess video port enabled and buffers registered: ", &bufArr->ppmStamp); 364 365 #endif 366 367 return (ret | Utils::ErrorUtils::omxToAndroidError(eError)); 368 369 EXIT: 370 CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError); 371 // Release image buffers 372 if ( NULL != mReleaseImageBuffersCallback ) { 373 mReleaseImageBuffersCallback(mReleaseData); 374 } 375 performCleanupAfterError(); 376 LOG_FUNCTION_NAME_EXIT; 377 return (ret | Utils::ErrorUtils::omxToAndroidError(eError)); 378 379 } 380 381 } // namespace Camera 382 } // namespace Ti 383