Android CameraHal NativeWindow相關(二):FrameProvider與NativeWindowDisplayAdapter

Leon 4 設置Frame ProvidermDisplayAdapter->setFrameProvider(mCameraAdapter)api

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,cookie

定義:CameraAdapter *mCameraAdapter;// HAL 中app

CameraAdapter是一個接口類,被BaseCameraAdapter繼承,BaseCameraAdapter被V4LCameraAdapter繼承ide

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。oop

mDisplayAdapter->setFrameProvider(mCameraAdapter)的實現ui

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的關係,this

Camera Adapter類圖

  CameraAdapter繼承於FrameNotifier,spa

  FrameNotifier是一個接口類,並繼承於MessageNotifier。3d

/**此接口類被從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仍是不少疑惑:

  一、消息通知給CameraAdapter後,CameraAdapter的相應方式?

  二、第五處及第六處中mGrallocHandleMap的使用,及兩個成員函數的做用?

下面的鏈接保留給上面這兩個疑問TODO1!!

 

看完ANativeWindowDisplayAdapter,再看第二個類AppCallbackNotifier對FrameProvider的調用,圖中共有六個函數回調用到。

 

但對AppCallbackNotifier不甚瞭解,看接下來的內容。Leon 5

相關文章
相關標籤/搜索