Примечание. Эта страница относится к пакету Camera2 . Если вашему приложению не требуются специальные низкоуровневые функции Camera2, мы рекомендуем использовать CameraX . И CameraX, и Camera2 поддерживают Android 5.0 (уровень API 21) и выше.
API-интерфейсы Camera2 поддерживают захват видео с расширенным динамическим диапазоном (HDR), что позволяет просматривать и записывать видеоконтент HDR с помощью камеры. По сравнению со стандартным динамическим диапазоном (SDR), HDR предлагает более широкий диапазон цветов и увеличивает динамический диапазон компонента яркости (с нынешних 100 кд/м2 до 1000 кд/м2). В результате качество видео более близко соответствует реальной жизни, с более насыщенными цветами, более яркими светлыми участками и более темными тенями.
Посмотрите, как HDR-видео передает закат с большей детализацией.
Предварительные требования к устройству
Не все устройства Android поддерживают захват видео HDR. Прежде чем записывать HDR-видео в своем приложении, определите, соответствует ли ваше устройство следующим предварительным требованиям:
- Ориентирован на Android 13 (уровень API 33).
- Имеет 10-битный или более мощный сенсор камеры. Дополнительную информацию о поддержке HDR см. в разделе Проверка поддержки HDR .
Поскольку не все устройства соответствуют предварительным требованиям, вы можете добавить отдельный путь к коду при настройке захвата видео HDR в своем приложении. Это позволит вашему приложению вернуться к SDR на несовместимых устройствах. Также рассмотрите возможность добавления опции пользовательского интерфейса для SDR. Затем пользователь может переключаться между SDR и HDR для своих нужд в записи видео.
Архитектура захвата HDR
На следующей диаграмме показаны основные компоненты архитектуры захвата HDR.
Когда устройство камеры захватывает кадр в формате HDR, платформа Camera2 выделяет буфер, в котором хранятся обработанные выходные данные датчика камеры. Он также прикрепляет соответствующие метаданные HDR, если этого требует профиль HDR. Затем платформа Camera2 ставит заполненный буфер в очередь для выходной поверхности, указанной в CaptureRequest
, такой как дисплей или видеокодер, как показано на схеме.
Проверьте поддержку HDR
Прежде чем записывать HDR-видео в приложении, определите, поддерживает ли устройство желаемый профиль HDR.
Используйте метод getCameraCharacteristics()
CameraManager
для получения экземпляра 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 desired 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. Затем он настраивает CameraCaptureSession
с поддерживаемым устройством профилем HDR в качестве OutputConfiguration
:
Котлин
/** * 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
для предварительного просмотра записи:
Котлин
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
.
Сначала получите OutputSurface
, который сопоставляется с буфером, в котором хранятся необработанные видеоданные. Для 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)
Дополнительные сведения о реализации см. в EncoderWrapper.kt
примера приложения Camera2Video.
HDR-форматы
Начиная с Android 13, устройства с камерами с 10-битным выходом должны поддерживать HLG10 для захвата и воспроизведения HDR. Кроме того, производители устройств могут включить любой формат HDR по своему выбору, используя архитектуру захвата HDR .
В следующей таблице приведены доступные форматы HDR и их возможности для захвата HDR-видео.
Формат | Передаточная функция (ТФ) | Метаданные | Кодек | Битовая глубина |
---|---|---|---|---|
HLG10 | ГВУ | Нет | HEVC | 10-битный |
HDR10 | ПК | Статический | HEVC | 10-битный |
HDR10+ | ПК | Динамический | HEVC | 10-битный |
Долби Видение 8.4 | ГВУ | Динамический | HEVC | 10-битный |
Ресурсы
Работающее приложение с функцией захвата HDR-видео см. в примере Camera2Video на GitHub.