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
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
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來調用的。
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