Leon 5
/** @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()中实现的。
/** @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()如下
///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。则线程会退出。
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。
void AppCallbackNotifier::setEventProvider(int32_t eventMask, MessageNotifier * eventNotifier) { } void AppCallbackNotifier::setFrameProvider(FrameNotifier *frameNotifier) { }
mEventQ用于处理
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。设置过程见下图:
说明:
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; }