Lecture de vidéos HDR

Le format HDR (High Dynamic Range ou HDR) offre une gamme de couleurs plus large contraste entre les blancs les plus éclatants et les ombres les plus sombres, ce qui génère une vidéo d'une qualité ressemblant davantage à ce que perçoit l'œil nu.

Vous pouvez configurer la lecture de vidéos HDR dans votre application pour les prévisualiser et les lire. contenus.

Dans cet article, nous partons du principe que vous avez déjà activé la fonctionnalité de base pour la lecture de vidéos votre application. Consultez la documentation d'ExoPlayer pour : plus de détails sur la lecture.

Conditions préalables pour l'appareil

Tous les appareils Android ne sont pas compatibles avec la lecture HDR. Avant de lire le contenu HDR contenu vidéo dans votre application, déterminez si votre appareil respecte les prérequis:

  • Cible Android 7.0 ou version ultérieure (couche d'API 24).
  • Dispose d'un décodeur compatible HDR et d'un accès à un écran compatible HDR.

Vérifier la compatibilité avec la lecture HDR

Utilisez Display.getHdrCapabilities() pour interroger les fonctionnalités HDR d'un écran. Cette méthode renvoie des informations sur les profils HDR compatibles et la plage de luminance de l'écran.

Le code suivant vérifie si l'appareil est compatible avec la lecture HLG10. À partir d'Android 13, HLG10 est la norme minimale que les fabricants d'appareils doivent prendre en charge si l'appareil est compatible avec la lecture HDR:

Kotlin

// Check if display supports the HDR type
val capabilities = display?.hdrCapabilities?.supportedHdrTypes ?: intArrayOf()
if (!capabilities.contains(HDR_TYPE_HLG)) {
  throw RuntimeException("Display does not support desired HDR type");
}

Java

// Check if display supports the HDR type
int[] list = getDisplay().getHdrCapabilities().getSupportedHdrTypes();
List capabilities = Arrays.stream(list).boxed().collect(Collectors.toList());
if (!capabilities.contains(HDR_TYPE_HLG)) {
 throw new RuntimeException("Display does not support desired HDR type");
}

Configurer la lecture HDR dans votre application

Si votre application utilise ExoPlayer, elle est compatible avec la lecture HDR par défaut. Pour connaître les étapes suivantes, consultez Vérifier la compatibilité avec la lecture HDR.

Si votre application n'utilise pas ExoPlayer, configurez la lecture HDR avec MediaCodec via SurfaceView.

Configurer MediaCodec à l'aide de SurfaceView

Configurez un flux de lecture MediaCodec standard à l'aide de SurfaceView. Cela vous permet d'afficher du contenu vidéo HDR sans intervention particulière pour la lecture HDR:

  • MediaCodec: décode le contenu vidéo HDR.
  • SurfaceView: affiche du contenu vidéo HDR.

Le code suivant vérifie si le codec est compatible avec le profil HDR, puis configure MediaCodec à l'aide de SurfaceView:

Kotlin

// Check if there's a codec that supports the specific HDR profile
val list = MediaCodecList(MediaCodecList.REGULAR_CODECS) var format = MediaFormat() /* media format from the container */;
format.setInteger(MediaFormat.KEY_PROFILE, MediaCodecInfo.CodecProfileLevel.AV1ProfileMain10)
val codecName = list.findDecoderForFormat (format) ?: throw RuntimeException ("No codec supports the format")

// Here is a standard MediaCodec playback flow
val codec: MediaCodec = MediaCodec.createByCodecName(codecName);
val surface: Surface = surfaceView.holder.surface
val callback: MediaCodec.Callback = (object : MediaCodec.Callback() {
   override fun onInputBufferAvailable(codec: MediaCodec, index: Int) {
      queue.offer(index)
   }

   override fun onOutputBufferAvailable(
      codec: MediaCodec,
      index: Int,
      info: MediaCodec.BufferInfo
   ) {
      codec.releaseOutputBuffer(index, timestamp)
   }

   override fun onError(codec: MediaCodec, e: MediaCodec.CodecException) {
      // handle error
   }

   override fun onOutputFormatChanged(
      codec: MediaCodec, format: MediaFormat
   ) {
      // handle format change
   }
})

codec.setCallback(callback)
codec.configure(format, surface, crypto, 0 /* flags */)
codec.start()
while (/* until EOS */) {
   val index = queue.poll()
   val buffer = codec.getInputBuffer(index)
   buffer?.put(/* write bitstream */)
   codec.queueInputBuffer(index, offset, size, timestamp, flags)
}
codec.stop()
codec.release()

Java

// Check if there's a codec that supports the specific HDR profile
MediaCodecList list = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
MediaFormat format = /* media format from the container */;
format.setInteger(
    MediaFormat.KEY_PROFILE, CodecProfileLevel.AV1ProfileMain10);
String codecName = list.findDecoderForFormat(format);
if (codecName == null) {
    throw new RuntimeException("No codec supports the format");
}

// Below is a standard MediaCodec playback flow
MediaCodec codec = MediaCodec.getCodecByName(codecName);
Surface surface = surfaceView.getHolder().getSurface();
MediaCodec.Callback callback = new MediaCodec.Callback() {
    @Override
    void onInputBufferAvailable(MediaCodec codec, int index) {
        queue.offer(index);
    }

    @Override
    void onOutputBufferAvailable(MediaCodec codec, int index) {
        // release the buffer for render
        codec.releaseOutputBuffer(index, timestamp);
    }

    @Override
    void onOutputFormatChanged(MediaCodec codec, MediaFormat format) {
        // handle format change
    }

    @Override
    void onError(MediaCodec codec, MediaCodec.CodecException ex) {
        // handle error
    }

};
codec.setCallback(callback);
codec.configure(format, surface, crypto, 0 /* flags */);
codec.start();
while (/* until EOS */) {
    int index = queue.poll();
    ByteBuffer buffer = codec.getInputBuffer(index);
    buffer.put(/* write bitstream */);
    codec.queueInputBuffer(index, offset, size, timestamp, flags);
}
codec.stop();
codec.release();

Pour découvrir d'autres implémentations de MediaCodec avec SurfaceView, consultez les exemples d'appareil photo Android.

Ressources

Pour en savoir plus sur la lecture HDR, consultez les ressources suivantes:

HDR

Contenus multimédias