您的位置:首页 > 移动开发 > Android开发

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

2013-09-18 18:46 423 查看
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继承

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的关系,



  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来调用的。



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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: