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

原文地址:https://www.cnblogs.com/leino11121/p/3328901.html