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

打開APP
userphoto
未登錄

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

開通VIP
解讀Android 4.0 Camera原生應(yīng)用程序的設(shè)計(jì)思路

解讀Android 4.0 Camera原生應(yīng)用程序的設(shè)計(jì)思路

http://my.oschina.net/jerikc/blog/90791

1. 設(shè)置攝像頭方向

2. 打開線程與預(yù)覽線程 

3. 設(shè)置參數(shù)

4. Camera外設(shè)按鍵

5. 自動(dòng)對(duì)焦與觸摸對(duì)焦

6. 拍照

7. 人臉檢測(cè)

8. 位置管理

9. 旋轉(zhuǎn)管理

10. 變焦

11. 錄像



Camera的架構(gòu)為典型的C/S架構(gòu),Client端,用戶的行為,是為應(yīng)用程序進(jìn)程,Server端,設(shè)備的功能,是為Camera服務(wù)守護(hù)進(jìn) 程,客戶端進(jìn)程承載用戶的需求,由Binder進(jìn)程間通信送往服務(wù)端實(shí)現(xiàn)設(shè)備的功能,服務(wù)端由回調(diào)函數(shù)和消息機(jī)制反饋數(shù)據(jù)返還給用戶。

ps查看進(jìn)程,類似 com.android.camera是為客戶端Camera進(jìn)程,/system/bin/mediaserver是為服務(wù)端守護(hù)進(jìn)程,由系統(tǒng)啟動(dòng)時(shí)開啟。


1. 設(shè)置攝像頭方向

Framework框架層的Camera對(duì)象(camera.java)里有一個(gè)類class CameraInfo,里面存放了兩個(gè)公有成員變量facing和orientation,即我們要討論的前后置和方向。 程序第一次初始化時(shí)initializeFirstTime(),通過(guò)getCameraInfo()得到前后置和方向的信息,客戶端發(fā)送請(qǐng)求 getCameraInfo()詢問(wèn)服務(wù)端,服務(wù)端調(diào)用抽象層拿數(shù)據(jù),抽象層參考底層camera sensor驅(qū)動(dòng)的數(shù)據(jù)facing和orientation,這兩個(gè)值在驅(qū)動(dòng)里是寫死的,不能由用戶改變,camera程序啟動(dòng)以后就把它們作為全局變 量存放起來(lái)。

1.1 前置與后置

后置back camera背對(duì)手機(jī)屏幕,朝外,像素高,前置front camera,面對(duì)自己,朝內(nèi),像素低。

1.2 方向

攝像頭模組有長(zhǎng)邊和短邊,比如采集圖像的比例為4:3,那么4為長(zhǎng)邊,3為短邊。設(shè)備屏幕也有長(zhǎng)邊和短邊,理論上,攝像頭模組的長(zhǎng)邊不能與屏幕的長(zhǎng)邊垂直,至于為什么呢,我語(yǔ)文水平太差,沒(méi)辦法很好地表達(dá)出來(lái)...總之目的就是為了顯示效果。


2 打開線程與預(yù)覽線程

onCreate()里會(huì)先后開啟CameraOpenThread和CameraPreviewThread。

打開camera還需要線程?CameraOpenThread名為打開,實(shí)為C/S connect連接服務(wù)端,binder進(jìn)程間通信,開銷較大。預(yù)覽線程必須在打開線程完成以后執(zhí)行,它貫穿始終直到進(jìn)程消亡為止,整個(gè)預(yù)覽過(guò)程相對(duì)復(fù) 雜,在抽象層和底層驅(qū)動(dòng)實(shí)現(xiàn),概括講,預(yù)覽線程再開啟兩個(gè)線程,一個(gè)拿sensor的frame,一個(gè)送往framebuffer經(jīng) surfaceflinger顯示出來(lái)。


3 設(shè)置參數(shù)

預(yù)覽拍照錄像之前,用戶需要設(shè)置很多參數(shù),比如閃光,白平衡,場(chǎng)景,對(duì)比度等。

程序里這些參數(shù)保存在SharedPreferences共享優(yōu)選項(xiàng)和Parameters兩個(gè)地方,Preferences包含 Parameters,打開程序讀取優(yōu)選項(xiàng)參數(shù),關(guān)閉程序保存優(yōu)選項(xiàng)參數(shù),考慮到用戶經(jīng)常會(huì)調(diào)整參數(shù),引入Parameters來(lái)保存從打開以后到關(guān)閉以 前這個(gè)中間過(guò)程的參數(shù)變量,Parameters的鍵值由抽象層根據(jù)硬件sensor的能力決定。


4. Camera外設(shè)按鍵

Manifest里注冊(cè)broadcast receiver,

        <receiver android:name="com.android.camera.CameraButtonIntentReceiver">
            <intent-filter>
                <action android:name="android.intent.action.CAMERA_BUTTON"/>
            </intent-filter>
        </receiver>

有些手機(jī)上有camera按鍵,用戶按下按鍵,android輸入系統(tǒng)有兩種實(shí)現(xiàn)方法,

1)發(fā)送廣播CAMERA_BUTTON,收到廣播后開啟主Activity。

2)上報(bào)鍵值KEYCODE_CAMERA,程序收到消息,可自定義實(shí)現(xiàn)功能,比如拍照。

    public boolean onKeyDown(int keyCode, KeyEvent event) {
        switch (keyCode) {
            case KeyEvent.KEYCODE_CAMERA:
                if (mFirstTimeInitialized && event.getRepeatCount() == 0) {
                    onShutterButtonClick();
                }
                return true;


5. 自動(dòng)對(duì)焦與觸摸對(duì)焦

外界事物由光線經(jīng)凸透鏡聚焦到sensor上成像,camera模組開啟馬達(dá)前后平移鏡頭取得最佳成像效果,這個(gè)過(guò)程稱之為對(duì)焦。

5.1 自動(dòng)對(duì)焦

1) camera模組會(huì)因感光強(qiáng)度變化而自動(dòng)開啟對(duì)焦,驅(qū)動(dòng)控制。

2) 用戶長(zhǎng)按快門,軟件控制自動(dòng)對(duì)焦。

3) 用戶按下快門拍照,拍攝前自動(dòng)對(duì)焦。

程序里,Camera對(duì)象實(shí)現(xiàn)類ShutterButton的接口OnShutterButtonListener里的方法 onShutterButtonFocus(boolean pressed)和onShutterButtonClick(),后者是拍照,下節(jié)討論,先看 onShutterButtonFocus(boolean pressed),這個(gè)pressed判斷是否為一次有效的長(zhǎng)按,如果是的話,執(zhí)行autoFocus(),這個(gè)autoFocus()也是Camera 對(duì)象實(shí)現(xiàn)類FocusManager的接口Listener里的方法,由binder交給camera service,最后在底層驅(qū)動(dòng)實(shí)現(xiàn)自動(dòng)對(duì)焦。

5.2 觸摸對(duì)焦

自動(dòng)對(duì)焦的對(duì)焦區(qū)域位于屏幕正中,用戶也可觸摸特定區(qū)域?qū)埂?

Camera對(duì)象實(shí)現(xiàn)類View的接口OnTouchListener里的方法onTouch(),輸入系統(tǒng)上報(bào)MotionEvent的xy坐標(biāo),保存在Parameters,執(zhí)行autoFocus(),抽象層讀取Paramters的觸摸點(diǎn)坐標(biāo),實(shí)現(xiàn)區(qū)域?qū)埂?


6. 拍照

拍照分四步,對(duì)焦,拍照,接收?qǐng)D片,保存圖片。

mCameraDevice.takePicture(mShutterCallback, mRawPictureCallback,
                mPostViewPictureCallback, new JpegPictureCallback(loc));

需要理解四個(gè)回調(diào)函數(shù),參考上一篇文章。

1)對(duì)焦

拍照前如果已經(jīng)區(qū)域?qū)?,則取消自動(dòng)對(duì)焦,反之,開啟一次自動(dòng)對(duì)焦。對(duì)焦完成后,底層發(fā)送對(duì)焦成功與否的消息給camera對(duì) 象,F(xiàn)ocusManager把狀態(tài)mState保存起來(lái),如果正在對(duì)焦未完成(mState == STATE_FOCUSING)則不可拍照,直到對(duì)焦完畢。

2)拍照

onShutterButtonClick() -> doSnap() -> capture() -> takePicture(),具體實(shí)現(xiàn)在抽象層和底層驅(qū)動(dòng),實(shí)質(zhì)就是拿一張預(yù)覽的圖像,抽象層讀取拍照時(shí)的Parameters參數(shù)配置,包括用戶選擇的 照片大小。

3)接收?qǐng)D片

通過(guò)回調(diào),由底層發(fā)送圖片給camera對(duì)象。

RawPictureCallback,得到原始圖片,需要軟件壓縮Jpeg。(YUV轉(zhuǎn)Jpeg)

JpegPictureCallback,直接得到Jpeg圖片,需要硬件壓縮Jpeg。

PostViewPictureCallback,拍完后預(yù)覽圖片。

4)保存圖片

交由線程ImageSaver保存圖片和生成thumbnails。

默認(rèn)路徑位于/mnt/sdcard/DCIM/Camera/


7. 人臉檢測(cè)

人臉檢測(cè)可以軟件實(shí)現(xiàn),可以硬件實(shí)現(xiàn),軟件實(shí)現(xiàn)增加CPU開銷,硬件實(shí)現(xiàn)增大耗電,鼓勵(lì)硬件實(shí)現(xiàn)...

上層Camera對(duì)象實(shí)現(xiàn)了 framework層Camera的接口FaceDetectionListener的方法onFaceDetection(Face[] faces, Camera camera),回調(diào)機(jī)制同上,硬件sensor識(shí)別臉部信息,發(fā)送face給camera對(duì)象,framework定義face的特征,比如眼睛,嘴 巴,上層保存mFaces數(shù)據(jù),更新UI。


8. 位置管理

位置管理LocationManager用來(lái)記錄拍攝圖片的GPS位置信息(經(jīng)維度),存入JPEG頭部插入的Exif里。

用戶在菜單“相機(jī)設(shè)置”里的"保存所在位置"選擇打開(前提是GPS已開啟),屏幕左上方會(huì)出現(xiàn)一個(gè)GPS圖標(biāo),表示現(xiàn)在可以記錄GPS信息了。

程序里,Camera對(duì)象實(shí)現(xiàn)了位置管理監(jiān)聽器LocationManager.Listener的接口showGpsOnScreenIndicator()和hideGpsOnScreenIndicator(),顯示或者隱藏GPS圖標(biāo)。

程序第一次初始化時(shí)initializeFirstTime(),通過(guò)讀取優(yōu)選項(xiàng)Preference得到bool值 recordLocation,判斷是否需要記錄GPS信息,如果需要,在拍照capture()里調(diào)用LocationManager的方法得到 Location loc,并將其存入Exif。


9. 旋轉(zhuǎn)管理

假設(shè)一臺(tái)手機(jī),camera正常安裝,豎直方向作為默認(rèn)方向(orientation == 0)拍攝照片,即拍攝“肖像照”(portrait),得到的照片顯示在屏幕上也是豎直方向。

如果把手機(jī)旋轉(zhuǎn)90度水平過(guò)來(lái)拍攝“山水照”(landscape),對(duì)于camera sensor來(lái)說(shuō),沒(méi)有旋轉(zhuǎn)的概念,所以軟件上要把圖片旋轉(zhuǎn)90度回來(lái)。


軟件上,需要借助方向監(jiān)聽器隨時(shí)更新方向信息,并保存在Parameters里,抽象層實(shí)現(xiàn)拍照功能時(shí)從Parameters里讀取方向。

具體的,camera對(duì)象內(nèi)部類MyOrientationEventListener的方法onOrientationChanged()保存方 向orientation的值,MyOrientationEventListener繼承 OrientationEventListener,OrientationEventListener的onSensorChanged()把從 sensorManager拿到的xyz坐標(biāo)轉(zhuǎn)換成方向。

程序啟動(dòng),注冊(cè)sensor監(jiān)聽器并使能,sensorManager不斷上報(bào)底層sensor數(shù)據(jù),通過(guò)消息機(jī)制發(fā)送到camera對(duì)象,后者計(jì) 算坐標(biāo)數(shù)據(jù)得到方向orientation的值(實(shí)際外包給orientationListener完成),最后保存Parameters。


10. 變焦

用戶拖動(dòng)Zoom橫條可放大縮小預(yù)覽畫面連續(xù)變焦,另一種所謂狀態(tài)變焦,其原理是一樣的。

camera對(duì)象的內(nèi)部類ZoomChangeListener實(shí)現(xiàn)ZoomControl的方法,實(shí)質(zhì)是把變焦的任務(wù)全權(quán)交給 ZoomControl。ZoomControl監(jiān)聽處理用戶的觸摸事件dispatchTouchEvent(),用來(lái)得到并處理變焦倍數(shù) mListener.onZoomValueChanged(index),它由mCameraDevice.startSmoothZoom()通過(guò) binder交給camera service,camera service再通過(guò)sendComand命令機(jī)制交給抽象層實(shí)現(xiàn)變焦,抽象層開啟變焦線程,變焦改變預(yù)覽,通過(guò)回調(diào)機(jī)制發(fā)送消息 CAMERA_MSG_ZOOM把變焦倍數(shù)返還給camera對(duì)象,最終camera對(duì)象收到消息 后,ZoomListener.onZoomChange()把變焦倍數(shù)保存到Parameters.


11. 錄像

ModePicker負(fù)責(zé)切換模式,一共有三種模式,普通模式,錄像模式和全景模式,Manifest里依次聲明這三個(gè)activity。

切換模式,銷毀原有activity,開啟新activity,伴隨關(guān)閉preview,重啟preview,保存配置,讀取配置,開銷很大。

錄像VideoCamera.java同預(yù)覽Camera.java的思路類似,按下錄像按鈕,程序監(jiān)聽用戶事件,開啟錄像,錄像交給MediaRecoder,StagefrightRecorder負(fù)責(zé)。


1. Overview

1.1 物理架構(gòu)

1.2 Android架構(gòu)

2. CameraService

3. HAL

4. Overlay

5. Video for Linux

1. Overview

 本文以Freescale IMX為例剖析camera攝像頭的系統(tǒng)架構(gòu)。

 

1.1 物理架構(gòu)

 硬件方面,camera系統(tǒng)分為主控制器和攝像頭設(shè)備,功能上主要有preview預(yù)覽,takePicture拍照和recording錄像。

1) IPU - Image Process Unit 圖像處理單元,用于控制攝像機(jī)和顯示屏。

2)圖像采集 - 由camera采集的圖像數(shù)據(jù)信息通過(guò)IPU的CSI接口控制。

3)DMA映射到內(nèi)存 - IPU將采集到得數(shù)據(jù)通過(guò)DMA映射到一段內(nèi)存。

4)隊(duì)列機(jī)制 - 為了更高效地傳送數(shù)據(jù),將內(nèi)存中的數(shù)據(jù)取出加入一隊(duì)列,并傳送到另一隊(duì)列。

5)視頻輸出 - 將視頻數(shù)據(jù)從隊(duì)列中取出,通過(guò)IPU控制這段獨(dú)立顯存,最終將視頻顯示出來(lái)。

 

1.2 Android架構(gòu)

Android的camera系統(tǒng)架構(gòu)自上而下分別為應(yīng)用層-框架層-硬件抽象層-linux驅(qū)動(dòng)層。

1) APP - Framework

應(yīng)用層與java框架層的間主要由Binder機(jī)制進(jìn)行通信。

系統(tǒng)初始化時(shí)會(huì)開啟一個(gè)CameraService的守護(hù)進(jìn)程,為上層應(yīng)用提供camera對(duì)的功能接口。

2) Framework - HAL

框架層與硬件抽象層間通過(guò)回調(diào)函數(shù)傳遞數(shù)據(jù)。

3) Overlay

Overlay層由ServiceFlinger和OverlayHal組成,實(shí)現(xiàn)視頻輸出功能,只有camera框架層或者視頻框架層能調(diào)用它,上層無(wú)法直接調(diào)用。

4) HAL - driver

抽象層位于用戶空間,通過(guò)系統(tǒng)調(diào)用如open(),read(),ioctl()等與內(nèi)核空間進(jìn)行數(shù)據(jù)傳遞。

 

2 CameraService

 Camera的主要功能有取景Preview,拍照takePicture和攝影Recording,下文以取景為例,剖析camera系統(tǒng)架構(gòu)。

 

要實(shí)現(xiàn)取景Preview功能,主要須調(diào)用CameraService::Client::startPreview()和 CameraService::Client::setOverlay(),前者通過(guò)mHardware->startPreview();調(diào)用 cameraHal硬件抽象層以實(shí)現(xiàn)取景的整個(gè)流程,后者通過(guò)mSurface->createOverlay();調(diào)用 surfaceFlinger層創(chuàng)建overlay_object對(duì)象。

 

3 HAL

 

startPreview主要完成三項(xiàng)任務(wù),配置圖象,配置內(nèi)存,開啟兩個(gè)存取buf隊(duì)列的線程。

1) cameraPreviewConfig()配置預(yù)覽圖象參數(shù)

CameraOpen() - 通過(guò)打開設(shè)備節(jié)點(diǎn)/dev/video0得以由系統(tǒng)接口與設(shè)備驅(qū)動(dòng)交互。

S_FMT - ioctl()的指令,設(shè)置圖象像素格式,將數(shù)據(jù)由硬件抽象層傳遞至Linux驅(qū)動(dòng),這里也就是v4l2。

G_FMT - 得到圖象像素格式,將數(shù)據(jù)由底層驅(qū)動(dòng)v4l2返回至硬件抽象層。

S_PARM - 設(shè)置模式的指令,這個(gè)指令傳到底層后,將會(huì)實(shí)現(xiàn)對(duì)camera硬件的控制。

2) cameraPreviewStart()開啟預(yù)覽,實(shí)際上配置了內(nèi)存

REQBUFS - 申請(qǐng)內(nèi)存,通過(guò)dma_alloc_coherent()為camera申請(qǐng)一端連續(xù)的dma內(nèi)存。

QUERYBUF - 詢問(wèn)內(nèi)存,將申請(qǐng)到內(nèi)存的物理地址,虛擬地址等數(shù)據(jù)從內(nèi)核空間傳遞到用戶空間。

QBUF - 加入隊(duì)列,將通過(guò)詢問(wèn)得到的buf加入一個(gè)隊(duì)列。

3) PreviewShowFrameThread()和PreviewShowFrameThread()

PreviewCaptureFrameThread()捕捉一幀數(shù)據(jù)的線程,通過(guò)DQBUF,從隊(duì)列中取出一個(gè)buf數(shù)據(jù),這里,一個(gè)buf即一幀數(shù)據(jù)即一張圖片。注意,如果camera沒(méi)有采集到圖片,這個(gè)線程會(huì)在DQBUF阻塞。

PreviewShowFrameThread()顯示一幀數(shù)據(jù)的線程。

mDataCb() - 回調(diào)函數(shù),將采集到的圖象數(shù)據(jù)傳回CameraService,再由CameraService傳遞給上層應(yīng)用。

mOverlay->dequeueBuffer() - 調(diào)用Overlay層,從Overlay層得到一個(gè)空閑的overlaybuffer,將圖象數(shù)據(jù)拷貝到這個(gè)buffer里。至于這個(gè)buffer后續(xù)的工作,即視頻輸出,則交給了Overlay去完成。

QUERYBUF & QBUF - 由于已經(jīng)從隊(duì)列里取出了一個(gè)buf,需要再詢問(wèn)并加入另一個(gè)buf到隊(duì)列里。

4) Overlay

CameraService::Client::startPreview()完成mHardware->startPreview();后 便去執(zhí)行CameraService::Client::setOverlay(),如果沒(méi)有任何overlay,則創(chuàng)建一個(gè)新的,通過(guò) mHardware->setOverlay(new Overlay(mOverlayRef))調(diào)用到SurfaceFlinger層,再由 overlay_dev->createOverlay();調(diào)用到overlay的硬件抽象層,抽象層創(chuàng)建并初始化overlay對(duì)象,與 cameraHal類似,通過(guò)ioctl()指令與底層v4l2通信,配置視頻參數(shù)和內(nèi)存空間。隨后開啟一個(gè)overlay線程,用于存取隊(duì)列中的視頻數(shù) 據(jù)。

注意,SurfaceFlinger里也會(huì)開啟一個(gè)處理overlay的surfaceFlinger線程,用于等待用戶事件,作相應(yīng)的overlay控制。

 

5 Video for Linux

 

v4l2 - video for linux 2是linux為視頻驅(qū)動(dòng)抽象出的一層統(tǒng)一的接口,數(shù)據(jù)結(jié)構(gòu)如下,

v4l2作為master主設(shè)備由(*attach)與camera從設(shè)備進(jìn)行綁定。

初始化函數(shù)probe()如下,

1) init_camera_struct()初始化v4l2主設(shè)備的數(shù)據(jù)結(jié)構(gòu),實(shí)現(xiàn)open(), read(), ioctl(), mmap()等操作。

2) v4l2_int_device_register(),注冊(cè)v4l2主設(shè)備,綁定camera從設(shè)備。

3) video_register_device()注冊(cè)linux video設(shè)備,建立/dev/video0設(shè)備節(jié)點(diǎn)。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Android Camera系統(tǒng)
Android camera轉(zhuǎn)載自http://blog.csdn.net/raindrophust/article/details/6205038
Android系統(tǒng)中視頻電話中camera部分?jǐn)?shù)據(jù)流分析
介紹 Android 的 Camera 框架
Android手機(jī)攝像頭編程入門
android 多媒體和相機(jī)詳解十
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服