使用Android框架做Camera,NativeWindow是绕不过去的,但这块对于我来说是个空白。今天的内容是将此部分弄清楚。
从CamerHal_Module开始,
/******************************************************************* * implementation of camera_device_ops functions *******************************************************************/ int camera_set_preview_window(struct camera_device * device, struct preview_stream_ops *window) { int rv = -EINVAL; aml_camera_device_t* aml_dev = NULL; LOGV("%s", __FUNCTION__); if(!device) return rv; aml_dev = (aml_camera_device_t*) device; rv = gCameraHals[aml_dev->cameraid]->setPreviewWindow(window); return rv; }
从CameraService中会将从Surface获得的NativeWindow通过此函数传递下来。CameraHal所有的画图操作都是进行在此window上。
上面的高亮代码会从之前初始化时得到Hal数组中得到当前Camera所对应的Hal,然后调用此Hal的setPreviewWindow()函数:
/** @brief Sets ANativeWindow object. Preview buffers provided to CameraHal via this object. DisplayAdapter will be interfacing with it to render buffers to display. @param[in] window The ANativeWindow object created by Surface flinger @return NO_ERROR If the ANativeWindow object passes validation criteria @todo Define validation criteria for ANativeWindow object. Define error codes for scenarios */ status_t CameraHal::setPreviewWindow(struct preview_stream_ops *window) { status_t ret = NO_ERROR; CameraAdapter::BuffersDescriptor desc; LOG_FUNCTION_NAME; mSetPreviewWindowCalled = true;// 1-------设置标志,指示此函数已被调用过,在startPreview()函数中做会判断,若为false会调用mCameraAdapter->sendCommand(CameraAdapter::CAMERA_SWITCH_TO_EXECUTING)后返回。此sendcommand暂未被实现。 ///If the Camera service passes a null window, we destroy existing window and free the DisplayAdapter
// window 指针为NULL的话,将会清除掉Display Adapter,并返回。此分支在CameraServise中的disconnect中被调用,用于彻底清除Display Adapter
//// Release the held ANativeWindow resources.
//if (mPreviewWindow != 0) {
//disconnectWindow(mPreviewWindow);
//mPreviewWindow = 0;
//mHardware->setPreviewWindow(mPreviewWindow);
//}
//mHardware.clear();
if(!window)
{ if(mDisplayAdapter.get() != NULL) { ///NULL window passed, destroy the display adapter if present CAMHAL_LOGEA("NULL window passed, destroying display adapter"); mDisplayAdapter.clear(); ///@remarks If there was a window previously existing, we usually expect another valid window to be passed by the client ///@remarks so, we will wait until it passes a valid window to begin the preview again mSetPreviewWindowCalled = false; } CAMHAL_LOGEA("NULL ANativeWindow passed to setPreviewWindow"); return NO_ERROR; }else
//如果window存在,而Display Adapter不存在,需要做很多事情。
if(mDisplayAdapter.get() == NULL) { // Need to create the display adapter since it has not been created // Create display adapter mDisplayAdapter = new ANativeWindowDisplayAdapter();// leon 2 ret = NO_ERROR; if(!mDisplayAdapter.get() || ((ret=mDisplayAdapter->initialize())!=NO_ERROR))// leon 3 display adapter 初始化 { if(ret!=NO_ERROR) { mDisplayAdapter.clear(); CAMHAL_LOGEA("DisplayAdapter initialize failed"); LOG_FUNCTION_NAME_EXIT; return ret; } else { CAMHAL_LOGEA("Couldn't create DisplayAdapter"); LOG_FUNCTION_NAME_EXIT; return NO_MEMORY; } } // DisplayAdapter needs to know where to get the CameraFrames from inorder to display // Since CameraAdapter is the one that provides the frames, set it as the frame provider for DisplayAdapter mDisplayAdapter->setFrameProvider(mCameraAdapter); // leon 4 设置视频数据的生产者 // Any dynamic errors that happen during the camera use case has to be propagated back to the application // via CAMERA_MSG_ERROR. AppCallbackNotifier is the class that notifies such errors to the application // Set it as the error handler for the DisplayAdapter mDisplayAdapter->setErrorHandler(mAppCallbackNotifier.get()); // leon 5 设置错误处理者,这里是使用AppCallbackNotifier // Update the display adapter with the new window that is passed from CameraService ret = mDisplayAdapter->setPreviewWindow(window);// leon 6 向display adpater设置显示窗口 if(ret!=NO_ERROR) { CAMHAL_LOGEB("DisplayAdapter setPreviewWindow returned error %d", ret); }
// mPreviewStartInProgress在startPreview()函数中,当window及display adapter为NULL时被设置为true.我的理解是,当startPreview在display adapter未被准备好时被调用,则设置此变量,等到准备好后可直接调用startPreview。 if(mPreviewStartInProgress)// previewstart正在进行中 { CAMHAL_LOGDA("setPreviewWindow called when preview running"); // Start the preview since the window is now available ret = startPreview(); // leon 7 } }
// 如果window及Display adapter都存在,则直接返回
else { /* If mDisplayAdpater is already created. No need to do anything. * We get a surface handle directly now, so we can reconfigure surface * itself in DisplayAdapter if dimensions have changed */ } LOG_FUNCTION_NAME_EXIT; return ret; }
上述代码段的注释说明:
Preview buffers provided to CameraHal via this object. DisplayAdapter will be interfacing with it to render buffers to display.
通过此对象获得提供给CameraHal的Preview Buffers。DisplayAdapter将会与之交互,把这些Buffer渲染显示。
leon 2
mDisplayAdapter = new ANativeWindowDisplayAdapter();// leon 2
我们此文的重点是ANativeWindowDisplayAdapter,先看一下类的定义
/** * Display handler class - This class basically handles the buffer posting to display
// 此类主要是用于处理用于显示的buffers。 */ class ANativeWindowDisplayAdapter : public DisplayAdapter // leon2.1 继承DisplayAdapter,需要看看这是个什么东西 { public: typedef struct { void *mBuffer; void *mUser; int mOffset; int mWidth; int mHeight; int mWidthStride; int mHeightStride; int mLength; CameraFrame::FrameType mType; } DisplayFrame;
typedef struct { void *mBuffer; void *mUser; int mOffset; int mWidth; int mHeight; int mWidthStride; int mHeightStride; int mLength; CameraFrame::FrameType mType; } DisplayFrame;
enum DisplayStates { DISPLAY_INIT = 0, DISPLAY_STARTED, DISPLAY_STOPPED, DISPLAY_EXITED }; public: ANativeWindowDisplayAdapter(); virtual ~ANativeWindowDisplayAdapter(); ///Initializes the display adapter creates any resources required virtual status_t initialize(); virtual int setPreviewWindow(struct preview_stream_ops *window); virtual int setFrameProvider(FrameNotifier *frameProvider); virtual int setErrorHandler(ErrorNotifier *errorNotifier); virtual int enableDisplay(int width, int height, struct timeval *refTime = NULL, S3DParameters *s3dParams = NULL); virtual int disableDisplay(bool cancel_buffer = true); virtual status_t pauseDisplay(bool pause); #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS //Used for shot to snapshot measurement virtual status_t setSnapshotTimeRef(struct timeval *refTime = NULL); #endif virtual int useBuffers(void* bufArr, int num); virtual bool supportsExternalBuffering(); //Implementation of inherited interfaces virtual void* allocateBuffer(int width, int height, const char* format, int &bytes, int numBufs); virtual uint32_t * getOffsets() ; virtual int getFd() ; virtual int freeBuffer(void* buf); virtual int maxQueueableBuffers(unsigned int& queueable); ///Class specific functions static void frameCallbackRelay(CameraFrame* caFrame); void frameCallback(CameraFrame* caFrame); void displayThread(); private: void destroy(); bool processHalMsg(); status_t PostFrame(ANativeWindowDisplayAdapter::DisplayFrame &dispFrame); bool handleFrameReturn(); status_t returnBuffersToWindow(); public: static const int DISPLAY_TIMEOUT; static const int FAILED_DQS_TO_SUSPEND; class DisplayThread : public Thread { ANativeWindowDisplayAdapter* mDisplayAdapter; MSGUTILS::MessageQueue mDisplayThreadQ; public: DisplayThread(ANativeWindowDisplayAdapter* da) : Thread(false), mDisplayAdapter(da) { } ///Returns a reference to the display message Q for display adapter to post messages MSGUTILS::MessageQueue& msgQ() { return mDisplayThreadQ; } virtual bool threadLoop() { mDisplayAdapter->displayThread(); return false; } enum DisplayThreadCommands { DISPLAY_START, DISPLAY_STOP, DISPLAY_FRAME, DISPLAY_EXIT }; }; //friend declarations friend class DisplayThread; private: int postBuffer(void* displayBuf); private: bool mFirstInit; bool mSuspend; int mFailedDQs; bool mPaused; //Pause state preview_stream_ops_t* mANativeWindow; sp<DisplayThread> mDisplayThread; FrameProvider *mFrameProvider; ///Pointer to the frame provider interface MSGUTILS::MessageQueue mDisplayQ; unsigned int mDisplayState; ///@todo Have a common class for these members mutable Mutex mLock; bool mDisplayEnabled; int mBufferCount; buffer_handle_t** mBufferHandleMap; native_handle_t** mGrallocHandleMap;//IMG_native_handle_t** mGrallocHandleMap;//TODO uint32_t* mOffsetsMap; int mFD; KeyedVector<int, int> mFramesWithCameraAdapterMap; sp<ErrorNotifier> mErrorNotifier; uint32_t mFrameWidth; uint32_t mFrameHeight; uint32_t mPreviewWidth; uint32_t mPreviewHeight; uint32_t mXOff; uint32_t mYOff; const char *mPixelFormat; uint32_t mNativeWindowPixelFormat; #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS //Used for calculating standby to first shot struct timeval mStandbyToShot; bool mMeasureStandby; //Used for shot to snapshot/shot calculation struct timeval mStartCapture; bool mShotToShot; #endif };