Android CameraHal NativeWindow相关(二):FrameProvider与NativeWindowDisplayAdapter
2013-09-18 18:46 白居不易 阅读(1094) 评论(0) 编辑 收藏 举报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继承
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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