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 
setParametersReprocess(const android::CameraParameters & params,CameraBuffer * buffers,BaseCameraAdapter::AdapterState state)32 status_t OMXCameraAdapter::setParametersReprocess(const android::CameraParameters &params,
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 
startReprocess()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 
stopReprocess()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 
disableReprocess()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 
UseBuffersReprocess(CameraBuffer * bufArr,int num)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