使用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;
CameraFrame::FrameType

 

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

};

相关文章:

  • 2022-12-23
  • 2021-09-07
  • 2021-06-21
  • 2021-12-26
  • 2022-12-23
  • 2021-09-02
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-08-26
相关资源
相似解决方案