Qualcomm Camera基礎

來源:互聯網
上載者:User

1. 設定網路攝影機方向

2. 開啟線程與預覽線程 

3. 設定參數

4. Camera外設按鍵

5. 自動對焦與觸摸對焦

6. 拍照

7. 臉部偵測

8. 位置管理

9. 旋轉管理

10. 變焦

11. 錄影

Camera的架構為典型的C/S架構,Client端,使用者的行為,是為應用程式進程,Server端,裝置的功能,是為Camera服務守護進程,用戶端進程承載使用者的需求,由Binder處理序間通訊送往服務端實現裝置的功能,服務端由回呼函數和訊息機制反饋資料返還給使用者。

ps查看進程,類似 com.android.camera是為用戶端Camera進程,/system/bin/mediaserver是為服務端守護進程,由系統啟動時開啟。

1. 設定網路攝影機方向

Framework架構層的Camera對象(camera.java)裡有一個類class CameraInfo,裡面存放了兩個公有成員變數facing和orientation,即我們要討論的前後置和方向。 程式第一次初始化時initializeFirstTime(),通過getCameraInfo()得到前後置和方向的資訊,用戶端發送請求getCameraInfo()詢問服務端,服務端調用抽象層拿資料,抽象層參考底層camera sensor驅動的資料facing和orientation,這兩個值在驅動裡是寫死的,不能由使用者改變,camera程式啟動以後就把它們作為全域變數存放起來。

1.1 前置與後置

後置back camera背對手機螢幕,朝外,像素高,前置front camera,面對自己,朝內,像素低。

1.2 方向

網路攝影機模組有長邊和短邊,比如採集映像的比例為4:3,那麼4為長邊,3為短邊。裝置螢幕也有長邊和短邊,理論上,網路攝影機模組的長邊不能與螢幕的長邊垂直,至於為什麼呢,我語文水平太差,沒辦法很好地表達出來...總之目的就是為了顯示效果。

2 開啟線程與預覽線程

onCreate()裡會先後開啟CameraOpenThread和CameraPreviewThread。

開啟camera還需要線程?CameraOpenThread名為開啟,實為C/S connect串連服務端,binder處理序間通訊,開銷較大。預覽線程必須在開啟線程完成以後執行,它貫穿始終直到進程消亡為止,整個預覽過程相對複雜,在抽象層和底層驅動實現,概括講,預覽線程再開啟兩個線程,一個拿sensor的frame,一個送往framebuffer經surfaceflinger顯示出來。

3 設定參數

預覽拍照錄影之前,使用者需要設定很多參數,比如閃光,白平衡,情境,對比等。

程式裡這些參數儲存在SharedPreferences共用優選項和Parameters兩個地方,Preferences包含Parameters,開啟程式讀取優選項參數,關閉程式儲存優選項參數,考慮到使用者經常會調整參數,引入Parameters來儲存從開啟以後到關閉以前這個中間過程的參數變數,Parameters的索引值由抽象層根據硬體sensor的能力決定。

4. Camera外設按鍵

Manifest裡註冊broadcast receiver,

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

有些手機上有camera按鍵,使用者按下按鍵,android輸入系統有兩種實現方法,

1)發送廣播CAMERA_BUTTON,收到廣播後開啟主Activity。

2)上報索引值KEYCODE_CAMERA,程式收到訊息,可自訂實現功能,比如拍照。

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

5. 自動對焦與觸摸對焦

外界事物由光線經凸透鏡聚焦到sensor上成像,camera模組開啟馬達前後平移鏡頭取得最佳成像效果,這個過程稱之為對焦。

5.1 自動對焦

1) camera模組會因感光強度變化而自動開啟對焦,驅動控制。

2) 使用者長按快門,軟體控制自動對焦。

3) 使用者按下快門拍照,拍攝前自動對焦。

程式裡,Camera對象實作類別ShutterButton的介面OnShutterButtonListener裡的方法onShutterButtonFocus(boolean pressed)和onShutterButtonClick(),後者是拍照,下節討論,先看onShutterButtonFocus(boolean pressed),這個pressed判斷是否為一次有效長按,如果是的話,執行autoFocus(),這個autoFocus()也是Camera對象實作類別FocusManager的介面Listener裡的方法,由binder交給camera
service,最後在底層驅動實現自動對焦。

5.2 觸摸對焦

自動對焦的對焦地區位於螢幕正中,使用者也可觸摸特定地區對焦。

Camera對象實作類別View的介面OnTouchListener裡的方法onTouch(),輸入系統上報MotionEvent的xy座標,儲存在Parameters,執行autoFocus(),抽象層讀取Paramters的觸摸點座標,實現地區對焦。

6. 拍照

拍照分四步,對焦,拍照,接收圖片,儲存圖片。

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

需要理解四個回呼函數,參考上一篇文章。

1)對焦

拍照前如果已經地區對焦,則取消自動對焦,反之,開啟一次自動對焦。對焦完成後,底層發送對焦成功與否的訊息給camera對象,FocusManager把狀態mState儲存起來,如果正在對焦未完成(mState == STATE_FOCUSING)則不可拍照,直到對焦完畢。

2)拍照

onShutterButtonClick() -> doSnap() -> capture() -> takePicture(),具體實現在抽象層和底層驅動,實質就是拿一張預覽的映像,抽象層讀取拍照時的Parameters參數配置,包括使用者選擇的照片大小。

3)接收圖片

通過回調,由底層發送圖片給camera對象。

RawPictureCallback,得到原始圖片,需要軟體壓縮Jpeg。(YUV轉Jpeg)

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

PostViewPictureCallback,拍完後預覽圖片。

4)儲存圖片

交由線程ImageSaver儲存圖片和產生thumbnails。

預設路徑位於/mnt/sdcard/DCIM/Camera/

7. 臉部偵測

臉部偵測可以軟體實現,可以硬體實現,軟體實現增加CPU開銷,硬體實現增大耗電,鼓勵硬體實現...

上層Camera對象實現了 framework層Camera的介面FaceDetectionListener的方法onFaceDetection(Face[] faces, Camera camera),回調機制同上,硬體sensor識別臉部資訊,發送face給camera對象,framework定義face的特徵,比如眼睛,嘴巴,上層儲存mFaces資料,更新UI。

8. 位置管理

位置管理LocationManager用來記錄拍攝圖片的GPS位置資訊(經維度),存入JPEG頭部插入的Exif裡。

使用者在菜單“相機設定”裡的"儲存所在位置"選擇開啟(前提是GPS已開啟),螢幕左上方會出現一個GPS表徵圖,表示現在可以記錄GPS資訊了。

程式裡,Camera對象實現了位置管理監聽器LocationManager.Listener的介面showGpsOnScreenIndicator()和hideGpsOnScreenIndicator(),顯示或者隱藏GPS表徵圖。

程式第一次初始化時initializeFirstTime(),通過讀取優選項Preference得到bool值recordLocation,判斷是否需要記錄GPS資訊,如果需要,在拍照capture()裡調用LocationManager的方法得到Location loc,並將其存入Exif。

9. 旋轉管理

假設一台手機,camera正常安裝,豎直方向作為預設方向(orientation == 0)拍攝照片,即拍攝“肖像照”(portrait),得到的照片顯示在螢幕上也是豎直方向。

如果把手機旋轉90度水平過來拍攝“山水照”(landscape),對於camera sensor來說,沒有旋轉的概念,所以軟體上要把圖片旋轉90度回來。

軟體上,需要藉助方向監聽器隨時更新方向資訊,並儲存在Parameters裡,抽象層實現拍照功能時從Parameters裡讀取方向。

具體的,camera對象內部類MyOrientationEventListener的方法onOrientationChanged()儲存方向orientation的值,MyOrientationEventListener繼承OrientationEventListener,OrientationEventListener的onSensorChanged()把從sensorManager拿到的xyz座標轉換成方向。

程式啟動,註冊sensor監聽器並使能,sensorManager不斷上報底層sensor資料,通過訊息機制發送到camera對象,後者計算座標資料得到方向orientation的值(實際外包給orientationListener完成),最後儲存Parameters。

10. 變焦

使用者拖動Zoom橫條可放大縮小預覽畫面連續變焦,另一種所謂狀態變焦,其原理是一樣的。

camera對象的內部類ZoomChangeListener實現ZoomControl的方法,實質是把變焦的任務全權交給ZoomControl。ZoomControl監聽處理使用者的觸摸事件dispatchTouchEvent(),用來得到並處理變焦倍數mListener.onZoomValueChanged(index),它由mCameraDevice.startSmoothZoom()通過 binder交給camera service,camera service再通過sendComand命令機制交給抽象層實現變焦,抽象層開啟變焦線程,變焦改變預覽,通過回調機制發送訊息CAMERA_MSG_ZOOM把變焦倍數返還給camera對象,最終camera對象收到訊息後,ZoomListener.onZoomChange()把變焦倍數儲存到Parameters.

11. 錄影

ModePicker負責切換模式,一共有三種模式,普通模式,錄影模式和取景模式,Manifest裡依次聲明這三個activity。

切換模式,銷毀原有activity,開啟新activity,伴隨關閉preview,重啟preview,儲存配置,讀取配置,開銷很大。

錄影VideoCamera.java同預覽Camera.java的思路類似,按下錄影按鈕,程式監聽使用者事件,開啟錄影,錄影交給MediaRecoder,StagefrightRecorder負責。

 本文轉載於http://blog.csdn.net/qq69696698/article/details/7399518

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.