Leon 5ios
/** @brief Sets ANativeWindow object. Preview buffers provided to CameraHal via this object. DisplayAdapter will be interfacing with it to render buffers to display. @param[in] window The ANativeWindow object created by Surface flinger @return NO_ERROR If the ANativeWindow object passes validation criteria @todo Define validation criteria for ANativeWindow object. Define error codes for scenarios */ status_t CameraHal::setPreviewWindow(struct preview_stream_ops *window) { // DisplayAdapter needs to know where to get the CameraFrames from in order to display // Since CameraAdapter is the one that provides the frames, set it as the frame provider for DisplayAdapter mDisplayAdapter->setFrameProvider(mCameraAdapter); // leon 4 // Any dynamic errors that happen during the camera use case has to be propagated back to the application // via CAMERA_MSG_ERROR. AppCallbackNotifier is the class that notifies such errors to the application // Set it as the error handler for the DisplayAdapter
//leon 5 任何Camera使用過程當中所發生的錯誤都必須經過CAMERA_MSG_ERROR傳遞給應用程序
// AppCallbackNotifier就是通知給上層應用的類。將其設置爲DisplayAdapter的錯誤處理者。 mDisplayAdapter->setErrorHandler(mAppCallbackNotifier.get()); }
以後,會調用mDisplayAdapter->setErrorHandler(mAppCallbackNotifier.get()).注意看上面的註釋。另外,此類的引用及初始化是在Hal::initialize()中實現的。app
/** @brief Initialize the Camera HAL Creates CameraAdapter, AppCallbackNotifier, DisplayAdapter and MemoryManager @param None @return NO_ERROR - On success NO_MEMORY - On failure to allocate memory for any of the objects @remarks Camera Hal internal function */ status_t CameraHal::initialize(CameraProperties::Properties* properties) { if(!mAppCallbackNotifier.get()) { /// Create the callback notifier mAppCallbackNotifier = new AppCallbackNotifier(); if( ( NULL == mAppCallbackNotifier.get() ) || ( mAppCallbackNotifier->initialize() != NO_ERROR)) { CAMHAL_LOGEA("Unable to create or initialize AppCallbackNotifier"); goto fail_loop; } } }
沒有找到構造函數,initialize()以下ide
///Initialization function for AppCallbackNotifier status_t AppCallbackNotifier::initialize() { mMeasurementEnabled = false; ///Create the app notifier thread mNotificationThread = new NotificationThread(this); if(!mNotificationThread.get()) { CAMHAL_LOGEA("Couldn't create Notification thread"); return NO_MEMORY; } ///Start the display thread status_t ret = mNotificationThread->run("NotificationThread", PRIORITY_URGENT_DISPLAY); if(ret!=NO_ERROR) { CAMHAL_LOGEA("Couldn't run NotificationThread"); mNotificationThread.clear(); return ret; } mUseMetaDataBufferMode = false; mUseVideoBuffers = false; mRawAvailable = false; return ret; }
NotificationThread定義以下:保存構造函數的參數,運行新建的線程函數
//Internal class definitions class NotificationThread : public Thread { AppCallbackNotifier* mAppCallbackNotifier; MSGUTILS::MessageQueue mNotificationThreadQ; public: enum NotificationThreadCommands { NOTIFIER_START, NOTIFIER_STOP, NOTIFIER_EXIT, }; public: NotificationThread(AppCallbackNotifier* nh) : Thread(false), mAppCallbackNotifier(nh) { } virtual bool threadLoop() { return mAppCallbackNotifier->notificationThread(); } MSGUTILS::MessageQueue &msgQ() { return mNotificationThreadQ;} };
線程最終的處理函數爲notificationThread()。類中定義的消息隊列mNotificationThreadQ只負責線程的退出,在收到NotificationThread::NOTIFIER_EXIT消息時,設置mNotifierState = AppCallbackNotifier::NOTIFIER_EXITED返回false,shouldLive則變爲false。則線程會退出。oop
bool AppCallbackNotifier::notificationThread() { bool shouldLive = true; status_t ret; LOG_FUNCTION_NAME; //CAMHAL_LOGDA("Notification Thread waiting for message"); ret = MSGUTILS::MessageQueue::waitForMsg(&mNotificationThread->msgQ(),// 供試用三個消息隊列,此消息隊列只是處理線程的狀態 &mEventQ,// 其餘兩個消息隊列稍候再看其應用場景 &mFrameQ, AppCallbackNotifier::NOTIFIER_TIMEOUT); //CAMHAL_LOGDA("Notification Thread received message"); if (mNotificationThread->msgQ().hasMsg()) { ///Received a message from CameraHal, process it CAMHAL_LOGDA("Notification Thread received message from Camera HAL"); shouldLive = processMessage();//在收到NotificationThread::NOTIFIER_EXIT消息時,設置mNotifierState = AppCallbackNotifier::NOTIFIER_EXITED返回false,shouldLive則變爲false。則線程會退出。
if(!shouldLive) { CAMHAL_LOGDA("Notification Thread exiting."); } } if(mEventQ.hasMsg()) { ///Received an event from one of the event providers CAMHAL_LOGDA("Notification Thread received an event from event provider (CameraAdapter)"); notifyEvent(); } if(mFrameQ.hasMsg()) { ///Received a frame from one of the frame providers //CAMHAL_LOGDA("Notification Thread received a frame from frame provider (CameraAdapter)"); notifyFrame(); } LOG_FUNCTION_NAME_EXIT; return shouldLive; }
其餘兩個消息隊列 mEventQ及mFrameQ,AppCallbackNorifier的兩個成員函數用於設置Provider,兩個Provider都是CameraAdapter。this
void AppCallbackNotifier::setEventProvider(int32_t eventMask, MessageNotifier * eventNotifier) { } void AppCallbackNotifier::setFrameProvider(FrameNotifier *frameNotifier) { }
mEventQ用於處理spa
enum CameraHalEventType { NO_EVENTS = 0x0, EVENT_FOCUS_LOCKED = 0x1, EVENT_FOCUS_ERROR = 0x2, EVENT_ZOOM_INDEX_REACHED = 0x4, EVENT_SHUTTER = 0x8, EVENT_FACE = 0x10, ///@remarks Future enum related to display, like frame displayed event, could be added here ALL_EVENTS = 0xFFFF ///Maximum of 16 event types supported };
mFrameQ用於處理:線程
enum FrameType { PREVIEW_FRAME_SYNC = 0x1, ///SYNC implies that the frame needs to be explicitly returned after consuming in order to be filled by camera again PREVIEW_FRAME = 0x2 , ///Preview frame includes viewfinder and snapshot frames IMAGE_FRAME_SYNC = 0x4, ///Image Frame is the image capture output frame IMAGE_FRAME = 0x8, VIDEO_FRAME_SYNC = 0x10, ///Timestamp will be updated for these frames VIDEO_FRAME = 0x20, FRAME_DATA_SYNC = 0x40, ///Any extra data assosicated with the frame. Always synced with the frame FRAME_DATA= 0x80, RAW_FRAME = 0x100, SNAPSHOT_FRAME = 0x200, ALL_FRAMES = 0xFFFF ///Maximum of 16 frame types supported };
這兩個消息隊列的套路跟ANativeWindowDisplayAdapter同樣,經過設置回調函數,並註冊事件。當Adapter發生已註冊的時間,則調用回調函數,回調函數中則會作相應的處理。達到的目的是將數據或消息回傳給Application。例如IMAGE_FRAME。設置過程見下圖:指針
說明:code
1~2. 在HAL初始化時會調用mAppCallbackNotifier->setFrameProvider(mCameraAdapter),將mCameraAdapter做爲參數傳遞進去,
3~4. 在mAppCallbackNotifier->setFrameProvider的實現中,現將傳入的參數從CameraAdapter轉換爲frameNotifier,而後再將其做爲參數構造FrameProvider。另外注意另外一重要參數frameCallbackRelay,frameCallbackRelay()是一回調函數。待會看看它幹了什麼?
5~7.以後FrameProvider註冊類型IMAGE_FRAME,使能此類型的回調處理
frameCallbackRelay(CameraFrame* caFrame)
1.從BaseCameraAdapter回調,傳遞的參數是CameraFrame指針
2.從指針中獲取Cookie,並調用frameCallback,frameCallback初始化一個消息,並加入到消息隊列中,
3.在消息隊列處理函數中,調用notifyFrame進行相應處理
回到文章的開頭,關於Leon 5的調用,將mAppCallbackNotifier通過類型轉換,賦值。
int ANativeWindowDisplayAdapter::setErrorHandler(ErrorNotifier *errorNotifier) { status_t ret = NO_ERROR; LOG_FUNCTION_NAME; if ( NULL == errorNotifier ) { CAMHAL_LOGEA("Invalid Error Notifier reference"); ret = -EINVAL; } if ( NO_ERROR == ret ) { mErrorNotifier = errorNotifier; } LOG_FUNCTION_NAME_EXIT; return ret; }
較簡單,使用
mNotifyCb(CAMERA_MSG_ERROR, CAMERA_ERROR_UNKNOWN, 0, mCallbackCookie);將消息回調。
總結一下,AppCallbackNotifier及DisplayAdapter兩個重要的類都是經過消息隊列與CameraAdapter交互的,但CameraAdapter對於消息隊列的註冊使用依然不明瞭。
Leon 6,最後是經過mDisplayAdapter->setPreviewWindow(window);更新Window。這是其餘window操做的基礎。
int ANativeWindowDisplayAdapter::setPreviewWindow(preview_stream_ops_t* window) { LOG_FUNCTION_NAME; ///Note that Display Adapter cannot work without a valid window object if ( !window) { CAMHAL_LOGEA("NULL window object passed to DisplayAdapter"); LOG_FUNCTION_NAME_EXIT; return BAD_VALUE; } ///Destroy the existing window object, if it exists destroy(); ///Move to new window obj mANativeWindow = window; LOG_FUNCTION_NAME_EXIT; return NO_ERROR; }