一、Camera2實現(xiàn)預(yù)覽、拍照、錄像三大基礎(chǔ)功能的流程框架圖
Camera2關(guān)鍵幾個類:
CameraManager
管理手機(jī)上的所有攝像頭設(shè)備。管理手機(jī)上的所有攝像頭設(shè)備,它的作用主要是獲取攝像頭列表和打開(openCamera)指定的攝像頭。
它其實是一個系統(tǒng)服務(wù),通過getSystemService(Context.CAMERA_SERVICE)獲取,它的作用主要是獲取攝像頭列表和打開指定的攝像頭。
通過CameraManager對象可以得到一些相機(jī)的基本信息,這個信息就存儲在CameraCharacteristic對象中。
除了獲取Camera的屬性信息外,CameraManager對象最重要的作用就是打開相機(jī)(openCamera),通過CameraManager才能真正的拿到CameraDevice對象去操作相機(jī)。
CameraDevice
具體的攝像頭設(shè)備,它有一系列參數(shù)(預(yù)覽尺寸、拍照尺寸等),可以通過CameraManager的getCameraCharacteristics()方法獲取。它的作用主要是創(chuàng)建CameraCaptureSession和CaptureRequest。
CameraCaptureSession
相機(jī)捕獲會話,代表上層與底層之間的一個會話,通過這個會話可以下發(fā)指令給相機(jī),讓相機(jī)執(zhí)行預(yù)覽、拍照錄像等操作,在mCameraDevice.createCaptureSession的回調(diào)中獲得。主要作用是用于處理拍照和預(yù)覽的工作(很重要)。
想從相機(jī)設(shè)備中獲取Image,首先要創(chuàng)建一個CameraCaptureSession把接收數(shù)據(jù)的載體傳給相機(jī)設(shè)備,目前能接收相機(jī)數(shù)據(jù)的載體是Surface和SurfaceTexture。
通過情況下,相機(jī)的預(yù)覽數(shù)據(jù)可以使用SurfaceView和TextureView接收。拍照使用ImageReader、錄視頻使用MediaCodec或MediaRecorder。
絕大部分的相機(jī)操作都是通過向 CameraCaptureSession 提交一個 Capture 請求實現(xiàn)的,例如拍照、連拍、設(shè)置閃光燈模式、觸摸對焦、顯示預(yù)覽畫面等等。
CaptureRequest
CaptureRequest代表相機(jī)捕獲請求,當(dāng)CaptureCaptureSession創(chuàng)建好之后,就可以使用這個會話來下發(fā)指令,表明當(dāng)前是需要預(yù)覽、拍照、還是錄像。CaptureRequest對象可以攜帶設(shè)置的參數(shù),比如是否自動對焦、自動曝光、自動白平衡等。CaptureRequest對象的創(chuàng)建使用了建造者模式,需要通過CaptureRequest.Builder來創(chuàng)建,通過調(diào)用build方法。
CaptureRequest 是向 CameraCaptureSession 提交 Capture 請求時的信息載體,其內(nèi)部包括了本次 Capture 的參數(shù)配置和接收圖像數(shù)據(jù)的 Surface。CaptureRequest 可以配置的信息非常多,包括圖像格式、圖像分辨率、傳感器控制、閃光燈控制、3A 控制等等,可以說絕大部分的相機(jī)參數(shù)都是通過 CaptureRequest 配置的。值得注意的是每一個 CaptureRequest 表示一幀畫面的操作,這意味著你可以精確控制每一幀的 Capture 操作。
CaptureRequest定義了輸出緩沖區(qū)以及顯示界面(TextureView或SurfaceView)等。
CaptureResut
CaptureResut代表捕獲請求返回的一些結(jié)果信息,從里面可以獲取一些Metadata數(shù)據(jù)信息。
CaptureResult 是每一次 Capture 操作的結(jié)果,里面包括了很多狀態(tài)信息,包括閃光燈狀態(tài)、對焦?fàn)顟B(tài)、時間戳等等。例如你可以在拍照完成的時候,通過 CaptureResult 獲取本次拍照時的對焦?fàn)顟B(tài)和時間戳。需要注意的是,CaptureResult 并不包含任何圖像數(shù)據(jù),前面我們在介紹 Surface 的時候說了,圖像數(shù)據(jù)都是從 Surface 獲取的。
Surface
Surface 是一塊用于填充圖像數(shù)據(jù)的內(nèi)存空間,例如你可以使用 SurfaceView 的 Surface 接收每一幀預(yù)覽數(shù)據(jù)用于顯示預(yù)覽畫面,也可以使用 ImageReader 的 Surface 接收 JPEG 或 YUV 數(shù)據(jù)。每一個 Surface 都可以有自己的尺寸和數(shù)據(jù)格式,你可以從 CameraCharacteristics 獲取某一個數(shù)據(jù)格式支持的尺寸列表。
二、概念
Capture
相機(jī)的所有操作和參數(shù)配置最終都是服務(wù)于圖像捕獲,例如對焦是為了讓某一個區(qū)域的圖像更加清晰,調(diào)節(jié)曝光補(bǔ)償是為了調(diào)節(jié)圖像的亮度。因此,在 Camera2 里面所有的相機(jī)操作和參數(shù)配置都被抽象成 Capture(捕獲),所以不要簡單的把 Capture 直接理解成是拍照,因為 Capture 操作可能僅僅是為了讓預(yù)覽畫面更清晰而進(jìn)行對焦而已。如果你熟悉 Camera1,那你可能會問 setFlashMode() 在哪?setFocusMode() 在哪?takePicture() 在哪?告訴你,它們都是通過 Capture 來實現(xiàn)的。
Capture 從執(zhí)行方式上又被細(xì)分為【單次模式】、【多次模式】和【重復(fù)模式】三種,我們來一一解釋下:
-
單次模式(One-shot):指的是只執(zhí)行一次的 Capture 操作,例如設(shè)置閃光燈模式、對焦模式和拍一張照片等。多個一次性模式的 Capture 會進(jìn)入隊列按順序執(zhí)行。
-
多次模式(Burst):指的是連續(xù)多次執(zhí)行指定的 Capture 操作,該模式和多次執(zhí)行單次模式的最大區(qū)別是連續(xù)多次 Capture 期間不允許插入其他任何 Capture 操作,例如連續(xù)拍攝 100 張照片,在拍攝這 100 張照片期間任何新的 Capture 請求都會排隊等待,直到拍完 100 張照片。多組多次模式的 Capture 會進(jìn)入隊列按順序執(zhí)行。
-
重復(fù)模式(Repeating):指的是不斷重復(fù)執(zhí)行指定的 Capture 操作,當(dāng)有其他模式的 Capture 提交時會暫停該模式,轉(zhuǎn)而執(zhí)行其他被模式的 Capture,當(dāng)其他模式的 Capture 執(zhí)行完畢后又會自動恢復(fù)繼續(xù)執(zhí)行該模式的 Capture,例如顯示預(yù)覽畫面就是不斷 Capture 獲取每一幀畫面。該模式的 Capture 是全局唯一的,也就是新提交的重復(fù)模式 Capture 會覆蓋舊的重復(fù)模式 Capture。
?一些只有 Camera2 才支持的高級特性
如果要我給出強(qiáng)有力的理由解釋為什么要使用 Camera2,那么通過 Camera2 提供的高級特性可以構(gòu)建出更加高質(zhì)量的相機(jī)應(yīng)用程序應(yīng)該是最佳理由了。
1)、在開啟相機(jī)之前檢查相機(jī)信息
出于某些原因,你可能需要先檢查相機(jī)信息再決定是否開啟相機(jī),例如檢查閃光燈是否可用。在 Caemra1 上,你無法在開機(jī)相機(jī)之前檢查詳細(xì)的相機(jī)信息,因為這些信息都是通過一個已經(jīng)開啟的相機(jī)實例提供的。在 Camera2 上,我們有了和相機(jī)實例完全剝離的 CameraCharacteristics 實例專門提供相機(jī)信息,所以我們可以在不開啟相機(jī)的前提下檢查幾乎所有的相機(jī)信息。
2)、在不開啟預(yù)覽的情況下拍照
在 Camera1 上,開啟預(yù)覽是一個很重要的環(huán)節(jié),因為只有在開啟預(yù)覽之后才能進(jìn)行拍照,因此即使顯示預(yù)覽畫面與實際業(yè)務(wù)需求相違背的時候,你也不得不開啟預(yù)覽。而 Camera2 則不強(qiáng)制要求你必須先開啟預(yù)覽才能拍照。
3)、一次拍攝多張不同格式和尺寸的圖片
在 Camera1 上,一次只能拍攝一張圖片,更不同談多張不同格式和尺寸的圖片了。而 Camera2 則支持一次拍攝多張圖片,甚至是多張格式和尺寸都不同的圖片。例如你可以同時拍攝一張 1440x1080 的 JPEG 圖片和一張全尺寸的 RAW 圖片。
4)、控制曝光時間
在暗環(huán)境下拍照的時候,如果能夠適當(dāng)延長曝光時間,就可以讓圖像畫面的亮度得到提高。在 Camera2 上,你可以在規(guī)定的曝光時長范圍內(nèi)配置拍照的曝光時間,從而實現(xiàn)拍攝長曝光圖片,你甚至可以延長每一幀預(yù)覽畫面的曝光時間讓整個預(yù)覽畫面在暗環(huán)境下也能保證一定的亮度。而在 Camera1 上你只能 YY 一下。
5)、連拍
連拍 30 張圖片這樣的功能在 Camera2 出現(xiàn)之前恐怕只有系統(tǒng)相機(jī)才能做到了(通過 OpenGL 截取預(yù)覽畫面的做法除外),也可能是出于這個原因,市面上的第三方相機(jī)無一例外都不支持連拍。有了 Camera2,你完全可以讓你的相機(jī)應(yīng)用程序支持連拍功能,甚至是連續(xù)拍 30 張使用不同曝光時間的圖片。
6)、靈活的 3A 控制
3A(AF、AE、AWB)的控制在 Camera2 上得到了最大化的放權(quán),應(yīng)用層可以根據(jù)業(yè)務(wù)需求靈活配置 3A 流程并且實時獲取 3A 狀態(tài),而 Camera1 在 3A 的控制和監(jiān)控方面提供的接口則要少了很多。例如你可以在拍照前進(jìn)行 AE 操作,并且監(jiān)聽本這次拍照是否點(diǎn)亮閃光燈。
?一些從 Camera1 遷移到 Camera2 的建議文章來源:http://www.zghlxwxcb.cn/news/detail-559089.html
如果你熟悉 Camera1,并且打算從 Camera1 遷移到 Camera2 的話,希望以下幾個建議可以對你起到幫助:
1)、Camera1 嚴(yán)格區(qū)分了預(yù)覽和拍照兩個流程,而 Camera2 則把這兩個流程都抽象成了 Capture 行為,只不過一個是不斷重復(fù)的 Capture,一個是一次性的 Capture 而已。
2)、Camera2 的一些 API 調(diào)用也會耗時,所以建議你使用獨(dú)立的線程執(zhí)行所有的相機(jī)操作,盡量避免直接在主線程調(diào)用 Camera2 的 API,HandlerThread 是一個不錯的選擇。
3)、Camera2 所有的相機(jī)操作都可以注冊相關(guān)的回調(diào)接口,然后在不同的回調(diào)方法里寫業(yè)務(wù)邏輯,這可能會讓你的代碼因為不夠線性而錯綜復(fù)雜,建議你可以嘗試使用子線程的阻塞方式來盡可能地保證代碼的線性執(zhí)行。例如在子線程阻塞等待 CaptureResult,然后繼續(xù)執(zhí)行后續(xù)的操作,而不是將代碼拆分到到 CaptureCallback.onCaptureCompleted() 方法里。文章來源地址http://www.zghlxwxcb.cn/news/detail-559089.html
到了這里,關(guān)于Android Camera2-預(yù)覽、拍照、錄像流程的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!