Android Camera OMXCameraAdapter.cpp初始化分析

Android Camera OMXCameraAdapter.cpp初始化分析

這幾天一直在研究android 的omx機制,我針對的android是4.0.3,主要是TI 的4430,4460的omx方式實現,這裏還是簡單的說一下爲什麼要研究這個文件
之前有一篇文章已經比較詳細的說過了OMAP4系列芯片了,這裏這個OMXCameraAdapter其實就是omap4 A9端的omx client,通過這個client與ducati端(也就是omap4的DSP端)的omx進行通信,可以把ducati端的這個omx簡單理解爲omx servicer,之前已經說了很多了andriod camera了,但是之前文章都是針對V4LCameraAdapter這個適配器進行的,這是大家都比較瞭解的,就是app通過V4L2這種方式與kernel camera driver實現交互,進而實現camera 的使用,包括數據回調等過程,但是這裏的OMX方法完全顛覆了我之前的想法,開始在研究OMX的時候自己就是調用這個死衚衕裏了,一直在試圖在OMX的實現中找到他到底是在哪麼訪問設備的,本來我是以後最終他還是通過V4L2這種方式,事實證明我錯了,OMX是一種完全不同於V4L2 的訪問camera的策略,他通過A9端的omx client和DSP端的omx通信,而且最終訪問camera的方法是在DSP端omx server接到到A9端的omx client配置後按照指定方法實現camera 的控制的,這裏ducati端到底是怎麼處理的我暫時沒有關注,暫時精力有限啊!
以上是我自己的見解,也許是完全錯誤的,待確認,這裏只是總結我的分析過程
經過上面我的概述,自然A9端的這個OMXCameraAdapter對於我來說就是一切了,分析它是必經之路啊
現在就開始:
首先要知道在哪裏實例化了這個類的對象,這個在之前已經說到過了,這個不在說明,重點看看他的initialize方法都幹了些甚麼?
  1. /*--------------------Camera Adapter Class STARTS here-----------------------------*/

  2. status_t OMXCameraAdapter::initialize(CameraProperties::Properties* caps)
  3. {
  4.     LOG_FUNCTION_NAME;

  5.     char value[PROPERTY_VALUE_MAX];
  6.     const char *mountOrientationString = NULL;

  7.     property_get("debug.camera.showfps", value, "0");
  8.     mDebugFps = atoi(value);
  9.     property_get("debug.camera.framecounts", value, "0");
  10.     mDebugFcs = atoi(value);

  11. #ifdef CAMERAHAL_OMX_PROFILING

  12.     property_get("debug.camera.profile", value, "0");
  13.     mDebugProfile = atoi(value);

  14. #endif

  15.     TIMM_OSAL_ERRORTYPE osalError = OMX_ErrorNone;
  16.     OMX_ERRORTYPE eError = OMX_ErrorNone;
  17.     status_t ret = NO_ERROR;

  18.     mLocalVersionParam.s.nVersionMajor = 0x1;
  19.     mLocalVersionParam.s.nVersionMinor = 0x1;
  20.     mLocalVersionParam.s.nRevision = 0x0 ;
  21.     mLocalVersionParam.s.nStep = 0x0;

  22.     mPending3Asettings = 0;//E3AsettingsAll;
  23.     mPendingCaptureSettings = 0;
  24.     mPendingPreviewSettings = 0;

  25.     if ( 0 != mInitSem.Count() )
  26.         {
  27.         CAMHAL_LOGEB("Error mInitSem semaphore count %d", mInitSem.Count());
  28.         LOG_FUNCTION_NAME_EXIT;
  29.         return NO_INIT;
  30.         }

  31.     ///Update the preview and image capture port indexes
  32.     mCameraAdapterParameters.mPrevPortIndex = OMX_CAMERA_PORT_VIDEO_OUT_PREVIEW;
  33.     // temp changed in order to build OMX_CAMERA_PORT_VIDEO_OUT_IMAGE;
  34.     mCameraAdapterParameters.mImagePortIndex = OMX_CAMERA_PORT_IMAGE_OUT_IMAGE;
  35.     mCameraAdapterParameters.mMeasurementPortIndex = OMX_CAMERA_PORT_VIDEO_OUT_MEASUREMENT;
  36.     //currently not supported use preview port instead
  37.     mCameraAdapterParameters.mVideoPortIndex = OMX_CAMERA_PORT_VIDEO_OUT_VIDEO;
  38.     mCameraAdapterParameters.mVideoInPortIndex = OMX_CAMERA_PORT_VIDEO_IN_VIDEO;
  39.     // 1.OMX_Init
  40.     eError = OMX_Init();
  41.     if (eError != OMX_ErrorNone) {
  42.         CAMHAL_LOGEB("OMX_Init() failed, error: 0x%x", eError);
  43.         return ErrorUtils::omxToAndroidError(eError);
  44.     }
  45.     mOmxInitialized = true;

  46.     // 2.Initialize the callback handles
  47.     OMX_CALLBACKTYPE callbacks;
  48.     callbacks.EventHandler = android::OMXCameraAdapterEventHandler;
  49.     callbacks.EmptyBufferDone = android::OMXCameraAdapterEmptyBufferDone;
  50.     callbacks.FillBufferDone = android::OMXCameraAdapterFillBufferDone;

  51.     // 3.Get the handle to the OMX Component
  52.     eError = OMXCameraAdapter::OMXCameraGetHandle(&mCameraAdapterParameters.mHandleComp, this, callbacks);
  53.     if(eError != OMX_ErrorNone) {
  54.         CAMHAL_LOGEB("OMX_GetHandle -0x%x", eError);
  55.     }
  56.     GOTO_EXIT_IF((eError != OMX_ErrorNone), eError);

  57.     mComponentState = OMX_StateLoaded;

  58.     CAMHAL_LOGVB("OMX_GetHandle -0x%x sensor_index = %lu", eError, mSensorIndex);
  59.     initDccFileDataSave(&mCameraAdapterParameters.mHandleComp, mCameraAdapterParameters.mPrevPortIndex);

  60.     eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp, OMX_CommandPortDisable, OMX_ALL,NULL);

  61.     if(eError != OMX_ErrorNone) {
  62.          CAMHAL_LOGEB("OMX_SendCommand(OMX_CommandPortDisable) -0x%x", eError);
  63.     }
  64.     GOTO_EXIT_IF((eError != OMX_ErrorNone), eError);

  65.     // 4.Register for port enable event
  66.     ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
  67.                                  OMX_EventCmdComplete,
  68.                                  OMX_CommandPortEnable,
  69.                                  mCameraAdapterParameters.mPrevPortIndex,
  70.                                  mInitSem);
  71.     if(ret != NO_ERROR) {
  72.          CAMHAL_LOGEB("Error in registering for event %d", ret);
  73.          goto EXIT;
  74.     }

  75.     // 5.Enable PREVIEW Port
  76.     eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp,
  77.                                  OMX_CommandPortEnable,
  78.                                  mCameraAdapterParameters.mPrevPortIndex,
  79.                                  NULL);
  80.     if(eError != OMX_ErrorNone) {
  81.         CAMHAL_LOGEB("OMX_SendCommand(OMX_CommandPortEnable) -0x%x", eError);
  82.     }
  83.     GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);

  84.     // 6.Wait for the port enable event to occur
  85.     ret = mInitSem.WaitTimeout(OMX_CMD_TIMEOUT);
  86.     if ( NO_ERROR == ret ) {
  87.          CAMHAL_LOGDA("-Port enable event arrived");
  88.     } else {
  89.          ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp,
  90.                             OMX_EventCmdComplete,
  91.                             OMX_CommandPortEnable,
  92.                             mCameraAdapterParameters.mPrevPortIndex,
  93.                             NULL);
  94.          CAMHAL_LOGEA("Timeout for enabling preview port expired!");
  95.          goto EXIT;
  96.      }

  97.     // 7.Select the sensor
  98.     OMX_CONFIG_SENSORSELECTTYPE sensorSelect;
  99.     OMX_INIT_STRUCT_PTR (&sensorSelect, OMX_CONFIG_SENSORSELECTTYPE);
  100.     sensorSelect.eSensor = (OMX_SENSORSELECT) mSensorIndex;
  101.     eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, ( OMX_INDEXTYPE ) OMX_TI_IndexConfigSensorSelect, &sensorSelect);
  102.     if ( OMX_ErrorNone != eError ) {
  103.         CAMHAL_LOGEB("Error while selecting the sensor index as %d - 0x%x", mSensorIndex, eError);
  104.         return BAD_VALUE;
  105.     } else {
  106.         CAMHAL_LOGDB("Sensor %d selected successfully", mSensorIndex);
  107.     }

  108. #ifdef CAMERAHAL_DEBUG

  109.     printComponentVersion(mCameraAdapterParameters.mHandleComp);

  110. #endif
  111.     // 8.初始化默認參數
  112.     mBracketingEnabled = false;
  113.     mZoomBracketingEnabled = false;
  114.     mBracketingBuffersQueuedCount = 0;
  115.     mBracketingRange = 1;
  116.     mLastBracetingBufferIdx = 0;
  117.     mBracketingBuffersQueued = NULL;
  118.     mOMXStateSwitch = false;
  119.     mBracketingSet = false;
  120. #ifdef CAMERAHAL_USE_RAW_IMAGE_SAVING
  121.     mRawCapture = false;
  122.     mYuvCapture = false;
  123. #endif

  124.     mCaptureSignalled = false;
  125.     mCaptureConfigured = false;
  126.     mReprocConfigured = false;
  127.     mRecording = false;
  128.     mWaitingForSnapshot = false;
  129.     mPictureFormatFromClient = NULL;

  130.     mCapabilitiesOpMode = MODE_MAX;
  131.     mCapMode = INITIAL_MODE;
  132.     mIPP = IPP_NULL;
  133.     mVstabEnabled = false;
  134.     mVnfEnabled = false;
  135.     mBurstFrames = 1;
  136.     mBurstFramesAccum = 0;
  137.     mCapturedFrames = 0;
  138.     mFlushShotConfigQueue = false;
  139.     mPictureQuality = 100;
  140.     mCurrentZoomIdx = 0;
  141.     mTargetZoomIdx = 0;
  142.     mPreviousZoomIndx = 0;
  143.     mReturnZoomStatus = false;
  144.     mZoomInc = 1;
  145.     mZoomParameterIdx = 0;
  146.     mExposureBracketingValidEntries = 0;
  147.     mZoomBracketingValidEntries = 0;
  148.     mSensorOverclock = false;
  149.     mAutoConv = OMX_TI_AutoConvergenceModeMax;
  150.     mManualConv = 0;
  151.     mDeviceOrientation = 0;
  152.     mCapabilities = caps;
  153.     mZoomUpdating = false;
  154.     mZoomUpdate = false;
  155.     mGBCE = BRIGHTNESS_OFF;
  156.     mGLBCE = BRIGHTNESS_OFF;
  157.     mParameters3A.ExposureLock = OMX_FALSE;
  158.     mParameters3A.WhiteBalanceLock = OMX_FALSE;

  159.     mEXIFData.mGPSData.mAltitudeValid = false;
  160.     mEXIFData.mGPSData.mDatestampValid = false;
  161.     mEXIFData.mGPSData.mLatValid = false;
  162.     mEXIFData.mGPSData.mLongValid = false;
  163.     mEXIFData.mGPSData.mMapDatumValid = false;
  164.     mEXIFData.mGPSData.mProcMethodValid = false;
  165.     mEXIFData.mGPSData.mVersionIdValid = false;
  166.     mEXIFData.mGPSData.mTimeStampValid = false;
  167.     mEXIFData.mModelValid = false;
  168.     mEXIFData.mMakeValid = false;

  169.     //update the mDeviceOrientation with the sensor mount orientation.
  170.     //So that the face detect will work before onOrientationEvent()
  171.     //get triggered.
  172.     CAMHAL_ASSERT(mCapabilities);
  173.     mountOrientationString = mCapabilities->get(CameraProperties::ORIENTATION_INDEX);
  174.     CAMHAL_ASSERT(mountOrientationString);
  175.     mDeviceOrientation = atoi(mountOrientationString);

  176.     if (mSensorIndex != 2) {
  177.         mCapabilities->setMode(MODE_HIGH_SPEED);
  178.     }

  179.     if (mCapabilities->get(CameraProperties::SUPPORTED_ZOOM_STAGES) != NULL) {
  180.         mMaxZoomSupported = mCapabilities->getInt(CameraProperties::SUPPORTED_ZOOM_STAGES) + 1;
  181.     } else {
  182.         mMaxZoomSupported = 1;
  183.     }

  184.     // 9.initialize command handling thread
  185.     if(mCommandHandler.get() == NULL)
  186.         mCommandHandler = new CommandHandler(this);

  187.     if ( NULL == mCommandHandler.get() )
  188.     {
  189.         CAMHAL_LOGEA("Couldn't create command handler");
  190.         return NO_MEMORY;
  191.     }

  192.     ret = mCommandHandler->run("CallbackThread", PRIORITY_URGENT_DISPLAY);
  193.     if ( ret != NO_ERROR )
  194.     {
  195.         if( ret == INVALID_OPERATION){
  196.             CAMHAL_LOGDA("command handler thread already runnning!!");
  197.             ret = NO_ERROR;
  198.         } else {
  199.             CAMHAL_LOGEA("Couldn't run command handlerthread");
  200.             return ret;
  201.         }
  202.     }

  203.     // 10.initialize omx callback handling thread
  204.     if(mOMXCallbackHandler.get() == NULL)
  205.         mOMXCallbackHandler = new OMXCallbackHandler(this);

  206.     if ( NULL == mOMXCallbackHandler.get() )
  207.     {
  208.         CAMHAL_LOGEA("Couldn't create omx callback handler");
  209.         return NO_MEMORY;
  210.     }

  211.     ret = mOMXCallbackHandler->run("OMXCallbackThread", PRIORITY_URGENT_DISPLAY);
  212.     if ( ret != NO_ERROR )
  213.     {
  214.         if( ret == INVALID_OPERATION){
  215.             CAMHAL_LOGDA("omx callback handler thread already runnning!!");
  216.             ret = NO_ERROR;
  217.         } else {
  218.             CAMHAL_LOGEA("Couldn't run omx callback handler thread");
  219.             return ret;
  220.         }
  221.     }

  222.     OMX_INIT_STRUCT_PTR (&mRegionPriority, OMX_TI_CONFIG_3A_REGION_PRIORITY);
  223.     OMX_INIT_STRUCT_PTR (&mFacePriority, OMX_TI_CONFIG_3A_FACE_PRIORITY);
  224.     mRegionPriority.nPortIndex = OMX_ALL;
  225.     mFacePriority.nPortIndex = OMX_ALL;

  226.     //Setting this flag will that the first setParameter call will apply all 3A settings
  227.     //and will not conditionally apply based on current values.
  228.     mFirstTimeInit = true;

  229.     //Flag to avoid calling setVFramerate() before OMX_SetParameter(OMX_IndexParamPortDefinition)
  230.     //Ducati will return an error otherwise.
  231.     mSetFormatDone = false;

  232.     memset(mExposureBracketingValues, 0, EXP_BRACKET_RANGE*sizeof(int));
  233.     memset(mZoomBracketingValues, 0, ZOOM_BRACKET_RANGE*sizeof(int));
  234.     mMeasurementEnabled = false;
  235.     mFaceDetectionRunning = false;
  236.     mFaceDetectionPaused = false;
  237.     mFDSwitchAlgoPriority = false;

  238.     memset(&mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex], 0, sizeof(OMXCameraPortParameters));
  239.     memset(&mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex], 0, sizeof(OMXCameraPortParameters));
  240.     memset(&mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoPortIndex], 0, sizeof(OMXCameraPortParameters));
  241.     memset(&mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoInPortIndex], 0, sizeof(OMXCameraPortParameters));

  242.     // 11.initialize 3A defaults
  243.     mParameters3A.Effect = getLUTvalue_HALtoOMX(OMXCameraAdapter::DEFAULT_EFFECT, EffLUT);
  244.     mParameters3A.FlashMode = getLUTvalue_HALtoOMX(OMXCameraAdapter::DEFAULT_FLASH_MODE, FlashLUT);
  245.     mParameters3A.SceneMode = getLUTvalue_HALtoOMX(OMXCameraAdapter::DEFAULT_SCENE_MODE, SceneLUT);
  246.     mParameters3A.EVCompensation = atoi(OMXCameraAdapter::DEFAULT_EV_COMPENSATION);
  247.     mParameters3A.Focus = getLUTvalue_HALtoOMX(OMXCameraAdapter::DEFAULT_FOCUS_MODE, FocusLUT);
  248.     mParameters3A.ISO = getLUTvalue_HALtoOMX(OMXCameraAdapter::DEFAULT_ISO_MODE, IsoLUT);
  249.     mParameters3A.Flicker = getLUTvalue_HALtoOMX(OMXCameraAdapter::DEFAULT_ANTIBANDING, FlickerLUT);
  250.     mParameters3A.Brightness = atoi(OMXCameraAdapter::DEFAULT_BRIGHTNESS);
  251.     mParameters3A.Saturation = atoi(OMXCameraAdapter::DEFAULT_SATURATION) - SATURATION_OFFSET;
  252.     mParameters3A.Sharpness = atoi(OMXCameraAdapter::DEFAULT_SHARPNESS) - SHARPNESS_OFFSET;
  253.     mParameters3A.Contrast = atoi(OMXCameraAdapter::DEFAULT_CONTRAST) - CONTRAST_OFFSET;
  254.     mParameters3A.WhiteBallance = getLUTvalue_HALtoOMX(OMXCameraAdapter::DEFAULT_WB, WBalLUT);
  255.     mParameters3A.Exposure = getLUTvalue_HALtoOMX(OMXCameraAdapter::DEFAULT_EXPOSURE_MODE, ExpLUT);
  256.     mParameters3A.ExposureLock = OMX_FALSE;
  257.     mParameters3A.FocusLock = OMX_FALSE;
  258.     mParameters3A.WhiteBalanceLock = OMX_FALSE;

  259.     mParameters3A.ManualExposure = 0;
  260.     mParameters3A.ManualExposureRight = 0;
  261.     mParameters3A.ManualGain = 0;
  262.     mParameters3A.ManualGainRight = 0;

  263.     mParameters3A.AlgoFixedGamma = OMX_TRUE;
  264.     mParameters3A.AlgoNSF1 = OMX_TRUE;
  265.     mParameters3A.AlgoNSF2 = OMX_TRUE;
  266.     mParameters3A.AlgoSharpening = OMX_TRUE;
  267.     mParameters3A.AlgoThreeLinColorMap = OMX_TRUE;
  268.     mParameters3A.AlgoGIC = OMX_TRUE;

  269.     LOG_FUNCTION_NAME_EXIT;
  270.     return ErrorUtils::omxToAndroidError(eError);

  271.     EXIT:

  272.     CAMHAL_LOGDB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
  273.     performCleanupAfterError();
  274.     LOG_FUNCTION_NAME_EXIT;
  275.     return ErrorUtils::omxToAndroidError(eError);
  276. }
就是這裏了,下面對上面的方法按步驟一一做分析

1.OMX_Init
從字面上就可以知道,要使用OMX這個方式,那就要爲使用它做準備啊,初始化,但我們還是嚴謹點,說一說吧,
  1. /** The OMX_Init method is used to initialize the OMX core. It shall be the
  2.     first call made into OMX and it should only be executed one time without
  3.     an interviening OMX_Deinit call. 
  4.     
  5.     The core should return from this call within 20 msec.

  6.     @return OMX_ERRORTYPE
  7.         If the command successfully executes, the return code will be
  8.         OMX_ErrorNone. Otherwise the appropriate OMX error will be returned.
  9.     @ingroup core
  10.  */
  11. OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Init(void);

2.Initialize the callback handles
這裏初始化callback handle,那麼上面初始化了三個handle,這三個handle具體都實現什麼用途呢?
當然一下不是我說的,是TI爲方便大家理解,在andriod底層加入了很多很全的註釋,一起看看吧
  1. typedef struct OMX_CALLBACKTYPE
  2. {
  3.     /** The EventHandler method is used to notify the application when an
  4.         event of interest occurs. Events are defined in the OMX_EVENTTYPE
  5.         enumeration. Please see that enumeration for details of what will
  6.         be returned for each type of event. Callbacks should not return
  7.         an error to the component, so if an error occurs, the application 
  8.         shall handle it internally. This is a blocking call.

  9.         The application should return from this call within 5 msec to avoid
  10.         blocking the component for an excessively long period of time.

  11.         @param hComponent
  12.             handle of the component to access. This is the component
  13.             handle returned by the call to the GetHandle function.
  14.         @param pAppData
  15.             pointer to an application defined value that was provided in the 
  16.             pAppData parameter to the OMX_GetHandle method for the component.
  17.             This application defined value is provided so that the application 
  18.             can have a component specific context when receiving the callback.
  19.         @param eEvent
  20.             Event that the component wants to notify the application about.
  21.         @param nData1
  22.             nData will be the OMX_ERRORTYPE for an error event and will be 
  23.             an OMX_COMMANDTYPE for a command complete event and OMX_INDEXTYPE for a OMX_PortSettingsChanged event.
  24.          @param nData2
  25.             nData2 will hold further information related to the event. Can be OMX_STATETYPE for
  26.             a OMX_CommandStateSet command or port index for a OMX_PortSettingsChanged event.
  27.             Default value is 0 if not used. )
  28.         @param pEventData
  29.             Pointer to additional event-specific data (see spec for meaning).
  30.       */

  31.    OMX_ERRORTYPE (*EventHandler)(
  32.         OMX_IN OMX_HANDLETYPE hComponent,
  33.         OMX_IN OMX_PTR pAppData,
  34.         OMX_IN OMX_EVENTTYPE eEvent,
  35.         OMX_IN OMX_U32 nData1,
  36.         OMX_IN OMX_U32 nData2,
  37.         OMX_IN OMX_PTR pEventData);

  38.     /** The EmptyBufferDone method is used to return emptied buffers from an
  39.         input port back to the application for reuse. This is a blocking call 
  40.         so the application should not attempt to refill the buffers during this
  41.         call, but should queue them and refill them in another thread. There
  42.         is no error return, so the application shall handle any errors generated
  43.         internally. 
  44.         
  45.         The application should return from this call within 5 msec.
  46.         
  47.         @param hComponent
  48.             handle of the component to access. This is the component
  49.             handle returned by the call to the GetHandle function.
  50.         @param pAppData
  51.             pointer to an application defined value that was provided in the 
  52.             pAppData parameter to the OMX_GetHandle method for the component.
  53.             This application defined value is provided so that the application 
  54.             can have a component specific context when receiving the callback.
  55.         @param pBuffer
  56.             pointer to an OMX_BUFFERHEADERTYPE structure allocated with UseBuffer
  57.             or AllocateBuffer indicating the buffer that was emptied.
  58.         @ingroup buf
  59.      */
  60.     OMX_ERRORTYPE (*EmptyBufferDone)(
  61.         OMX_IN OMX_HANDLETYPE hComponent,
  62.         OMX_IN OMX_PTR pAppData,
  63.         OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);

  64.     /** The FillBufferDone method is used to return filled buffers from an
  65.         output port back to the application for emptying and then reuse. 
  66.         This is a blocking call so the application should not attempt to 
  67.         empty the buffers during this call, but should queue the buffers 
  68.         and empty them in another thread. There is no error return, so 
  69.         the application shall handle any errors generated internally. The 
  70.         application shall also update the buffer header to indicate the
  71.         number of bytes placed into the buffer. 

  72.         The application should return from this call within 5 msec.
  73.         
  74.         @param hComponent
  75.             handle of the component to access. This is the component
  76.             handle returned by the call to the GetHandle function.
  77.         @param pAppData
  78.             pointer to an application defined value that was provided in the 
  79.             pAppData parameter to the OMX_GetHandle method for the component.
  80.             This application defined value is provided so that the application 
  81.             can have a component specific context when receiving the callback.
  82.         @param pBuffer
  83.             pointer to an OMX_BUFFERHEADERTYPE structure allocated with UseBuffer
  84.             or AllocateBuffer indicating the buffer that was filled.
  85.         @ingroup buf
  86.      */
  87.     OMX_ERRORTYPE (*FillBufferDone)(
  88.         OMX_OUT OMX_HANDLETYPE hComponent,
  89.         OMX_OUT OMX_PTR pAppData,
  90.         OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer);

  91. } OMX_CALLBACKTYPE;
EmptyBufferDone 方法用來實現從組件的輸入端口獲取到空的緩衝區返回給應用層使得可以重新被使用,這是一個阻塞型的調用,這個調用期間你不可以使用fillThisBuffer方法去fill這個緩衝區,你應該在另外一個線程中進行這個工作,這個回調方法不會提示error信息,所以需要用戶端自己去分辨,並處理這些信息,保存錯誤信息;
EventHandler方法用來通知應用層一些應用層可能感興趣的一些事件,事件分很多類型,已經用枚舉方式定義在OMX_EVENTTYPE中,這個回調方法同樣不會提示error信息,所以需要用戶端自己去分辨,並處理這些信息,保存錯誤信息;
FillBufferDone方法用來實現從組件的輸出端口獲取到經過解碼等很多操作的buffer,並且放回給應用層,應用層獲取使用後,在通過emptyThisBuffer方法清空buffer再次利用,這個回調方法同樣不會提示error信息,所以需要用戶端自己去分辨,並處理這些信息,保存錯誤信息,這裏應用層還有一件很重要的事情要做,應用程序要更新緩衝區header的位置,新數據加入,header後移;

3.Get the handle to the OMX Component
  1. OMX_ERRORTYPE OMXCameraAdapter::OMXCameraGetHandle(OMX_HANDLETYPE *handle, OMX_PTR pAppData,
  2.         const OMX_CALLBACKTYPE & callbacks)
  3. {
  4.     OMX_ERRORTYPE eError = OMX_ErrorUndefined;

  5.     for ( int i = 0; i < 5; ++) {
  6.         if ( i > 0 ) {
  7.             // sleep for 100 ms before next attempt
  8.             usleep(100000);
  9.         }

  10.         // setup key parameters to send to Ducati during init
  11.         OMX_CALLBACKTYPE oCallbacks = callbacks;

  12.         // get handle
  13.         eError = OMX_GetHandle(handle, (OMX_STRING)"OMX.TI.DUCATI1.VIDEO.CAMERA", pAppData, &oCallbacks);
  14.         if ( eError == OMX_ErrorNone ) {
  15.             return OMX_ErrorNone;
  16.         }

  17.         CAMHAL_LOGEB("OMX_GetHandle() failed, error: 0x%x", eError);
  18.     }

  19.     *handle = 0;
  20.     return eError;
  21. }
這個傳入上面初始化的callbacks,是爲了獲取到handle,這個handle對應一個組件,每個組件同樣擁有自己的callbacks方法,所以這裏不同的組件公用callbacks,看看這個OMX_GetHandle吧,因爲有註釋,可以更好理解啊,嘿嘿
  1. /** The OMX_GetHandle method will locate the component specified by the
  2.     component name given, load that component into memory and then invoke
  3.     the component's methods to create an instance of the component. 
  4.     
  5.     The core should return from this call within 20 msec.
  6.     
  7.     @param [out] pHandle
  8.         pointer to an OMX_HANDLETYPE pointer to be filled in by this method.
  9.     @param [in] cComponentName
  10.         pointer to a null terminated string with the component name. The
  11.         names of the components are strings less than 127 bytes in length
  12.         plus the trailing null for a maximum size of 128 bytes. An example 
  13.         of a valid component name is "OMX.TI.AUDIO.DSP.MIXER\0". Names are 
  14.         assigned by the vendor, but shall start with "OMX." and then have 
  15.         the Vendor designation next.
  16.     @param [in] pAppData
  17.         pointer to an application defined value that will be returned
  18.         during callbacks so that the application can identify the source
  19.         of the callback.
  20.     @param [in] pCallBacks
  21.         pointer to a OMX_CALLBACKTYPE structure that will be passed to the
  22.         component to initialize it with. 
  23.     @return OMX_ERRORTYPE
  24.         If the command successfully executes, the return code will be
  25.         OMX_ErrorNone. Otherwise the appropriate OMX error will be returned.
  26.     @ingroup core
  27.  */
  28. OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle(
  29.     OMX_OUT OMX_HANDLETYPE* pHandle, 
  30.     OMX_IN OMX_STRING cComponentName,
  31.     OMX_IN OMX_PTR pAppData,
  32.     OMX_IN OMX_CALLBACKTYPE* pCallBacks);
這個方法會通過name獲取到想要的組件,並且加載組件的內存,請求組件中定義的方法實例化組件

4.設置組件最初狀態爲OMX_StateLoaded狀態,並disable所以command port
mComponentState = OMX_StateLoaded;
eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp, OMX_CommandPortDisable, OMX_ALL,NULL);
這裏必須重點說說OMX_SendCommand這個方法
  1. /** Send a command to the component. This call is a non-blocking call.
  2.     The component should check the parameters and then queue the command
  3.     to the component thread to be executed. The component thread shall 
  4.     send the EventHandler() callback at the conclusion of the command. 
  5.     This macro will go directly from the application to the component (via
  6.     a core macro). The component will return from this call within 5 msec.
  7.     
  8.     When the command is "OMX_CommandStateSet" the component will queue a
  9.     state transition to the new state idenfied in nParam.
  10.     
  11.     When the command is "OMX_CommandFlush", to flush a port's buffer queues,
  12.     the command will force the component to return all buffers NOT CURRENTLY 
  13.     BEING PROCESSED to the application, in the order in which the buffers 
  14.     were received.
  15.     
  16.     When the command is "OMX_CommandPortDisable" or 
  17.     "OMX_CommandPortEnable", the component's port (given by the value of
  18.     nParam) will be stopped or restarted. 
  19.     
  20.     When the command "OMX_CommandMarkBuffer" is used to mark a buffer, the
  21.     pCmdData will point to a OMX_MARKTYPE structure containing the component
  22.     handle of the component to examine the buffer chain for the mark. nParam1
  23.     contains the index of the port on which the buffer mark is applied.

  24.     Specification text for more details. 
  25.     
  26.     @param [in] hComponent
  27.         handle of component to execute the command
  28.     @param [in] Cmd
  29.         Command for the component to execute
  30.     @param [in] nParam
  31.         Parameter for the command to be executed. When Cmd has the value 
  32.         OMX_CommandStateSet, value is a member of OMX_STATETYPE. When Cmd has 
  33.         the value OMX_CommandFlush, value of nParam indicates which port(s) 
  34.         to flush. -is used to flush all ports a single port index will 
  35.         only flush that port. When Cmd has the value "OMX_CommandPortDisable"
  36.         or "OMX_CommandPortEnable", the component's port is given by 
  37.         the value of nParam. When Cmd has the value "OMX_CommandMarkBuffer"
  38.         the components pot is given by the value of nParam.
  39.     @param [in] pCmdData
  40.         Parameter pointing to the OMX_MARKTYPE structure when Cmd has the value
  41.         "OMX_CommandMarkBuffer". 
  42.     @return OMX_ERRORTYPE
  43.         If the command successfully executes, the return code will be
  44.         OMX_ErrorNone. Otherwise the appropriate OMX error will be returned.
  45.     @ingroup comp
  46.  */
  47. #define OMX_SendCommand( \
  48.          hComponent, \
  49.          Cmd, \
  50.          nParam, \
  51.          pCmdData) \
  52.      ((OMX_COMPONENTTYPE*)hComponent)->SendCommand( \
  53.          hComponent, \
  54.          Cmd, \
  55.          nParam, \
  56.          pCmdData) /* Macro End */
通過這個方法給組件發送一個command,組件接收到command後會檢查傳入的參數並將這個command壓入隊列,待組件的處理線程處理,處理完成後會通過上面初始化的EventHandler通知應用層處理結果,最多不會超出5min,超過則超時報錯,具體的command type上面註釋中已經說明,簡單說明一下吧
在上面參數中分爲以下幾種情況:
1.Cmd 爲OMX_CommandStateSet
這種command用於組件狀態之間的切換
這個第三個參數nParam代表參數類型是OMX_STATETYPE,是組件的狀態參數

2.Cmd 爲OMX_CommandFlush
這種command用於刷新組件緩衝區,不管是否緩衝區經過處理,緩衝區數據都會按照接收的順序交給應用層
這個第三個參數nParam代表參數類型是組件的port,第四個參數pCmdData都爲NULL

3.Cmd 爲OMX_CommandPortDisable或者OMX_CommandPortEnable
這個情況下,第三個參數nParam代表要設置disable或enable的組件的port,OMX_ALL表示所有的組件,第四個參數pCmdData都爲NULL

4.Cmd 爲OMX_CommandMarkBuffer
這種command用於標記組件緩衝區
這個第三個參數nParam代表參數類型是組件的port,第四個參數的類型是OMX_MARKTYPE 結構

5.Register for port enable event
調用方式如下:
ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,//這個參數指定組件的handle
                                 OMX_EventCmdComplete,//這個參數是EventType
                                 OMX_CommandPortEnable,//nData1
                                 mCameraAdapterParameters.mPrevPortIndex,//nData2
                                 mInitSem);//這個參數是信號量,保證同步

  1. status_t OMXCameraAdapter::RegisterForEvent(OMX_IN OMX_HANDLETYPE hComponent,
  2.                                           OMX_IN OMX_EVENTTYPE eEvent,
  3.                                           OMX_IN OMX_U32 nData1,
  4.                                           OMX_IN OMX_U32 nData2,
  5.                                           OMX_IN Semaphore &semaphore)
  6. {
  7.     status_t ret = NO_ERROR;
  8.     ssize_t res;
  9.     Mutex::Autolock lock(mEventLock);

  10.     LOG_FUNCTION_NAME;
  11.     TIUTILS::Message * msg = ( struct TIUTILS::Message * ) malloc(sizeof(struct TIUTILS::Message));
  12.     if ( NULL != msg )
  13.         {
  14.         msg->command = ( unsigned int ) eEvent;
  15.         msg->arg1 = ( void * ) nData1;
  16.         msg->arg2 = ( void * ) nData2;
  17.         msg->arg3 = ( void * ) &semaphore;
  18.         msg->arg4 = ( void * ) hComponent;
  19.         res = mEventSignalQ.add(msg);
  20.         if ( NO_MEMORY == res )
  21.             {
  22.             CAMHAL_LOGEA("No ressources for inserting OMX events");
  23.             free(msg);
  24.             ret = -ENOMEM;
  25.             }
  26.         }

  27.     LOG_FUNCTION_NAME_EXIT;

  28.     return ret;
  29. }
這裏將傳入的數據打包到message結構中,並且添加到mEventSignalQ隊列中,這裏先不說爲什麼,之後再說明

6.Enable PREVIEW Port
eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp,
                                 OMX_CommandPortEnable,
                                 mCameraAdapterParameters.mPrevPortIndex,
                                 NULL);
前面disable了所有組件,這裏保證了只有previewPort enable了

7.Wait for the port enable event to occur
調用過程如下:
ret = mInitSem.WaitTimeout(OMX_CMD_TIMEOUT);
這裏我自己的感覺還是比較難於理解,因爲自己在看這部分一開始也沒有喫透
所以這裏是我眼中的重點,重點啊
首先上面第6步 sendcommand to 組件,那麼組件就該給應用層以反饋,叫做callback也可以,這裏是通過我們上面初始化的OMXCameraAdapterEventHandler這個callback來應答應用層的,我們就看看這個方法的具體實現方法
  1. /* Application callback Functions */
  2. /*========================================================*/
  3. /* @ fn SampleTest_EventHandler :: Application callback */
  4. /*========================================================*/
  5. OMX_ERRORTYPE OMXCameraAdapter::OMXCameraAdapterEventHandler(OMX_IN OMX_HANDLETYPE hComponent,
  6.                                           OMX_IN OMX_EVENTTYPE eEvent,
  7.                                           OMX_IN OMX_U32 nData1,
  8.                                           OMX_IN OMX_U32 nData2,
  9.                                           OMX_IN OMX_PTR pEventData)
  10. {

  11.     LOG_FUNCTION_NAME;

  12.     OMX_ERRORTYPE eError = OMX_ErrorNone;
  13.     CAMHAL_LOGDB("+OMX_Event %x, %d %d", eEvent, (int)nData1, (int)nData2);

  14.     switch (eEvent) {
  15.         case OMX_EventCmdComplete:
  16.             CAMHAL_LOGDB("+OMX_EventCmdComplete %d %d", (int)nData1, (int)nData2);

  17.             if (OMX_CommandStateSet == nData1) {
  18.                 mCameraAdapterParameters.mState = (OMX_STATETYPE) nData2;

  19.             } else if (OMX_CommandFlush == nData1) {
  20.                 CAMHAL_LOGDB("OMX_CommandFlush received for port %d", (int)nData2);

  21.             } else if (OMX_CommandPortDisable == nData1) {
  22.                 CAMHAL_LOGDB("OMX_CommandPortDisable received for port %d", (int)nData2);

  23.             } else if (OMX_CommandPortEnable == nData1) {//我們發送的是OMX_CommandPortEnable命令,所以這了nData1就是command type
  24.                 CAMHAL_LOGDB("OMX_CommandPortEnable received for port %d", (int)nData2);

  25.             } else if (OMX_CommandMarkBuffer == nData1) {
  26.                 ///This is not used currently
  27.             }

  28.             CAMHAL_LOGDA("-OMX_EventCmdComplete");
  29.         break;

  30.         case OMX_EventIndexSettingChanged:
  31.             CAMHAL_LOGDB("OMX_EventIndexSettingChanged event received data1 0x%x, data2 0x%x",
  32.                             ( unsigned int ) nData1, ( unsigned int ) nData2);
  33.             break;

  34.         case OMX_EventError:
  35.             CAMHAL_LOGDB("OMX interface failed to execute OMX command %d", (int)nData1);
  36.             CAMHAL_LOGDA("See OMX_INDEXTYPE for reference");
  37.             if ( NULL != mErrorNotifier && ( ( OMX_U32 ) OMX_ErrorHardware == nData1 ) && mComponentState != OMX_StateInvalid)
  38.               {
  39.                 CAMHAL_LOGEA("***Got Fatal Error Notification***\n");
  40.                 mComponentState = OMX_StateInvalid;
  41.                 /*
  42.                 Remove any unhandled events and
  43.                 unblock any waiting semaphores
  44.                 */
  45.                 if ( !mEventSignalQ.isEmpty() )
  46.                   {
  47.                     for (unsigned int i = 0 ; i < mEventSignalQ.size(); i++ )
  48.                       {
  49.                         CAMHAL_LOGEB("***Removing %d EVENTS***** \n", mEventSignalQ.size());
  50.                         //remove from queue and free msg
  51.                         TIUTILS::Message *msg = mEventSignalQ.itemAt(i);
  52.                         if ( NULL != msg )
  53.                           {
  54.                             Semaphore *sem = (Semaphore*) msg->arg3;
  55.                             if ( sem )
  56.                               {
  57.                                 sem->Signal();
  58.                               }
  59.                             free(msg);
  60.                           }
  61.                       }
  62.                     mEventSignalQ.clear();
  63.                   }
  64.                 ///Report Error to App
  65.                 mErrorNotifier->errorNotify(CAMERA_ERROR_FATAL);
  66.               }
  67.             break;

  68.         case OMX_EventMark:
  69.         break;

  70.         case OMX_EventPortSettingsChanged:
  71.         break;

  72.         case OMX_EventBufferFlag:
  73.         break;

  74.         case OMX_EventResourcesAcquired:
  75.         break;

  76.         case OMX_EventComponentResumed:
  77.         break;

  78.         case OMX_EventDynamicResourcesAvailable:
  79.         break;

  80.         case OMX_EventPortFormatDetected:
  81.         break;

  82.         default:
  83.         break;
  84.     }

  85.     ///Signal to the thread(s) waiting that the event has occured
  86.     SignalEvent(hComponent, eEvent, nData1, nData2, pEventData);//這裏纔是重點

  87.    LOG_FUNCTION_NAME_EXIT;
  88.    return eError;

  89.     EXIT:

  90.     CAMHAL_LOGEB("Exiting function %s because of eError=%x", __FUNCTION__, eError);
  91.     LOG_FUNCTION_NAME_EXIT;
  92.     return eError;
  93. }
我們接着看看SignalEvent的實現
  1. OMX_ERRORTYPE OMXCameraAdapter::SignalEvent(OMX_IN OMX_HANDLETYPE hComponent,
  2.                                           OMX_IN OMX_EVENTTYPE eEvent,
  3.                                           OMX_IN OMX_U32 nData1,
  4.                                           OMX_IN OMX_U32 nData2,
  5.                                           OMX_IN OMX_PTR pEventData)
  6. {
  7.     Mutex::Autolock lock(mEventLock);
  8.     TIUTILS::Message *msg;
  9.     bool eventSignalled = false;

  10.     LOG_FUNCTION_NAME;

  11.     if ( !mEventSignalQ.isEmpty() )
  12.         {
  13.         CAMHAL_LOGDA("Event queue not empty");

  14.         for ( unsigned int i = 0 ; i < mEventSignalQ.size() ; i++ )
  15.             {
  16.             msg = mEventSignalQ.itemAt(i);
  17.             if ( NULL != msg )
  18.                 {
  19.                 if( ( msg->command != 0 || msg->command == ( unsigned int ) ( eEvent ) )
  20.                     && ( !msg->arg1 || ( OMX_U32 ) msg->arg1 == nData1 )
  21.                     && ( !msg->arg2 || ( OMX_U32 ) msg->arg2 == nData2 )
  22.                     && msg->arg3)
  23.                     {
  24.                     Semaphore *sem = (Semaphore*) msg->arg3;
  25.                     CAMHAL_LOGDA("Event matched, signalling sem");
  26.                     mEventSignalQ.removeAt(i);
  27.                     //Signal the semaphore provided
  28.                     sem->Signal();
  29.                     free(msg);
  30.                     break;
  31.                     }
  32.                 }
  33.             }
  34.         }
  35.     else
  36.         {
  37.         CAMHAL_LOGDA("Event queue empty!!!");
  38.         }

  39.     // Special handling for any unregistered events
  40.     if (!eventSignalled) {
  41.         // Handling for focus callback
  42.         if ((nData2 == OMX_IndexConfigCommonFocusStatus) &&
  43.             (eEvent == (OMX_EVENTTYPE) OMX_EventIndexSettingChanged)) {
  44.                 TIUTILS::Message msg;
  45.                 msg.command = OMXCallbackHandler::CAMERA_FOCUS_STATUS;
  46.                 msg.arg1 = NULL;
  47.                 msg.arg2 = NULL;
  48.                 mOMXCallbackHandler->put(&msg);
  49.         }
  50.     }

  51.     LOG_FUNCTION_NAME_EXIT;

  52.     return OMX_ErrorNone;
  53. }
這裏我們只關注上面的實現,至於下面handle focus callback這裏咱不做說明,以後可能會再次碰到
我們看看上面的語句到底做了什麼,檢測到mEventSignalQ這個消息隊列中有消息,而這裏在第6步中不是剛剛往這個消息隊列中添加了一個消息嘛!看來他們有點曖昧,接着看,進行了遍歷查找的操作,那麼找的到底是什麼呢?上面的判斷條件很明確,不同的一點馬虎,看看這個消息隊列中是是否有和我從組件發來的消息一致的消息,找到了,那就說明消息處理完了,組件成功應答給應用層了,那麼就得到了那個信號量,並且發送一個信號給wait方法,wait方法接到信號立即返回,否則一直等待直到超時,超時返回非零值,否則返回零,程序中如果wait超時,調用RemoveEvent方法
  1. OMX_ERRORTYPE OMXCameraAdapter::RemoveEvent(OMX_IN OMX_HANDLETYPE hComponent,
  2.                                             OMX_IN OMX_EVENTTYPE eEvent,
  3.                                             OMX_IN OMX_U32 nData1,
  4.                                             OMX_IN OMX_U32 nData2,
  5.                                             OMX_IN OMX_PTR pEventData)
  6. {
  7.   Mutex::Autolock lock(mEventLock);
  8.   TIUTILS::Message *msg;
  9.   LOG_FUNCTION_NAME;

  10.   if ( !mEventSignalQ.isEmpty() )
  11.     {
  12.       CAMHAL_LOGDA("Event queue not empty");

  13.       for ( unsigned int i = 0 ; i < mEventSignalQ.size() ; i++ )
  14.         {
  15.           msg = mEventSignalQ.itemAt(i);
  16.           if ( NULL != msg )
  17.             {
  18.               if( ( msg->command != 0 || msg->command == ( unsigned int ) ( eEvent ) )
  19.                   && ( !msg->arg1 || ( OMX_U32 ) msg->arg1 == nData1 )
  20.                   && ( !msg->arg2 || ( OMX_U32 ) msg->arg2 == nData2 )
  21.                   && msg->arg3)
  22.                 {
  23.                   Semaphore *sem = (Semaphore*) msg->arg3;
  24.                   CAMHAL_LOGDA("Event matched, signalling sem");
  25.                   mEventSignalQ.removeAt(i);
  26.                   free(msg);
  27.                   break;
  28.                 }
  29.             }
  30.         }
  31.     }
  32.   else
  33.     {
  34.       CAMHAL_LOGEA("Event queue empty!!!");
  35.     }
  36.   LOG_FUNCTION_NAME_EXIT;

  37.   return OMX_ErrorNone;
  38. }
這個方法檢查mEventSignalQ如果中有成員消息,那麼就清除掉mEventSignalQ其中的所有消息,這個是錯誤處理,以後還是會接着使用mEventSignalQ這個消息隊列的,這裏已經說的很清楚了,爲什麼在OMX_SendCommand之前要RegisterForEvent,就是爲了要判斷組件有沒有按照我發送給他的命令幹活,處理完後給我應答了,我就認爲他乖乖的按照我的要求做了事情,這裏那叫一個重要,因爲後面還會有很多這個機制的使用
這裏有一個地方我還是要提及一下,那就是組件回饋的enent類型,直接貼在這裏
  1. /** @ingroup comp */
  2. typedef enum OMX_EVENTTYPE
  3. {
  4.     OMX_EventCmdComplete, /**< component has sucessfully completed a command */
  5.     OMX_EventError, /**< component has detected an error condition */
  6.     OMX_EventMark, /**< component has detected a buffer mark */
  7.     OMX_EventPortSettingsChanged, /**< component is reported a port settings change */
  8.     OMX_EventBufferFlag, /**< component has detected an EOS */ 
  9.     OMX_EventResourcesAcquired, /**< component has been granted resources and is
  10.                                        automatically starting the state change from
  11.                                        OMX_StateWaitForResources to OMX_StateIdle. */
  12.    OMX_EventComponentResumed, /**< Component resumed due to reacquisition of resources */
  13.    OMX_EventDynamicResourcesAvailable, /**< Component has acquired previously unavailable dynamic resources */
  14.    OMX_EventPortFormatDetected, /**< Component has detected a supported format. */
  15.    OMX_EventKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
  16.    OMX_EventVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
  17.    OMX_EventMax = 0x7FFFFFFF
  18. } OMX_EVENTTYPE;

8.Select the sensor
這裏我們首先看看OMX_CONFIG_SENSORSELECTTYPE這個結構
定義在以下目錄:hardware\ti\omap4xxx\domx\omx_core\inc\OMX_TI_IVCommon.h
  1.  /*
  2.  * Sensor Select
  3.  */
  4. typedef struct OMX_CONFIG_SENSORSELECTTYPE {
  5. OMX_U32 nSize; /**< Size of the structure in bytes */
  6. OMX_VERSIONTYPE nVersion; /**< OMX specification version info */
  7. OMX_U32 nPortIndex; /**< Port that this struct applies to */
  8. OMX_SENSORSELECT eSensor; /**< sensor select */
  9. } OMX_CONFIG_SENSORSELECTTYPE;
接着來看下面這個方法的實現
OMX_INIT_STRUCT_PTR (&sensorSelect, OMX_CONFIG_SENSORSELECTTYPE);
  1. #define OMX_INIT_STRUCT_PTR(_s_, _name_) \
  2.     memset((_s_), 0x0, sizeof(_name_)); \
  3.     (_s_)->nSize = sizeof(_name_); \
  4.     (_s_)->nVersion.s.nVersionMajor = 0x1; \
  5.     (_s_)->nVersion.s.nVersionMinor = 0x1; \
  6.     (_s_)->nVersion.s.nRevision = 0x0; \
  7.     (_s_)->nVersion.s.nStep = 0x0
這個方法只是對sensorSelect這個結構進行初始化和填充而已,傳入OMX_CONFIG_SENSORSELECTTYPE結構體只是爲了獲取他的大小,挺大財小用不是嗎??嘿嘿
最後調用OMX_SetConfig()這個方法
  1. /** The OMX_SetConfig macro will send one of the configuration 
  2.     structures to a component. Each structure shall be sent one at a time,
  3.     each in a separate invocation of the macro. This macro can be invoked 
  4.     anytime after the component has been loaded. The application shall 
  5.     allocate the correct structure and shall fill in the structure size 
  6.     and version information (as well as the actual data) before invoking 
  7.     this macro. The application is free to dispose of this structure after 
  8.     the call as the component is required to copy any data it shall retain. 
  9.     This is a blocking call. 
  10.     
  11.     The component should return from this call within 5 msec.
  12.     
  13.     @param [in] hComponent
  14.         Handle of the component to be accessed. This is the component
  15.         handle returned by the call to the OMX_GetHandle function.
  16.     @param [in] nConfigIndex
  17.         Index of the structure to be sent. This value is from the
  18.         OMX_INDEXTYPE enumeration above.
  19.     @param [in] pComponentConfigStructure
  20.         pointer to application allocated structure to be used for
  21.         initialization by the component.
  22.     @return OMX_ERRORTYPE
  23.         If the command successfully executes, the return code will be
  24.         OMX_ErrorNone. Otherwise the appropriate OMX error will be returned.
  25.     @ingroup comp
  26.  */
  27. #define OMX_SetConfig( \
  28.         hComponent, \
  29.         nConfigIndex, \
  30.         pComponentConfigStructure) \
  31.     ((OMX_COMPONENTTYPE*)hComponent)->SetConfig( \
  32.         hComponent, \
  33.         nConfigIndex, \
  34.         pComponentConfigStructure) /* Macro End */

9.參數初始化
其中最重要的是initialize方法引入的參數傳遞給了mCapabilities 
mCapabilities = caps;
並且通過mCapabilities->get()方法獲得相應的參數初始化

10.initialize command handling thread
這裏只是創建了一個CommandHandler線程,並且啓動了這個線程,我們重點看看這個線程都幹了些甚麼
  1. bool OMXCameraAdapter::CommandHandler::Handler()
  2. {
  3.     TIUTILS::Message msg;
  4.     volatile int forever = 1;
  5.     status_t stat;
  6.     ErrorNotifier *errorNotify = NULL;

  7.     LOG_FUNCTION_NAME;

  8.     while ( forever )
  9.         {
  10.         stat = NO_ERROR;
  11.         CAMHAL_LOGDA("Handler: waiting for messsage...");
  12.         TIUTILS::MessageQueue::waitForMsg(&mCommandMsgQ, NULL, NULL, -1);
  13.         {
  14.         Mutex::Autolock lock(mLock);
  15.         mCommandMsgQ.get(&msg);
  16.         }
  17.         CAMHAL_LOGDB("msg.command = %d", msg.command);
  18.         switch ( msg.command ) {
  19.             case CommandHandler::CAMERA_START_IMAGE_CAPTURE:
  20.             {
  21.                 OMXCameraAdapter::CachedCaptureParameters* cap_params =
  22.                         static_cast<OMXCameraAdapter::CachedCaptureParameters*>(msg.arg2);
  23.                 stat = mCameraAdapter->startImageCapture(false, cap_params);
  24.                 delete cap_params;
  25.                 break;
  26.             }
  27.             case CommandHandler::CAMERA_PERFORM_AUTOFOCUS:
  28.             {
  29.                 stat = mCameraAdapter->doAutoFocus();
  30.                 break;
  31.             }
  32.             case CommandHandler::COMMAND_EXIT:
  33.             {
  34.                 CAMHAL_LOGDA("Exiting command handler");
  35.                 forever = 0;
  36.                 break;
  37.             }
  38.             case CommandHandler::CAMERA_SWITCH_TO_EXECUTING:
  39.             {
  40.                 stat = mCameraAdapter->doSwitchToExecuting();
  41.                 break;
  42.             }
  43.             case CommandHandler::CAMERA_START_REPROCESS:
  44.             {
  45.                 OMXCameraAdapter::CachedCaptureParameters* cap_params =
  46.                         static_cast<OMXCameraAdapter::CachedCaptureParameters*>(msg.arg2);
  47.                 stat = mCameraAdapter->startReprocess();
  48.                 stat = mCameraAdapter->startImageCapture(false, cap_params);
  49.                 delete cap_params;
  50.                 break;
  51.             }
  52.         }

  53.         }

  54.     LOG_FUNCTION_NAME_EXIT;

  55.     return false;
  56. }

11.initialize omx callback handling thread
這裏和上面很類似,創建一個OMXCallbackHandler線程,並啓動這個線程,同樣看看這個線程都幹了些甚麼
  1. bool OMXCameraAdapter::OMXCallbackHandler::Handler()
  2. {
  3.     TIUTILS::Message msg;
  4.     volatile int forever = 1;
  5.     status_t ret = NO_ERROR;

  6.     LOG_FUNCTION_NAME;

  7.     while(forever){
  8.         TIUTILS::MessageQueue::waitForMsg(&mCommandMsgQ, NULL, NULL, -1);
  9.         {
  10.         Mutex::Autolock lock(mLock);
  11.         mCommandMsgQ.get(&msg);
  12.         mIsProcessed = false;
  13.         }

  14.         switch ( msg.command ) {
  15.             case OMXCallbackHandler::CAMERA_FILL_BUFFER_DONE:
  16.             {
  17.                 ret = mCameraAdapter->OMXCameraAdapterFillBufferDone(( OMX_HANDLETYPE ) msg.arg1,
  18.                                                                      ( OMX_BUFFERHEADERTYPE *) msg.arg2);
  19.                 break;
  20.             }
  21.             case OMXCallbackHandler::CAMERA_FOCUS_STATUS:
  22.             {
  23.                 mCameraAdapter->handleFocusCallback();
  24.                 break;
  25.             }
  26.             case CommandHandler::COMMAND_EXIT:
  27.             {
  28.                 CAMHAL_LOGDA("Exiting OMX callback handler");
  29.                 forever = 0;
  30.                 break;
  31.             }
  32.         }

  33.         {
  34.             android::AutoMutex locker(mLock);
  35.             CAMHAL_UNUSED(locker);

  36.             mIsProcessed = mCommandMsgQ.isEmpty();
  37.             if ( mIsProcessed )
  38.                 mCondition.signal();
  39.         }
  40.     }

  41.     // force the condition to wake
  42.     {
  43.         android::AutoMutex locker(mLock);
  44.         CAMHAL_UNUSED(locker);

  45.         mIsProcessed = true;
  46.         mCondition.signal();
  47.     }

  48.     LOG_FUNCTION_NAME_EXIT;
  49.     return false;
  50. }

12.initialize 3A defaults
這裏暫不做說明,都是對很多參數的基本初始化
到這裏爲止,OMXCameraAdapter的初始化就結束了
待續。。。。。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章