Запись видео в формате HDR

Примечание. На этой странице рассматривается пакет Camera2. Если вашему приложению не требуются определенные низкоуровневые функции Camera2, рекомендуем использовать CameraX. Обе библиотеки поддерживают Android 5.0 (API уровня 21) и более поздние версии.

API Camera2 поддерживают съемку видео в расширенном динамическом диапазоне (HDR). Это позволяет просматривать и записывать HDR-видеоконтент с помощью камеры. По сравнению со стандартным динамическим диапазоном (SDR) HDR предлагает более широкий диапазон цветов и увеличивает динамический диапазон компонента яркости (с текущих 100 кд/м2 до 1000 кд/м2). Это позволяет получить качество видео, которое более точно соответствует реальной жизни, с насыщенными цветами, яркими светлыми участками и глубокими тенями.

Посмотрите, как HDR-видео передает закат во всех деталях.

Закат, снятый в качестве SDR Закат, снятый в формате HDR
Рисунок 1. Сравнение качества видео SDR (сверху) и HDR (снизу).

Требования к устройствам

Не все устройства Android поддерживают запись видео в формате HDR. Прежде чем записывать HDR-видео в приложении, убедитесь, что ваше устройство соответствует следующим требованиям:

  • Целевой уровень API – 33 (Android 13).
  • Устройство оснащено датчиком камеры с поддержкой 10-битного или более высокого разрешения. Подробнее о том, как проверить поддержку HDR…

Поскольку не все устройства соответствуют требованиям, вы можете добавить отдельный путь выполнения при настройке записи HDR-видео в приложении. Это позволит приложению переключаться на SDR на несовместимых устройствах. Также рекомендуем добавить в интерфейс вариант SDR. После этого пользователь сможет переключаться между SDR и HDR при записи видео.

Архитектура HDR-съемки

На следующей схеме показаны основные компоненты архитектуры HDR-съемки.

Схема архитектуры HDR-съемки.
Рисунок 2. Схема архитектуры HDR-съемки.

Когда камера снимает кадр в HDR, фреймворк Camera2 выделяет буфер, в котором хранятся обработанные выходные данные датчика камеры. При необходимости также добавляются метаданные HDR. Затем фреймворк Camera2 ставит заполненный буфер в очередь для выходной поверхности, указанной в CaptureRequest, например для дисплея или видеокодера, как показано на диаграмме.

Как проверить, поддерживается ли HDR

Прежде чем записывать HDR-видео в приложении, определите, поддерживает ли устройство выбранный профиль HDR.

Используйте метод CameraManager getCameraCharacteristics(), чтобы получить экземпляр CameraCharacteristics, который можно запросить для получения информации о возможностях HDR вашего устройства.

Чтобы проверить, поддерживает ли устройство HLG10, выполните следующие действия: HLG10 – это базовый стандарт HDR, который производители устройств должны поддерживать на камерах с 10-битным выводом.

  1. Сначала проверьте, поддерживает ли устройство 10-битные профили (глубина цвета для HLG10):

    private fun isTenBitProfileSupported(cameraId: String): Boolean {
        val cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId)
        val availableCapabilities = cameraCharacteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)
            ?: return false
        for (capability in availableCapabilities) {
            if (capability == CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT) {
                return true
            }
        }
        return false
    }

  2. Затем проверьте, поддерживает ли устройство 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) ?: false
        }
        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<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)

Подробную информацию о реализации можно найти в файле EncoderWrapper.kt примера приложения Camera2Video.

Форматы 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-видео можно найти в репозитории Camera2Video на GitHub.