注意:本頁面所述是指 Camera2 套件。除非應用程式需要 Camera2 的特定低階功能,否則建議使用 CameraX。CameraX 和 Camera2 均支援 Android 5.0 (API 級別 21) 以上版本。
Camera2 API 支援高動態範圍 (HDR) 影片拍攝功能,讓您使用相機預覽及錄製 HDR 影片內容。相較於標準動態範圍 (SDR),HDR 提供更廣泛的色彩範圍,並增加亮度元素的動態範圍 (從目前的 100 cd/m2 提高至 1000s cd/m2)。這項技術可呈現更豐富的色彩、更明亮的亮部和更深沉的陰影,讓影片畫質更貼近現實。
看看 HDR 影片如何捕捉更生動細緻的日落畫面。
裝置必要條件
並非所有 Android 裝置都支援 HDR 影片拍攝功能。在應用程式中擷取 HDR 影片前,請先確認裝置是否符合下列必要條件:
- 指定 Android 13 (API 級別 33)。
- 搭載 10 位元以上的相機感應器。如要進一步瞭解 HDR 支援,請參閱「確認 HDR 支援情形」。
並非所有裝置都符合必要條件,因此您可以在應用程式中設定 HDR 影片擷取功能時,新增獨立的程式碼路徑。這樣一來,應用程式就能在不相容的裝置上改用 SDR。此外,建議您為 SDR 新增 UI 選項。使用者可以視錄影需求,在 SDR 和 HDR 之間切換。
HDR 拍攝架構
下圖顯示 HDR 擷取架構的主要元件。
當相機裝置以 HDR 模式擷取影格時,Camera2 架構會分配緩衝區,用於儲存處理過的相機感應器輸出內容。如果 HDR 設定檔需要,也會附加各自的 HDR 中繼資料。接著,Camera2 架構會將填入的緩衝區排入佇列,用於 CaptureRequest 中參照的輸出介面,例如顯示器或影片編碼器,如圖所示。
確認 HDR 支援情形
在應用程式中擷取 HDR 影片之前,請先確認裝置是否支援您選擇的 HDR 設定檔。
使用 CameraManager
getCameraCharacteristics() 方法取得 CameraCharacteristics 例項,以便查詢裝置的 HDR 功能。
請按照下列步驟,確認裝置是否支援 HLG10。HLG10 是基準 HDR 標準,裝置製造商必須在具有 10 位元輸出的相機上支援此標準。
首先,請確認裝置是否支援 10 位元設定檔 (HLG10 的位元深度):
private fun isTenBitProfileSupported(cameraId: String): Boolean { val cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId) val availableCapabilities = cameraCharacteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES) for (capability in availableCapabilities!!) { if (capability == CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT) { return true } } return false }接著,檢查裝置是否支援 HLG10 (或其他支援的設定檔):
@RequiresApi(api = 33) private fun isHLGSupported(cameraId: String): Boolean { if (isTenBitProfileSupported(cameraId)) { Val cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId) val availableProfiles = cameraCharacteristics .get(CameraCharacteristics.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES)!! .getSupportedProfiles() // Checks for the chosen profile, in this case HLG10 return availableProfiles.contains(DynamicRangeProfiles.HLG10) } return false; }
如果裝置支援 HDR,isHLGSupported() 一律會傳回 true。詳情請參閱 CameraCharacteristics 參考說明文件。
設定 HDR 擷取
確認裝置支援 HDR 後,請設定應用程式,從相機擷取原始 HDR 影片串流。使用 setDynamicRangeProfile() 為串流的 OutputConfiguration 提供裝置支援的 HDR 設定檔,然後在建立時傳遞至 CameraCaptureSession。請參閱支援的 HDR 設定檔清單。
在下列程式碼範例中,setupSessionDynamicRangeProfile() 會先檢查裝置是否搭載 Android 13。接著,系統會使用裝置支援的 HDR 設定檔,將 CameraCaptureSession 設為 OutputConfiguration:
/**
* Creates a [CameraCaptureSession] with a dynamic range profile.
*/
private fun setupSessionWithDynamicRangeProfile(
dynamicRange: Long,
device: CameraDevice,
targets: List<Surface>,
handler: Handler? = null,
stateCallback: CameraCaptureSession.StateCallback
): Boolean {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) {
val outputConfigs = mutableListOf<OutputConfiguration>()
for (target in targets) {
val outputConfig = OutputConfiguration(target)
//sets the dynamic range profile, for example DynamicRangeProfiles.HLG10
outputConfig.setDynamicRangeProfile(dynamicRange)
outputConfigs.add(outputConfig)
}
device.createCaptureSessionByOutputConfigurations(
outputConfigs, stateCallback, handler
)
return true
} else {
device.createCaptureSession(targets, stateCallback, handler)
return false
}
}
相機應用程式初始化相機時,會傳送重複的 CaptureRequest 來預覽錄製內容:
session.setRepeatingRequest(previewRequest, null, cameraHandler)
以及開始錄影:
// Start recording repeating requests, which stops the ongoing preview
// repeating requests without having to explicitly call
// `session.stopRepeating`
session.setRepeatingRequest(recordRequest,
object : CameraCaptureSession.CaptureCallback() {
override fun onCaptureCompleted(session: CameraCaptureSession,
request: CaptureRequest, result: TotalCaptureResult) {
if (currentlyRecording) {
encoder.frameAvailable()
}
}
}, cameraHandler)
編碼 HDR 攝影機串流影像
如要對 HDR 攝影機串流影像進行編碼,並將檔案寫入磁碟,請使用 MediaCodec。
首先,取得輸出 Surface,其對應至儲存原始影片資料的緩衝區。如果是 MediaCodec,請使用 createInputSurface()。
如要初始化 MediaCodec,應用程式必須建立 MediaFormat,並指定轉碼器設定檔、色域、色彩範圍和轉換函式:
val mimeType = when {
dynamicRange == DynamicRangeProfiles.STANDARD -> MediaFormat.MIMETYPE_VIDEO_AVC
dynamicRange < DynamicRangeProfiles.PUBLIC_MAX ->
MediaFormat.MIMETYPE_VIDEO_HEVC
else -> throw IllegalArgumentException("Unknown dynamic range format")
}
val codecProfile = when {
dynamicRange == DynamicRangeProfiles.HLG10 ->
MediaCodecInfo.CodecProfileLevel.HEVCProfileMain10
dynamicRange == DynamicRangeProfiles.HDR10 ->
MediaCodecInfo.CodecProfileLevel.HEVCProfileMain10HDR10
dynamicRange == DynamicRangeProfiles.HDR10_PLUS ->
MediaCodecInfo.CodecProfileLevel.HEVCProfileMain10HDR10Plus
else -> -1
}
// Failing to correctly set color transfer causes quality issues
// for example, washout and color clipping
val transferFunction = when (codecProfile) {
MediaCodecInfo.CodecProfileLevel.HEVCProfileMain10 ->
MediaFormat.COLOR_TRANSFER_HLG
MediaCodecInfo.CodecProfileLevel.HEVCProfileMain10HDR10 ->
MediaFormat.COLOR_TRANSFER_ST2084
MediaCodecInfo.CodecProfileLevel.HEVCProfileMain10HDR10Plus ->
MediaFormat.COLOR_TRANSFER_ST2084
else -> MediaFormat.COLOR_TRANSFER_SDR_VIDEO
}
val format = MediaFormat.createVideoFormat(mimeType, width, height)
// Set some properties. Failing to specify some of these can cause the MediaCodec
// configure() call to throw an exception.
format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface)
format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate)
format.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate)
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL)
if (codecProfile != -1) {
format.setInteger(MediaFormat.KEY_PROFILE, codecProfile)
format.setInteger(MediaFormat.KEY_COLOR_STANDARD,
MediaFormat.COLOR_STANDARD_BT2020)
format.setInteger(MediaFormat.KEY_COLOR_RANGE, MediaFormat.COLOR_RANGE_LIMITED)
format.setInteger(MediaFormat.KEY_COLOR_TRANSFER, transferFunction)
format.setFeatureEnabled(MediaCodecInfo.CodecCapabilities.FEATURE_HdrEditing,
true)
}
mediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE)
如要進一步瞭解實作方式,請參閱 Camera2Video 範例應用程式的 EncoderWrapper.kt。
HDR 格式
自 Android 13 起,具備 10 位元輸出功能的相機裝置必須支援 HLG10,才能拍攝和播放 HDR 影片。此外,裝置製造商可以使用 HDR 擷取架構,啟用任何選擇的 HDR 格式。
下表匯總可用的 HDR 格式及其 HDR 影片擷取功能。
| 格式 | 傳遞函數 (TF) | 中繼資料 | 轉碼器 | 位元深度 |
|---|---|---|---|---|
| HLG10 | HLG | 否 | HEVC | 10 位元 |
| HDR10 | PQ | 靜態 | HEVC | 10 位元 |
| HDR10+ | PQ | 動態 | HEVC | 10 位元 |
| Dolby Vision 8.4 | HLG | 動態 | HEVC | 10 位元 |
資源
如需具備 HDR 影片拍攝功能的應用程式,請參閱 GitHub 上的 Camera2Video 範例。