Nagrywanie filmów HDR

Uwaga: ta strona dotyczy pakietu Aparat2. Jeśli Twoja aplikacja nie wymaga konkretnych, niskopoziomowych funkcji z Aparatu 2, zalecamy używanie AparatuX. Aparaty CameraX i Aparat 2 obsługują Androida 5.0 (poziom interfejsu API 21) i nowsze wersje.

Obsługa interfejsów API Camera2 Nagrywanie filmów High Dynamic Range (HDR) pozwala wyświetlać podgląd nagrywać filmy HDR za pomocą aparatu. W porównaniu do standardowych kreacji dynamicznych Zakres (SDR) zapewnia szerszy zakres kolorów i zwiększa zakres składnika luminancji (od bieżącego 100 cd/m2 do 1000 s w przypadku cd/m2). Dzięki temu jakość wideo jest bardziej zgodna z rzeczywistością, bogatsze kolory, jaśniejsze podświetlenia i ciemniejsze cienie.

Zobacz, jak w trybie HDR uwieczniasz zachód słońca w bardziej wyrazistych szczegółach.

. Rysunek 1. Porównanie jakości filmu SDR (u góry) i HDR (u dołu).
.
.

Wymagania wstępne dla urządzenia

Nie wszystkie urządzenia z Androidem obsługują nagrywanie filmów HDR. Zanim nagrasz film HDR w aplikacji, sprawdź, czy Twoje urządzenie spełnia spełnić te wymagania wstępne:

  • Jest kierowana na Androida 13 (poziom API 33).
  • wyposażony w 10-bitowy lub większy czujnik aparatu, Więcej informacji o HDR Pomoc znajdziesz w artykule Sprawdzanie obsługi HDR.

Nie wszystkie urządzenia spełniają wymagania wstępne, więc możesz dodać oddzielny kod. podczas konfigurowania nagrywania filmu HDR w aplikacji. Dzięki temu aplikacja może wrócić do trybu SDR na niezgodnych urządzeniach. Zastanów się też nad dodaniem w interfejsie opcji SDR. Użytkownik może wtedy przełączyć między SDR a HDR.

Architektura przechwytywania HDR

Poniższy diagram przedstawia główne elementy architektury przechwytywania HDR.

Schemat architektury przechwytywania HDR.
Rysunek 2. Schemat architektury przechwytywania HDR.

Gdy aparat rejestruje klatkę w trybie HDR, platforma Camera2 przydziela bufor, który zapisuje przetworzone dane wyjściowe z czujnika aparatu. Dołącza też odpowiednie metadane HDR, jeśli wymaga tego profil HDR. Platforma Camera2 umieszcza następnie zapełniony bufor w kolejce na powierzchni wyjściowej. wspomniane w CaptureRequest, takie jak wyświetlacz czy zgodnie z ilustracją.

Sprawdź, czy obsługuje HDR

Zanim nagrasz film HDR w aplikacji, sprawdź, czy urządzenie obsługuje wybranego profilu HDR.

Użyj metody CameraManager getCameraCharacteristics(), aby uzyskać CameraCharacteristics , o które można zapytać o możliwości HDR na Twoim urządzeniu.

Aby sprawdzić, czy urządzenie obsługuje HLG10, wykonaj te czynności. HLG10 to bazowy standard HDR, który musi obsługiwać producenci urządzeń w przypadku aparatów z wyjściem 10-bitowym.

  1. Najpierw sprawdź, czy urządzenie obsługuje 10-bitowe profile (z głębią bitową w przypadku 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
    }
    
  2. Następnie sprawdź, czy urządzenie obsługuje HLG10 (lub inny obsługiwany profil):

    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;
    }
    

Jeśli urządzenie obsługuje HDR, funkcja isHLGSupported() zawsze zwraca wartość true. Więcej informacji: CameraCharacteristics dokumentacji referencyjnej.

Konfigurowanie nagrywania HDR

Gdy upewnisz się, że Twoje urządzenie obsługuje HDR, skonfiguruj aplikację, aby nagrywać nieprzetworzony strumień wideo HDR z kamery. Użyj setDynamicRangeProfile(), aby podać OutputConfiguration transmisji za pomocą profilu HDR obsługiwanego przez urządzenie, do CameraCaptureSession po utworzeniu. Zobacz listę obsługiwanych profili HDR.

W tym przykładowym kodzie setupSessionDynamicRangeProfile() najpierw sprawdza się że na urządzeniu jest zainstalowany Android 13. Następnie skonfiguruje urządzenie CameraCaptureSession przy użyciu Profil HDR jako OutputConfiguration:

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
      }
  }

}

Gdy aplikacja aparatu uruchamia kamerę, wysyła powtarzanie CaptureRequest aby wyświetlić podgląd nagrania:

Kotlin

session.setRepeatingRequest(previewRequest, null, cameraHandler)

Aby rozpocząć nagrywanie filmu:

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)

Kodowanie transmisji z kamery HDR

Aby zakodować strumień HDR z kamery i zapisać plik na dysku: użyj MediaCodec.

Najpierw pobierz OutputSurface, który jest mapowany do bufora, w którym przechowywane są nieprzetworzone dane wideo. W przypadku usługi MediaCodec, użyj funkcji createInputSurface().

Aby zainicjować MediaCodec, aplikacja musi utworzyć MediaFormat z określoną wartością profil kodeka, przestrzeń kolorów, zakres kolorów i funkcję transferu:

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)

Więcej informacji o wdrażaniu znajdziesz w przykładowej aplikacji Camera2Video EncoderWrapper.kt

Formaty HDR

Urządzenia z aparatami z możliwością wyjścia 10-bitowego (począwszy od Androida 13) muszą obsługiwać HLG10 w celu przechwytywania HDR. playback. Producenci urządzeń mogą też włączyć dowolny format HDR. korzystając z architektury przechwytywania HDR.

W tabeli poniżej znajdziesz podsumowanie dostępnych formatów HDR i ich możliwości. w trybie HDR.

Format Funkcja transferu (TF) Metadane Kodek Głębia bitowa
HLG10 protokół HLG Nie protokół HEVC 10-bitowy
HDR10 PQ Statyczny protokół HEVC 10-bitowy
HDR10+ PQ Dynamiczne protokół HEVC 10-bitowy
Dolby Vision 8.4 protokół HLG Dynamiczne protokół HEVC 10-bitowy

Materiały

Informacje o działającej aplikacji z funkcją nagrywania filmów HDR znajdziesz w Przykład z aparatu Camera2Video w GitHubie.