zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    MFC永久窗口对象与临时窗口对象
    深入理解MFC子类化
    四大图像库:OpenCV/FreeImage/CImg/CxImage
    IPicture总结
    在MFC下实现图像放大镜
    VC实现图片拖拽及动画
    利用COM组件IPicture读取jpg、gif、bmp图片文件数据和显示图片
    tomcat启动时报:IOException while loading persisted sessions: java.io.EOFException的解决方案
    Java配置文件Properties的读取、写入与更新操作
    java读取Properties文件及赋值
  • 原文地址:https://www.cnblogs.com/leino11121/p/3330629.html
Copyright © 2011-2022 走看看