• Android CameraHal NativeWindow相关(二):FrameProvider与NativeWindowDisplayAdapter


    Leon 4 设置Frame ProvidermDisplayAdapter->setFrameProvider(mCameraAdapter)

    status_t CameraHal::setPreviewWindow(struct preview_stream_ops *window)
    {
            if(!mDisplayAdapter.get() || ((ret=mDisplayAdapter->initialize())!=NO_ERROR)) // Leon 3
            {
            }
    
            // 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
    }

    先看一下setFrameProvider的参数mCameraAdapter,

    定义:CameraAdapter *mCameraAdapter;// HAL 中

    CameraAdapter是一个接口类,被BaseCameraAdapter继承,BaseCameraAdapter被V4LCameraAdapter继承

    Camera Adapter类图

    CameraAdapter

    mCameraAdapter的初始化是在status_t CameraHal::initialize(CameraProperties::Properties* properties) 中实现的。

    status_t CameraHal::initialize(CameraProperties::Properties* properties)
    {
        mCameraAdapter = CameraAdapter_Factory(sensor_index);  //赋值
        if ( ( NULL == mCameraAdapter ) || (mCameraAdapter->initialize(properties)!=NO_ERROR))// 此处的初始化是通过ioctl (mCameraHandle, VIDIOC_QUERYCAP, &mVideoInfo->cap)向设备查询其能力并向mParas设置一些有用的参数
            {
            CAMHAL_LOGEA("Unable to create or initialize CameraAdapter");
            mCameraAdapter = NULL;
            goto fail_loop;
            }
    }
    extern "C" CameraAdapter* CameraAdapter_Factory(size_t sensor_index)
    {
        CameraAdapter *adapter = NULL;
        Mutex::Autolock lock(gAdapterLock);
    
        LOG_FUNCTION_NAME;
    
        adapter = new V4LCameraAdapter(sensor_index);
        if ( adapter ) {
            CAMHAL_LOGDB("New V4L Camera adapter instance created for sensor %d", sensor_index);
        } else {
            CAMHAL_LOGEA("Camera adapter create failed!");
        }
    
        LOG_FUNCTION_NAME_EXIT;
    
        return adapter;// 此处返回的是V4LCameraAdapter类型的对象指针。
    }

    OK,从上面知道mDisplayAdapter->setFrameProvider(mCameraAdapter)中的参数是V4LCameraAdapter类型的,继承于BaseCameraAdapter,BaseCameraAdapter继承于CameraAdapter。

    mDisplayAdapter->setFrameProvider(mCameraAdapter)的实现

    int ANativeWindowDisplayAdapter::setFrameProvider(FrameNotifier *frameProvider)// Leon 4.1参数的类型为FrameNotifier* 需要看一下FrameNotifier与CameraAdapter的关系
    {
        LOG_FUNCTION_NAME;
    
        // Check for NULL pointer
        if ( !frameProvider ) {
            CAMHAL_LOGEA("NULL passed for frame provider");
            LOG_FUNCTION_NAME_EXIT;
            return BAD_VALUE;
        }
    
        //Release any previous frame providers
        if ( NULL != mFrameProvider ) {
            delete mFrameProvider;
        }
    
        /** Dont do anything here, Just save the pointer for use when display is
             actually enabled or disabled
        */
        mFrameProvider = new FrameProvider(frameProvider, this, frameCallbackRelay);// Leon4.2 重要的函数,分析其实现
    
        LOG_FUNCTION_NAME_EXIT;
    
        return NO_ERROR;
    }

    Leon 4.1  FrameNotifier与CameraAdapter的关系,

    Camera Adapter类图

      CameraAdapter继承于FrameNotifier,

      FrameNotifier是一个接口类,并继承于MessageNotifier。

    /**此接口类被从Camera Adapter中抽象出来作为Frame Provider,此接口应被Camera Adapter完全实现,跟踪一下成员函数的实现,是在BaseCameraAdapter中实现的。
      * Interace class abstraction for Camera Adapter to act as a frame provider
      * This interface is fully implemented by Camera Adapter
      */
    class FrameNotifier : public MessageNotifier
    {
    public:
        virtual void returnFrame(void* frameBuf, CameraFrame::FrameType frameType) = 0;
        virtual void addFramePointers(void *frameBuf, void *buf) = 0;
        virtual void removeFramePointers() = 0;
    
        virtual ~FrameNotifier() {};
    };
    /** 被那些需要与依赖类通讯的类实现,依赖类使用这些接口去注册事件。例如BaseCamerAdapter实现了此类,而调用则在FrameProvider中。
      * Interface class implemented by classes that have some events to communicate to dependendent classes
      * Dependent classes use this interface for registering for events
      */
    class MessageNotifier
    {
    public:
        static const uint32_t EVENT_BIT_FIELD_POSITION;
        static const uint32_t FRAME_BIT_FIELD_POSITION;
    
        ///@remarks Msg type comes from CameraFrame and CameraHalEvent classes
        ///           MSB 16 bits is for events and LSB 16 bits is for frame notifications
        ///         FrameProvider and EventProvider classes act as helpers to event/frame
        ///         consumers to call this api
        virtual void enableMsgType(int32_t msgs, frame_callback frameCb=NULL, event_callback eventCb=NULL, void* cookie=NULL) = 0;
        virtual void disableMsgType(int32_t msgs, void* cookie) = 0;
    
        virtual ~MessageNotifier() {};
    };

     延伸出来的内容:类图中,两个接口类的实现都是在BaseCameraAdapter中实现的,而调用则是通过FrameProvider中FrameNotifier的引用FrameNotifier来调用的。

    Camera Adapter类图

    Leon 4.2

    我们再来看Leon 4.2中FrameProvider的构造,定义了FrameNotifier及MessageNotifier的同名函数,这两个接口类的接口函数都是在此类中的函数实现中被调用。

    mFrameProvider = new FrameProvider(frameProvider, this, frameCallbackRelay);// Leon4.2 重要的函数,分析其实现

     其构造函数在其类的定义(CameraHal.h)中:

    /**   * Wrapper class around Frame Notifier, which is used by display and notification classes for interacting with Camera Adapter
      */
    class FrameProvider
    {
        FrameNotifier* mFrameNotifier;
        void* mCookie;
        frame_callback mFrameCallback;
    
    public:
        FrameProvider(FrameNotifier *fn, void* cookie, frame_callback frameCallback)
            :mFrameNotifier(fn), mCookie(cookie),mFrameCallback(frameCallback) { } // 将从CameraAdapter中类型转换来的frameProvider在类中保存其引用,并将frameCallbackRelay函数做类内部成员赋值。我们在上面的分析中已经提到frameCallbackRelay,此回调函数会调用到PostFrame
      int enableFrameNotification(int32_t frameTypes); 
      int disableFrameNotification(int32_t frameTypes);
      int returnFrame(void *frameBuf, CameraFrame::FrameType frameType);
      void addFramePointers(void *frameBuf, void *buf);
      
    void removeFramePointers();
    };

    FrameProvider会被两个类引用到ANativeWindowDisplayAdapter及AppCallbackNotifier,下图中的ANativeWindowDisplayAdapter中的成员函数都会调用到FrameProvider的引用,

     

     先看ANativeWindowDisplayAdapter 内部的调用

    第一处:析构函数中会通过disableFrameNotification Disable 掉所有之前enable过的通知。先不管通知的实现,

    ANativeWindowDisplayAdapter::~ANativeWindowDisplayAdapter()
    {
        Semaphore sem;
        MSGUTILS::Message msg;
        ///If Frame provider exists
        if (mFrameProvider) {
            // Unregister with the frame provider
            mFrameProvider->disableFrameNotification(CameraFrame::ALL_FRAMES);
            delete mFrameProvider;
            mFrameProvider = NULL;
        }
    }

    第二处:setFrameProvider中会先删除掉以前的Provider,之后在新建

    int ANativeWindowDisplayAdapter::setFrameProvider(FrameNotifier *frameProvider)
    {
        // Check for NULL pointer
        if ( !frameProvider ) {
            CAMHAL_LOGEA("NULL passed for frame provider");
            LOG_FUNCTION_NAME_EXIT;
            return BAD_VALUE;
        }
    
        //Release any previous frame providers
        if ( NULL != mFrameProvider ) {
            delete mFrameProvider;
        }
    
        /** Dont do anything here, Just save the pointer for use when display is
             actually enabled or disabled
        */
        mFrameProvider = new FrameProvider(frameProvider, this, frameCallbackRelay);
    
        return NO_ERROR;
    }

    第三处:当displayThread进入STARTED状态后,使用PREVIEW_FRAME_SYNC参数使能通知。

    int ANativeWindowDisplayAdapter::enableDisplay(int width, int height, struct timeval *refTime, S3DParameters *s3dParams)
    {
        Semaphore sem;
        MSGUTILS::Message msg;
    
        LOG_FUNCTION_NAME;
    
        if ( mDisplayEnabled )
        {
            CAMHAL_LOGDA("Display is already enabled");
            LOG_FUNCTION_NAME_EXIT;
    
            return NO_ERROR;
        }
    
    
        //Send START_DISPLAY COMMAND to display thread. Display thread will start and then wait for a message
        sem.Create();
        msg.command = DisplayThread::DISPLAY_START;
    
        // Send the semaphore to signal once the command is completed
        msg.arg1 = &sem;
    
        ///Post the message to display thread
        mDisplayThread->msgQ().put(&msg);
    
        ///Wait for the ACK - implies that the thread is now started and waiting for frames
        sem.Wait();
    
        // Register with the frame provider for frames
        mFrameProvider->enableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC);
    
        mDisplayEnabled = true;
        mPreviewWidth = width;
        mPreviewHeight = height;
    
        CAMHAL_LOGVB("mPreviewWidth = %d mPreviewHeight = %d", mPreviewWidth, mPreviewHeight);
    
        LOG_FUNCTION_NAME_EXIT;
    
        return NO_ERROR;
    }

     第四处:在disableDisplay时,使用PREVIEW_fRAME_SYNC参数Disable掉通知

    int ANativeWindowDisplayAdapter::disableDisplay(bool cancel_buffer)
    {
        status_t ret = NO_ERROR;
        GraphicBufferMapper &mapper = GraphicBufferMapper::get();
    
        LOG_FUNCTION_NAME;
    
        if(!mDisplayEnabled)
        {
            CAMHAL_LOGDA("Display is already disabled");
            LOG_FUNCTION_NAME_EXIT;
            return ALREADY_EXISTS;
        }
    
        // Unregister with the frame provider here
        mFrameProvider->disableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC);
        mFrameProvider->removeFramePointers();
    }

    第五处:申请buffer,但mGrallocHandleMap是什么?

    // Implementation of inherited interfaces
    void* ANativeWindowDisplayAdapter::allocateBuffer(int width, int height, const char* format, int &bytes, int numBufs)
    {
            mFrameProvider->addFramePointers(mGrallocHandleMap[i] , y_uv);
    }

    第六处:在处理从NativeWindow dequeue出来的buffer时,需要使用。

    bool ANativeWindowDisplayAdapter::handleFrameReturn()
    {
        mFramesWithCameraAdapterMap.add((int) mGrallocHandleMap[i], i);
    
        CAMHAL_LOGVB("handleFrameReturn: found graphic buffer %d of %d", i, mBufferCount-1);
        mFrameProvider->returnFrame( (void*)mGrallocHandleMap[i], CameraFrame::PREVIEW_FRAME_SYNC);
        LOG_FUNCTION_NAME_EXIT;
        return true;
    }

    关于FrameProvider还是很多疑惑:

      1、消息通知给CameraAdapter后,CameraAdapter的相应方式?

      2、第五处及第六处中mGrallocHandleMap的使用,及两个成员函数的作用?

    下面的连接保留给上面这两个疑问TODO1!!

    看完ANativeWindowDisplayAdapter,再看第二个类AppCallbackNotifier对FrameProvider的调用,图中共有六个函数回调用到。

    但对AppCallbackNotifier不甚了解,看接下来的内容。Leon 5

  • 相关阅读:
    自己写库—构建库函数雏形
    暑假第二周计划
    初学Oracle
    暑假第一周计划
    读书笔记六
    读书笔记五
    读书笔记四
    读书笔记三
    读书笔记
    系统目标文档
  • 原文地址:https://www.cnblogs.com/leino11121/p/3328901.html
Copyright © 2020-2023  润新知