国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
Android系統(tǒng)中視頻電話中camera部分?jǐn)?shù)據(jù)流分析

最近在研究如何移植Androidcamera系統(tǒng),對(duì)camera的應(yīng)用場景做了一些分析。Camera一般用于圖像瀏覽、拍照和視頻錄制。圖像瀏覽和拍照的數(shù)據(jù)流是比較清晰的,這里就不做贅述了。視頻錄制應(yīng)用于視頻電話中。撥打視頻電話時(shí),既可以看見對(duì)方的圖像,又可以看見自己的圖像;當(dāng)然,對(duì)方也是如此。從camera獲取的圖像數(shù)據(jù),既需要在本地瀏覽,還需要video encoder編碼后傳輸?shù)綄?duì)方手機(jī)。這樣的場景中,圖像數(shù)據(jù)要同時(shí)做previewrecord兩種操作。

一、回調(diào)函數(shù)傳遞

首先需要將客戶端的回調(diào)函數(shù)傳遞到底層,當(dāng)?shù)讓荧@取完圖像數(shù)據(jù)后,回調(diào)該函數(shù),通知上層,做相應(yīng)的處理。

AndroidCameraInput作為客戶端,它有兩個(gè)成員,分別為:

sp<android::Camera> mCamera;

sp<AndroidCameraInputListener> mListener;

AndroidCameraInput就可以通過mCamera訪問camera系統(tǒng)的對(duì)外接口。

AndroidCameraInputListener繼承于類CameraListener,它有三個(gè)成員函數(shù),分別為:

virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2){}

virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr);

virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);

這里需要說明的是postDataTimestamp(),它是客戶端實(shí)現(xiàn)的回調(diào)函數(shù),其定義為:

void AndroidCameraInputListener:: postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr){}

當(dāng)camera HAL層捕獲到一幀數(shù)據(jù)后,就會(huì)調(diào)用該回調(diào)函數(shù),告訴客戶端??蛻舳嗽谶@個(gè)回調(diào)函數(shù)里先判斷參數(shù)msgType是不是CAMERA_MSG_VIDEO_FRAME,如果是,即表示要對(duì)該幀數(shù)據(jù)進(jìn)行編碼處理,編碼結(jié)束后會(huì)調(diào)用mCamera的函數(shù)releaseRecordingFrame(),其對(duì)應(yīng)的HAL層的定義為:

void QualcommCameraHardware::releaseRecordingFrame(const sp<IMemory>& mem_attibute_((unused))){}

在這個(gè)函數(shù)里,會(huì)調(diào)用函數(shù)LINK_camera_release_frame()告訴camera硬件,存放當(dāng)前幀的buffer可以被釋放,用于下一幀使用。

回調(diào)函數(shù)postDataTimestamp()如何注冊(cè)到HAL層,這里需要詳細(xì)說明。

在客戶端中,是通過mCamerasetListener()函數(shù)將mListener注冊(cè)到mCamera中的,既將幾個(gè)回調(diào)函數(shù)注冊(cè)給mCamera

mCamera->setListener(mListener);

mCamera繼承于類BnCameraClient,而BnCameraClient繼承于類ICameraClient。類ICameraClient有純虛函數(shù):

virtual void dataCallbackTimstamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& data) = 0;

Camera中定義了虛函數(shù)dataCallbackTimstamp()并做了實(shí)現(xiàn):

virtual void dataCallbackTimstamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& data);

dataCallbackTimstamp()實(shí)現(xiàn)中,調(diào)用了類Camera的成員mListener的成員函數(shù)postDataTimestamp()。

CameraService有成員類Client,類Client有成員:

sp<ICameraClient> mCameraClient;

sp<CameraHardwareInterface> mHardware;

在類CameraService的成員類Client構(gòu)造函數(shù)中:

CameraService::Client::Client(constsp<CameraService>& cameraService, constsp<ICameraClient>& cameraClient, pid_t clientPid){}

其中調(diào)用了mHardware的函數(shù)setCallbacks()

mHardware->setCallbacks(notifyCallback,

                                   dataCallback,

                                   dataCallbackTimestamp,

                                   mCameraService.get());

如下函數(shù):

bool QualcommCameraHardware::setCallbacks(preview_callback pcb, void *puser,

                                                 recording_callback rcb, void *ruser){}

recording_callback賦給了mHardware的成員mRecordingCallback,至此,已將類AndroidCameraInput中的回調(diào)函數(shù)postDataTimestamp()傳遞給了cameraHAL層的成員mRecordingCallback。

 

二、數(shù)據(jù)buffer分配

在提供的Android代碼中,有一個(gè)camera HAL層的實(shí)例,即QualcommCameraHardware。在類QualcommCameraHardware中,默認(rèn)分配了6個(gè)buffer,其中4個(gè)preview buffer,1個(gè)raw buffer,1個(gè)JPEG buffer。在視頻電話中,只用了preview buffer。

QualcommCameraHardware在函數(shù)initPreview()中對(duì)preview buffer做了初始化。

bool QualcommCameraHardware::initPreview(){}

其中有code為:

mPreviewHeap = new PreviewPmemPool(kRawFrameHeaderSize +

                     mPreviewWidth * mPreviewHeight * 2, //worst

                     kPreviewBufferCount,

                     mPreviewFrameSize,

                     kRawFrameHeaderSize,

                     “preview”);

QualcommCameraHardware::PreviewPmemPool::PreviewPmemPool(

            int buffer_size, int num_buffers,

            int frame_size,

            int frame_offset,

            const char *name) :

        QualcommCameraHardware::PmemPool("/dev/pmem_adsp",

                                         buffer_size,

                                         num_buffers,

                                         frame_size,

                                         frame_offset,

                                         name)

    {

        LOGV("constructing PreviewPmemPool");

        if (initialized()) {

            LINK_camera_assoc_pmem(QDSP_MODULE_VFETASK,

                                   mFd,

                                   mHeap->base(),

                                   mAlignedSize,

                                   0); // external

        }

    }

QualcommCameraHardwares使用PMEM驅(qū)動(dòng)對(duì)preview buffer進(jìn)行了分配。Android PMEM是其專用的驅(qū)動(dòng),稱為物理內(nèi)存驅(qū)動(dòng)。在HAL層分配完preview buffer后,通過函數(shù)LINK_camera_assoc_pmem將分配信息傳遞給底層庫。底層庫中有對(duì)這4個(gè)preview buffer的管理機(jī)制。

視頻電話中,當(dāng)camera捕獲一幀數(shù)據(jù)后,存儲(chǔ)該數(shù)據(jù)的buffer會(huì)被同時(shí)用于previewrecord。只用當(dāng)客戶端調(diào)用了函數(shù)releaseRecordingFrame()之后才能將對(duì)應(yīng)的buffer釋放掉,用于其它幀使用。

 

三、視頻錄制調(diào)用

客戶端類AndroidCameraInput啟動(dòng)record,通過下面的調(diào)用:

mCamera->startRecording();

其會(huì)調(diào)到函數(shù):

status_t CameraService::Client::startRecording(){}

此處為mHardware設(shè)置了message CAMERA_MSG_VIDEO_FRAME,并調(diào)用函數(shù) startCameraMode()。其定義為:

status_t CameraService::Client::startCameraMode(camera_mode mode){}

參數(shù)camera_modeCAMERA_RECORDING_MODE,于是調(diào)了startRecordingMode。其定義為:

status_t CameraService::Client::startRecordingMode(){}

其中會(huì)先啟動(dòng)preview,如果它沒有啟動(dòng)的話,調(diào)用了startPreviewMode,即:

status_t CameraService::Client::startPreviewMode(){}

這里會(huì)處理preview的顯示介質(zhì),如果使用Overlay顯示,會(huì)設(shè)置相應(yīng)的Overlay,同時(shí)調(diào)用mHardware->startPreview()以啟動(dòng)preview;否則先調(diào)用mHardware->startPreview()啟動(dòng)preview,然后設(shè)置buffer:調(diào)用函數(shù)registerPreviewBuffers(),其定義為:

status_t CameraService::Client::registerPreviewBuffers(){}

這里會(huì)調(diào)用mHardware->getPreviewHeap(),從HAL層獲得previewbuffer,將其設(shè)置給Surface去顯示preview的結(jié)果。

QualcommCameraHardware對(duì)startPreview的定義如下:

status_t QualcommCameraHardware::startPreview(preview_callback pcb, void *puser){}

它調(diào)用了startPreviewInternal(),其定義為:

status_t QualcommCameraHardware:startPreviewInternal(preview_callback pcb, void (puser, recording_callback rcb, void *ruser){}

函數(shù)里調(diào)用了setCallbacks(pcb, puser, rcb, ruser),更新了previewrecord的回調(diào)函數(shù)。另外調(diào)用函數(shù)LINK_camera_start_preview(camera_cb, this),向driver層傳遞函數(shù)camera_cb。其定義為:

void QualcommCameraHardware::camera_cb(camera_cb_type cb, const void *client_data, camera_func_type func, int32_t parm4){}

函數(shù)里,當(dāng)mCameraStateQCS_PREVIEW_IN_PROGRESS時(shí),preview成功,同時(shí)調(diào)用函數(shù)receivePreviewFrame,其定義為:

void QualcommCameraHardware::receivePreviewFrame(camera_frame_type *frame){}

它調(diào)用了回調(diào)函數(shù)mPreviewCallbackmRecordingCallback,這就回調(diào)了函數(shù)postDataTimstamp(),告訴客戶端一幀數(shù)據(jù)已經(jīng)獲取成功,其可以開始編碼了。

前面已經(jīng)講過,當(dāng)客戶端對(duì)該幀數(shù)據(jù)的處理結(jié)束后,會(huì)告訴底層庫釋放該幀所占用的buffer空間,以備其他幀使用。

如此,previewrecord同時(shí)進(jìn)行,即可實(shí)現(xiàn)視頻電話功能。

 

四、Preview數(shù)據(jù)的顯示

Preview數(shù)據(jù)可以通過OverlaySurface兩種介質(zhì)去顯示,下面分別作以介紹。

1、  使用Overlay顯示

如果要使用Overlay,底層硬件必須支持Overlay。在CameraService::Client的構(gòu)造函數(shù)中,有相應(yīng)的判斷。

CameraService::Client::Client(const sp<CameraService>& cameraService,

        const sp<ICameraClient>& cameraClient, pid_t clientPid){}

mUseOverlay = mHardware->useOverlay();如果返回值為true,則表示硬件支持Overlay;否則只能使用Surface顯示。

status_t CameraService::Client::startPreviewMode(){}中,判斷如果Overlay可用,就會(huì)調(diào)用函數(shù)setOverlay(),其定義為:

status_t CameraService::Client::setOverlay(){}

其中會(huì)通過mSurface->createOverlay()創(chuàng)建Overlay,然后通過函數(shù)mHardware->setOverlay(new Overlay(mOverlayRef));將其設(shè)置給mHardware。

Android系統(tǒng)中提供了Overlay的接口,其具體實(shí)現(xiàn)需要自己做。在TI的實(shí)例中,在創(chuàng)建Overlay時(shí),它就為Overlay申請(qǐng)了8個(gè)buffer。然后在HAL層,通過Overlay的接口:void* getBufferAddress(overlay_buffer_t buffer),獲得Overlaybuffer地址。將該buffer傳遞給硬件,camera硬件將捕獲的數(shù)據(jù)填充到該buffer中。然后通過Overlay的接口:status_t queueBuffer(overlay_buffer_t buffer),將該buffer加入到Overlay的隊(duì)列中。最后調(diào)用Overlay的接口:status_t dequeueBuffer(overlay_buffer_t* buffer),將那個(gè)buffer從隊(duì)列中取出,此時(shí)即Overlay已經(jīng)對(duì)其顯示過了。dequeueBuffer()一般應(yīng)該是一個(gè)阻塞函數(shù),當(dāng)顯示完成后這個(gè)函數(shù)才返回。

當(dāng)然,Overlaybuffer也可以在HAL層申請(qǐng),然后通過queueBuffer(),將buffer加入到Overlay的隊(duì)列中。

2、  使用Surface顯示

CameraService的函數(shù):status_t CameraService::Client::startPreviewMode()中,如果使用Surface,會(huì)調(diào)用函數(shù)registerPreviewBuffers()Surface注冊(cè)buffersregisterPreviewBuffers()的定義為:

status_t CameraService::Client::registerPreviewBuffers(){}

其中有:

ISurface::BufferHeap buffers(w, h, w, h,

                                 PIXEL_FORMAT_YCbCr_420_SP,

                                 transform,

                                 0,

                                 mHardware->getPreviewHeap());

 

    status_t ret = mSurface->registerBuffers(buffers);

其將mHardwarepreview heap傳遞給了Surface

當(dāng)Camera的底層庫中獲取到了preview數(shù)據(jù),它會(huì)回調(diào)函數(shù):

void QualcommCameraHardware::camera_cb(camera_cb_type cb,

                                           const void *client_data,

                                           camera_func_type func,

                                           int32_t parm4){}

其中,在preview模式下,會(huì)調(diào)用函數(shù):

void QualcommCameraHardware::receivePreviewFrame(camera_frame_type *frame){}

它有代碼如下:

mPreviewCallback(mPreviewHeap->mBuffers[offset],

                                 mPreviewCallbackCookie);

這是回調(diào)了preview的回調(diào)函數(shù)。其定義為:

void CameraService::Client::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, void* user){}

其中,preview模式下,會(huì)調(diào)用函數(shù):

void CameraService::Client::handlePreviewData(const sp<IMemory>& mem){}

其通過mSurface->postBuffer(offset),將存儲(chǔ)當(dāng)前捕獲數(shù)據(jù)的buffer送給Surface去顯示。

函數(shù)CameraService::Client::stopPreview()中會(huì)調(diào)用函數(shù):

mSurface->unregisterBuffers(),以釋放原來注冊(cè)的buffers。

當(dāng)回調(diào)了preview的回調(diào)函數(shù)mPreviewCallback之后,如果mRecordingCallback為空,則直接調(diào)用LINK_camera_release_frame(),釋放當(dāng)前圖像數(shù)據(jù)的buffer;否則調(diào)用回調(diào)函數(shù)mRecordingCallback,進(jìn)入錄制的流程。

 

以上就是我對(duì)Android系統(tǒng)中,視頻電話的Camera部分的數(shù)據(jù)流的一個(gè)簡單分析。如有問題,還望各位高手指點(diǎn),謝謝。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
android Camera 架構(gòu)簡介
介紹 Android 的 Camera 框架
Camera顯示之Hal層的適配(一)
Android的Camera架構(gòu)介紹
Android Camera分析
Android 4.0 Camera架構(gòu)分析之Camera初始化
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服