97干视频,99国产精品懂色,亚洲精品99久久久久中文字幕,伊人五月丁香综合AⅤ,国产精品成人免费999

  您的位置:華清遠見教育科技集團 >> 新聞動態(tài) >> Android資料 >> Android Camera錄像過程分析  
 
Android Camera錄像過程分析
分享到:

Android視頻編碼的實現(xiàn)是在Android 1.5中才引入的,其設(shè)計主要圍繞著Camera子系統(tǒng)進行。在進行Camera錄像時,流程與拍照基本相同。需要了解的是,對于應(yīng)用開發(fā)者而言,錄像的上層接口為MediaRecorder。下圖所示為原生層MediaRecorder的狀態(tài)遷移過程。Android的視頻編碼框架代碼位于mydroid\frameworks\base\media目錄下。


視頻編碼狀態(tài)圖

下面簡要介紹在進行錄像時,Java層調(diào)用Camera原生服務(wù)的過程。下圖顯示的是基于CameraHardwareStub的Camera錄像過程。


Camera錄像過程

流程說明:

當用戶需要進行錄像時,首先要進行Camera設(shè)備的連接,然后進行預(yù)覽,為了進行錄像,需要通過擴展的Java JNI調(diào)用Camera客戶端的Camera::startRecording()方法?蛻舳藭埱驝amera服務(wù)器端提供錄像服務(wù),在這一過程中,Camera服務(wù)器端會激活CAMERA_ MSG_VIDEO_FRAME消息類型,并將Camera模式設(shè)置為CAMERA_RECORDING_MODE。

為了進行錄像,首先預(yù)先設(shè)置錄像回調(diào)函數(shù)(在mRecordingCallback回調(diào)函數(shù)中,上層實現(xiàn)將收到傳過去的幀),然后啟動預(yù)覽,下面是QualcommCameraHardware::startRecording()方法的實現(xiàn)過程:

代碼:QualcommCameraHardware:: startRecording ()方法的實現(xiàn)過程

獲取媒體播放服務(wù)的實現(xiàn)如下:

代碼:MediaPlayer::getMediaPlayerService()的實現(xiàn)

status_t QualcommCameraHardware::startRecording(recording_callback rcb, void *ruser)
    {
    LOGV("start Recording E");
    Mutex::Autolock l(&mLock);
    {
    Mutex::Autolock cbLock(&mCallbackLock);
    if (mPreviewstatus) {
      mRecordingCallback=rcb;    //設(shè)置錄像回調(diào)
      mRecordingCallbackCookie=ruser;    //設(shè)置錄像Cookie回調(diào)
      return NO_ERROR;
      }
    }
    if (!initPreview()) {    //初始化預(yù)覽
      LOGE("startPreview X initPreview failed. Not starting preview.");
      return UNKNOWN_ERROR;
      }
    {
    Mutex::Autolock cbLock(&mCallbackLock);
    mRecordingCallback=rcb;
    mRecordingCallbackCookie=ruser;
    mPreviewstatus=TRUE;
    mCameraRunning=mParameters.getCameraEnabledVal();
    }
    //向Camera驅(qū)動發(fā)送CAMERA_START_PREVIEW,開始預(yù)覽
    if (!native_start_preview(camerafd)) {
      LOGE("main: start_preview failed!\n");
      return UNKNOWN_ERROR;
    }
    LOGV("waiting for QCS_PREVIEW_IN_PROGRESS");
    LOGV("Start Recording X");
    return NO_ERROR;
    }

在進行預(yù)覽或者錄像時,需要將圖像渲染到屏幕。在這一過程中,首先需要創(chuàng)建PMEM預(yù)覽緩沖,然后將該緩沖進行注冊,接著創(chuàng)建frame_thread線程,下面是Qualcomm CameraHardware::initPreview()方法的實現(xiàn)過程:

代碼:QualcommCameraHardware::initPreview()方法的實現(xiàn)過程

bool QualcommCameraHardware::initPreview()
    {
    LOGV("initPreview: preview size=%dx%d", mPreviewWidth, mPreviewHeight);
    int cnt=0;
    dimension->picture_width= PICTURE_WIDTH;
    dimension->picture_height=PICTURE_HEIGHT;
    if((native_set_dimension(camerafd, dimension) ==TRUE)) {
    // 初始化SF幀
    mPreviewFrameSize=mPreviewWidth * mPreviewHeight * 3/2;
    //創(chuàng)建PMEM預(yù)覽緩沖
    mPreviewHeap=
    new PreviewPmemPool(kRawFrameHeaderSize +
        mPreviewWidth * mPreviewHeight * 3/2,
        kPreviewBufferCount,
        mPreviewFrameSize,
        kRawFrameHeaderSize,
        "preview");
    if (!mPreviewHeap->initialized()) {
      mPreviewHeap=NULL;
      return false;
    }
    LOGI("hal display_width=%d height=%d\n",
    (int)dimension->display_width, (int)dimension->display_height);
    frame_size=(clp2(dimension->display_width * dimension->display_height *3/2));
    unsigned char activeBuffer;
    for (cnt=0; cnt < PREVIEW_FRAMES_NUM; cnt++) {
    frames[cnt].fd=mPreviewHeap->mHeapnew[cnt]->heapID();
    frames[cnt].buffer=(unsigned long)mPreviewHeap->mHeapnew[cnt]->base();
    LOGE("hal_mmap #%d start=%x end=%x", (int)cnt, (int)frames[cnt].buffer,
    (int)(frames[cnt].buffer+frame_size-1));
    frames[cnt].y_off=0;
    frames[cnt].cbcr_off=dimension->display_width * dimension->display_height;
    if (frames[cnt].buffer==0) {
    LOGV("main: malloc failed!\n");
    return 0;
    }
    if (cnt==PREVIEW_FRAMES_NUM-1) {
    activeBuffer=FALSE;
    } else {
    activeBuffer=TRUE;
    }
    frames[cnt].path=MSM_FRAME_ENC;
    LOGV("do_mmap pbuf=0x%x, pmem_fd=%d, active=%d\n",(unsigned int)frames[cnt].buffer, frames[cnt].fd, activeBuffer);
    native_register_preview_bufs(camerafd, //注冊PMEM緩沖dimension,&frames[cnt],activeBuffer);
      }
    }
    if (frame_count==1) {
      frame_count--;
      lastframe=frames[PREVIEW_FRAMES_NUM-1];
    //創(chuàng)建frame_thread線程
    pthread_create(&frame_thread, NULL,LINK_cam_frame,&frames[PREVIEW_FRAMES_NUM-1]);
     }
    return true;
    }

需要說明的是,PreviewPmemPool、RawPmemPool、AshmemPool都是基于MemPool內(nèi)存池的,MemPool內(nèi)存池則是基于Android PMEM虛擬設(shè)備的,Android PMEM用于向用戶空間提供連續(xù)的物理內(nèi)存區(qū)域。Android PMEM虛擬設(shè)備的作用主要有兩個方面,第一,CPU核與GPU(Graphic Processing Unit)或者VPU(Vector Permutate Unit)共享的緩沖;第二,用做Android原生服務(wù)的內(nèi)存堆。

當錄像結(jié)束時,要調(diào)用QualcommCameraHardware::stopRecording()方法停止錄像,下面是該方法的實現(xiàn)過程:

代碼:QualcommCameraHardware::stopRecording()方法的實現(xiàn)過程

void QualcommCameraHardware::stopRecording()
    {
    LOGV("stopRecording: E");
    Mutex::Autolock l(&mLock);
    int cnt=0;
    {
        Mutex::Autolock cbLock(&mCallbackLock);
        mRecordingCallback=NULL; //清空回調(diào)
        mRecordingCallbackCookie=NULL;
        mReleaseRecordingFrame=TRUE;
        mRecordWait.signal();
        mCameraRunning=0;
        if(mPreviewCallback !=NULL)
        return;
        mPreviewstatus=NULL;
    }
    native_stop_preview(camerafd);    //停止預(yù)覽
    LOGV("stopRecording: Freeing preview heap.");
        if (!frame_count) {
        LINK_camframe_terminate();
        if (pthread_join(frame_thread, NULL) !=0) {//結(jié)束frame_thread線程
        LOGE("frame_thread exit failure!\n");
        } else
        LOGE("pthread_cancel succeeded on frame_thread\n");
        for (cnt=0; cnt< PREVIEW_FRAMES_NUM-1; ++cnt) {
        native_unregister_preview_bufs(camerafd,dimension,frames[cnt].fd,(unsigned char *)frames[cnt].buffer); //注銷PMEM緩沖
        }
        native_unregister_preview_bufs(camerafd, dimension,lastframe.fd,(unsigned char *)lastframe.buffer);
        frame_count=1;
        }
    mPreviewHeap=NULL;
    mRecordingCallback=NULL;
    LOGV("stopRecording: X");
    }

在結(jié)束錄像過程中,會首先將錄像用的回調(diào)函數(shù)如mRecordingCallback、mRecordingCallbackCookie清空,通過native_stop_preview()向Camera驅(qū)動發(fā)送CAMERA_STOP_PREVIEW消息結(jié)束預(yù)覽,然后調(diào)用pthread_join()結(jié)束frame_thread線程,后調(diào)用native_unregister_preview_bufs()注銷預(yù)覽用的PMEM緩沖。

 更多相關(guān)文章

·Android 原生層媒體播放過程
·Android 視頻解碼過程詳解
·Android 視頻編碼源碼分享
·Android 雙緩沖局部渲染
·Android Overlay硬件加速