注: このページでは、Camera2 パッケージについて説明します。アプリで Camera2 の特定の低レベルの機能が必要な場合を除き、CameraX を使用することをおすすめします。CameraX と Camera2 は、どちらも Android 5.0(API レベル 21)以降に対応しています。
Camera2 API は ハイ ダイナミック レンジ(HDR)動画キャプチャをサポートしており、カメラを使用して HDR 動画コンテンツをプレビュー、 録画できます。標準ダイナミック レンジ(SDR)と比較して、HDR はより幅広い色に対応し、輝度コンポーネントのダイナミック レンジを拡大します(現在の 100 cd/m2 から 1,000 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 は、デバイス メーカーが 10 ビット出力のカメラでサポートする必要があるベースライン HDR 標準です。
まず、デバイスが 10 ビット プロファイル(HLG10 のビット深度)をサポートしているかどうかを確認します。
Kotlin
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(または 別のサポートされているプロファイル)をサポートしているかどうかを確認します。
Kotlin
@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 desired profile, in this case HLG10 return availableProfiles.contains(DynamicRangeProfiles.HLG10) } return false; }
デバイスが HDR をサポートしている場合、isHLGSupported() は常に true
を返します。
詳しくは、
CameraCharacteristics
リファレンス ドキュメントをご覧ください。
HDR キャプチャを設定する
デバイスが HDR をサポートしていることを確認したら、カメラから RAW HDR
動画ストリームをキャプチャするようにアプリを設定します。
setDynamicRangeProfile()を使用して、デバイスでサポートされている HDR プロファイルをストリームの OutputConfiguration
に指定します。このプロファイルは、作成時に CameraCaptureSession
に渡されます。
サポートされている HDR プロファイルのリストをご覧ください。
次のコードサンプルでは、setupSessionDynamicRangeProfile() はまず、デバイスが Android 13
を実行していることを確認します。
次に、デバイスでサポートされている HDR プロファイルを OutputConfiguration
として使用して CameraCaptureSession を設定します。
Kotlin
/** * Creates a [CameraCaptureSession] with a dynamic range profile. */ private fun setupSessionWithDynamicRangeProfile( dynamicRange: Long, device: CameraDevice, targets: List, handler: Handler? = null, stateCallback: CameraCaptureSession.StateCallback ): Boolean { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) { val outputConfigs = mutableListOf () 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
を送信します。
Kotlin
session.setRepeatingRequest(previewRequest, null, cameraHandler)
また、動画の録画を開始します。
Kotlin
// 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 を使用します。
まず、RAW 動画データを格納するバッファにマッピングされる OutputSurface,
を取得します。
MediaCodec
の場合は、createInputSurface()を使用します。
MediaCodec を初期化するには、アプリで、指定された
コーデック プロファイル、色空間、色範囲、伝達関数を使用して
MediaFormatを作成する必要があります。
Kotlin
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 ビット出力機能を備えたカメラデバイスは、HDR キャプチャと 再生で HLG10 をサポートする必要があります。 また、デバイス メーカーは、HDR キャプチャ アーキテクチャを使用して、任意の HDR 形式を有効にできます。 HDR キャプチャ アーキテクチャ
次の表に、HDR 動画キャプチャで使用可能な HDR 形式とその機能をまとめます。
| 形式 | 伝達関数(TF) | メタデータ | コーデック | ビット深度 |
|---|---|---|---|---|
| HLG10 | HLG | いいえ | HEVC | 10 ビット |
| HDR10 | PQ | 静的 | HEVC | 10 ビット |
| HDR10+ | PQ | 動的 | HEVC | 10 ビット |
| ドルビー ビジョン 8.4 | HLG | 動的 | HEVC | 10 ビット |
リソース
HDR 動画キャプチャ機能を備えた動作するアプリについては、 GitHub の Camera2Video サンプル をご覧ください。