1 /* Copyright (C) 2010 Texas Instruments, Inc. All rights reserved. */
3 #include <autolock.h>
4 #include <output.h>
5 #include <OMXVisionCam.h>
7 #undef VCAM_SET_FORMAT_ROTATION
8 #define USE_WB_GAIN_PATCH // enable the hardcoded WB gain get/set apis
10 #ifdef USE_WB_GAIN_PATCH
11 #include "OMXVisionCam_WB_patch.h"
12 #endif
14 //#define _USE_GAMMA_RESET_HC_ // enable the hard coded reset system for gamma tables
16 #include "OMXVisionCam_Gamma_Tbl.h"
18 #define HERE {printf("=======> OMX - %d <=======", __LINE__);fflush(stdout);}
20 #ifdef USE_WB_GAIN_PATCH
21 #define RED 0
22 #define GREEN_RED 1
23 #define GREEN_BLUE 2
24 #define BLUE 3
26 #define CALCULATE_WB_GAINS_OFFSET(type,in,out) out = (type *)(in + 4 + in[4] + in[8])
27 #endif // USE_WB_GAIN_PATCH
29 #define GAMMA_TABLE_SIZE 1024*sizeof(uint16_t)
31 #define OMX_CHECK(error, function) {\
32 error = function;\
33 if (error != OMX_ErrorNone) {\
34 ERROR("OMX Error 0x%08x in "#function" on line # %u", error, __LINE__);\
35 }\
36 }
38 #define OMX_CONVERT_RETURN_IF_ERROR(error, function) {\
39 error = function;\
40 if (error != OMX_ErrorNone) {\
41 ERROR("OMX Error 0x%08x in "#function" on line # %u", error, __LINE__);\
42 return ConvertError(error);\
43 }\
44 }
46 #define OMX_STRUCT_INIT(str, type, pVersion) {\
47 memset(&str, 0, sizeof(type));\
48 str.nSize = sizeof(type);\
49 memcpy(&str.nVersion, pVersion, sizeof(OMX_VERSIONTYPE));\
50 str.nPortIndex = OMX_ALL;\
51 }
53 #define OMX_STRUCT_INIT_PTR(ptr, type, pVersion) {\
54 memset(ptr, 0, sizeof(type));\
55 ptr->nSize = sizeof(type);\
56 memcpy(&ptr->nVersion, pVersion, sizeof(OMX_VERSIONTYPE));\
57 ptr->nPortIndex = OMX_ALL;\
58 }
60 #define LOOP_PORTS( port, cnt ) \
61 for( cnt = ( VCAM_PORT_ALL == port ? VCAM_PORT_PREVIEW : port ); \
62 cnt < ( VCAM_PORT_ALL == port ? VCAM_PORT_MAX : port + 1 ); \
63 cnt++ \
64 )
66 void* FocusThreadLauncher(void *arg)
67 {
68 OMXVisionCam *pCam = reinterpret_cast<OMXVisionCam *>(arg);
69 pCam->waitForFocus();
70 return 0;
71 }
73 void* PreemptionThreadLauncher( void *arg )
74 {
75 OMXVisionCam *pCam = reinterpret_cast<OMXVisionCam *>(arg);
76 pCam->PreemptionService();
77 return 0;
78 }
80 void* FrameThreadFunc(void* user) {
81 OMXVisionCam* pCam = static_cast<OMXVisionCam*>(user);
82 OMX_IN OMX_BUFFERHEADERTYPE* pBuffHeader;
83 do {
84 if (pCam->mFrameCbData.frames.empty()){
85 pthread_mutex_lock(&pCam->mFrameCbData.mutex);
86 } else {
87 pBuffHeader = pCam->mFrameCbData.frames.front();
88 pCam->mFrameCbData.frames.pop_front();
89 if (pBuffHeader != NULL) {
90 pCam->frameReceivedSrvc(pBuffHeader);
91 }
92 }
93 } while (pBuffHeader != NULL);
95 return NULL;
96 }
98 static void PrintOMXState(OMX_STATETYPE state)
99 {
100 const char *state_names[] = {
101 "OMX_StateInvalid",
102 "OMX_StateLoaded",
103 "OMX_StateIdle",
104 "OMX_StateExecuting",
105 "OMX_StatePause",
106 "OMX_StateWaitForResources"
107 };
108 if (state < (sizeof(state_names) / sizeof(const char*))) {
109 MSG("OMX-CAMERA is in state %s", state_names[state]);
110 }
111 }
113 OMX_U32 frameRates[] = {1, 5, 15, 24, 30, 60};
116 /* Constructor - Open the Shared Library, containing the Camera Adapter and
117 * gen an instance of the Adapter.
118 */
119 OMXVisionCam::OMXVisionCam()
120 {
121 m_callback = NULL;
122 m_focuscallback = NULL;
123 pthread_mutex_init(&mFrameBufferLock, NULL);
124 pthread_mutex_init(&mUserRequestLock, NULL);
125 memset(&mCurGreContext, 0, sizeof(mCurGreContext));
126 }
128 int OMXVisionCam::init(void *cookie)
129 {
130 mFlushInProcess = false;
131 OMX_ERRORTYPE omxError = OMX_ErrorNone;
132 int greError = 0;
134 #if TIME_PROFILE
135 PopulateTimeProfiler();
136 #endif // TIME_PROFILE
138 MSG("OMXVisionCam::OMXVisionCam");
139 MSG("OMXVisionCam compiled: %s, %s", __DATE__, __TIME__ );
140 mLocalVersion = new OMX_VERSIONTYPE();
141 m_callback = NULL;
142 m_focuscallback = NULL;
144 m_cookie = cookie; // save the cookie value;
146 mLocalVersion->s.nVersionMajor = 1;
147 mLocalVersion->s.nVersionMinor = 1;
148 mLocalVersion->s.nRevision = 0 ;
149 mLocalVersion->s.nStep = 0;
151 sem_init(&mGreLocalSem, 0, 1); // set the max count
152 sem_wait(&mGreLocalSem); // pre-decrement the current count otherwise the first wait will pass early
153 sem_init(&mGreFocusSem, 0, 1); // set the max count
154 sem_wait(&mGreFocusSem); // pre-decrement the current count otherwise the first wait will pass early
156 // Initialize the Vision Core
157 MSG("Calling OMX_Init()");
158 OMX_CONVERT_RETURN_IF_ERROR(omxError, OMX_Init());
160 OMX_CALLBACKTYPE omxCallbacks;
161 omxCallbacks.EventHandler = OMXVisionCam::EventHandler;
162 omxCallbacks.EmptyBufferDone = OMXVisionCam::EmptyBufferDone;
163 omxCallbacks.FillBufferDone = OMXVisionCam::FillBufferDone;
165 memset( &(mCurGreContext), 0, sizeof( VCAM_ComponentContext ) );
167 mCurGreContext.mPortsInUse[VCAM_PORT_ALL] = OMX_ALL;
168 mCurGreContext.mPortsInUse[VCAM_PORT_PREVIEW] = VCAM_CAMERA_PORT_VIDEO_OUT_PREVIEW;
169 mCurGreContext.mPortsInUse[VCAM_PORT_VIDEO] = VCAM_CAMERA_PORT_VIDEO_OUT_VIDEO;
171 for( int i = VCAM_PORT_PREVIEW; i < VCAM_PORT_MAX; i++ )
172 {
173 mBuffersInUse[i].mBuffers = NULL;
174 mBuffersInUse[i].mNumberBuffers = 0;
175 mCurGreContext.mCameraPortParams[i].mColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
176 mCurGreContext.mCameraPortParams[i].mWidth = QVGA_WIDTH;
177 mCurGreContext.mCameraPortParams[i].mHeight = QVGA_HEIGHT;
178 mCurGreContext.mCameraPortParams[i].mFrameRate = INITIAL_FRAMERATE;
179 for(uint32_t buf = 0; buf < VCAM_NUM_BUFFERS; buf++ )
180 mCurGreContext.mCameraPortParams[i].mBufferHeader[buf] = NULL;
181 mFrameDescriptors[i] = NULL;
182 }
184 mCurGreContext.mHandleComp = NULL;
186 MSG("Calling OMX_GetHandle()");
187 OMX_CONVERT_RETURN_IF_ERROR(omxError,OMX_GetHandle(&( mCurGreContext.mHandleComp ),
188 (OMX_STRING)"OMX.TI.DUCATI1.VIDEO.CAMERA",
189 this ,
190 &omxCallbacks));
191 GetDucatiVersion();
193 OMX_CONVERT_RETURN_IF_ERROR(omxError,OMX_SendCommand(mCurGreContext.mHandleComp,
194 OMX_CommandPortDisable,
195 OMX_ALL,
196 NULL));
199 // #if defined(BLAZE) || defined(SDP) || defined(BLAZE_TABLET)
200 {
201 OMX_U32 pr = 4;
203 memcpy( &mVisionCamPriority.nVersion, mLocalVersion, sizeof(OMX_VERSIONTYPE));
204 mVisionCamPriority.nGroupID = CAMERA_GROUP_ID;
205 mVisionCamPriority.nGroupPriority = pr;
206 mVisionCamPriority.nSize = sizeof(OMX_PRIORITYMGMTTYPE);
208 omxError = OMX_SetParameter(mCurGreContext.mHandleComp, OMX_IndexParamPriorityMgmt ,&mVisionCamPriority);
209 }
210 // #else
211 // ERROR("No Priority Management is enabled on this platform!");
212 // #endif
214 pthread_mutex_lock(&mFrameCbData.mutex);
215 pthread_create(&mFrameThread, NULL, FrameThreadFunc, this);
216 mUseFramePackaging = false;
218 m_frameNum = 0;
219 mPreemptionState = VCAM_PREEMPT_INACTIVE;
220 mFaceDetectionEnabled = false;
221 mReturnToExecuting = false;
222 #ifdef _USE_GAMMA_RESET_HC_
223 mGammaResetPolulated = false;
224 #endif // _USE_GAMMA_RESET_HC_
226 return greError;
227 }
229 int OMXVisionCam::deinit()
230 {
231 int greError = 0;
232 OMX_ERRORTYPE omxError = OMX_ErrorNone;
234 // Free the handle for the Camera component
235 if (mCurGreContext.mHandleComp)
236 {
237 // free the handle
238 MSG("Calling OMX_FreeHandle(0x%08x)", (unsigned)(mCurGreContext.mHandleComp));
239 omxError = OMX_FreeHandle(mCurGreContext.mHandleComp);
240 greError = ConvertError(omxError);
241 mCurGreContext.mHandleComp = 0;
242 if( 0 != greError )
243 {
244 ERROR("ERROR: error freeing OMX handle.OMX_FreeHandle() returned 0x%x", omxError);
245 }
247 // Deinitialize the OMX Core
248 MSG("Calling OMX_Deinit()");
249 omxError = OMX_Deinit();
250 greError = ConvertError(omxError);
251 if( 0 != greError )
252 {
253 ERROR("ERROR: error in OMX_Deinit.OMX err: 0x%x", omxError);
254 }
255 }
257 mFrameCbData.frames.push_back(NULL);
258 pthread_mutex_unlock(&mFrameCbData.mutex);
259 pthread_join(mFrameThread, NULL);
261 #if TIME_PROFILE
262 for(int i = 0; i < VCAM_TIME_TARGET_MAX; i++)
263 if( mTimeProfiler[i] ) // dump and clear
264 delete mTimeProfiler[i];
265 #endif
267 delete mLocalVersion;
269 sem_destroy(&mGreLocalSem);
270 sem_destroy(&mGreFocusSem);
272 return greError;
273 }
275 /* Destructor - free all recources used by Vision Cam and from us */
276 OMXVisionCam::~OMXVisionCam()
277 {
278 pthread_mutex_destroy(&mFrameBufferLock);
279 pthread_mutex_destroy(&mUserRequestLock);
280 MSG("OMX Vision Cam is destroyed!");
281 }
283 /**
284 * This is used to get esier the state of component.
285 */
286 inline OMX_STATETYPE OMXVisionCam::getComponentState()
287 {
288 OMX_STATETYPE state = OMX_StateInvalid;
290 if( mCurGreContext.mHandleComp )
291 {
292 OMX_GetState( mCurGreContext.mHandleComp, &state );
293 }
294 PrintOMXState(state);
295 return state;
296 }
298 /**
299 * Initialisation of OMX_PARAM_PORTDEFINITIONTYPE
300 * needed for various configurations
301 */
302 inline OMX_ERRORTYPE OMXVisionCam::initPortCheck( OMX_PARAM_PORTDEFINITIONTYPE * portCheck , OMX_U32 portIndex )
303 {
304 OMX_ERRORTYPE omxError = OMX_ErrorNone;
305 OMX_STRUCT_INIT_PTR(portCheck, OMX_PARAM_PORTDEFINITIONTYPE, mLocalVersion)
307 if( VCAM_PORT_ALL < portIndex && VCAM_PORT_MAX > portIndex )
308 {
309 portCheck->nPortIndex = mCurGreContext.mPortsInUse[portIndex];
310 omxError = OMX_GetParameter(mCurGreContext.mHandleComp,
311 OMX_IndexParamPortDefinition,
312 portCheck);
313 MSG("PORT CHECK[%u], E:%d P:%d B#:%u %ux%u C:%d",
314 (uint32_t)portCheck->nPortIndex,
315 portCheck->bEnabled,
316 portCheck->bPopulated,
317 (uint32_t)portCheck->nBufferCountActual,
318 (uint32_t)portCheck->format.video.nFrameWidth,
319 (uint32_t)portCheck->format.video.nFrameHeight,
320 portCheck->format.video.eColorFormat);
322 }
323 else
324 omxError = OMX_ErrorBadParameter;
326 if( omxError != OMX_ErrorNone )
327 {
328 ERROR("OMX_GetParameter - 0x%x in initPortCheck(%lu)",
329 omxError, mCurGreContext.mPortsInUse[portIndex]);
330 }
331 return omxError;
332 }
333 /**
334 @brief Method to convert from OMX_ERRORTYPE to GesturError_e
335 @param error Any of the standard OMX error codes defined in the OpenMAX 1.x Specification.
336 @return int
337 */
338 int OMXVisionCam::ConvertError(OMX_ERRORTYPE error)
339 {
340 int status = 0;
341 switch(error)
342 {
343 case OMX_ErrorNone:
344 status = 0;
345 break;
346 case OMX_ErrorBadParameter:
347 status = -EINVAL;
348 break;
349 case OMX_ErrorIncorrectStateOperation:
350 status = -EBADE;
351 break;
352 case OMX_ErrorHardware:
353 status = -EIO;
354 break;
355 default:
356 status = -ESTALE; /* Something stupid */
357 break;
358 }
359 if (error != OMX_ErrorNone) {
360 ERROR("Converting OMX Error 0x%08x to int %d", error, status);
361 }
362 return status;
363 }
365 int OMXVisionCam::getLutValue( int searchVal, ValueTypeOrigin origin, const int lut[][2], int lutSize)
366 {
367 int idxToGet = (origin == VCAM_VALUE_TYPE ? OMX_VALUE_TYPE : VCAM_VALUE_TYPE );
368 for( int i = 0; i < lutSize; i++ )
369 {
370 if( lut[i][origin] == searchVal )
371 return lut[i][idxToGet];
372 }
374 return -EINVAL;
375 }
377 void OMXVisionCam::GetDucatiVersion()
378 {
379 if( mCurGreContext.mHandleComp )
380 {
381 OMX_VERSIONTYPE compVersion;
382 OMX_VERSIONTYPE specVersion;
383 char compName[128];
384 OMX_UUIDTYPE compUUID[128];
385 OMX_ERRORTYPE omxError = OMX_ErrorNone;
386 MSG("Querying Component Version!");
387 omxError = OMX_GetComponentVersion(mCurGreContext.mHandleComp,
388 compName,
389 &compVersion,
390 &specVersion,
391 compUUID);
392 if (omxError == OMX_ErrorNone)
393 {
394 MSG("\tComponent Name: [%s]", compName);
395 MSG("\tComponent Version: [%u]", (unsigned int)compVersion.nVersion);
396 MSG("\tSpec Version: [%u]", (unsigned int)specVersion.nVersion);
397 MSG("\tComponent UUID: [%s]", (char*)compUUID);
398 }
399 }
400 }
402 int OMXVisionCam::transitToState(OMX_STATETYPE targetState, serviceFunc transitionService, void * data )
403 {
404 int greError = 0;
405 OMX_ERRORTYPE omxError = OMX_ErrorNone;
406 sem_t sem; // this semaphore does not need to be global
408 if( OMX_StateInvalid == targetState )
409 return -EINVAL;
411 sem_init(&sem, 0, 1);
412 sem_wait(&sem); // predecrement so that the later wait will actually block
414 omxError = RegisterForEvent( mCurGreContext.mHandleComp,
415 OMX_EventCmdComplete,
416 OMX_CommandStateSet,
417 targetState,
418 &sem,
419 -1 // Infinite timeout
420 );
422 if( OMX_ErrorNone == omxError )
423 {
424 omxError = OMX_SendCommand( mCurGreContext.mHandleComp ,
425 OMX_CommandStateSet,
426 targetState,
427 NULL );
428 switch( omxError )
429 {
430 case OMX_ErrorNone:
431 {
432 if( transitionService )
433 {
434 greError = transitionService( this, data );
435 }
436 break;
437 }
439 case OMX_ErrorIncorrectStateTransition:
440 {
441 greError = -EINVAL;
442 break;
443 }
445 case OMX_ErrorInsufficientResources:
446 {
447 if( OMX_StateIdle == targetState )
448 {
449 mPreemptionState = VCAM_PREEMPT_WAIT_TO_START;
450 greError = PreemptionService();
451 }
452 break;
453 }
455 case OMX_ErrorSameState:
456 break;
458 default:
459 greError = ConvertError(omxError);
460 break;
461 }
463 if( greError != 0 || OMX_ErrorSameState == omxError )
464 {
465 // unregister the event
466 EventHandler( mCurGreContext.mHandleComp,
467 this,
468 (OMX_EVENTTYPE)OMX_EventCmdComplete,
469 (OMX_U32)OMX_CommandStateSet,
470 (OMX_U32)targetState,
471 NULL
472 );
473 }
474 else //( 0 == greError )
475 {
476 MSG("Waiting for state transition. State requested: %d", (int)targetState);
477 sem_wait(&sem);
478 MSG("Camera is now in state %d", (int)targetState);
479 }
480 }
482 sem_destroy(&sem);
484 return greError;
485 }
487 int OMXVisionCam::portEnableDisable( OMX_COMMANDTYPE enCmd, serviceFunc enablementService, VisionCamPort_e port )
488 {
489 int greError = 0;
490 OMX_ERRORTYPE omxError = OMX_ErrorNone;
492 OMX_PARAM_PORTDEFINITIONTYPE portCheck;
493 VCAM_PortParameters * portData = NULL;
495 mCurGreContext.mCameraPortParams[VCAM_PORT_ALL].mIsActive = true;
497 int32_t p;
498 LOOP_PORTS( port , p )
499 {
500 initPortCheck(&portCheck, p);
501 portData = &mCurGreContext.mCameraPortParams[p];
503 // check to see if the port is already enabled/disabled and that we wanted that state
504 if( (OMX_TRUE == portCheck.bEnabled) && (enCmd == OMX_CommandPortEnable) )
505 {
506 portData->mIsActive = true;
507 continue;
508 }
510 if( (OMX_FALSE == portCheck.bEnabled) && (enCmd == OMX_CommandPortDisable) )
511 {
512 portData->mIsActive = false;
513 continue;
514 }
516 // we wanted to transition from one state to the other
518 // ports with no buffers can't be enabled or disabled.
519 if( portData->mNumBufs == 0 )
520 continue;
522 // we have buffers, so enable/disable the port!
523 MSG("Registering for port enable/disable event");
524 omxError = RegisterForEvent( mCurGreContext.mHandleComp,
525 OMX_EventCmdComplete,
526 enCmd,
527 mCurGreContext.mPortsInUse[p],
528 &mGreLocalSem,
529 -1 /*Infinite timeout */
530 );
532 if( OMX_ErrorNone == omxError )
533 {
534 omxError = OMX_SendCommand( mCurGreContext.mHandleComp,
535 enCmd,
536 mCurGreContext.mPortsInUse[p],
537 NULL
538 );
539 }
541 if( enablementService && OMX_ErrorNone == omxError )
542 {
543 greError = enablementService( this, (void*)(&p) );
544 }
546 if( OMX_ErrorNone == omxError && 0 == greError )
547 {
548 sem_wait(&mGreLocalSem);
549 }
550 else
551 {
552 // unregister event
553 EventHandler( mCurGreContext.mHandleComp,
554 this,
555 (OMX_EVENTTYPE)OMX_EventCmdComplete,
556 (OMX_U32)enCmd,
557 (OMX_U32)mCurGreContext.mPortsInUse[p],
558 NULL
559 );
560 }
562 initPortCheck(&portCheck, p);
564 if( OMX_TRUE == portCheck.bEnabled )
565 {
566 portData->mIsActive = true;
567 mFramePackage.mExpectedFrames[p] = true;
568 }
569 else
570 {
571 portData->mIsActive = false;
572 mFramePackage.mExpectedFrames[p] = false;
573 }
574 }
576 mCurGreContext.mCameraPortParams[VCAM_PORT_ALL].mIsActive = true;
577 int32_t p2;
578 LOOP_PORTS(VCAM_PORT_ALL, p2)
579 {
580 if( mCurGreContext.mCameraPortParams[p2].mIsActive == false )
581 {
582 mCurGreContext.mCameraPortParams[VCAM_PORT_ALL].mIsActive = false;
583 break;
584 }
585 }
587 return greError;
588 }
590 int OMXVisionCam::fillPortBuffers( VisionCamPort_e port )
591 {
592 int greError = 0;
593 OMX_ERRORTYPE omxError = OMX_ErrorNone;
594 VCAM_PortParameters *portData = NULL;
596 portData = &mCurGreContext.mCameraPortParams[port];
597 if (portData->mIsActive == true) {
599 for( int index = 0; index < portData->mNumBufs; index++ )
600 {
601 if( portData && portData->mBufferHeader[index] )
602 {
603 MSG("FILL BUFF HDR[%d]:%p PORT:%u", index, portData->mBufferHeader[index], (uint32_t)mCurGreContext.mPortsInUse[port]);
604 omxError = OMX_FillThisBuffer(mCurGreContext.mHandleComp,
605 (OMX_BUFFERHEADERTYPE*)( portData->mBufferHeader[index]));
606 if (omxError != OMX_ErrorNone)
607 {
608 ERROR("OMX_FillThisBuffer() returned error 0x%x", omxError );
609 greError = ConvertError(omxError);
610 break;
611 }
612 }
613 else
614 {
615 greError = -ENOMEM;
616 }
617 }
618 }
619 else
620 {
621 greError = -EBADE;
622 }
623 if (omxError != OMX_ErrorNone)
624 {
625 greError = ConvertError(omxError);
626 }
628 return greError;
629 }
631 int OMXVisionCam::freePortBuffers( VisionCamPort_e port )
632 {
633 int greError = 0;
634 OMX_ERRORTYPE omxError = OMX_ErrorNone;
635 VCAM_PortParameters *portData = NULL;
637 AutoLock lock(&mFrameBufferLock);
639 int32_t p;
640 LOOP_PORTS( port , p )
641 {
642 portData = &mCurGreContext.mCameraPortParams[p];
643 for( int buff = 0; buff < portData->mNumBufs; buff++ )
644 {
645 omxError = OMX_FreeBuffer( mCurGreContext.mHandleComp,
646 mCurGreContext.mPortsInUse[p],
647 portData->mBufferHeader[buff]
648 );
649 portData->mBufferHeader[buff] = NULL;
650 if (omxError != OMX_ErrorNone)
651 {
652 ERROR("OMX_FreeBuffer() returned error 0x%x", omxError );
653 greError = ConvertError(omxError);
654 break;
655 }
656 }
657 }
659 return greError;
660 }
662 int OMXVisionCam::populatePort( VisionCamPort_e port )
663 {
664 int greError = 0;
665 OMX_ERRORTYPE omxError = OMX_ErrorNone;
666 VCAM_PortParameters * data = NULL;
668 int32_t p;
669 LOOP_PORTS( port , p )
670 {
671 OMX_TI_PARAM_USEBUFFERDESCRIPTOR desc;
672 OMX_STRUCT_INIT(desc, OMX_TI_PARAM_USEBUFFERDESCRIPTOR, mLocalVersion);
673 // No idea
674 desc.nPortIndex = mCurGreContext.mPortsInUse[p];
675 // For 2D buffer
676 desc.bEnabled = OMX_FALSE;
677 omxError = OMX_SetParameter(mCurGreContext.mHandleComp, (OMX_INDEXTYPE) OMX_TI_IndexUseDmaBuffers, &desc);
678 MSG("Configuring port %u for DMAbuf handles (err=0x%08x)", p, omxError);
679 data = &mCurGreContext.mCameraPortParams[p];
681 for( int indBuff = 0; indBuff < data->mNumBufs; indBuff++ )
682 {
683 OMX_BUFFERHEADERTYPE *pBufferHdr;
684 OMX_U8 *buffer = NULL;
686 // Pass array of file descriptors
687 buffer = (OMX_U8*)mBuffersInUse[p].mBuffers[indBuff].fd;
688 MSG("VCAM: Using FDs %d and %d", ((int*) buffer)[0], ((int*) buffer)[1]);
689 omxError = OMX_UseBuffer( mCurGreContext.mHandleComp,
690 &pBufferHdr,
691 mCurGreContext.mPortsInUse[p],
692 0,
693 data->mBufSize,
694 buffer );
696 if( OMX_ErrorNone != omxError )
697 {
698 ERROR("VCAM: ERROR: OMX_UseBuffer() returned 0x%x ( %d )", omxError, omxError);
699 greError = ConvertError(omxError);
700 break;
701 }
703 pBufferHdr->pAppPrivate = (OMX_PTR)&mBuffersInUse[p].mBuffers[indBuff];
704 MSG("pAppPrivate=%p mBuffers[indBuff]=%p", pBufferHdr->pAppPrivate, &mBuffersInUse[p].mBuffers[indBuff]);
705 pBufferHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
706 memcpy( &(pBufferHdr->nVersion), mLocalVersion, sizeof( OMX_VERSIONTYPE ) );
708 data->mBufferHeader[indBuff] = pBufferHdr;
710 if( NULL == mFrameDescriptors[p][indBuff]->mFrameBuff )
711 mFrameDescriptors[p][indBuff]->mFrameBuff = pBufferHdr->pAppPrivate;
712 }
713 }
715 return greError;
716 }
718 int OMXVisionCam::useBuffers(BufferMeta* meta, uint32_t numImages, VisionCamPort_e port )
719 {
720 int greError = 0;
722 if ( numImages == 0 || port <= VCAM_PORT_ALL || port >= VCAM_PORT_MAX)
723 {
724 ERROR("Invalid parameters to useBuffers()");
725 return -EINVAL;
726 }
728 // alloc the array for frame descriptors
729 if( !mFrameDescriptors[port] )
730 {
731 mFrameDescriptors[port] = new VisionCamFrame* [numImages];
732 if( NULL == mFrameDescriptors[port] )
733 {
734 greError = -ENOMEM;
735 }
737 for( uint32_t i = 0; i < numImages && 0 == greError; i++ )
738 {
739 mFrameDescriptors[port][i] = new VisionCamFrame();
741 if( mFrameDescriptors[port][i] )
742 {
743 mFrameDescriptors[port][i]->clear();
744 }
745 else
746 {
747 while( i )
748 delete mFrameDescriptors[port][--i];
750 delete [] mFrameDescriptors[port];
751 mFrameDescriptors[port] = NULL;
753 greError = -ENOMEM;
754 }
755 }
756 }
758 if( 0 == greError )
759 {
760 VCAM_PortParameters * data = &mCurGreContext.mCameraPortParams[port];
762 mBuffersInUse[port].mBuffers = meta;
763 mBuffersInUse[port].mNumberBuffers = (unsigned)numImages;
765 data->mNumBufs = mBuffersInUse[port].mNumberBuffers;
766 data->mStride = mBuffersInUse[port].mBuffers[0].buffer->pitches[0];
768 if( OMX_StateIdle != getComponentState() )
769 {
770 greError = transitToState( OMX_StateIdle );
771 }
772 }
774 return greError;
775 }
777 int OMXVisionCam::flushBuffers( VisionCamPort_e port)
778 {
779 int greError = 0;
780 OMX_ERRORTYPE omxError = OMX_ErrorNone;
782 if( OMX_StateExecuting != getComponentState() )
783 {
784 return greError;
785 }
787 int32_t p;
788 LOOP_PORTS( port , p )
789 {
790 sem_t sem;
791 sem_init(&sem, 0, 1);
792 sem_wait(&sem); // predecrement so that the next wait won't fire ahead of time.
793 omxError = RegisterForEvent(mCurGreContext.mHandleComp,
794 OMX_EventCmdComplete,
795 OMX_CommandFlush,
796 mCurGreContext.mPortsInUse[p],
797 &sem,
798 -1 /*Infinite timeout*/
799 );
801 if( OMX_ErrorNone == omxError )
802 {
803 omxError = OMX_SendCommand( mCurGreContext.mHandleComp,
804 OMX_CommandFlush,
805 mCurGreContext.mPortsInUse[p],
806 NULL );
807 }
809 if( OMX_ErrorNone == omxError )
810 {
811 sem_wait(&sem);
812 }
814 sem_destroy(&sem);
815 }
816 return greError;
817 }
819 /* Send command to Camera */
820 int OMXVisionCam::sendCommand( VisionCamCmd_e cmdId, void *param, uint32_t size, VisionCamPort_e port)
821 {
822 int greError = 0;
823 OMX_ERRORTYPE omxError = OMX_ErrorNone;
825 AutoLock lock(&mUserRequestLock);
827 MSG("SEND CMD: 0x%04x, %p, %zu, %d", cmdId, param, size, port);
829 switch (cmdId)
830 {
831 case VCAM_CMD_PREVIEW_START:
832 {
833 greError = startPreview(port);
834 break;
835 }
837 case VCAM_CMD_PREVIEW_STOP:
838 {
839 if( OMX_StateExecuting == getComponentState() )
840 greError = stopPreview(port);
841 else
842 greError = -EBADE;
843 break;
844 }
846 case VCAM_EXTRA_DATA_START:
847 {
848 int i, EDataType;
849 for( i = 0; i < VCAM_EXTRA_DATA_TYPE_MAX; i++ )
850 {
851 if( ExtraDataTypeLUT[ i ][ 0 ] == *( (int*)param ) )
852 {
853 EDataType = ExtraDataTypeLUT[ i ][ 1 ];
854 break;
855 }
856 }
857 if( i == VCAM_EXTRA_DATA_TYPE_MAX )
858 {
859 greError = -EINVAL;
860 break;
861 }
863 OMX_CONFIG_EXTRADATATYPE xData;
864 OMX_STRUCT_INIT(xData, OMX_CONFIG_EXTRADATATYPE, mLocalVersion);
865 #if defined(TUNA) || defined(MAGURO)
866 xData.eCameraView = OMX_2D_Prv;
867 #endif
868 if( OMX_ExtraDataNone == EDataType )
869 {
870 for( int i = 1; i < VCAM_EXTRA_DATA_TYPE_MAX; i++ )
871 {// stop extra data transfer for all types of data
872 if( 0 == greError )
873 {
874 xData.eExtraDataType = (OMX_EXT_EXTRADATATYPE)ExtraDataTypeLUT[i][1];
875 xData.bEnable = OMX_FALSE;
876 int32_t p;
877 LOOP_PORTS( port, p )
878 {
879 xData.nPortIndex = p;
880 omxError = OMX_SetConfig( mCurGreContext.mHandleComp, ( OMX_INDEXTYPE )OMX_IndexConfigOtherExtraDataControl, &xData);
881 }
882 }
883 }
884 }
885 else
886 {
887 if( 0 == greError )
888 {
889 xData.eExtraDataType = ( OMX_EXT_EXTRADATATYPE )EDataType;
890 xData.bEnable = OMX_TRUE;
892 omxError = OMX_SetConfig( mCurGreContext.mHandleComp, ( OMX_INDEXTYPE )OMX_IndexConfigOtherExtraDataControl, &xData);
893 }
894 }
895 break;
896 }
898 case VCAM_EXTRA_DATA_STOP:
899 {
900 int i, EDataType;
901 for( i = 0; i < VCAM_EXTRA_DATA_TYPE_MAX; i++ )
902 {
903 if( ExtraDataTypeLUT[ i ][ 0 ] == *( (int*)param ) )
904 {
905 EDataType = ExtraDataTypeLUT[ i ][ 1 ];
906 break;
907 }
908 }
909 if( i == VCAM_EXTRA_DATA_TYPE_MAX )
910 {
911 greError = -EINVAL;
912 break;
913 }
915 OMX_CONFIG_EXTRADATATYPE xData;
916 OMX_STRUCT_INIT(xData, OMX_CONFIG_EXTRADATATYPE, mLocalVersion);
917 #if defined(TUNA) || defined(MAGURO)
918 xData.eCameraView = OMX_2D_Prv;
919 #endif
920 if( OMX_ExtraDataNone == EDataType )
921 {
922 for( int i = 1; i < VCAM_EXTRA_DATA_TYPE_MAX; i++ )
923 {
924 // greError = OMX_GetConfig( mCurGreContext.mHandleComp, ( OMX_INDEXTYPE )OMX_IndexConfigOtherExtraDataControl, &xData);
925 if( 0 == greError )
926 {
927 xData.eExtraDataType = (OMX_EXT_EXTRADATATYPE)ExtraDataTypeLUT[i][1];
928 xData.bEnable = OMX_FALSE;
929 int32_t p;
930 LOOP_PORTS(port, p)
931 {
932 xData.nPortIndex = p;
933 omxError = OMX_SetConfig( mCurGreContext.mHandleComp, ( OMX_INDEXTYPE )OMX_IndexConfigOtherExtraDataControl, &xData);
934 }
935 }
936 }
937 }
938 else
939 {
940 if( 0 == greError )
941 {
942 xData.eExtraDataType = ( OMX_EXT_EXTRADATATYPE )EDataType;
943 // greError = OMX_GetConfig( mCurGreContext.mHandleComp, ( OMX_INDEXTYPE )OMX_IndexConfigOtherExtraDataControl, &xData);
945 xData.bEnable = OMX_FALSE;
947 omxError = OMX_SetConfig( mCurGreContext.mHandleComp, ( OMX_INDEXTYPE )OMX_IndexConfigOtherExtraDataControl, &xData);
948 }
949 }
950 break;
951 }
953 case VCAM_CMD_LOCK_AE:
954 case VCAM_CMD_LOCK_AWB:
955 {
956 OMX_INDEXTYPE index;
957 OMX_IMAGE_CONFIG_LOCKTYPE lockCfg;
958 OMX_STRUCT_INIT(lockCfg, OMX_IMAGE_CONFIG_LOCKTYPE, mLocalVersion);
959 if (VCAM_CMD_LOCK_AE == cmdId)
960 {
961 index = (OMX_INDEXTYPE)OMX_IndexConfigImageExposureLock;
962 }
963 else if (VCAM_CMD_LOCK_AWB == cmdId)
964 {
965 index = (OMX_INDEXTYPE)OMX_IndexConfigImageWhiteBalanceLock;
966 }
967 else
968 {
969 greError = -EINVAL;
970 break;
971 }
972 OMX_GetConfig(mCurGreContext.mHandleComp, index, &lockCfg);
973 lockCfg.bLock = *((OMX_BOOL*)param);
974 OMX_SetConfig(mCurGreContext.mHandleComp, index, &lockCfg);
975 break;
976 }
977 #if TIME_PROFILE
978 case VCAM_DUMP_TIMES:
979 {
980 for( int i = 0; i < VCAM_TIME_TARGET_MAX; i++ )
981 if( mTimeProfiler[i] )
982 mTimeProfiler[i]->dump();
983 break;
984 }
985 #endif // TIME_PROFILE
986 case VCAM_CMD_FACE_DETECTION:
987 {
988 mFaceDetectionEnabled = *((bool*)(param));
989 enableFaceDetect(port);
990 break;
991 }
992 #if ( defined(DUCATI_1_5) || defined(DUCATI_2_0) ) && defined(OMX_CAMERA_SUPPORTS_MANUAL_CONTROLS)
993 case VCAM_CMD_FREEZE_AWB_PARAMS:
994 {
995 OMX_TI_CONFIG_FREEZE_AWB wbFreeze;
996 OMX_STRUCT_INIT( wbFreeze, OMX_TI_CONFIG_FREEZE_AWB, mLocalVersion);
997 wbFreeze.nTimeDelay = *((uint32_t*)param);
999 omxError = OMX_SetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexConfigFreezeAWB, &wbFreeze );
1000 break;
1001 }
1003 case VCAM_CMD_FREEZE_AGC_PARAMS:
1004 {
1005 OMX_TI_CONFIG_FREEZE_AE aeFreeze;
1006 OMX_STRUCT_INIT( aeFreeze, OMX_TI_CONFIG_FREEZE_AE, mLocalVersion);
1007 aeFreeze.nTimeDelay = *((uint32_t*)param);
1009 omxError = OMX_SetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexConfigFreezeAutoExp, &aeFreeze );
1010 break;
1011 }
1012 #endif
1013 case VCAM_CMD_SET_CLIENT_NOTIFICATION_CALLBACK:
1014 {
1015 mClientNotifier.mNotificationCallback = (VisionCamClientNotifier::VisionCamClientNotifierCallback)(param);
1016 break;
1017 }
1019 case VCAM_CMD_PACK_FRAMES:
1020 {
1021 mUseFramePackaging = *((bool*)param);
1022 break;
1023 }
1025 default:
1026 {
1027 ERROR("Impossible command id requested: %d", cmdId);
1028 ERROR("see VisionCamParam_e for possible command ids");
1029 greError = -EINVAL;
1030 }
1031 }
1033 if (greError == 0)
1034 greError = ConvertError(omxError);
1036 if (greError != 0)
1037 {
1038 ERROR("OMXVisionCam::sendCommand() exits with error %d for command id %d", greError, cmdId);
1039 }
1041 return greError;
1042 }
1044 /*
1045 * APIs to configure Vision Cam
1046 */
1047 int OMXVisionCam::setParameter( VisionCamParam_e paramId, void* param, uint32_t size, VisionCamPort_e port)
1048 {
1049 int greError = 0;
1050 OMX_ERRORTYPE omxError = OMX_ErrorNone;
1052 AutoLock lock(&mUserRequestLock);
1054 if (param == NULL || size == 0 || port >= VCAM_PORT_MAX)
1055 {
1056 ERROR("NULL param pointer passed to %s()",__func__);
1057 return -EINVAL;
1058 }
1059 else
1060 {
1061 MSG("SET PARAM: 0x%04x, %p, %zu (0x%08x), %d", paramId, param, size, (size==4?*(uint32_t *)param:0), port);
1062 }
1064 if (getComponentState() == OMX_StateInvalid)
1065 return -EBADE;
1067 switch( paramId )
1068 {
1069 case VCAM_PARAM_HEIGHT:
1070 {
1071 int32_t p;
1072 LOOP_PORTS( port , p )
1073 mCurGreContext.mCameraPortParams[p].mHeight = *((OMX_U32*)param);
1074 break;
1075 }
1077 case VCAM_PARAM_WIDTH:
1078 {
1079 int32_t p;
1080 LOOP_PORTS( port , p )
1081 mCurGreContext.mCameraPortParams[p].mWidth = *((OMX_U32*)param);
1082 break;
1083 }
1086 case VCAM_PARAM_COLOR_SPACE_FOURCC:
1087 {
1088 uint32_t color = *((uint32_t*)param);
1089 switch (color) {
1090 case FOURCC('U','Y','V','Y'):
1091 case FOURCC('Y','U','Y','V'):
1092 mCurGreContext.mCameraPortParams[port].mColorFormat =
1093 OMX_COLOR_FormatCbYCrY;
1094 break;
1095 case FOURCC('N','V','1','2'):
1096 mCurGreContext.mCameraPortParams[port].mColorFormat =
1097 OMX_COLOR_FormatYUV420SemiPlanar;
1098 break;
1099 default:
1100 greError = -EINVAL;
1101 }
1102 if (greError == 0) {
1103 int32_t p;
1104 LOOP_PORTS(port , p) {
1105 OMX_PARAM_PORTDEFINITIONTYPE portCheck;
1106 omxError = initPortCheck( &portCheck, p );
1107 portCheck.format.video.eColorFormat =
1108 mCurGreContext.mCameraPortParams[port].mColorFormat;
1109 omxError = OMX_SetParameter(mCurGreContext.mHandleComp,
1110 OMX_IndexParamPortDefinition, &portCheck);
1111 }
1112 }
1113 break;
1114 }
1116 case VCAM_PARAM_DO_AUTOFOCUS:
1117 {
1118 if (OMX_StateExecuting == getComponentState())
1119 {
1120 greError = startAutoFocus( *((VisionCamFocusMode*)param) );
1121 }
1122 else
1123 {
1124 greError = ConvertError(OMX_ErrorIncorrectStateOperation);
1125 }
1126 break;
1127 }
1129 case VCAM_PARAM_DO_MANUALFOCUS:
1130 {
1131 if (OMX_StateExecuting == getComponentState())
1132 {
1133 mManualFocusDistance = *((uint32_t*)param);
1134 greError = startAutoFocus( VCAM_FOCUS_CONTROL_ON );
1135 }
1136 else
1137 {
1138 greError = ConvertError(OMX_ErrorIncorrectStateOperation);
1139 }
1140 break;
1141 }
1143 case VCAM_PARAM_BRIGHTNESS:
1144 {
1145 OMX_CONFIG_BRIGHTNESSTYPE brightness;
1146 brightness.nSize = sizeof(OMX_CONFIG_BRIGHTNESSTYPE);
1147 brightness.nBrightness = *((int*)param);
1148 memcpy( &brightness.nVersion, mLocalVersion, sizeof(mLocalVersion) );
1150 int32_t p = port;
1151 // LOOP_PORTS( port , p )
1152 {
1153 brightness.nPortIndex = mCurGreContext.mPortsInUse[p];
1154 omxError = OMX_SetConfig( mCurGreContext.mHandleComp, OMX_IndexConfigCommonBrightness, &brightness);
1155 }
1156 break;
1157 }
1159 case VCAM_PARAM_CONTRAST:
1160 {
1161 OMX_CONFIG_CONTRASTTYPE contrast;
1162 contrast.nSize = sizeof( OMX_CONFIG_CONTRASTTYPE );
1163 contrast.nContrast = *((int*)param);
1164 memcpy( &contrast.nVersion, mLocalVersion, sizeof(mLocalVersion) );
1166 int32_t p = port;
1167 // LOOP_PORTS( port , p )
1168 {
1169 contrast.nPortIndex = mCurGreContext.mPortsInUse[p];
1170 omxError = OMX_SetConfig( mCurGreContext.mHandleComp, OMX_IndexConfigCommonContrast, &contrast);
1171 }
1172 break;
1173 }
1175 case VCAM_PARAM_SHARPNESS:
1176 {
1177 OMX_IMAGE_CONFIG_PROCESSINGLEVELTYPE procSharpness;
1178 procSharpness.nSize = sizeof( OMX_IMAGE_CONFIG_PROCESSINGLEVELTYPE );
1179 procSharpness.nLevel = *((int*)param);
1180 memcpy( &procSharpness.nVersion, mLocalVersion, sizeof(mLocalVersion) );
1182 if( procSharpness.nLevel == 0 )
1183 procSharpness.bAuto = OMX_TRUE;
1184 else
1185 procSharpness.bAuto = OMX_FALSE;
1187 int32_t p = port;
1188 // LOOP_PORTS( port , p )
1189 {
1190 procSharpness.nPortIndex = mCurGreContext.mPortsInUse[p];
1191 omxError = OMX_SetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_IndexConfigSharpeningLevel, &procSharpness);
1192 }
1193 break;
1194 }
1196 case VCAM_PARAM_SATURATION:
1197 {
1198 OMX_CONFIG_SATURATIONTYPE saturation;
1199 saturation.nSize = sizeof(OMX_CONFIG_SATURATIONTYPE);
1200 saturation.nSaturation = *((int*)param);
1201 memcpy( &saturation.nVersion, mLocalVersion, sizeof(mLocalVersion) );
1203 int32_t p = port;
1204 // LOOP_PORTS( port , p )
1205 {
1206 saturation.nPortIndex = mCurGreContext.mPortsInUse[p];
1207 omxError = OMX_SetConfig( mCurGreContext.mHandleComp,
1208 OMX_IndexConfigCommonSaturation,
1209 &saturation
1210 );
1211 }
1212 break;
1213 }
1215 case VCAM_PARAM_FPS_FIXED:
1216 {
1217 bool enableAgain[VCAM_PORT_MAX];
1219 int32_t p;
1220 LOOP_PORTS(VCAM_PORT_ALL , p)
1221 enableAgain[p] = mCurGreContext.mCameraPortParams[p].mIsActive;
1223 stopPreview(VCAM_PORT_ALL);
1224 int32_t i;
1225 LOOP_PORTS(VCAM_PORT_ALL , i)
1226 {
1227 mCurGreContext.mCameraPortParams[i].mFrameRate = (*((int*)param));
1228 if( enableAgain[i] )
1229 startPreview( (VisionCamPort_e)i );
1230 }
1232 break;
1233 }
1235 case VCAM_PARAM_FPS_VAR:
1236 {
1237 VisionCamVarFramerateType varFrate;
1238 memcpy( &varFrate , param , sizeof( VisionCamVarFramerateType ) );
1240 bool enableAgain[VCAM_PORT_MAX];
1242 int32_t p;
1243 LOOP_PORTS( VCAM_PORT_ALL , p )
1244 {
1245 enableAgain[p] = mCurGreContext.mCameraPortParams[p].mIsActive;
1246 }
1248 stopPreview(VCAM_PORT_ALL);
1250 if( varFrate.mMin != 0 )
1251 {
1252 // @todo implement when needed OMX interface is present
1253 varFrate = varFrate;
1254 }
1256 int32_t i;
1257 LOOP_PORTS( VCAM_PORT_ALL , i )
1258 {
1259 mCurGreContext.mCameraPortParams[i].mFrameRate = varFrate.mMax;
1260 if( enableAgain[i] )
1261 startPreview( (VisionCamPort_e)i );
1262 }
1263 break;
1264 }
1266 case VCAM_PARAM_FLICKER:
1267 {
1268 OMX_CONFIG_FLICKERCANCELTYPE flicker;
1269 flicker.nSize = sizeof( OMX_CONFIG_FLICKERCANCELTYPE );
1270 memcpy( &flicker.nVersion, mLocalVersion, sizeof(mLocalVersion) );
1271 flicker.eFlickerCancel = *(OMX_COMMONFLICKERCANCELTYPE *)param;
1273 int32_t p = port;
1274 // LOOP_PORTS( VCAM_PORT_ALL , p )
1275 {
1276 flicker.nPortIndex = mCurGreContext.mPortsInUse[p];
1277 omxError = OMX_SetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_IndexConfigFlickerCancel, &flicker );
1278 }
1279 break;
1280 }
1282 case VCAM_PARAM_CROP:
1283 {
1284 OMX_CONFIG_RECTTYPE crop;
1285 crop.nSize = sizeof( OMX_CONFIG_RECTTYPE );
1286 crop.nLeft = ((VisionCamRectType*)param)->mLeft;
1287 crop.nTop = ((VisionCamRectType*)param)->mTop;
1288 crop.nWidth = ((VisionCamRectType*)param)->mWidth;
1289 crop.nHeight = ((VisionCamRectType*)param)->mHeight;
1290 memcpy( &crop.nVersion, mLocalVersion, sizeof(mLocalVersion) );
1292 int32_t p = port;
1293 // LOOP_PORTS( port , p )
1294 {
1295 crop.nPortIndex = mCurGreContext.mPortsInUse[p];
1296 omxError = OMX_SetConfig( mCurGreContext.mHandleComp, OMX_IndexConfigCommonOutputCrop, &crop );
1297 }
1298 break;
1299 }
1301 case VCAM_PARAM_STEREO_INFO:
1302 {
1303 VisionCamStereoInfo *info = (VisionCamStereoInfo *)param;
1304 OMX_TI_FRAMELAYOUTTYPE frameLayout;
1305 OMX_STRUCT_INIT(frameLayout, OMX_TI_FRAMELAYOUTTYPE, mLocalVersion);
1306 OMX_TI_CONFIG_CONVERGENCETYPE acParams;
1307 OMX_STRUCT_INIT(acParams, OMX_TI_CONFIG_CONVERGENCETYPE, mLocalVersion);
1308 if ( info && size == sizeof(VisionCamStereoInfo))
1309 {
1310 int32_t p = port;
1311 // LOOP_PORTS( port , p )
1312 {
1313 frameLayout.nPortIndex = mCurGreContext.mPortsInUse[p];
1314 MSG("Stereo Info: Layout %u, SubSampling: %u", info->layout, info->subsampling);
1316 frameLayout.eFrameLayout = (OMX_TI_STEREOFRAMELAYOUTTYPE)getLutValue( (int)info->layout, VCAM_VALUE_TYPE,
1317 StereoLayoutLUT, ARR_SIZE(StereoLayoutLUT)
1318 );
1319 if (info->layout == VCAM_STEREO_LAYOUT_TOPBOTTOM)
1320 frameLayout.eFrameLayout = OMX_TI_StereoFrameLayoutTopBottom;
1321 else if (info->layout == VCAM_STEREO_LAYOUT_LEFTRIGHT)
1322 frameLayout.eFrameLayout = OMX_TI_StereoFrameLayoutLeftRight;
1323 frameLayout.nSubsampleRatio = info->subsampling << 7; // in Q15.7 format
1324 omxError = OMX_SetParameter( mCurGreContext.mHandleComp,
1325 (OMX_INDEXTYPE)OMX_TI_IndexParamStereoFrmLayout,
1326 &frameLayout
1327 );
1329 if( OMX_ErrorNone == omxError )
1330 {
1331 acParams.nPortIndex = mCurGreContext.mPortsInUse[p];
1333 acParams.nManualConverence = 0;
1334 acParams.eACMode = OMX_TI_AutoConvergenceModeDisable;
1336 omxError = OMX_SetConfig( mCurGreContext.mHandleComp,
1337 (OMX_INDEXTYPE)OMX_TI_IndexConfigAutoConvergence,
1338 &acParams
1339 );
1340 if( OMX_ErrorNone != omxError )
1341 {
1342 ERROR("ERROR OMXVisionCam: Failed to disable auto convergence.");
1343 }
1344 }
1345 else
1346 {
1347 ERROR("ERROR OMXVisionCam: Failed to set stero layout");
1348 }
1349 }
1350 }
1351 else
1352 {
1353 ERROR("ERROR OMXVisionCam: attempt to set param with id VCAM_PARAM_STEREO_INFO with an invalid args");
1354 greError = -EINVAL;
1355 }
1356 break;
1357 }
1359 case VCAM_PARAM_CAP_MODE:
1360 {
1361 if (param != NULL)
1362 {
1363 VisionCamCaptureMode mode = *(VisionCamCaptureMode *)param;
1365 OMX_CONFIG_CAMOPERATINGMODETYPE opMode;
1366 opMode.nSize = sizeof( OMX_CONFIG_CAMOPERATINGMODETYPE );
1367 memcpy( &opMode.nVersion, mLocalVersion, sizeof(mLocalVersion) );
1369 opMode.eCamOperatingMode = (OMX_CAMOPERATINGMODETYPE)getLutValue(mode, VCAM_VALUE_TYPE, CaptureModeLUT, ARR_SIZE(CaptureModeLUT) );
1371 MSG("Requested VisionCamCaptureMode %d", mode);
1372 MSG("Requested OMX_CAMOPERATINGMODETYPE %d", opMode.eCamOperatingMode);
1374 bool enableAgain[VCAM_PORT_MAX];
1376 int32_t p;// mark and stop all working ports
1377 LOOP_PORTS( VCAM_PORT_ALL , p )
1378 {
1379 enableAgain[p] = mCurGreContext.mCameraPortParams[p].mIsActive;
1380 if( mCurGreContext.mCameraPortParams[p].mIsActive )
1381 portEnableDisable(OMX_CommandPortDisable, freePortBuffersSrvc, (VisionCamPort_e)p );
1382 }
1384 int32_t oldstate = getComponentState();
1385 for(int32_t st = oldstate - 1; st >= OMX_StateLoaded; st--)
1386 {
1387 if( OMX_StatePause == oldstate && OMX_StateExecuting == st )
1388 continue;
1390 transitToState( (OMX_STATETYPE)st );
1391 }
1393 if( OMX_StateLoaded == getComponentState() || OMX_StateWaitForResources == getComponentState() )
1394 {
1395 omxError = OMX_SetParameter( mCurGreContext.mHandleComp,
1396 (OMX_INDEXTYPE)OMX_IndexCameraOperatingMode,
1397 &opMode );
1399 greError = ConvertError(omxError);
1400 }
1402 for(int32_t st = (1 + getComponentState()); st <= oldstate; st++)
1403 {
1404 if( OMX_StatePause == oldstate && OMX_StateExecuting == st)
1405 continue;
1407 transitToState( (OMX_STATETYPE)st );
1408 }
1410 int32_t por;
1411 LOOP_PORTS( VCAM_PORT_ALL , por )
1412 if( enableAgain[por])
1413 {
1414 portEnableDisable(OMX_CommandPortEnable, populatePortSrvc, (VisionCamPort_e)por);
1415 fillPortBuffers((VisionCamPort_e)por);
1416 }
1417 }
1418 else
1419 greError = -EINVAL;
1420 break;
1421 }
1423 case VCAM_PARAM_SENSOR_SELECT:
1424 {
1425 if (param != NULL)
1426 {
1427 OMX_CONFIG_SENSORSELECTTYPE sensor;
1428 OMX_STRUCT_INIT(sensor, OMX_CONFIG_SENSORSELECTTYPE, mLocalVersion);
1429 sensor.nPortIndex = mCurGreContext.mPortsInUse[VCAM_PORT_ALL];
1430 sensor.eSensor = *((OMX_SENSORSELECT*)param);
1431 MSG("Selecting sensor index = %u", sensor.eSensor);
1432 omxError = OMX_SetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexConfigSensorSelect, &sensor);
1433 }
1434 else
1435 greError = -EINVAL;
1436 break;
1437 }
1439 case VCAM_PARAM_EXPOSURE_COMPENSATION:
1440 {
1441 OMX_CONFIG_EXPOSUREVALUETYPE expValues;
1442 OMX_STRUCT_INIT(expValues, OMX_CONFIG_EXPOSUREVALUETYPE, mLocalVersion);
1444 memcpy( &expValues.nVersion , mLocalVersion , sizeof( *mLocalVersion ) );
1445 omxError = OMX_GetConfig( mCurGreContext.mHandleComp , OMX_IndexConfigCommonExposureValue , &expValues );
1447 if( OMX_ErrorNone == omxError )
1448 {
1449 int compVal = *((int*)param);
1450 expValues.xEVCompensation = ( compVal * ( 1 << 16 ) ) / 10;
1452 int32_t p = port;
1453 // LOOP_PORTS( port , p )
1454 {
1455 expValues.nPortIndex = mCurGreContext.mPortsInUse[p];
1456 omxError = OMX_SetConfig( mCurGreContext.mHandleComp , OMX_IndexConfigCommonExposureValue , &expValues );
1457 }
1458 }
1459 break;
1460 }
1462 case VCAM_PARAM_RESOLUTION:
1463 {
1464 if( param != NULL )
1465 {
1466 int res;
1468 if( *((int*)param) < 0 || *((int*)param) >= VCAM_RESOL_MAX )
1469 {
1470 greError = -EINVAL;
1471 break;
1472 }
1474 int32_t p = port;
1475 LOOP_PORTS( port , p )
1476 {
1477 res = *((int*)param);
1478 if( 0 == greError )
1479 if( mCurGreContext.mCameraPortParams[p].mIsActive )
1480 greError = -EBADE;
1482 if( 0 == greError )
1483 {
1484 if( VCAM_PORT_VIDEO == p
1485 && ( VisionCamResolutions[res].mWidth > VisionCamResolutions[VCAM_RES_VGA].mWidth
1486 || VisionCamResolutions[res].mHeight > VisionCamResolutions[VCAM_RES_VGA].mHeight ) )
1487 {
1488 res = VCAM_RES_VGA;
1489 }
1491 mCurGreContext.mCameraPortParams[p].mWidth = VisionCamResolutions[res].mWidth;
1492 mCurGreContext.mCameraPortParams[p].mHeight = VisionCamResolutions[res].mHeight;
1493 }
1494 }
1495 }
1496 else
1497 greError = -EINVAL;
1499 break;
1500 }
1502 case VCAM_PARAM_MANUAL_EXPOSURE:
1503 {
1504 OMX_CONFIG_EXPOSUREVALUETYPE expValues;
1505 OMX_STRUCT_INIT(expValues, OMX_CONFIG_EXPOSUREVALUETYPE, mLocalVersion);
1506 int32_t p = port;
1508 // LOOP_PORTS( port , p )
1509 {
1510 expValues.nPortIndex = mCurGreContext.mPortsInUse[p];
1511 omxError = OMX_GetConfig( mCurGreContext.mHandleComp , OMX_IndexConfigCommonExposureValue , &expValues );
1513 if( OMX_ErrorNone == omxError )
1514 {
1515 if( *(OMX_U32*)param )
1516 {
1517 expValues.nShutterSpeedMsec = *(OMX_U32*)param;
1518 expValues.bAutoShutterSpeed = OMX_FALSE;
1519 }
1520 else
1521 expValues.bAutoShutterSpeed = OMX_TRUE;
1523 omxError = OMX_SetConfig( mCurGreContext.mHandleComp , OMX_IndexConfigCommonExposureValue , &expValues );
1524 }
1525 }
1526 break;
1527 }
1529 case VCAM_PARAM_EXPOSURE_ISO:
1530 {
1531 OMX_CONFIG_EXPOSUREVALUETYPE expValues;
1532 OMX_STRUCT_INIT(expValues, OMX_CONFIG_EXPOSUREVALUETYPE, mLocalVersion);
1533 int32_t p = port;
1534 // LOOP_PORTS( port , p )
1535 {
1537 expValues.nPortIndex = mCurGreContext.mPortsInUse[p];
1538 omxError = OMX_GetConfig(mCurGreContext.mHandleComp, OMX_IndexConfigCommonExposureValue, &expValues);
1539 if( OMX_ErrorNone == omxError )
1540 {
1541 if( *(OMX_U32*)param )
1542 {
1543 expValues.nSensitivity = *(OMX_U32*)param;
1544 expValues.bAutoSensitivity = OMX_FALSE;
1545 }
1546 else
1547 expValues.bAutoSensitivity = OMX_TRUE;
1549 omxError = OMX_SetConfig( mCurGreContext.mHandleComp , OMX_IndexConfigCommonExposureValue , &expValues );
1550 }
1551 }
1552 break;
1553 }
1555 case VCAM_PARAM_AWB_MODE:
1556 {
1557 OMX_CONFIG_WHITEBALCONTROLTYPE wb;
1558 OMX_STRUCT_INIT(wb, OMX_CONFIG_WHITEBALCONTROLTYPE, mLocalVersion);
1560 int32_t p = port;
1561 // LOOP_PORTS( port , p )
1562 {
1563 wb.nPortIndex = mCurGreContext.mPortsInUse[p];
1564 wb.eWhiteBalControl = *(OMX_WHITEBALCONTROLTYPE *)param;
1565 omxError = OMX_SetConfig( mCurGreContext.mHandleComp,
1566 OMX_IndexConfigCommonWhiteBalance,
1567 &wb);
1568 }
1569 break;
1570 }
1572 case VCAM_PARAM_COLOR_TEMP:
1573 {
1574 OMX_CONFIG_WHITEBALCONTROLTYPE wb;
1575 OMX_STRUCT_INIT(wb, OMX_CONFIG_WHITEBALCONTROLTYPE, mLocalVersion);
1577 if( 0 == *(int*)param )
1578 wb.eWhiteBalControl = OMX_WhiteBalControlAuto;
1579 else
1580 wb.eWhiteBalControl = OMX_WhiteBalControlOff; // @todo change to manual when proper OMX headers arrive
1582 int32_t p = port;
1583 // LOOP_PORTS( port , p )
1584 {
1585 wb.nPortIndex = mCurGreContext.mPortsInUse[p];
1586 omxError = OMX_SetConfig( mCurGreContext.mHandleComp,
1587 OMX_IndexConfigCommonWhiteBalance,
1588 &wb );
1589 }
1590 break;
1591 }
1593 case VCAM_PARAM_WB_COLOR_GAINS:
1594 {
1595 #ifdef USE_WB_GAIN_PATCH
1596 VisionCamWhiteBalGains wbGains = *((VisionCamWhiteBalGains*)param);
1597 uint16_t * tmp;
1598 CALCULATE_WB_GAINS_OFFSET(uint16_t,mWBbuffer,tmp);
1600 tmp[ RED ] = wbGains.mRed;
1601 tmp[ GREEN_RED ] = wbGains.mGreen_r;
1602 tmp[ GREEN_BLUE ] = wbGains.mGreen_b;
1603 tmp[ BLUE ] = wbGains.mBlue;
1605 OMX_TI_CONFIG_SHAREDBUFFER skipBuffer;
1606 skipBuffer.nSize = sizeof( OMX_TI_CONFIG_SHAREDBUFFER );
1607 memcpy( &skipBuffer.nVersion , mLocalVersion , sizeof(mLocalVersion) );
1609 if( wbGains.mRed >= COLOR_GAIN_MIN && wbGains.mRed <= COLOR_GAIN_MAX
1610 && wbGains.mGreen_b >= COLOR_GAIN_MIN && wbGains.mGreen_b <= COLOR_GAIN_MAX
1611 && wbGains.mGreen_r >= COLOR_GAIN_MIN && wbGains.mGreen_r <= COLOR_GAIN_MAX
1612 && wbGains.mBlue >= COLOR_GAIN_MIN && wbGains.mBlue <= COLOR_GAIN_MAX )
1613 {
1614 skipBuffer.pSharedBuff = (OMX_U8*)mWBbuffer;
1615 skipBuffer.nSharedBuffSize = sizeof(mWBbuffer);
1616 }
1617 else if( !wbGains.mRed && !wbGains.mGreen_b && !wbGains.mGreen_r && !wbGains.mBlue )
1618 { /// all gains are zero => auto mode
1619 skipBuffer.pSharedBuff = (OMX_U8*)mWBresetBuffer;
1620 skipBuffer.nSharedBuffSize = sizeof(mWBresetBuffer);
1621 }
1622 else
1623 {
1624 greError = -EINVAL;
1625 break;
1626 }
1628 int32_t p = port;
1629 // LOOP_PORTS(port, p)
1630 {
1631 skipBuffer.nPortIndex = p;
1632 omxError = OMX_SetConfig( mCurGreContext.mHandleComp,
1633 (OMX_INDEXTYPE) OMX_TI_IndexConfigAAAskipBuffer,
1634 &skipBuffer );
1635 }
1636 #endif // USE_WB_GAIN_PATCH
1637 break;
1638 }
1640 case VCAM_PARAM_GAMMA_TBLS:
1641 {
1642 VisionCamGammaTableType *gammaTbl = (VisionCamGammaTableType*)(param);
1643 OMX_TI_CONFIG_SHAREDBUFFER skipBuffer;
1644 OMX_STRUCT_INIT(skipBuffer, OMX_TI_CONFIG_SHAREDBUFFER, mLocalVersion);
1646 uint32_t* base = (uint32_t *)(mGammaTablesBuf + 12); // 12 bytes offset for first table
1647 uint16_t *redTbl = (uint16_t*)(base[0] + (uint32_t)&base[2]);
1648 uint16_t *blueTbl = (uint16_t*)(base[1] + (uint32_t)&base[2]);
1649 uint16_t *greenTbl = (uint16_t*)(base[2] + (uint32_t)&base[2]);
1651 #ifdef _USE_GAMMA_RESET_HC_
1652 if( !mGammaResetPolulated )
1653 {
1654 skipBuffer.pSharedBuff = (OMX_U8*)mGammaResetTablesBuf;
1655 skipBuffer.nSharedBuffSize = sizeof(mGammaResetTablesBuf);
1656 omxError = OMX_GetConfig( mCurGreContext.mHandleComp,
1657 (OMX_INDEXTYPE) OMX_TI_IndexConfigAAAskipBuffer,
1658 &skipBuffer );
1660 if( OMX_ErrorNone == omxError )
1661 mGammaResetPolulated = true;
1662 }
1663 #endif // _USE_GAMMA_RESET_HC_
1665 if( gammaTbl->mRedTable && gammaTbl->mGreenTable && gammaTbl->mBlueTable )
1666 {
1667 if( gammaTbl->mRedTable != redTbl )
1668 {
1669 memcpy(redTbl, gammaTbl->mRedTable, GAMMA_TABLE_SIZE );
1670 }
1672 if( gammaTbl->mGreenTable != greenTbl )
1673 {
1674 memcpy(greenTbl, gammaTbl->mGreenTable, GAMMA_TABLE_SIZE );
1675 }
1677 if( gammaTbl->mBlueTable != blueTbl )
1678 {
1679 memcpy(blueTbl, gammaTbl->mBlueTable, GAMMA_TABLE_SIZE );
1680 }
1682 skipBuffer.pSharedBuff = (OMX_U8*)mGammaTablesBuf;
1683 skipBuffer.nSharedBuffSize = sizeof(mGammaTablesBuf)/sizeof(mGammaTablesBuf[0]);
1684 }
1685 else
1686 {
1687 #ifdef _USE_GAMMA_RESET_HC_
1688 if( mGammaResetPolulated )
1689 {
1690 skipBuffer.pSharedBuff = (OMX_U8*)mGammaResetTablesBuf;
1691 skipBuffer.nSharedBuffSize = sizeof(mGammaResetTablesBuf)/sizeof(mGammaResetTablesBuf[0]);
1692 }
1693 else
1694 {
1695 ERROR("No data present in reset Gamma Tables. Leaving Gamma unchanged!!!");
1696 }
1697 #else
1698 skipBuffer.pSharedBuff = (OMX_U8*)mGammaResetTablesBuf;
1699 skipBuffer.nSharedBuffSize = sizeof(mGammaResetTablesBuf)/sizeof(mGammaResetTablesBuf[0]);
1700 #endif // _USE_GAMMA_RESET_HC_
1701 }
1703 omxError = OMX_SetConfig( mCurGreContext.mHandleComp,
1704 (OMX_INDEXTYPE) OMX_TI_IndexConfigAAAskipBuffer,
1705 &skipBuffer );
1707 break;
1708 }
1710 #if defined(VCAM_SET_FORMAT_ROTATION)
1711 case VCAM_PARAM_ROTATION:
1712 {
1713 int32_t p;
1714 LOOP_PORTS( port , p )
1715 {
1716 mCurGreContext.mCameraPortParams[p].mRotation = *((OMX_S32 *)param);
1717 }
1718 break;
1719 }
1720 #else
1721 case VCAM_PARAM_ROTATION:
1722 {
1723 OMX_CONFIG_ROTATIONTYPE rotation;
1724 OMX_STRUCT_INIT(rotation, OMX_CONFIG_ROTATIONTYPE, mLocalVersion);
1725 rotation.nRotation = *((OMX_S32*)param);
1727 int32_t p;
1728 LOOP_PORTS( port , p )
1729 {
1730 rotation.nPortIndex = mCurGreContext.mPortsInUse[p];
1731 OMX_CHECK(omxError, OMX_SetConfig(mCurGreContext.mHandleComp,
1732 OMX_IndexConfigCommonRotate,
1733 &rotation));
1734 MSG("Setting Rotation to %ld (size: %u)", rotation.nRotation, sizeof(rotation));
1735 }
1736 break;
1737 }
1738 #endif
1739 case VCAM_PARAM_MIRROR:
1740 {
1741 int i;
1742 OMX_CONFIG_MIRRORTYPE mirror;
1743 OMX_STRUCT_INIT(mirror, OMX_CONFIG_MIRRORTYPE, mLocalVersion);
1745 for( i = 0; i < VCAM_MIRROR_MAX; i++ )
1746 {
1747 if( MirrorTypeLUT[i][0] == *((VisionCamMirrorType*)param) )
1748 {
1749 mirror.eMirror = (OMX_MIRRORTYPE) MirrorTypeLUT[i][1];
1750 break;
1751 }
1752 }
1754 if( i < VCAM_MIRROR_MAX )
1755 {
1756 int32_t p;
1757 LOOP_PORTS( port , p )
1758 {
1759 mirror.nPortIndex = mCurGreContext.mPortsInUse[p];
1760 omxError = OMX_SetConfig( mCurGreContext.mHandleComp,
1761 OMX_IndexConfigCommonMirror,
1762 &mirror );
1763 }
1764 }
1765 else
1766 greError = -EINVAL;
1767 break;
1768 }
1770 #if ( defined(DUCATI_1_5) || defined(DUCATI_2_0) ) && defined(OMX_CAMERA_SUPPORTS_MANUAL_CONTROLS)
1771 case VCAM_PARAM_AWB_MIN_DELAY_TIME:
1772 {
1773 uint32_t timeDelay = *((uint32_t*)param);
1774 if( timeDelay > AE_Delay_Time_Max )
1775 {
1776 greError = -EINVAL;
1777 }
1778 else
1779 {
1780 OMX_TI_CONFIG_AE_DELAY aeDelay;
1781 OMX_STRUCT_INIT( aeDelay, OMX_TI_CONFIG_AE_DELAY, mLocalVersion );
1782 aeDelay.nDelayTime = timeDelay;
1784 int32_t p = port;
1785 // LOOP_PORTS( port , p )
1786 {
1787 aeDelay.nPortIndex = p;
1788 omxError = OMX_SetConfig( mCurGreContext.mHandleComp,
1789 ( OMX_INDEXTYPE )OMX_TI_IndexConfigAutoExpMinDelayTime,
1790 &aeDelay
1791 );
1792 }
1793 }
1794 break;
1795 }
1796 #endif
1797 #if ( defined(DUCATI_1_5) || defined(DUCATI_2_0) ) && defined(OMX_CAMERA_SUPPORTS_GESTURES)
1798 case VCAM_PARAM_GESTURES_INFO:
1799 {
1800 VisionCamGestureInfo *info = (VisionCamGestureInfo*)param;
1801 if( info->mGestureType >= VCAM_GESTURE_EVENT_MAX || info->mGestureType < VCAM_GESTURE_EVENT_INVALID )
1802 {
1803 greError= -EINVAL;
1804 }
1806 if( info->mRegionsNum >= VCAM_Max_Gesture_Per_Frame )
1807 {
1808 greError= -EINVAL;
1809 }
1811 if( 0 == greError )
1812 {
1813 OMX_TI_CONFIG_GESTURES_INFO gestInfo;
1814 OMX_STRUCT_INIT( gestInfo, OMX_TI_CONFIG_GESTURES_INFO , mLocalVersion );
1816 gestInfo.nTimeStamp = info->timeStamp;
1817 gestInfo.nNumDetectedGestures = info->mRegionsNum;
1818 gestInfo.eType = (OMX_TI_GESTURES_TYPE)getLutValue( info->mGestureType, VCAM_VALUE_TYPE,
1819 GestureTypeLUT, ARR_SIZE(GestureTypeLUT)
1820 );
1822 for(uint32_t i = 0; i < info->mRegionsNum ; i++ )
1823 {
1824 OMX_STRUCT_INIT(gestInfo.nGestureAreas[i], OMX_CONFIG_OBJECT_RECT_TYPE , mLocalVersion );
1825 gestInfo.nGestureAreas[i].eType = (OMX_TI_OBJECT_TYPE)getLutValue( (int)(info->mRegions[i].mObjType), VCAM_VALUE_TYPE,
1826 ObjectTypeLUT, ARR_SIZE(ObjectTypeLUT)
1827 );
1829 gestInfo.nGestureAreas[i].nTop = info->mRegions[i].mTop;
1830 gestInfo.nGestureAreas[i].nLeft = info->mRegions[i].mLeft;
1831 gestInfo.nGestureAreas[i].nWidth = info->mRegions[i].mWidth;
1832 gestInfo.nGestureAreas[i].nHeight = info->mRegions[i].mHeight;
1833 }
1835 if( OMX_TI_GESTURE_NO_GESTURE != gestInfo.eType)
1836 {
1837 int32_t p = port;
1838 // LOOP_PORTS( port , p )
1839 {
1840 gestInfo.nPortIndex = mCurGreContext.mPortsInUse[p];
1841 omxError = OMX_SetConfig( mCurGreContext.mHandleComp,
1842 (OMX_INDEXTYPE)OMX_TI_IndexConfigDetectedGesturesInfo,
1843 &gestInfo
1844 );
1845 }
1846 }
1847 else
1848 greError = -EINVAL;
1849 }
1851 break;
1852 }
1853 #endif
1854 #if ( defined(DUCATI_1_5) || defined(DUCATI_2_0) ) && defined(OMX_CAMERA_SUPPORTS_MANUAL_CONTROLS)
1855 case VCAM_PARAM_AGC_MIN_DELAY_TIME:
1856 {
1857 int32_t delay = *((int32_t*)param);
1858 OMX_TI_CONFIG_AE_DELAY agcDelTime;
1859 OMX_STRUCT_INIT( agcDelTime, OMX_TI_CONFIG_AE_DELAY, mLocalVersion );
1860 agcDelTime.nDelayTime = delay;
1862 int32_t p = port;
1863 // LOOP_PORTS( port , p )
1864 {
1865 agcDelTime.nPortIndex = p;
1866 omxError = OMX_SetConfig( mCurGreContext.mHandleComp,
1867 (OMX_INDEXTYPE)OMX_TI_IndexConfigAutoExpMinDelayTime,
1868 &agcDelTime );
1869 }
1870 break;
1871 }
1873 case VCAM_PARAM_AGC_LOW_TH:
1874 {
1875 int32_t lowTH = *((int32_t*)param);
1876 OMX_TI_CONFIG_AE_THRESHOLD ae;
1878 OMX_STRUCT_INIT( ae, OMX_TI_CONFIG_AE_THRESHOLD, mLocalVersion );
1880 int32_t p = port;
1881 // LOOP_PORTS( port , p )
1882 {
1883 ae.nPortIndex = p;
1884 omxError = OMX_GetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexConfigAutoExpThreshold, &ae );
1886 if( OMX_ErrorNone == omxError )
1887 {
1888 ae.uMinTH = lowTH;
1889 omxError = OMX_SetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexConfigAutoExpThreshold, &ae );
1890 }
1891 }
1892 break;
1893 }
1894 case VCAM_PARAM_AGC_HIGH_TH:
1895 {
1896 int32_t highTH = *((int32_t*)param);
1898 OMX_TI_CONFIG_AE_THRESHOLD ae;
1899 OMX_STRUCT_INIT( ae, OMX_TI_CONFIG_AE_THRESHOLD, mLocalVersion );
1901 int32_t p = port;
1902 // LOOP_PORTS( port , p )
1903 {
1904 ae.nPortIndex = p;
1905 omxError = OMX_GetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexConfigAutoExpThreshold, &ae );
1907 if( OMX_ErrorNone == omxError )
1908 {
1909 ae.uMaxTH = highTH;
1910 omxError = OMX_SetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexConfigAutoExpThreshold, &ae );
1911 }
1912 }
1913 break;
1914 }
1915 #endif
1916 case VCAM_PARAM_NAME:
1917 // do nothing as this is not supported but it should not fail either
1918 break;
1919 default:
1920 {
1921 ERROR("Impossible parameter id requested: %d", paramId);
1922 ERROR("see VisionCamParam_e for possible parameter ids");
1923 greError = -ENOSYS;
1924 if(paramId < VCAM_PARAM_MIN || paramId > VCAM_PARAM_MAX)
1925 greError = -EINVAL;
1926 }
1927 }
1929 if( OMX_ErrorNone != omxError )
1930 {
1931 greError = ConvertError(omxError);
1932 }
1934 if( greError != 0 )
1935 {
1936 ERROR("setParameter() exits with error 0x%x (dec: %d) [OMX:0x%08x] for param id 0x%x",
1937 greError, greError, omxError, paramId);
1938 }
1940 return greError;
1941 }
1943 /*
1944 * APIs to get configured Vision Cam parameters
1945 */
1946 int OMXVisionCam::getParameter( VisionCamParam_e paramId, void* param, uint32_t size, VisionCamPort_e port)
1947 {
1948 int greError = 0;
1949 OMX_ERRORTYPE omxError = OMX_ErrorNone;
1951 AutoLock lock(&mUserRequestLock);
1953 if (param == NULL || size == 0 || port >= VCAM_PORT_MAX)
1954 {
1955 ERROR("NULL param pointer passed to %s", __func__);
1956 return -EINVAL;
1957 }
1958 else
1959 {
1960 MSG("GET PARAM: 0x%04x, %p, %u (0x%08x)", paramId, param, size, (size==4?*(uint32_t *)param:0));
1961 }
1963 if( VCAM_PORT_ALL == port)
1964 {
1965 ERROR("%s called on port ALL. Please specifu a port!", __func__);
1966 return -EINVAL;
1967 }
1968 switch( paramId )
1969 {
1970 case VCAM_PARAM_HEIGHT:
1971 {
1972 OMX_PARAM_PORTDEFINITIONTYPE portCheck;
1973 omxError = initPortCheck( &portCheck , port );
1975 if( OMX_ErrorNone == omxError )
1976 {
1977 *(int*)param = portCheck.format.video.nFrameHeight;
1978 }
1979 break;
1980 }
1982 case VCAM_PARAM_WIDTH:
1983 {
1984 OMX_PARAM_PORTDEFINITIONTYPE portCheck;
1985 omxError = initPortCheck( &portCheck , port );
1987 if( OMX_ErrorNone == omxError )
1988 {
1989 *(int*)param = portCheck.format.video.nFrameWidth;
1990 }
1991 break;
1992 }
1994 case VCAM_PARAM_COLOR_SPACE_FOURCC:
1995 {
1996 OMX_PARAM_PORTDEFINITIONTYPE portCheck;
1997 omxError = initPortCheck(&portCheck, port);
1999 switch (portCheck.format.video.eColorFormat) {
2000 case OMX_COLOR_FormatCbYCrY:
2001 *((int*)param) = FOURCC('Y','U','Y','V');
2002 break;
2003 case OMX_COLOR_FormatYUV420SemiPlanar:
2004 *((int*)param) = FOURCC('N','V','1','2');
2005 break;
2006 default:
2007 greError = -EINVAL;
2008 }
2009 break;
2010 }
2012 case VCAM_PARAM_DO_AUTOFOCUS:
2013 {
2014 int i = 0;
2015 OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focus;
2016 OMX_STRUCT_INIT(focus, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE, mLocalVersion);
2018 omxError = OMX_GetConfig(mCurGreContext.mHandleComp, OMX_IndexConfigFocusControl, &focus);
2019 if( OMX_ErrorNone == omxError )
2020 {
2021 for( i = 0; i < VCAM_FOCUS_CONTROL_MAX; i++ )
2022 {
2023 if ( FocusModeLUT[ i ][ 1 ] == focus.eFocusControl )
2024 {
2025 *(int*)param = FocusModeLUT[ i ][ 0 ];
2026 break;
2027 }
2028 }
2029 if( VCAM_FOCUS_CONTROL_MAX == i )
2030 greError = -EINVAL;
2031 }
2033 break;
2034 }
2036 case VCAM_PARAM_DO_MANUALFOCUS:
2037 {
2038 OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focus;
2039 OMX_STRUCT_INIT(focus, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE, mLocalVersion);
2041 omxError = OMX_GetConfig(mCurGreContext.mHandleComp, OMX_IndexConfigFocusControl, &focus);
2042 if( OMX_ErrorNone == omxError )
2043 {
2044 (*(int*)param) = focus.nFocusSteps;
2045 }
2046 break;
2047 }
2049 case VCAM_PARAM_BRIGHTNESS:
2050 {
2051 OMX_CONFIG_BRIGHTNESSTYPE brightness;
2052 OMX_STRUCT_INIT(brightness, OMX_CONFIG_BRIGHTNESSTYPE, mLocalVersion );
2054 omxError = OMX_GetConfig( mCurGreContext.mHandleComp, OMX_IndexConfigCommonBrightness, &brightness);
2055 if( OMX_ErrorNone == omxError )
2056 {
2057 *((uint32_t*)param) = brightness.nBrightness;
2058 }
2059 break;
2060 }
2062 case VCAM_PARAM_CONTRAST:
2063 {
2064 OMX_CONFIG_CONTRASTTYPE contrast;
2065 OMX_STRUCT_INIT(contrast, OMX_CONFIG_CONTRASTTYPE, mLocalVersion );
2067 omxError = OMX_GetConfig( mCurGreContext.mHandleComp, OMX_IndexConfigCommonContrast, &contrast);
2068 if( OMX_ErrorNone == omxError )
2069 {
2070 *((int*)param) = contrast.nContrast;
2071 }
2072 break;
2073 }
2075 case VCAM_PARAM_SHARPNESS:
2076 {
2077 OMX_IMAGE_CONFIG_PROCESSINGLEVELTYPE procSharpness;
2078 OMX_STRUCT_INIT( procSharpness, OMX_IMAGE_CONFIG_PROCESSINGLEVELTYPE, mLocalVersion );
2080 omxError = OMX_GetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_IndexConfigSharpeningLevel, &procSharpness);
2082 if( OMX_ErrorNone == omxError )
2083 {
2084 if( OMX_TRUE == procSharpness.bAuto )
2085 *((int*)param) = 0;
2086 else
2087 *((int*)param) = procSharpness.nLevel;
2088 }
2089 break;
2090 }
2092 case VCAM_PARAM_SATURATION:
2093 {
2094 OMX_CONFIG_SATURATIONTYPE saturation;
2095 OMX_STRUCT_INIT(saturation, OMX_CONFIG_SATURATIONTYPE, mLocalVersion);
2096 omxError = OMX_GetConfig( mCurGreContext.mHandleComp, OMX_IndexConfigCommonSaturation, &saturation);
2098 if( OMX_ErrorNone == omxError )
2099 {
2100 *((int*)param) = saturation.nSaturation;
2101 }
2102 break;
2103 }
2105 case VCAM_PARAM_FPS_FIXED:
2106 {
2107 OMX_PARAM_PORTDEFINITIONTYPE portCheck;
2108 omxError = initPortCheck( &portCheck , port );
2110 if( OMX_ErrorNone == omxError )
2111 {
2112 *((uint32_t*)param) = portCheck.format.video.xFramerate >> 16;
2113 }
2114 break;
2115 }
2117 case VCAM_PARAM_FPS_VAR:
2118 {
2119 ERROR("No Getting Api for this Parameter %d", paramId);
2120 break;
2121 }
2123 case VCAM_PARAM_FLICKER:
2124 {
2125 OMX_CONFIG_FLICKERCANCELTYPE flicker;
2126 OMX_STRUCT_INIT( flicker, OMX_CONFIG_FLICKERCANCELTYPE, mLocalVersion );
2127 omxError = OMX_GetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_IndexConfigFlickerCancel, &flicker );
2129 if( OMX_ErrorNone == omxError )
2130 {
2131 *((int*)param) = flicker.eFlickerCancel;
2132 }
2133 break;
2134 }
2136 case VCAM_PARAM_CROP:
2137 {
2138 OMX_CONFIG_RECTTYPE crop;
2139 OMX_STRUCT_INIT(crop, OMX_CONFIG_RECTTYPE, mLocalVersion);
2141 omxError = OMX_GetConfig( mCurGreContext.mHandleComp, OMX_IndexConfigCommonOutputCrop, &crop );
2143 if( OMX_ErrorNone == omxError )
2144 {
2145 ((VisionCamRectType*)param)->mLeft = crop.nLeft;
2146 ((VisionCamRectType*)param)->mTop = crop.nTop;
2147 ((VisionCamRectType*)param)->mWidth = crop.nWidth;
2148 ((VisionCamRectType*)param)->mHeight = crop.nHeight;
2149 }
2150 break;
2151 }
2153 case VCAM_PARAM_CAP_MODE:
2154 {
2155 if (param != NULL)
2156 {
2157 int i = 0;
2158 OMX_CONFIG_CAMOPERATINGMODETYPE opMode;
2159 opMode.nSize = sizeof(OMX_CONFIG_CAMOPERATINGMODETYPE);
2160 memcpy(&opMode .nVersion, mLocalVersion , sizeof(OMX_VERSIONTYPE));
2162 omxError = OMX_GetParameter( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_IndexCameraOperatingMode, &opMode );
2164 if( OMX_ErrorNone == omxError )
2165 {
2166 for (i = 0; i < VCAM_CAP_MODE_MAX; i++)
2167 {
2168 if (CaptureModeLUT[i][1] == opMode.eCamOperatingMode)
2169 {
2170 memcpy( param, &CaptureModeLUT[i][0], sizeof(int) );
2171 break;
2172 }
2173 }
2175 if( VCAM_CAP_MODE_MAX == CaptureModeLUT[i][0])
2176 {
2177 greError = -EINVAL;
2178 break;
2179 }
2180 }
2181 }
2182 break;
2183 }
2185 case VCAM_PARAM_SENSOR_SELECT:
2186 {
2187 OMX_CONFIG_SENSORSELECTTYPE sensor;
2188 OMX_STRUCT_INIT(sensor, OMX_CONFIG_SENSORSELECTTYPE, mLocalVersion);
2190 omxError = OMX_GetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexConfigSensorSelect, &sensor);
2192 if( OMX_ErrorNone == omxError)
2193 {
2194 *((int*)param) = sensor.eSensor;
2195 }
2196 break;
2197 }
2199 case VCAM_PARAM_EXPOSURE_COMPENSATION:
2200 {
2201 OMX_CONFIG_EXPOSUREVALUETYPE expValues;
2202 OMX_STRUCT_INIT( expValues, OMX_CONFIG_EXPOSUREVALUETYPE, mLocalVersion );
2203 omxError = OMX_GetConfig( mCurGreContext.mHandleComp , OMX_IndexConfigCommonExposureValue , &expValues );
2205 if( OMX_ErrorNone == omxError )
2206 {
2207 expValues.xEVCompensation *= 10;
2208 int compVal = expValues.xEVCompensation / (1 << 16);
2209 *((int*)param) = compVal;
2210 }
2211 break;
2212 }
2214 case VCAM_PARAM_RESOLUTION:
2215 {
2216 int i = VCAM_RESOL_MAX;
2217 unsigned int width, height;
2218 OMX_PARAM_PORTDEFINITIONTYPE portCheck;
2219 omxError = initPortCheck( &portCheck , port );
2221 if( OMX_ErrorNone == omxError )
2222 {
2223 width = portCheck.format.video.nFrameWidth;
2224 height = portCheck.format.video.nFrameHeight;
2225 for( i = 0; i < VCAM_RESOL_MAX; i++)
2226 {
2227 if( VisionCamResolutions[i].mWidth == width
2228 && VisionCamResolutions[i].mHeight == height)
2229 {
2230 *((int*)param) = i;
2231 break;
2232 }
2233 }
2234 if( VCAM_RESOL_MAX == i )
2235 {
2236 greError = -EINVAL;
2237 }
2238 }
2239 break;
2240 }
2242 case VCAM_PARAM_2DBUFFER_DIM:
2243 {
2244 OMX_CONFIG_RECTTYPE frame;
2245 OMX_STRUCT_INIT(frame, OMX_CONFIG_RECTTYPE, mLocalVersion);
2246 VisionCamResType *pRes = (VisionCamResType *)param;
2248 frame.nPortIndex = mCurGreContext.mPortsInUse[port];
2249 if (pRes && size == sizeof(VisionCamResType))
2250 {
2251 // Set the port definition to update width and height first.
2252 omxError = setPortDef( port );
2254 if( OMX_ErrorNone == omxError )
2255 {
2256 omxError = OMX_GetParameter(mCurGreContext.mHandleComp,
2257 (OMX_INDEXTYPE)OMX_TI_IndexParam2DBufferAllocDimension,
2258 &frame);
2259 }
2261 if (OMX_ErrorNone == omxError)
2262 {
2263 pRes->mWidth = frame.nWidth;
2264 pRes->mHeight = frame.nHeight;
2265 }
2266 else
2267 {
2268 ERROR("Failed to query the 2D Buffer Dimensions! (err=0x%08x)", omxError);
2269 memset(pRes, 0, sizeof(VisionCamResType));
2270 // omxError will convert to greError
2271 }
2272 }
2273 else
2274 greError = -EINVAL;
2275 break;
2276 }
2278 case VCAM_PARAM_MANUAL_EXPOSURE:
2279 {
2280 OMX_CONFIG_EXPOSUREVALUETYPE expValues;
2281 OMX_STRUCT_INIT(expValues, OMX_CONFIG_EXPOSUREVALUETYPE, mLocalVersion);
2283 omxError = OMX_GetConfig( mCurGreContext.mHandleComp , OMX_IndexConfigCommonExposureValue , &expValues );
2285 if( OMX_ErrorNone == omxError )
2286 {
2287 if( OMX_TRUE == expValues.bAutoShutterSpeed )
2288 {
2289 *(OMX_U32*)param = 0;
2290 }
2291 else
2292 {
2293 *(OMX_U32*)param = expValues.nShutterSpeedMsec;
2294 }
2295 }
2296 break;
2297 }
2299 case VCAM_PARAM_EXPOSURE_ISO:
2300 {
2301 OMX_CONFIG_EXPOSUREVALUETYPE expValues;
2302 OMX_STRUCT_INIT( expValues, OMX_CONFIG_EXPOSUREVALUETYPE, mLocalVersion );
2304 omxError = OMX_GetConfig( mCurGreContext.mHandleComp , OMX_IndexConfigCommonExposureValue , &expValues );
2306 if( OMX_ErrorNone == omxError )
2307 {
2308 if( OMX_TRUE == expValues.bAutoSensitivity )
2309 {
2310 *(uint32_t*)param = 0;
2311 }
2312 else
2313 *(uint32_t*)param = expValues.nSensitivity;
2314 }
2315 break;
2316 }
2318 case VCAM_PARAM_AWB_MODE:
2319 {
2320 OMX_CONFIG_WHITEBALCONTROLTYPE wb;
2321 OMX_STRUCT_INIT(wb, OMX_CONFIG_WHITEBALCONTROLTYPE, mLocalVersion );
2323 omxError = OMX_GetConfig( mCurGreContext.mHandleComp,
2324 OMX_IndexConfigCommonWhiteBalance,
2325 &wb);
2327 if( OMX_ErrorNone == omxError )
2328 {
2329 *(int *)param = (int)wb.eWhiteBalControl;
2330 }
2331 break;
2332 }
2334 case VCAM_PARAM_COLOR_TEMP:
2335 {
2336 ERROR("No Getting Api for this Parameter %d", paramId);
2337 break;
2338 }
2339 case VCAM_PARAM_WB_COLOR_GAINS:
2340 {
2341 #ifdef USE_WB_GAIN_PATCH
2342 OMX_TI_CONFIG_SHAREDBUFFER skipBuffer;
2344 skipBuffer.nSize = sizeof( OMX_TI_CONFIG_SHAREDBUFFER );
2345 memcpy( &skipBuffer.nVersion , mLocalVersion , sizeof(mLocalVersion) );
2346 skipBuffer.pSharedBuff = (OMX_U8*)mWBbuffer;
2347 skipBuffer.nSharedBuffSize = sizeof(mWBbuffer);
2349 omxError = OMX_GetConfig( mCurGreContext.mHandleComp,
2350 (OMX_INDEXTYPE) OMX_TI_IndexConfigAAAskipBuffer,
2351 &skipBuffer );
2353 if( OMX_ErrorNone == omxError )
2354 {
2355 VisionCamWhiteBalGains wbGains;
2356 uint16_t * tmp;
2357 CALCULATE_WB_GAINS_OFFSET(uint16_t, mWBbuffer, tmp );
2359 wbGains.mRed = tmp[ RED ];
2360 wbGains.mGreen_r = tmp[ GREEN_RED ];
2361 wbGains.mGreen_b = tmp[ GREEN_BLUE ];
2362 wbGains.mBlue = tmp[ BLUE ];
2364 *((VisionCamWhiteBalGains*)param) = wbGains;
2365 }
2366 #endif // USE_WB_GAIN_PATCH
2367 break;
2368 }
2370 case VCAM_PARAM_GAMMA_TBLS:
2371 {
2373 VisionCamGammaTableType *gammaTbl = (VisionCamGammaTableType*)param;
2374 OMX_TI_CONFIG_SHAREDBUFFER skipBuffer;
2375 skipBuffer.nSize = sizeof( OMX_TI_CONFIG_SHAREDBUFFER );
2376 memcpy( &skipBuffer.nVersion , mLocalVersion , sizeof(mLocalVersion) );
2378 skipBuffer.pSharedBuff = (OMX_U8*)mGammaTablesBuf;
2379 skipBuffer.nSharedBuffSize = sizeof(mGammaTablesBuf);
2381 omxError = OMX_GetConfig( mCurGreContext.mHandleComp,
2382 (OMX_INDEXTYPE) OMX_TI_IndexConfigAAAskipBuffer,
2383 &skipBuffer );
2385 if( OMX_ErrorNone == omxError )
2386 {
2387 gammaTbl->mTableSize = GAMMA_TABLE_SIZE;
2389 uint32_t* base = (uint32_t *)(mGammaTablesBuf + 12); // 12 bytes offset for red table
2390 gammaTbl->mRedTable = (uint16_t*)(base[0] + (uint32_t)&base[2]);
2391 gammaTbl->mBlueTable = (uint16_t*)(base[1] + (uint32_t)&base[2]);
2392 gammaTbl->mGreenTable = (uint16_t*)(base[2] + (uint32_t)&base[2]);
2393 }
2394 break;
2395 }
2397 case VCAM_PARAM_ROTATION:
2398 {
2399 OMX_CONFIG_ROTATIONTYPE rotation;
2400 OMX_STRUCT_INIT(rotation, OMX_CONFIG_ROTATIONTYPE, mLocalVersion);
2401 omxError = OMX_GetConfig(mCurGreContext.mHandleComp,
2402 OMX_IndexConfigCommonRotate,
2403 &rotation);
2404 if (OMX_ErrorNone == omxError)
2405 *((OMX_S32*)param) = rotation.nRotation;
2406 break;
2407 }
2409 case VCAM_PARAM_MIRROR:
2410 {
2411 if( VCAM_PORT_ALL == port )
2412 {
2413 greError = -EINVAL;
2414 }
2415 else
2416 {
2417 int i;
2418 OMX_CONFIG_MIRRORTYPE mirror;
2419 mirror.nSize = sizeof( OMX_CONFIG_MIRRORTYPE );
2420 mirror.nPortIndex = mCurGreContext.mPortsInUse[port];
2421 memcpy( &mirror.nVersion, mLocalVersion, sizeof(mLocalVersion));
2423 omxError = OMX_GetConfig( mCurGreContext.mHandleComp,
2424 OMX_IndexConfigCommonMirror,
2425 &mirror );
2427 if( OMX_ErrorNone == omxError )
2428 {
2429 for( i = 0; i < VCAM_MIRROR_MAX; i++ )
2430 {
2431 if( MirrorTypeLUT[i][1] == mirror.eMirror )
2432 {
2433 *((VisionCamMirrorType*)param) = (VisionCamMirrorType) MirrorTypeLUT[i][0];
2434 break;
2435 }
2436 }
2438 if( i >= VCAM_MIRROR_MAX )
2439 greError = -EINVAL;
2440 }
2441 }
2442 break;
2443 }
2445 #if ( defined(DUCATI_1_5) || defined(DUCATI_2_0) ) && defined(OMX_CAMERA_SUPPORTS_MANUAL_CONTROLS)
2446 case VCAM_PARAM_AWB_MIN_DELAY_TIME:
2447 {
2448 uint32_t *timeDelay = (uint32_t*)param;
2449 OMX_TI_CONFIG_AE_DELAY aeDelay;
2450 OMX_STRUCT_INIT( aeDelay, OMX_TI_CONFIG_AE_DELAY, mLocalVersion );
2452 omxError = OMX_GetConfig( mCurGreContext.mHandleComp,
2453 ( OMX_INDEXTYPE )OMX_TI_IndexConfigAutoExpMinDelayTime,
2454 &aeDelay
2455 );
2456 if( OMX_ErrorNone == omxError )
2457 {
2458 *timeDelay = aeDelay.nDelayTime;
2459 }
2460 break;
2461 }
2462 #endif
2463 #if ( defined(DUCATI_1_5) || defined(DUCATI_2_0) ) && defined(OMX_CAMERA_SUPPORTS_GESTURES)
2464 case VCAM_PARAM_GESTURES_INFO:
2465 {
2466 VisionCamGestureInfo *info = (VisionCamGestureInfo *)param;
2467 OMX_TI_CONFIG_GESTURES_INFO gestInfo;
2468 int ret = 0;
2470 OMX_STRUCT_INIT( gestInfo, OMX_TI_CONFIG_GESTURES_INFO , mLocalVersion );
2472 omxError = OMX_GetConfig( mCurGreContext.mHandleComp,
2473 (OMX_INDEXTYPE)OMX_TI_IndexConfigDetectedGesturesInfo,
2474 &gestInfo
2475 );
2477 if( OMX_ErrorNone != omxError )
2478 break;
2480 ret = (VisionCamGestureEvent_e)getLutValue( gestInfo.eType, OMX_VALUE_TYPE,
2481 GestureTypeLUT, ARR_SIZE(GestureTypeLUT)
2482 );
2484 if( -EINVAL == (int)ret )
2485 {
2486 greError = -EINVAL;
2487 }
2488 else
2489 {
2490 info->mGestureType = (VisionCamGestureEvent_e)ret;
2491 info->mRegionsNum = gestInfo.nNumDetectedGestures;
2492 if( info->mRegionsNum >= VCAM_Max_Gesture_Per_Frame )
2493 {
2494 greError= -EINVAL;
2495 break;
2496 }
2498 #ifdef __cplusplus
2499 info->mRegions = new VisionCamObjectRectType[ info->mRegionsNum ];
2500 #else
2501 if( NULL == info->mRegions )
2502 {
2503 ERROR("Please allocate the mRegions buffer");
2504 ERROR("Check for necessery size in mRegionsNum");
2506 greError= STATUS_NO_RESOURCES;
2507 break;
2508 }
2509 #endif
2511 for(uint32_t i = 0; i < info->mRegionsNum; i++ )
2512 {
2513 info->mRegions[i].mObjType= (VisionCamObjectType)getLutValue(
2514 (int)(gestInfo.nGestureAreas[i].eType),
2515 OMX_VALUE_TYPE,
2516 ObjectTypeLUT,
2517 ARR_SIZE(ObjectTypeLUT)
2518 );
2520 gestInfo.nGestureAreas[i].nTop = info->mRegions[i].mTop;
2521 gestInfo.nGestureAreas[i].nLeft = info->mRegions[i].mLeft;
2522 gestInfo.nGestureAreas[i].nWidth = info->mRegions[i].mWidth;
2523 gestInfo.nGestureAreas[i].nHeight = info->mRegions[i].mHeight;
2524 }
2526 info->timeStamp = gestInfo.nTimeStamp;
2527 }
2529 break;
2530 }
2531 #endif
2532 #if ( defined(DUCATI_1_5) || defined(DUCATI_2_0) ) && defined(OMX_CAMERA_SUPPORTS_MANUAL_CONTROLS)
2533 case VCAM_PARAM_AGC_MIN_DELAY_TIME:
2534 {
2535 uint32_t *delay = (uint32_t*)param;
2536 OMX_TI_CONFIG_AE_DELAY agcDelTime;
2537 OMX_STRUCT_INIT( agcDelTime, OMX_TI_CONFIG_AE_DELAY, mLocalVersion );
2539 omxError = OMX_GetConfig( mCurGreContext.mHandleComp,
2540 (OMX_INDEXTYPE)OMX_TI_IndexConfigAutoExpMinDelayTime,
2541 &agcDelTime );
2543 if( OMX_ErrorNone != omxError )
2544 break;
2546 *delay = agcDelTime.nDelayTime;
2547 break;
2548 }
2550 case VCAM_PARAM_AGC_LOW_TH:
2551 {
2552 uint32_t *lowTH = (uint32_t*)param;
2553 OMX_TI_CONFIG_AE_THRESHOLD ae;
2555 OMX_STRUCT_INIT( ae, OMX_TI_CONFIG_AE_THRESHOLD, mLocalVersion );
2557 omxError = OMX_GetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexConfigAutoExpThreshold, &ae );
2559 if( OMX_ErrorNone != omxError )
2560 break;
2562 *lowTH = ae.uMinTH;
2563 break;
2564 }
2566 case VCAM_PARAM_AGC_HIGH_TH:
2567 {
2568 uint32_t *highTH = (uint32_t*)param;
2570 OMX_TI_CONFIG_AE_THRESHOLD ae;
2571 OMX_STRUCT_INIT( ae, OMX_TI_CONFIG_AE_THRESHOLD, mLocalVersion );
2573 omxError = OMX_GetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexConfigAutoExpThreshold, &ae );
2575 if( OMX_ErrorNone != omxError )
2576 break;
2578 *highTH = ae.uMaxTH;
2579 break;
2580 }
2581 #endif
2583 default:
2584 {
2585 ERROR("Impossible parameter id requested: %d", paramId);
2586 ERROR("see VisionCamParam_e for possible parameter ids");
2587 greError = -EINVAL;
2588 }
2589 }
2591 if( OMX_ErrorNone != omxError )
2592 {
2593 greError = ConvertError(omxError);
2594 }
2596 if( greError != 0 )
2597 {
2598 ERROR("getParameter() exits with error 0x%x (dec: %d) for param id %d", greError, greError, paramId);
2599 }
2601 return greError;
2602 }
2604 OMX_ERRORTYPE OMXVisionCam::getFocusStatus(OMX_FOCUSSTATUSTYPE *status)
2605 {
2606 OMX_ERRORTYPE eError = OMX_ErrorNone;
2607 OMX_PARAM_FOCUSSTATUSTYPE focusStatus;
2608 OMX_STRUCT_INIT(focusStatus, OMX_PARAM_FOCUSSTATUSTYPE, mLocalVersion);
2610 // Get the focus status
2611 OMX_CHECK(eError,OMX_GetConfig(mCurGreContext.mHandleComp,
2612 OMX_IndexConfigCommonFocusStatus,
2613 &focusStatus));
2614 if (eError == OMX_ErrorNone)
2615 *status = focusStatus.eFocusStatus;
2616 return eError;
2617 }
2619 int OMXVisionCam::waitForFocus()
2620 {
2621 OMX_ERRORTYPE omxError = OMX_ErrorNone;
2622 OMX_FOCUSSTATUSTYPE focusStatus;
2624 omxError = RegisterForEvent(mCurGreContext.mHandleComp,
2625 (OMX_EVENTTYPE) OMX_EventIndexSettingChanged,
2626 OMX_ALL,
2627 OMX_IndexConfigCommonFocusStatus,
2628 &mGreFocusSem,
2629 -1);
2630 if (OMX_ErrorNone == omxError)
2631 {
2632 OMX_CONFIG_CALLBACKREQUESTTYPE focusRequestCallback;
2633 OMX_STRUCT_INIT(focusRequestCallback, OMX_CONFIG_CALLBACKREQUESTTYPE, mLocalVersion);
2634 focusRequestCallback.bEnable = OMX_TRUE;
2635 focusRequestCallback.nIndex = OMX_IndexConfigCommonFocusStatus;
2637 // subscribe for focus state changes
2638 OMX_CHECK(omxError,OMX_SetConfig(mCurGreContext.mHandleComp,
2639 (OMX_INDEXTYPE) OMX_IndexConfigCallbackRequest,
2640 &focusRequestCallback));
2641 #ifdef VCAM_CAUTIOUS
2642 // make sure it's been registered
2643 OMX_CHECK(omxError,OMX_GetConfig(mCurGreContext.mHandleComp,
2644 (OMX_INDEXTYPE) OMX_IndexConfigCallbackRequest,
2645 &focusRequestCallback));
2647 #endif
2648 if (OMX_ErrorNone == omxError && focusRequestCallback.bEnable == OMX_TRUE)
2649 {
2650 MSG("Waiting for Focus Callback!");
2651 // wait for focus to arrive
2652 sem_wait(&mGreFocusSem);
2654 // Give the client the focus greError
2655 omxError = getFocusStatus(&focusStatus);
2656 MSG("Focus Status: %u", focusStatus);
2657 if (OMX_ErrorNone == omxError)
2658 {
2659 if (m_focuscallback)
2660 m_focuscallback((int)focusStatus);
2661 }
2662 }
2663 }
2664 return ConvertError(omxError);
2665 }
2667 int OMXVisionCam::startAutoFocus( VisionCamFocusMode focusMode )
2668 {
2669 int i;
2670 OMX_ERRORTYPE omxError = OMX_ErrorNone;
2671 bool haveEvent = true;
2672 OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focus;
2674 if (focusMode == VCAM_FOCUS_CONTROL_OFF ||
2675 focusMode == VCAM_FOCUS_CONTROL_AUTO ||
2676 focusMode == VCAM_FOCUS_CONTROL_CONTINOUS_NORMAL ||
2677 focusMode == VCAM_FOCUS_CONTROL_CONTINOUS_EXTENDED)
2678 {
2679 haveEvent = false;
2680 }
2682 // initialize the structure
2683 OMX_STRUCT_INIT(focus, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE, mLocalVersion);
2684 for( i = 0 ; i < VCAM_FOCUS_CONTROL_MAX ; i++ )
2685 {
2686 if( FocusModeLUT[ i ][ 0 ] == focusMode )
2687 {
2688 focus.eFocusControl = ( OMX_IMAGE_FOCUSCONTROLTYPE )FocusModeLUT[ i ][ 1 ];
2689 if( focus.eFocusControl == OMX_IMAGE_FocusControlOn )
2690 focus.nFocusSteps = mManualFocusDistance;
2691 break;
2692 }
2693 }
2695 if (i == VCAM_FOCUS_CONTROL_MAX)
2696 {
2697 ERROR("Unsupported focus mode requested: %d", focusMode );
2698 return -EINVAL;
2699 }
2701 MSG("Focus Requested Steps @ %lu, Index @ %lu", focus.nFocusSteps, focus.nFocusStepIndex);
2703 // tell the OMX component to change the focus control mode
2704 OMX_CHECK(omxError,OMX_SetConfig(mCurGreContext.mHandleComp, OMX_IndexConfigFocusControl, &focus));
2705 #ifdef VCAM_CAUTIOUS
2706 // ask it what mode it's in now
2707 OMX_CHECK(omxError, OMX_GetConfig(mCurGreContext.mHandleComp, OMX_IndexConfigFocusControl, &focus));
2708 #endif
2709 MSG("Focus Control Mode = 0x%08x", focus.eFocusControl);
2710 if (OMX_ErrorNone == omxError && focus.eFocusControl != OMX_IMAGE_FocusControlOff)
2711 {
2712 if (haveEvent)
2713 {
2714 pthread_t thread;
2715 pthread_create(&thread, NULL, FocusThreadLauncher, this);
2716 // the thread will die by itself, we don't need to join it.
2717 }
2718 }
2720 return ConvertError(omxError);
2721 }
2723 /* This will set the preview buffer sizzes, format, etc.
2724 */
2725 OMX_ERRORTYPE OMXVisionCam::setPortDef( int port )
2726 {
2727 OMX_ERRORTYPE omxError = OMX_ErrorNone;
2729 VCAM_PortParameters * portData = NULL;
2730 OMX_PARAM_PORTDEFINITIONTYPE portCheck;
2732 int32_t p;
2733 LOOP_PORTS( port , p )
2734 {
2735 omxError = initPortCheck(&portCheck, p);
2737 if( omxError == OMX_ErrorNone )
2738 {
2739 portData = &mCurGreContext.mCameraPortParams[p];
2740 portCheck.format.video.nFrameWidth = portData->mWidth;
2741 portCheck.format.video.nFrameHeight = portData->mHeight;
2742 portCheck.format.video.eColorFormat = portData->mColorFormat;
2743 portCheck.format.video.nStride = portData->mStride;
2744 portCheck.format.video.xFramerate = portData->mFrameRate << 16;
2745 portCheck.nBufferCountActual = portData->mNumBufs;
2747 omxError = OMX_SetParameter(mCurGreContext.mHandleComp,
2748 OMX_IndexParamPortDefinition,
2749 &portCheck);
2750 }
2752 if( omxError == OMX_ErrorNone )
2753 omxError = initPortCheck(&portCheck, p);
2755 if( omxError == OMX_ErrorNone )
2756 portData->mBufSize = portCheck.nBufferSize;
2758 #if defined(VCAM_SET_FORMAT_ROTATION)
2759 // set the rotation type on the port
2760 if ( omxError == OMX_ErrorNone)
2761 {
2762 OMX_CONFIG_ROTATIONTYPE rotType;
2763 OMX_STRUCT_INIT(rotType, OMX_CONFIG_ROTATIONTYPE, mLocalVersion);
2764 rotType.nRotation = mCurGreContext.mCameraPortParams[p].mRotation;
2765 rotType.nPortIndex = mCurGreContext.mPortsInUse[p];
2766 MSG("VCAM: Configuring for Rotation %li",rotType.nRotation);
2767 OMX_CHECK(omxError, OMX_SetConfig(mCurGreContext.mHandleComp,
2768 OMX_IndexConfigCommonRotate,
2769 &rotType));
2770 }
2771 #endif
2772 }
2774 return omxError;
2775 }
2777 /* This will start the preview.
2778 * Before that setParameter() sould be called, to configure the preview port.
2779 * This method is only called internal for OMXVisionCam
2780 * by sendCommand().
2781 */
2782 int OMXVisionCam::startPreview( VisionCamPort_e port )
2783 {
2784 int greError = 0;
2786 if( port < VCAM_PORT_ALL || port > VCAM_PORT_MAX - 1 )
2787 {
2788 ERROR("startPreview() called, but port is not specified properly.");
2789 return -EINVAL;
2790 }
2792 mFlushInProcess = false;
2794 switch((int)getComponentState())
2795 {
2796 case OMX_StateIdle:
2797 {
2798 greError = transitToState( OMX_StateExecuting );
2799 mReturnToExecuting = true;
2800 break;
2801 }
2802 case OMX_StateLoaded:
2803 case OMX_StateWaitForResources:
2804 case OMX_StateInvalid:
2805 {
2806 ERROR("Calling startPreview() in an inproper state.");
2807 greError = -EBADE;
2808 break;
2809 }
2810 case OMX_StateExecuting:
2811 case OMX_StatePause:
2812 {
2813 break;
2814 }
2815 default:
2816 break;
2817 }
2819 AutoLock lock(&mFrameBufferLock);
2821 OMX_ERRORTYPE omxError;
2822 omxError = setPortDef( port );
2823 greError = ConvertError(omxError);
2825 if( 0 == greError )
2826 {
2827 greError = portEnableDisable( OMX_CommandPortEnable, populatePortSrvc, port);
2828 }
2830 if( 0 == greError )
2831 {
2832 // first fill the video port buffers, then preview port
2833 // otherwise preview port will start working right after it receive its frames
2834 // so it won't wait for video port to get ready
2835 if( VCAM_PORT_ALL == port || VCAM_PORT_VIDEO == port )
2836 {
2837 greError = fillPortBuffers(VCAM_PORT_VIDEO);
2838 }
2840 if( VCAM_PORT_ALL == port || VCAM_PORT_PREVIEW == port )
2841 {
2842 greError = fillPortBuffers(VCAM_PORT_PREVIEW);
2843 }
2844 }
2846 return greError;
2847 }
2849 /**
2850 * This will stop the preview
2851 *
2852 */
2853 int OMXVisionCam::stopPreview( VisionCamPort_e port )
2854 {
2855 int greError = 0;
2856 bool goToIdle = true;
2858 mFlushInProcess = true;
2860 flushBuffers( port );
2861 greError = portEnableDisable( OMX_CommandPortDisable, freePortBuffersSrvc, port );
2863 if( 0 == greError )
2864 {
2865 for( int p = VCAM_PORT_PREVIEW; p < VCAM_PORT_MAX; p++)
2866 {
2867 if( mCurGreContext.mCameraPortParams[p].mIsActive )
2868 {
2869 goToIdle = false;
2870 break;
2871 }
2872 }
2874 if ( goToIdle && OMX_StateExecuting == getComponentState() )
2875 {
2876 transitToState( OMX_StateIdle );
2877 }
2878 }
2880 return greError;
2881 }
2883 /**
2884 * This will free all the buffers on the preview port
2885 * and switch to loaded state.
2886 */
2887 int OMXVisionCam::releaseBuffers( VisionCamPort_e port)
2888 {
2889 int greError = 0;
2891 OMX_PARAM_PORTDEFINITIONTYPE portCheck[ VCAM_PORT_MAX ];
2893 int32_t p;
2894 LOOP_PORTS( port , p )
2895 {
2896 initPortCheck(&portCheck[p], p);
2898 for( uint32_t indBuff = 0; indBuff < portCheck[p].nBufferCountActual; indBuff++ )
2899 {
2900 if( mFrameDescriptors && mFrameDescriptors[p] && mFrameDescriptors[p][indBuff] )
2901 delete mFrameDescriptors[p][indBuff];
2902 }
2904 if( mFrameDescriptors && mFrameDescriptors[p] )
2905 {
2906 delete mFrameDescriptors[p];
2907 mFrameDescriptors[p] = NULL;
2908 }
2909 }
2911 if (OMX_StateIdle == getComponentState())
2912 transitToState( OMX_StateLoaded, NULL, NULL );
2914 return greError;
2915 }
2917 /** This will configure the component to start/stop face detection.
2918 * Will also start/stop face detection extra data
2919 * faces coordinates will be written into camera frame received
2920 * in preview callback
2921 */
2922 int OMXVisionCam::enableFaceDetect(VisionCamPort_e port)
2923 {
2924 OMX_ERRORTYPE omxError = OMX_ErrorNone;
2925 OMX_CONFIG_OBJDETECTIONTYPE objDetection;
2926 OMX_STRUCT_INIT( objDetection, OMX_CONFIG_OBJDETECTIONTYPE ,mLocalVersion);
2927 objDetection.nPortIndex = mCurGreContext.mPortsInUse[port];
2929 if (mFaceDetectionEnabled)
2930 objDetection.bEnable = OMX_TRUE;
2931 else
2932 objDetection.bEnable = OMX_FALSE;
2934 omxError = OMX_SetConfig(mCurGreContext.mHandleComp, (OMX_INDEXTYPE) OMX_IndexConfigImageFaceDetection, &objDetection);
2935 if( OMX_ErrorNone == omxError )
2936 {
2937 OMX_CONFIG_EXTRADATATYPE xData;
2938 OMX_STRUCT_INIT(xData, OMX_CONFIG_EXTRADATATYPE, mLocalVersion);
2940 xData.nPortIndex = mCurGreContext.mPortsInUse[port];
2941 xData.eExtraDataType = OMX_FaceDetection;
2942 #if defined(TUNA) || defined(MAGURO)
2943 xData.eCameraView = OMX_2D_Prv;
2944 #endif
2945 if (mFaceDetectionEnabled)
2946 xData.bEnable = OMX_TRUE;
2947 else
2948 xData.bEnable = OMX_FALSE;
2950 OMX_CHECK(omxError,OMX_SetConfig(mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_IndexConfigOtherExtraDataControl, &xData));
2951 }
2952 return ConvertError(omxError);
2953 }
2955 /** Fill the face coordinates field in camera frame,
2956 * which will be received by OMXVisionCam client at each frame.
2957 */
2958 void OMXVisionCam::getFacesCoordinates( VisionCamFrame *frame)
2959 {
2960 OMX_OTHER_EXTRADATATYPE* extraData = (OMX_OTHER_EXTRADATATYPE*)frame->mExtraDataBuf;
2961 OMX_U8 *pExtraLimit = (OMX_U8 *)extraData + frame->mExtraDataLength;
2962 OMX_FACEDETECTIONTYPE *facesData;
2963 if( extraData == NULL )
2964 {
2965 frame->mDetectedFacesNum = 0;
2966 return;
2967 }
2969 // find the faces data buffers
2970 while( (OMX_EXTRADATATYPE)OMX_FaceDetection != extraData->eType && extraData->data )
2971 {
2972 MSG("Current Extra Data Section Size: %lu", extraData->nDataSize);
2973 extraData = (OMX_OTHER_EXTRADATATYPE*)(extraData->data + extraData->nDataSize);
2975 if( (OMX_U8 *)extraData >= pExtraLimit )
2976 {
2977 ERROR("ERROR: METADATA: Bad size field in metadata. %p >= %p", extraData, pExtraLimit);
2978 return;
2979 }
2981 if( 0 == extraData->nDataSize )
2982 {
2983 ERROR("METADATA: No face data detected!");
2984 frame->mDetectedFacesNum = 0;
2985 memset( frame->mFaces, 0, MAX_FACES_COUNT*sizeof(VisionCamFaceType) );
2986 return;
2987 }
2988 }
2990 if( extraData->data )
2991 {
2992 facesData = (OMX_FACEDETECTIONTYPE *)(extraData->data);
2994 frame->mDetectedFacesNum = facesData->ulFaceCount;
2996 MSG("METADATA: FACE # %d!", frame->mDetectedFacesNum);
2998 for(uint32_t i = 0; i < frame->mDetectedFacesNum; i++)
2999 {
3000 memcpy( &(frame->mFaces[i]), &(facesData->tFacePosition[i].nScore), sizeof(VisionCamFaceType)) ;
3001 }
3002 }
3003 }
3005 /** Parse through the extra data type structure to find the pointer to the relevent
3006 * data type. This is to abstract the port number, version, and packet structure from the client.
3007 */
3008 void OMXVisionCam::getMetadataPtrs( VisionCamFrame *frame)
3009 {
3010 OMX_OTHER_EXTRADATATYPE* extraData = (OMX_OTHER_EXTRADATATYPE*)frame->mExtraDataBuf;
3011 OMX_U8 *pExtraLimit = (OMX_U8 *)extraData + frame->mExtraDataLength;
3012 frame->mMetadata.mAutoWBGains = NULL;
3013 frame->mMetadata.mManualWBGains = NULL;
3014 frame->mMetadata.mAncillary = NULL;
3015 frame->mMetadata.mHistogram2D = NULL;
3016 frame->mMetadata.mHistogramL = NULL;
3017 frame->mMetadata.mHistogramR = NULL;
3019 if( extraData == NULL )
3020 {
3021 return;
3022 }
3024 while( extraData->eType && extraData->nDataSize && extraData->data ) // keep looping while there is more extra data and double check size
3025 {
3026 switch( extraData->eType )
3027 {
3028 case OMX_AncillaryData:
3029 {
3030 OMX_TI_ANCILLARYDATATYPE *ancillaryData = NULL;
3031 MSG("METADATA: Found Ancillary Data Section!");
3032 ancillaryData = (OMX_TI_ANCILLARYDATATYPE *)(extraData->data);
3033 frame->mMetadata.mAncillary= (VisionCamAncillary*)&ancillaryData->nAncillaryDataVersion;
3034 break;
3035 }
3037 case OMX_WhiteBalance:
3038 {
3039 OMX_TI_WHITEBALANCERESULTTYPE *wbData = NULL;
3040 MSG("METADATA: Found White Balance Result Data Section!");
3041 wbData = (OMX_TI_WHITEBALANCERESULTTYPE *)(extraData->data);
3042 frame->mMetadata.mAutoWBGains = (VisionCamWhiteBalGains*)&wbData->nGainR;
3043 break;
3044 }
3045 #ifndef __QNX__
3046 case OMX_TI_WhiteBalanceOverWrite:
3047 {
3048 OMX_TI_WHITEBALANCERESULTTYPE *wbManData = NULL;
3049 MSG("METADATA: Found White Balance Overwrite Data Section!");
3050 wbManData = (OMX_TI_WHITEBALANCERESULTTYPE *)(extraData->data);
3051 frame->mMetadata.mManualWBGains = (VisionCamWhiteBalGains*)&wbManData->nGainR;
3052 break;
3053 }
3054 #endif
3055 #if defined(DUCATI_2_0)
3056 case OMX_Histogram:
3057 {
3058 OMX_TI_HISTOGRAMTYPE *histData = NULL;
3059 MSG("METADATA: Found Histogram Result Data Section!");
3060 histData = (OMX_TI_HISTOGRAMTYPE *)(extraData->data);
3061 #if defined(TUNA) || defined(MAGURO) || 1
3062 if((OMX_TI_CAMERAVIEWTYPE)(histData->eCameraView) == OMX_2D_Prv)
3063 frame->mMetadata.mHistogram2D = (VisionCamHistogram*)&histData->nBins;
3064 else if((OMX_TI_CAMERAVIEWTYPE)(histData->eCameraView) == OMX_3D_Left_Prv)
3065 frame->mMetadata.mHistogramL = (VisionCamHistogram*)&histData->nBins;
3066 else if((OMX_TI_CAMERAVIEWTYPE)(histData->eCameraView) == OMX_3D_Right_Prv)
3067 frame->mMetadata.mHistogramR = (VisionCamHistogram*)&histData->nBins;
3068 #else
3069 frame->mMetadata.mHistogram2D = (VisionCamHistogram*)&histData->nBins;
3070 #endif
3071 break;
3072 }
3073 #endif
3074 default:
3075 {
3076 break;
3077 }
3078 }
3079 MSG("Current Extra Data Section Size: %lu", extraData->nDataSize);
3080 extraData = (OMX_OTHER_EXTRADATATYPE*)(extraData->data + extraData->nDataSize);
3081 if( (OMX_U8 *)extraData >= pExtraLimit )
3082 {
3083 ERROR("ERROR: METADATA: Bad size field in metadata. %p >= %p", extraData, pExtraLimit);
3084 break;
3085 }
3086 }
3087 }
3089 /** This shall be called by the user of this class when it finishes working
3090 * with the frame and to notify VisionCam that the frame buffer is
3091 * free.
3092 */
3093 int OMXVisionCam::returnFrame(VisionCamFrame *cameraFrame)
3094 {
3095 OMX_ERRORTYPE omxError = OMX_ErrorNone;
3096 int32_t i = 0;
3097 if (mFlushInProcess)
3098 return 0;
3100 if (cameraFrame == NULL)
3101 return -EINVAL;
3103 if (OMX_StateExecuting == getComponentState())
3104 {
3105 VisionCamPort_e port = cameraFrame->mFrameSource;
3106 VCAM_PortParameters * portData = &mCurGreContext.mCameraPortParams[port];
3107 for (i = 0; i < portData->mNumBufs; i++)
3108 {
3109 if (portData->mBufferHeader[i] &&
3110 portData->mBufferHeader[i]->pAppPrivate == cameraFrame->mFrameBuff)
3111 {
3112 omxError = OMX_FillThisBuffer(mCurGreContext.mHandleComp,
3113 mCurGreContext.mCameraPortParams[port].mBufferHeader[i]);
3114 if (OMX_ErrorNone != omxError)
3115 {
3116 ERROR("ERROR: OMX_FillThisBuffer() returned 0x%x in %s", omxError, __func__);
3117 }
3118 else
3119 {
3120 MSG("frame returned successfully in %s", __func__);
3121 }
3122 break;
3123 }
3124 }
3125 if( i == portData->mNumBufs)
3126 {
3127 ERROR("ERROR: returned frame not found in %s", __func__);
3128 }
3129 }
3130 else
3131 {
3132 ERROR("Returning Frame when OMX-CAMERA is in the wrong state or image is NULL");
3133 }
3135 return ConvertError(omxError);
3136 }
3138 int OMXVisionCam::PreemptionService(/*VisionCamPreemptionActivity_e activity*/)
3139 {
3140 OMX_ERRORTYPE omxError = OMX_ErrorNone;
3141 VCAM_PortParameters * portData = NULL;
3143 switch( mPreemptionState )
3144 {
3145 case VCAM_PREEMPT_SUSPEND:
3146 {
3147 // Register for Loaded state switch event
3148 omxError = RegisterForEvent(mCurGreContext.mHandleComp,
3149 OMX_EventCmdComplete,
3150 OMX_CommandStateSet,
3151 OMX_StateLoaded,
3152 &mGreLocalSem,
3153 -1); // Infinite timeout
3155 if( OMX_ErrorNone == omxError )
3156 {
3157 for( int port = VCAM_PORT_PREVIEW; port < VCAM_PORT_MAX; port++ )
3158 {
3159 // Free the OMX Buffers
3160 portData = &mCurGreContext.mCameraPortParams[port];
3161 for( int i = 0; i < portData->mNumBufs; i++ )
3162 {
3163 omxError = OMX_FreeBuffer(mCurGreContext.mHandleComp,
3164 mCurGreContext.mPortsInUse[port],
3165 portData->mBufferHeader[i]);
3167 portData->mBufferHeader[i] = NULL;
3169 if( OMX_ErrorNone != omxError )
3170 {
3171 ERROR("Preemption Service: Error 0x%x while freeing buffers!", omxError);
3172 break;
3173 }
3174 }
3175 }
3176 }
3178 if( OMX_ErrorNone == omxError )
3179 sem_wait(&mGreLocalSem);
3181 if( mClientNotifier.mNotificationCallback && OMX_ErrorNone == omxError )
3182 mClientNotifier.mNotificationCallback(VisionCamClientNotifier::VCAM_MESSAGE_PREEMPT_SUSPEND_ACTIVITY);
3184 // Register for WAIT state switch event
3185 omxError = RegisterForEvent(mCurGreContext.mHandleComp,
3186 OMX_EventCmdComplete,
3187 OMX_CommandStateSet,
3188 OMX_StateWaitForResources,
3189 &mGreLocalSem,
3190 -1); // Infinite timeout
3192 if( OMX_ErrorNone == omxError )
3193 {
3194 omxError = OMX_SendCommand(mCurGreContext.mHandleComp,
3195 OMX_CommandStateSet,
3196 OMX_StateWaitForResources,
3197 NULL);
3198 }
3200 if( OMX_ErrorNone == omxError )
3201 sem_wait(&mGreLocalSem);
3203 break;
3204 }
3205 case VCAM_PREEMPT_RESUME:
3206 {
3207 if( mClientNotifier.mNotificationCallback )
3208 mClientNotifier.mNotificationCallback(VisionCamClientNotifier::VCAM_MESSAGE_PREEMPT_RESUME_ACTIVITY);
3210 // Register for IDLE state switch event
3211 omxError = RegisterForEvent(mCurGreContext.mHandleComp,
3212 OMX_EventCmdComplete,
3213 OMX_CommandStateSet,
3214 OMX_StateIdle,
3215 &mGreLocalSem,
3216 -1); //Infinite timeout
3217 if( OMX_ErrorNone != omxError )
3218 {
3219 ERROR("Preemption Service: Error 0x%x while registering for Idle state wait.", omxError);
3220 break;
3221 }
3223 for( int port = VCAM_PORT_PREVIEW; port < VCAM_PORT_MAX; port++ )
3224 {
3225 portData = &mCurGreContext.mCameraPortParams[port];
3226 for( int buff = 0; buff < portData->mNumBufs; buff++ )
3227 {
3228 OMX_BUFFERHEADERTYPE *pBufferHdr;
3229 OMX_U8 *buffer = (OMX_U8*)mBuffersInUse[port].mBuffers[buff].fd;
3231 omxError = OMX_UseBuffer( mCurGreContext.mHandleComp,
3232 &pBufferHdr,
3233 mCurGreContext.mPortsInUse[port],
3234 0,
3235 portData->mBufSize,
3236 buffer
3237 );
3239 if( OMX_ErrorNone != omxError )
3240 {
3241 ERROR("Preemption Service: Error 0x%x while passing buffers to OMX Component.", omxError);
3242 break;
3243 }
3245 pBufferHdr->pAppPrivate = (OMX_PTR)&mBuffersInUse[port].mBuffers[buff];
3247 pBufferHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
3249 memcpy( &(pBufferHdr->nVersion), mLocalVersion, sizeof( OMX_VERSIONTYPE ) );
3251 portData->mBufferHeader[buff] = pBufferHdr;
3252 }
3253 }
3255 sem_wait(&mGreLocalSem);
3257 // if (mReturnToExecuting)
3258 // {
3259 for( int port = VCAM_PORT_PREVIEW; port < VCAM_PORT_MAX; port++ )
3260 {
3261 if( mCurGreContext.mCameraPortParams[port].mIsActive )
3262 startPreview( (VisionCamPort_e)port );
3263 }
3264 // }
3265 break;
3266 }
3268 case VCAM_PREEMPT_WAIT_TO_START:
3269 {
3270 if( mClientNotifier.mNotificationCallback && OMX_ErrorNone == omxError )
3271 mClientNotifier.mNotificationCallback(VisionCamClientNotifier::VCAM_MESSAGE_PREEMPT_WAIT_RESOURCES);
3273 // Register for WAIT state switch event
3274 omxError = RegisterForEvent(mCurGreContext.mHandleComp,
3275 OMX_EventCmdComplete,
3276 OMX_CommandStateSet,
3277 OMX_StateWaitForResources,
3278 &mGreLocalSem,
3279 -1); // Infinite timeout
3281 if( OMX_ErrorNone == omxError )
3282 {
3283 omxError = OMX_SendCommand(mCurGreContext.mHandleComp,
3284 OMX_CommandStateSet,
3285 OMX_StateWaitForResources,
3286 NULL);
3287 }
3289 if( OMX_ErrorNone == omxError )
3290 sem_wait(&mGreLocalSem);
3292 // Register for WAIT state switch event
3293 omxError = RegisterForEvent(mCurGreContext.mHandleComp,
3294 OMX_EventResourcesAcquired,
3295 0,
3296 0,
3297 &mGreLocalSem,
3298 -1); // Infinite timeout
3300 if( OMX_ErrorNone == omxError )
3301 sem_wait(&mGreLocalSem);
3303 if( mClientNotifier.mNotificationCallback && OMX_ErrorNone == omxError )
3304 mClientNotifier.mNotificationCallback(VisionCamClientNotifier::VCAM_MESSAGE_PREAMPT_REASOURCES_READY);
3306 break;
3307 }
3308 default:
3310 break;
3311 }
3313 if( OMX_ErrorNone == omxError )
3314 mPreemptionState = VCAM_PREEMPT_INACTIVE;
3316 return ConvertError(omxError);
3317 }
3319 OMX_ERRORTYPE OMXVisionCam::RegisterForEvent(OMX_IN OMX_HANDLETYPE hComponent,
3320 OMX_IN OMX_EVENTTYPE eEvent,
3321 OMX_IN OMX_U32 nData1,
3322 OMX_IN OMX_U32 nData2,
3323 OMX_IN sem_t *semaphore,
3324 OMX_IN OMX_U32 timeout)
3325 {
3326 OMXVCAM_Msg_t *msg = (OMXVCAM_Msg_t *)calloc(1, sizeof(OMXVCAM_Msg_t));
3327 OMX_ERRORTYPE err = OMX_ErrorNone;
3328 if (msg)
3329 {
3330 msg->eEvent = eEvent;
3331 msg->nData1 = nData1;
3332 msg->nData2 = nData2;
3333 msg->semaphore = semaphore;
3334 msg->hComponent = hComponent;
3335 msg->timeout = timeout;
3336 mEventSignalQ.push_back(msg);
3337 MSG("Registering for Event %d (0x%08x)", eEvent,eEvent);
3338 }
3339 else
3340 {
3341 err = OMX_ErrorInsufficientResources;
3342 }
3343 return err;
3345 }
3347 extern "C" int node_compare_vcam_msg(void* a, void* b)
3348 {
3349 OMXVCAM_Msg_t *msgA = (OMXVCAM_Msg_t *)a;
3350 OMXVCAM_Msg_t *msgB = (OMXVCAM_Msg_t *)b;
3352 MSG("Comparing Node %p and Node %p",msgA, msgB);
3354 if (msgA->eEvent == msgB->eEvent &&
3355 msgA->nData1 == msgB->nData1 &&
3356 msgA->nData2 == msgB->nData2 &&
3357 msgA->hComponent == msgB->hComponent)
3358 return 0;
3359 else if (msgA->eEvent < msgB->eEvent)
3360 return -1;
3361 else // if (msgA->event > msgB->event)
3362 return 1;
3363 }
3365 /** OMXVisionCam Event Handler from OMX-CAMERA */
3366 OMX_ERRORTYPE OMXVisionCam::EventHandler(OMX_IN OMX_HANDLETYPE hComponent,
3367 OMX_IN OMX_PTR pAppData,
3368 OMX_IN OMX_EVENTTYPE eEvent,
3369 OMX_IN OMX_U32 nData1,
3370 OMX_IN OMX_U32 nData2,
3371 OMX_IN OMX_PTR pEventData)
3372 {
3373 // make a local pointer to the instance class which registered this callback.
3374 OMXVisionCam *pOMXCam = (OMXVisionCam*)pAppData;
3375 size_t len = pOMXCam->mEventSignalQ.size();
3377 MSG("OMXVisionCam::EventHandler() event=%d arg1=%08x arg2=%08x ptr=%p (len=%zu)", eEvent, (uint32_t)nData1, (uint32_t)nData2, pEventData, len);
3378 // check the queue to see if we were waiting on an event
3379 if (len > 0)
3380 {
3381 OMXVCAM_Msg_t* msg = NULL;
3382 std::list<OMXVCAM_Msg_t*>::iterator it;
3383 for (it = pOMXCam->mEventSignalQ.begin(); it != pOMXCam->mEventSignalQ.end(); ++it) {
3384 if ((*it)->eEvent > eEvent) {
3385 break;
3386 }
3387 if (((*it)->eEvent == eEvent) &&
3388 ((*it)->nData1 == nData1) &&
3389 ((*it)->nData2 == nData2) &&
3390 ((*it)->hComponent == hComponent)) {
3391 msg = *it;
3392 break;
3393 }
3394 }
3396 // find the list event which matches this event
3397 if (msg != NULL)
3398 {
3399 MSG("Found Event in List which matches incoming event!");
3400 if (msg->semaphore)
3401 sem_post(msg->semaphore);
3403 pOMXCam->mEventSignalQ.erase(it);
3404 free(msg);
3405 }
3406 else
3407 {
3408 MSG("No matching event found in list!");
3409 }
3410 }
3412 switch( eEvent )
3413 {
3414 case OMX_EventError:
3415 {
3416 switch( nData1 )
3417 {
3418 case OMX_ErrorResourcesPreempted:
3419 break;
3420 case OMX_ErrorResourcesLost:
3421 {
3422 pthread_t thread;
3423 ERROR("OMXVisionCam lost resources!");
3424 pOMXCam->mPreemptionState = VCAM_PREEMPT_SUSPEND;
3425 pthread_create(&thread, NULL, PreemptionThreadLauncher, pOMXCam);
3426 break;
3427 }
3428 case OMX_ErrorInsufficientResources:
3429 {
3430 pthread_t thread;
3431 ERROR("OMXVisionCam has insufficient resources!");
3432 pOMXCam->mPreemptionState = VCAM_PREEMPT_SUSPEND;
3433 pthread_create(&thread, NULL, PreemptionThreadLauncher, pOMXCam);
3434 break;
3435 }
3436 case OMX_ErrorIncorrectStateOperation:
3437 {
3438 break;
3439 }
3440 case OMX_ErrorInvalidState:
3441 {
3442 break;
3443 }
3444 default:
3446 break;
3447 }
3448 break;
3449 }
3450 case OMX_EventResourcesAcquired:
3451 {
3452 break;
3453 }
3454 case OMX_EventCmdComplete:
3455 {
3456 switch (nData1)
3457 {
3458 case OMX_CommandStateSet:
3459 PrintOMXState((OMX_STATETYPE)nData2);
3460 break;
3461 case OMX_CommandFlush:
3462 case OMX_CommandPortDisable:
3463 case OMX_CommandPortEnable:
3464 break;
3465 }
3466 break;
3467 }
3468 case OMX_EventPortSettingsChanged:
3469 case OMX_EventIndexSettingChanged:
3470 MSG("*** Port/Index Settings have Changed!");
3471 break;
3472 default:
3473 break;
3474 }
3475 return OMX_ErrorNone;
3476 }
3478 //GRE Empty buffer done callback
3479 OMX_ERRORTYPE OMXVisionCam::EmptyBufferDone(OMX_IN OMX_HANDLETYPE hComponent,
3480 OMX_IN OMX_PTR pAppData,
3481 OMX_IN OMX_BUFFERHEADERTYPE* pBuffHeader)
3482 {
3483 // OMXVisionCam *pOMXCam = (OMXVisionCam *)pAppData;
3484 pAppData = pAppData;
3485 hComponent = hComponent;
3486 pBuffHeader = pBuffHeader;
3487 return OMX_ErrorNotImplemented;
3488 }
3490 //GRE fill buffer done callback
3491 OMX_ERRORTYPE OMXVisionCam::FillBufferDone(OMX_IN OMX_HANDLETYPE hComponent,
3492 OMX_IN OMX_PTR pAppData,
3493 OMX_IN OMX_BUFFERHEADERTYPE* pBuffHeader) {
3494 OMXVisionCam* pCam = static_cast<OMXVisionCam*>(pAppData);
3495 MSG("OMX-CAMERA has returned a frame (%p) offset=%lu!", pBuffHeader->pAppPrivate, pBuffHeader->nOffset);
3496 pCam->mFrameCbData.frames.push_back(pBuffHeader);
3497 pthread_mutex_unlock(&pCam->mFrameCbData.mutex);
3498 return OMX_ErrorNone;
3499 }
3501 void OMXVisionCam::frameReceivedSrvc(void *data)
3502 {
3503 OMX_BUFFERHEADERTYPE* pBuffHeader = (OMX_BUFFERHEADERTYPE* )data;
3504 VisionCamFrame *cFrame = NULL;
3505 VisionCamPort_e portInd = VCAM_PORT_MAX;
3507 if( !data )
3508 {
3509 return;
3510 }
3512 if( mFlushInProcess )
3513 {
3514 return;
3515 }
3517 AutoLock lock(&mFrameBufferLock);
3519 switch(pBuffHeader->nOutputPortIndex)
3520 {
3521 case VCAM_CAMERA_PORT_VIDEO_OUT_PREVIEW:
3522 {
3523 portInd = VCAM_PORT_PREVIEW;
3524 break;
3525 }
3526 case VCAM_CAMERA_PORT_VIDEO_OUT_VIDEO:
3527 {
3528 portInd = VCAM_PORT_VIDEO;
3529 break;
3530 }
3531 default:
3532 {
3533 portInd = VCAM_PORT_MAX;
3534 break;
3535 }
3536 }
3538 if( portInd > VCAM_PORT_ALL && portInd < VCAM_PORT_MAX && mCurGreContext.mCameraPortParams[portInd].mIsActive )
3539 {
3540 // find the frame descriptor corresponding to received buffer
3541 for( int i = 0; i < mCurGreContext.mCameraPortParams[portInd].mNumBufs; i++ )
3542 {
3543 if( mFrameDescriptors[portInd][i]->mFrameBuff == pBuffHeader->pAppPrivate )
3544 {
3545 cFrame = mFrameDescriptors[portInd][i];
3546 break;
3547 }
3548 }
3549 }
3551 if( cFrame )
3552 {
3553 cFrame->mFrameSource = portInd;
3554 cFrame->mLength = pBuffHeader->nFilledLen;
3555 cFrame->mTimestamp = pBuffHeader->nTimeStamp;
3556 cFrame->mWidth = mCurGreContext.mCameraPortParams[portInd].mWidth;
3557 cFrame->mHeight = mCurGreContext.mCameraPortParams[portInd].mHeight;
3558 cFrame->mCookie = m_cookie;
3559 cFrame->mContext = this;
3560 cFrame->mMetadata.mAutoWBGains = NULL;
3561 cFrame->mMetadata.mManualWBGains = NULL;
3562 cFrame->mMetadata.mAncillary = NULL;
3563 cFrame->mMetadata.mHistogram2D = NULL;
3564 cFrame->mMetadata.mHistogramL = NULL;
3565 cFrame->mMetadata.mHistogramR = NULL;
3566 cFrame->mExtraDataBuf = NULL;
3567 cFrame->mExtraDataLength = 0;
3568 cFrame->mDetectedFacesNum = 0;
3569 memset( cFrame->mFaces, 0, MAX_FACES_COUNT * sizeof(VisionCamFaceType) );
3571 if( VCAM_PORT_PREVIEW == cFrame->mFrameSource )
3572 m_frameNum++;
3574 if (m_callback != NULL)
3575 {
3576 m_callback(cFrame);
3577 }
3578 }
3579 else
3580 {
3581 ERROR("ERROR: a frame buffer is received, but there is no matching buffer." );
3582 }
3583 }
3585 #if TIME_PROFILE
3586 void OMXVisionCam::PopulateTimeProfiler()
3587 {
3588 mTimeProfiler[ first ] = new VisionCamTimePtofile("first");
3589 mTimeProfiler[ second ] = new VisionCamTimePtofile();
3590 mTimeProfiler[ last ] = new VisionCamTimePtofile();
3591 }
3593 VisionCamTimePtofile::VisionCamTimePtofile( const char * name ){
3594 memset( &mStart, 0, sizeof(struct timeval) );
3595 memset( &mEnd, 0, sizeof(struct timeval) );
3597 if( name )
3598 mName = name;
3599 else
3600 mName = "unknown";
3601 };
3603 VisionCamTimePtofile::~VisionCamTimePtofile(){
3604 dump();
3605 };
3607 void VisionCamTimePtofile::dump() {
3608 if( mEnd.tv_usec && mStart.tv_usec )
3609 {
3610 double time = (double)(mEnd.tv_usec = mStart.tv_usec) / (double)1000;
3611 printf("TIME: %s - %g [ms]\r", mName, time );
3612 memset( &mStart, 0, sizeof(struct timeval) );
3613 memset( &mEnd, 0, sizeof(struct timeval) );
3614 }
3615 }
3617 #endif // TIME_PROFILE