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 ¶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
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