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
29namespace Ti {
30namespace Camera {
31
32status_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
97status_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
133EXIT:
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
140status_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
197EXIT:
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
203status_t OMXCameraAdapter::disableReprocess(){
204    status_t ret = NO_ERROR;
205    OMX_ERRORTYPE eError = OMX_ErrorNone;
206
207    // no-op..for now
208
209EXIT:
210    return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
211}
212
213status_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
369EXIT:
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