Android CameraHal NativeWindow相关(三)- Leon 5 (mDisplayAdapter->setErrorHandler(mAppCallbackNotifier.get());)

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;
}
原文地址:https://www.cnblogs.com/leino11121/p/3330629.html