Android?Camera?API作用及使用指南
一 StreamConfigurationMap
1. StreamConfigurationMap 的作用
StreamConfigurationMap
是 Android Camera2 API 中的一個核心類,用于描述相機(jī)設(shè)備支持的輸出流配置,包含以下信息:
- 支持的格式與分辨率:例如 YUV_420_888、JPEG、RAW 等格式及其對應(yīng)的分辨率列表。
- 輸入/輸出流組合規(guī)則:例如哪些格式可以同時用于 預(yù)覽、拍照 或 錄像。
- 硬件能力限制:例如是否支持 硬件級圖像處理(如 YUV 重處理)、動態(tài)范圍模式(HDR)等。
- 幀率與時長限制:如某些分辨率下支持的最小/最大幀率,或視頻錄制的最大時長。
應(yīng)用通過 CameraCharacteristics
獲取 StreamConfigurationMap
,并基于此配置合理的 CaptureSession
(例如選擇預(yù)覽和拍照的兼容分辨率)。
2. 與 cameraprovider 交互關(guān)系
(1) 數(shù)據(jù)來源
- CameraProvider 提供原始數(shù)據(jù):
Camera HAL 實(shí)現(xiàn)(如 android.hardware.camera.provider@2.4
)通過 getCameraCharacteristics()
方法向框架上報硬件能力,包括支持的流配置(格式、分辨率、動態(tài)范圍等)。
- 框架封裝為 StreamConfigurationMap:
框架層(如 CameraService
)解析 HAL 返回的元數(shù)據(jù),將其轉(zhuǎn)換為應(yīng)用可直接使用的 StreamConfigurationMap
。
(2) 配置流程示例
- 應(yīng)用請求相機(jī)能力:
- 應(yīng)用調(diào)用
CameraManager.getCameraCharacteristics(cameraId)
。
- 應(yīng)用調(diào)用
- 框架查詢 HAL:
CameraService
通過CameraProvider
的 HAL 接口獲取該相機(jī)的元數(shù)據(jù)。
- HAL 返回底層配置:
CameraProvider
從硬件或板級配置文件(如cam_board.xml
)中讀取支持的流配置,傳遞給框架。
- 構(gòu)建 StreamConfigurationMap:
- 框架將原始數(shù)據(jù)(如
SCALER_AVAILABLE_STREAM_CONFIGURATIONS
)封裝為StreamConfigurationMap
對象。
- 框架將原始數(shù)據(jù)(如
- 應(yīng)用使用配置:
- 應(yīng)用根據(jù)
StreamConfigurationMap
選擇兼容的流組合(例如同時支持1080p@30fps
預(yù)覽和12MP
拍照)。
- 應(yīng)用根據(jù)
(3) 關(guān)鍵數(shù)據(jù)結(jié)構(gòu)對應(yīng)
HAL 元數(shù)據(jù)字段(如 android.scaler ) | StreamConfigurationMap 方法 | 作用 |
---|---|---|
SCALER_AVAILABLE_STREAM_CONFIGURATIONS | getOutputSizes(int format) | 獲取某格式支持的分辨率列表 |
SCALER_AVAILABLE_MIN_FRAME_DURATIONS | getOutputMinFrameDuration(int format) | 獲取某分辨率下最小幀間隔(決定最大幀率) |
REQUEST_AVAILABLE_CAPABILITIES | isOutputSupportedFor(int useCase) | 檢查是否支持特定用例(如 ZSL) |
3. 實(shí)際示例
假設(shè)一個相機(jī)設(shè)備支持以下配置(通過 CameraProvider
上報):
- YUV_420_888: 1920x1080@30fps, 1280x720@60fps
- JPEG: 4000x3000@10fps
則 StreamConfigurationMap
會生成如下信息:
// 獲取 YUV 格式支持的分辨率 Size[] yuvSizes = streamConfigMap.getOutputSizes(ImageFormat.YUV_420_888); // 結(jié)果: [1920x1080, 1280x720] // 檢查是否支持硬件級 YUV 重處理 boolean isReprocessSupported = streamConfigMap.isOutputSupportedFor( CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING);
StreamConfigurationMap
是應(yīng)用層獲取相機(jī)輸出能力的接口,而 CameraProvider
是底層硬件能力的提供者。前者依賴后者上報的元數(shù)據(jù),二者共同實(shí)現(xiàn) 硬件能力到應(yīng)用接口的透明映射,是 Android Camera 系統(tǒng)分層架構(gòu)的核心設(shè)計(jì)之一。
在 Android 相機(jī)系統(tǒng)(Camera2 API)中,OutputConfiguration
和 StreamConfigurationMap
是與相機(jī)輸出流配置相關(guān)的兩個關(guān)鍵類,它們在相機(jī)工作流程中扮演不同角色。以下是它們的詳細(xì)介紹及關(guān)系分析:
二. OutputConfiguration
1 作用
作用:
OutputConfiguration
是 Android 5.0(API 21)引入的類,用于定義單個相機(jī)輸出流的配置。它的核心功能包括:
- 封裝輸出目標(biāo)(如
Surface
或SurfaceView
)。 - 配置物理相機(jī)(在多攝像頭設(shè)備中指定物理傳感器)。
- 管理共享輸出流(允許多個
Surface
共享同一輸出流)。 - 使用場景:
- 當(dāng)創(chuàng)建
CameraCaptureSession
時,需傳入一組OutputConfiguration
對象,描述所有輸出流。 - 關(guān)鍵方法:
addSurface(Surface surface)
:添加共享的Surface
。setPhysicalCameraId(String id)
:指定物理相機(jī)(用于雙攝/多攝設(shè)備)。getSurfaces()
:獲取關(guān)聯(lián)的Surface
列表。
- 示例:
// 創(chuàng)建 ImageReader 并獲取 Surface ImageReader imageReader = ImageReader.newInstance(width, height, format, maxImages); Surface imageSurface = imageReader.getSurface(); // 創(chuàng)建 OutputConfiguration OutputConfiguration outputConfig = new OutputConfiguration(imageSurface); // 可選:配置共享 Surface 或物理相機(jī) // outputConfig.addSurface(anotherSurface); // outputConfig.setPhysicalCameraId("2"); // 創(chuàng)建 CameraCaptureSession List<OutputConfiguration> outputConfigs = new ArrayList<>(); outputConfigs.add(outputConfig); cameraDevice.createCaptureSessionByOutputConfigurations(outputConfigs, callback, handler);
2. 與 StreamConfigurationMap 關(guān)系
協(xié)作流程:
- Step 1:通過
StreamConfigurationMap
查詢設(shè)備支持的輸出參數(shù)(格式、分辨率等)。 - Step 2:根據(jù)合法參數(shù)創(chuàng)建輸出目標(biāo)(如
ImageReader
或SurfaceView
)。 - Step 3:將輸出目標(biāo)封裝到
OutputConfiguration
,用于創(chuàng)建CameraCaptureSession
。
依賴關(guān)系:
OutputConfiguration
的參數(shù)(如格式、分辨率)必須符合StreamConfigurationMap
的約束,否則會話創(chuàng)建會失敗。StreamConfigurationMap
提供理論支持,OutputConfiguration
負(fù)責(zé)實(shí)際配置。
擴(kuò)展功能:
OutputConfiguration
支持高級功能(如多攝像頭共享輸出流),而StreamConfigurationMap
僅描述硬件能力。- 在 Android 10(API 29)后,
OutputConfiguration
新增對動態(tài)分辨率、物理攝像頭綁定的支持。
3. 常見問題
Q1: 為什么需要同時使用兩者?
A:
StreamConfigurationMap是相機(jī)設(shè)備的“能力說明書”,告訴開發(fā)者硬件支持哪些輸出配置。
OutputConfiguration是實(shí)際構(gòu)建輸出流的“施工圖”,將合法的參數(shù)綁定到具體的
Surface`。
二者配合確保相機(jī)輸出流的正確性和高效性
Q2: 如何避免 InvalidSurfaceException
?
A: 確保 OutputConfiguration
的 Surface
參數(shù)(格式、分辨率)在 StreamConfigurationMap
的合法范圍內(nèi)。
Q3: 多攝像頭場景如何處理?
A: 使用 OutputConfiguration.setPhysicalCameraId()
指定物理攝像頭,并通過 StreamConfigurationMap
檢查該攝像頭是否支持目標(biāo)參數(shù)。
總結(jié) StreamConfigurationMap
是相機(jī)設(shè)備的“能力說明書”,告訴開發(fā)者硬件支持哪些輸出配置。OutputConfiguration
是實(shí)際構(gòu)建輸出流的“施工圖”,將合法的參數(shù)綁定到具體的 Surface
。二者配合確保相機(jī)輸出流的正確性和高效性,是 Camera2 API 中不可或缺的組件。
在 Android Camera2 API 中,CameraCaptureSession
是管理相機(jī)數(shù)據(jù)流和捕獲請求的核心組件。它與 OutputConfiguration
密切相關(guān),共同決定了相機(jī)的輸出目標(biāo)(如預(yù)覽、拍照、錄像等)的配置和運(yùn)行機(jī)制。以下是詳細(xì)解釋及其與 OutputConfiguration
的關(guān)系:
三 CameraCaptureSession
1. 作用
CameraCaptureSession
是相機(jī)設(shè)備(CameraDevice
)與輸出目標(biāo)(Surface
)之間的橋梁,負(fù)責(zé):
管理輸出流:綁定多個 Surface
(如預(yù)覽的 SurfaceView
、拍照的 ImageReader
),并確保數(shù)據(jù)正確傳輸?shù)竭@些目標(biāo)。
提交捕獲請求:通過 capture()
或 setRepeatingRequest()
發(fā)送請求(CaptureRequest
),控制相機(jī)的行為(如自動對焦、曝光、幀率等)。
處理異步事件:監(jiān)聽相機(jī)狀態(tài)(如對焦完成、幀捕獲完成)并回調(diào)給應(yīng)用。
2 生命周期
- 創(chuàng)建:通過
CameraDevice.createCaptureSession()
或createCaptureSessionByOutputConfigurations()
創(chuàng)建。 - 活動狀態(tài):可提交捕獲請求,相機(jī)數(shù)據(jù)流向綁定的
Surface
。 - 關(guān)閉:調(diào)用
close()
釋放資源,不可再發(fā)送請求。
3.創(chuàng)建 CameraCaptureSession
創(chuàng)建會話時,需要指定一組輸出目標(biāo)(Surface
或 OutputConfiguration
)。兩種方法:
傳統(tǒng)方式(基于 Surface
列表):
cameraDevice.createCaptureSession( List<Surface> outputs, // 直接傳遞 Surface 列表 CameraCaptureSession.StateCallback callback, Handler handler );
適用于簡單場景,但靈活性有限(例如不支持多攝像頭或動態(tài)分辨率)。
基于 OutputConfiguration
的方式(API 21+,擴(kuò)展功能在后續(xù)版本增強(qiáng)):
cameraDevice.createCaptureSessionByOutputConfigurations( List<OutputConfiguration> outputConfigurations, // 封裝了 Surface 的高級配置 CameraCaptureSession.StateCallback callback, Handler handler );
支持更復(fù)雜的配置(如共享流、物理攝像頭綁定、動態(tài)分辨率等)。
4. 與 OutputConfiguration 的關(guān)系
(1) OutputConfiguration 是會話的輸入
- 功能:
OutputConfiguration
封裝了一個或多個Surface
的配置信息,用于定義輸出流的特性:- 單個或共享的
Surface
:通過addSurface()
添加多個Surface
,共享同一數(shù)據(jù)流(例如預(yù)覽和錄像共享同一幀數(shù)據(jù))。 - 物理攝像頭綁定:在雙攝/多攝設(shè)備中,通過
setPhysicalCameraId()
指定輸出流來自哪個物理攝像頭。 - 動態(tài)分辨率(API 23+):允許在會話運(yùn)行時動態(tài)調(diào)整分辨率(需硬件支持)。
- 單個或共享的
- 優(yōu)勢:相比直接傳遞
Surface
列表,OutputConfiguration
提供了更細(xì)粒度的控制能力。
(2) 創(chuàng)建會話的流程
- 查詢設(shè)備支持:通過
StreamConfigurationMap
確認(rèn)相機(jī)支持的格式和分辨率。 - 創(chuàng)建輸出目標(biāo):根據(jù)合法參數(shù)創(chuàng)建
Surface
(如ImageReader
、SurfaceView
)。 - 封裝為 OutputConfiguration:將
Surface
及其附加配置(如物理攝像頭)封裝到OutputConfiguration
。 - 創(chuàng)建會話:調(diào)用
createCaptureSessionByOutputConfigurations()
,傳入OutputConfiguration
列表。
(3) 關(guān)鍵約束
- 不可變性:一旦
CameraCaptureSession
創(chuàng)建成功,其綁定的OutputConfiguration
不可修改(如新增或移除Surface
)。若需更改,必須關(guān)閉當(dāng)前會話并重新創(chuàng)建。 - 硬件限制:
OutputConfiguration
的配置(如分辨率、格式)必須符合StreamConfigurationMap
的支持范圍。
5. 示例:使用 OutputConfiguration 創(chuàng)建會話
// 創(chuàng)建兩個輸出目標(biāo):預(yù)覽 Surface 和拍照 ImageReader SurfaceView surfaceView = ... // 預(yù)覽的 SurfaceView ImageReader imageReader = ImageReader.newInstance(4032, 3024, ImageFormat.JPEG, 3); // 封裝為 OutputConfiguration OutputConfiguration previewConfig = new OutputConfiguration(surfaceView.getHolder().getSurface()); OutputConfiguration captureConfig = new OutputConfiguration(imageReader.getSurface()); // 可選:配置共享流或物理攝像頭 // previewConfig.addSurface(anotherSurface); // 共享同一個流 // captureConfig.setPhysicalCameraId("1"); // 指定物理攝像頭 List<OutputConfiguration> outputConfigs = new ArrayList<>(); outputConfigs.add(previewConfig); outputConfigs.add(captureConfig); // 創(chuàng)建 CameraCaptureSession cameraDevice.createCaptureSessionByOutputConfigurations(outputConfigs, new CameraCaptureSession.StateCallback() { @Override public void onConfigured(@NonNull CameraCaptureSession session) { // 會話就緒,可提交 CaptureRequest } @Override public void onConfigureFailed(@NonNull CameraCaptureSession session) { // 配置失?。▍?shù)不合法或硬件問題) } }, null // 可選 Handler );
6. 高級功能與兼容性
- 共享流(Shared Surfaces):
- 多個
Surface
共享同一輸出流(例如預(yù)覽和 AI 分析共享數(shù)據(jù)),減少內(nèi)存和功耗。 - 實(shí)現(xiàn)方式:通過
OutputConfiguration.addSurface()
添加多個Surface
。
- 多個
- 動態(tài)分辨率(Dynamic Resolution)(API 23+):
- 允許在會話運(yùn)行時動態(tài)調(diào)整輸出分辨率(需設(shè)備支持)。
- 通過
OutputConfiguration.setDynamicRangeProfile()
配置。
- 多攝像頭支持(API 28+):
- 在雙攝設(shè)備中,通過
OutputConfiguration.setPhysicalCameraId()
指定輸出流來源。
- 在雙攝設(shè)備中,通過
7. 常見問題與解決方案
- 問題1:
createCaptureSession
失敗,錯誤為IllegalArgumentException
。 - 原因:
OutputConfiguration
參數(shù)不合法(如分辨率超出支持范圍)。 - 解決:檢查
StreamConfigurationMap
的合法參數(shù)。 - 問題2:無法在運(yùn)行時修改輸出流。
- 原因:
CameraCaptureSession
的配置不可變。 - 解決:關(guān)閉當(dāng)前會話,重新創(chuàng)建新的會話。
- 問題3:多攝像頭場景下數(shù)據(jù)流混亂。
- 原因:未正確指定
setPhysicalCameraId()
。 - 解決:確保每個
OutputConfiguration
綁定到正確的物理攝像頭。
總結(jié)
CameraCaptureSession
:是相機(jī)數(shù)據(jù)流的核心控制器,負(fù)責(zé)管理輸出目標(biāo)和捕獲請求。- 與
OutputConfiguration
的關(guān)系:OutputConfiguration
是會話的輸入,定義了每個輸出流的具體配置(如Surface
、物理攝像頭)。CameraCaptureSession
通過OutputConfiguration
的配置,確保數(shù)據(jù)流符合硬件能力(由StreamConfigurationMap
定義)。- 使用
OutputConfiguration
可以啟用高級功能(如共享流、多攝像頭),而傳統(tǒng)Surface
列表方式功能受限。
通過合理使用 OutputConfiguration
,開發(fā)者可以更靈活地配置相機(jī)輸出流,滿足復(fù)雜場景的需求(如多攝、動態(tài)分辨率、低功耗共享流)。
到此這篇關(guān)于Android Camera API 介紹的文章就介紹到這了,更多相關(guān)Android Camera API內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
淺析Android Service中實(shí)現(xiàn)彈出對話框的坑
這篇文章主要介紹了Android Service中實(shí)現(xiàn)彈出對話框的坑,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-04-04Android開發(fā)常用標(biāo)簽小結(jié)
這篇文章主要介紹了Android開發(fā)常用標(biāo)簽,分析總結(jié)了Android開發(fā)中常見標(biāo)簽的使用技巧,需要的朋友可以參考下2015-05-05Android studio實(shí)現(xiàn)菜單操作
這篇文章主要為大家詳細(xì)介紹了Android studio實(shí)現(xiàn)菜單操作,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-10-10SurfaceView實(shí)現(xiàn)紅包雨平移動畫
這篇文章主要為大家詳細(xì)介紹了SurfaceView實(shí)現(xiàn)紅包雨平移動畫,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-07-07Android?PickerScrollView滑動選擇控件使用方法詳解
這篇文章主要為大家詳細(xì)介紹了Android?PickerScrollView滑動選擇控件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-04-04Kotlin 協(xié)程 supervisorScope {} 運(yùn)行崩潰解決方法
看過很多?supervisorScope {}?文檔的使用,我照抄一摸一樣的代碼,運(yùn)行就崩潰,最后找到了解決方法,應(yīng)該是kotlin版本更新做過改動,當(dāng)前我使用的是?androidx.core:core-ktx:1.9.0,本文給大家介紹Kotlin 協(xié)程 supervisorScope {} 運(yùn)行崩潰解決方法,感興趣的朋友一起看看吧2024-01-01Android webview注入JS代碼 修改網(wǎng)頁內(nèi)容操作
這篇文章主要介紹了Android webview注入JS代碼 修改網(wǎng)頁內(nèi)容操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03Android實(shí)現(xiàn)將View保存成Bitmap的方法
這篇文章主要介紹了Android實(shí)現(xiàn)將View保存成Bitmap的方法,涉及Android畫布Canvas、位圖bitmap及View的相關(guān)使用技巧,需要的朋友可以參考下2016-06-06Android 6.0 藍(lán)牙搜索不到設(shè)備原因,MIUI權(quán)限申請機(jī)制方法
今天小編就為大家分享一篇Android6.0 藍(lán)牙搜索不到設(shè)備原因,MIUI權(quán)限申請機(jī)制方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-07-07