Ajouter une vidéo spatiale à votre application

Le SDK Jetpack XR est compatible avec la lecture de vidéos stéréoscopiques côte à côte sur des surfaces planes. Dans une vidéo stéréoscopique, chaque frame se compose d'une image pour l'œil gauche et d'une image pour l'œil droit afin de donner aux spectateurs une impression de profondeur, également appelée stéréopsie.

Vous pouvez afficher des vidéos 2D non stéréoscopiques dans les applications Android XR à l'aide des API Media standards utilisées pour le développement Android sur d'autres facteurs de forme.

Lire des vidéos côte à côte avec Jetpack SceneCore

Dans les vidéos côte à côte, chaque frame stéréoscopique est présenté sous la forme de deux images disposées horizontalement l'une à côté de l'autre. Les images vidéo de haut et de bas sont disposées verticalement les unes à côté des autres.

La vidéo côte à côte n'est pas un codec, mais plutôt une façon d'organiser les images stéréoscopiques. Cela signifie qu'elle peut être encodée dans n'importe quel codec compatible avec Android.

Vous pouvez charger une vidéo côte à côte à l'aide de Media3 Exoplayer, puis la rendre à l'aide de la nouvelle SurfaceEntity. Pour créer un SurfaceEntity, appelez SurfaceEntity.create, comme illustré dans l'exemple suivant.

val stereoSurfaceEntity = SurfaceEntity.create(
    xrSession,
    SurfaceEntity.StereoMode.SIDE_BY_SIDE,
    Pose(Vector3(0.0f, 0.0f, -1.5f)),
    SurfaceEntity.CanvasShape.Quad(1.0f, 1.0f)
)
val videoUri = Uri.Builder()
    .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
    .path("sbs_video.mp4")
    .build()
val mediaItem = MediaItem.fromUri(videoUri)

val exoPlayer = ExoPlayer.Builder(this).build()
exoPlayer.setVideoSurface(stereoSurfaceEntity.getSurface())
exoPlayer.setMediaItem(mediaItem)
exoPlayer.prepare()
exoPlayer.play()

Lire une vidéo MV-HEVC avec Jetpack SceneCore

La norme de codec MV-HEVC est optimisée et conçue pour les vidéos stéréoscopiques, ce qui permet à votre application de lire efficacement des vidéos immersives de haute qualité. Les fichiers MV-HEVC comportent un flux principal (généralement l'œil gauche) et un flux stéréo avec l'autre œil.

Comme pour les vidéos côte à côte, vous pouvez charger une vidéo en utilisant Media3 Exoplayer et la rendre à l'aide de SurfaceEntity. Vous devez indiquer si votre fichier MV-HEVC est primaire à gauche ou à droite dans le paramètre stereoMode lorsque vous appelez SurfaceEntity.create.

// Create the SurfaceEntity with the StereoMode corresponding to the MV-HEVC content
val stereoSurfaceEntity = SurfaceEntity.create(
    xrSession,
    SurfaceEntity.StereoMode.MULTIVIEW_LEFT_PRIMARY,
    Pose(Vector3(0.0f, 0.0f, -1.5f)),
    SurfaceEntity.CanvasShape.Quad(1.0f, 1.0f)
)
val videoUri = Uri.Builder()
    .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
    .path("mvhevc_video.mp4")
    .build()
val mediaItem = MediaItem.fromUri(videoUri)

val exoPlayer = ExoPlayer.Builder(this).build()
exoPlayer.setVideoSurface(stereoSurfaceEntity.getSurface())
exoPlayer.setMediaItem(mediaItem)
exoPlayer.prepare()
exoPlayer.play()

Lire des vidéos à 180° et à 360° avec Jetpack SceneCore

SurfaceEntity permet de lire des vidéos à 180° sur des surfaces hémisphériques et des vidéos à 360° sur des surfaces sphériques. Le paramètre radius fait référence à la taille radiale des surfaces respectives en mètres par défaut.

Le code suivant montre comment configurer SurfaceEntity pour la lecture sur un hémisphère à 180° et une sphère à 360°. Lorsque vous utilisez ces formes de canevas, positionnez la surface en exploitant la pose de la tête de l'utilisateur pour offrir une expérience immersive.

// Set up the surface for playing a 180° video on a hemisphere.
val hemisphereStereoSurfaceEntity =
    SurfaceEntity.create(
        xrSession,
        SurfaceEntity.StereoMode.SIDE_BY_SIDE,
        xrSession.scene.spatialUser.head?.transformPoseTo(
            Pose.Identity,
            xrSession.scene.activitySpace
        )!!,
        SurfaceEntity.CanvasShape.Vr180Hemisphere(1.0f),
    )
// ... and use the surface for playing the media.

// Set up the surface for playing a 360° video on a sphere.
val sphereStereoSurfaceEntity =
    SurfaceEntity.create(
        xrSession,
        SurfaceEntity.StereoMode.TOP_BOTTOM,
        xrSession.scene.spatialUser.head?.transformPoseTo(
            Pose.Identity,
            xrSession.scene.activitySpace
        )!!,
        SurfaceEntity.CanvasShape.Vr360Sphere(1.0f),
    )
// ... and use the surface for playing the media.

Contrôle avancé de SurfaceEntity

Pour un contrôle plus avancé du rendu vidéo et d'image, comme l'application d'effets matériels personnalisés, vous pouvez travailler directement avec SurfaceEntity à partir de la bibliothèque SceneCore.

Les sections suivantes décrivent certaines des fonctionnalités avancées disponibles sur SurfaceEntity.

Appliquer l'estompage des bords

Adoucissez les bords de la surface pour l'aider à se fondre dans l'environnement en définissant la propriété edgeFeather.

// Create a SurfaceEntity.
val surfaceEntity = SurfaceEntity.create(
    session = xrSession,
    pose = Pose(Vector3(0.0f, 0.0f, -1.5f))
)

// Feather the edges of the surface.
surfaceEntity.edgeFeather =
    SurfaceEntity.EdgeFeatheringParams.SmoothFeather(0.1f, 0.1f)

Appliquer un masque alpha

Appliquez un masque alpha pour créer des surfaces non rectangulaires ou ajouter des effets de transparence. Commencez par charger un Texture à partir d'un élément, puis attribuez-le à la propriété primaryAlphaMaskTexture :

// Create a SurfaceEntity.
val surfaceEntity = SurfaceEntity.create(
    session = xrSession,
    pose = Pose(Vector3(0.0f, 0.0f, -1.5f))
)

// Load the texture in a coroutine scope.
activity.lifecycleScope.launch {
    val alphaMaskTexture =
        Texture.create(
            xrSession,
            Paths.get("textures", "alpha_mask.png"),
            TextureSampler.create()
        )

    // Apply the alpha mask.
    surfaceEntity.primaryAlphaMaskTexture = alphaMaskTexture

    // To remove the mask, set the property to null.
    surfaceEntity.primaryAlphaMaskTexture = null
}

Lire des vidéos spatiales avec Jetpack Compose pour XR

Si vous souhaitez apprendre à lire des vidéos à l'aide de Jetpack Compose pour XR, découvrez comment ajouter une surface pour le contenu d'image ou vidéo.