Camera HAL層代碼分析2

camera open之後,可以調用startPreview函數進行preview,今天主要講解Camera HAL層startPreview的follow。

先判定camera是否打開,沒有打開則直接返回。

status_t CameraHardware:: startPreview()
{

    status_t ret = NO_ERROR;
    int PreviewFrameSize;
    if (mCameraOpened == false)
        return UNKNOWN_ERROR;

HAL層有提供函數判定Camera是否打開:

bool CameraHardware::isCameraOpened()
{
    return mCameraOpened;
};

camera打開後,先判定是否已經在preview,如果已經preview,直接返回

 ALOGI("startPreview");
    Mutex::Autolock lock(mPreviewLock);
    if (mPreviewEnabled) {
        ALOGE("Preview already running");
        return ALREADY_EXISTS;
    }

根據preview的格式,計算previewFramesize:

if (strcmp(mParameters.getPreviewFormat(), CameraParameters::PIXEL_FORMAT_YUV420SP) == 0 ||
        strcmp(mParameters.getPreviewFormat(), CameraParameters::PIXEL_FORMAT_YUV420P) == 0 ) {
        // YUV420SP
        mPreviewFrameSize = mWidth * mHeight * 3 / 2;
    } else {
        // YUV422
        mPreviewFrameSize = mWidth * mHeight * 2;
    }

最後進行JpegDecoder初始化以及開啓decoder和preview thread

 mJpegDecoder.Init();

    usleep(1000 * 1000 );

    mPreviewEnabled = true;
    mDecodeThread = new DecodeThread(this);
    mPreviewThread = new PreviewThread(this);

在CameraHardWare.h中定義DecodeThread:

    class DecodeThread : public Thread {
        CameraHardware* mHal;
    public:
        DecodeThread(CameraHardware* hal) :
#ifdef SINGLE_PROCESS
        // In single process mode this thread needs to be a java thread,
        // since we won't be calling through the binder.
        Thread(true),
#else
        Thread(false),
#endif
        mHal(hal) {}
        virtual void onFirstRef() {
            run("CameraDecodeThread", PRIORITY_URGENT_DISPLAY);
        }
        virtual bool threadLoop() {
            mHal->decodeThread();
            // loop until we need to quit
            return true;
        }
    };

可以看到,此線程一直在執行mHal->decodeThread();,即調用CameraHardware::decodeThread()

在CameraHardWare.h中定義PreviewThread:

    class PreviewThread : public Thread {
        CameraHardware* mHal;
    public:
        PreviewThread(CameraHardware* hal) :
#ifdef SINGLE_PROCESS
        // In single process mode this thread needs to be a java thread,
        // since we won't be calling through the binder.
        Thread(true),
#else
        Thread(false),
#endif
        mHal(hal) {}
        virtual void onFirstRef() {
            run("CameraPreviewThread", PRIORITY_URGENT_DISPLAY);
        }
        virtual bool threadLoop() {
            mHal->previewThread();
            // loop until we need to quit
            return true;
        }
    };

同decodeThread,最終調用到CameraHardware::previewThread()。

 

int CameraHardware::decodeThread()
{
    if (mPreviewEnabled && mImageFormat == V4L2_PIX_FMT_MJPEG
        &&( mANativeWindow != NULL || mRecordingEnabled)) {
        void* buf = mJpegDecoder.GetEmptyYuvBuffer();

        if (buf == NULL)
            return NO_ERROR;

        char *rawFramePointer = mCamera->GrabRawFrame();
        if (rawFramePointer) {
            if (mJpegDecoder.Decode(mPreviewBufs, rawFramePointer, mCamera->videoIn->buf.bytesused, buf))
                mJpegDecoder.SetYuvBufferState(buf, false);
        } else if (!rawFramePointer) {
            ALOGE("Got EMPTY raw data !!!!!");
            usleep(1000 * 50 );
            return UNKNOWN_ERROR;
        }

#if DUMP_JPEG
        char fname[50];
        FILE *file;
        static int nCapture = 0;
        sprintf(fname, "/var/tmp/media/capture-%06u.jpg", nCapture);
        nCapture++;

        if (nCapture >= 5)
            nCapture = 0;
        file = fopen(fname, "wb");
        if (file != NULL) {
            fwrite(rawFramePointer, mCamera->videoIn->buf.bytesused, 1, file);
            fclose(file);
        }
#endif

        mCamera->ProcessRawFrameDone();
    }

    return NO_ERROR;
}

主要是對camera獲取的buffer數據進行decode,可以通過DUMP_JPEG查看preview的圖片。

同樣在previewThread中可以打印出當前preview的fps:

#if COUNT_FPS
            static time_t start, end;
            static int totalframe = 0;

            if (totalframe == 0)
                time(&start);
            time(&end);

            totalframe ++;
            if (difftime (end,start) >= 1) {
                ALOGI("FPS(%d, %d) ::::::::::::::::: %d", mWidth, mHeight, totalframe);
                totalframe = 0;
            }
#endif


 

 


 


 


 



 




 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章