Aggiungere video spaziali alla tua app

L'SDK Jetpack XR supporta la riproduzione di video stereoscopici side-by-side su superfici piane. Nei video stereoscopici, ogni frame è composto da un'immagine per l'occhio sinistro e una per l'occhio destro, per dare agli spettatori un senso di profondità, noto anche come stereopsi.

Puoi eseguire il rendering di video 2D non stereoscopici sulle app Android XR con le API multimediali standard utilizzate per lo sviluppo Android su altri fattori di forma.

Riprodurre video affiancati utilizzando Jetpack SceneCore

Con il video affiancato, ogni frame stereoscopico viene presentato come due immagini disposte orizzontalmente una accanto all'altra. I frame video superiore e inferiore sono disposti verticalmente uno accanto all'altro.

Il video side-by-side non è un codec, ma un modo per organizzare i fotogrammi stereoscopici, il che significa che può essere codificato in uno qualsiasi dei codec supportati da Android.

Puoi caricare video affiancati utilizzando Media3 Exoplayer e poi eseguirne il rendering utilizzando il nuovo SurfaceEntity. Per creare un SurfaceEntity, chiama SurfaceEntity.create, come mostrato nell'esempio seguente.

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()

Riprodurre video MV-HEVC utilizzando Jetpack SceneCore

Lo standard del codec MV-HEVC è ottimizzato e progettato per i video stereoscopici, consentendo alla tua app di riprodurre in modo efficiente video immersivi di ottima qualità. I file MV-HEVC hanno uno stream principale, di solito l'occhio sinistro, e uno stream stereo con l'altro occhio.

Come per il video affiancato, puoi caricarlo utilizzando Media3 Exoplayer e renderizzarlo utilizzando SurfaceEntity. Quando chiami SurfaceEntity.create, devi specificare se il file MV-HEVC è primario a sinistra o a destra nel parametro stereoMode.

// 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()

Riprodurre video a 180 e 360 gradi utilizzando Jetpack SceneCore

SurfaceEntity supporta la riproduzione di video a 180° su superfici emisferiche e di video a 360° su superfici sferiche. Il parametro radius si riferisce alle dimensioni radiali delle rispettive superfici in metri per impostazione predefinita.

Il seguente codice mostra come configurare SurfaceEntity per la riproduzione su un emisfero a 180° e una sfera a 360°. Quando utilizzi queste forme della tela, posiziona la superficie sfruttando la postura della testa dell'utente per offrire un'esperienza immersiva.

// 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.

Controllo avanzato di SurfaceEntity

Per un controllo più avanzato del rendering di video e immagini, ad esempio per applicare effetti materiali personalizzati, puoi lavorare direttamente con SurfaceEntity dalla libreria SceneCore.

Le sezioni seguenti descrivono alcune delle funzionalità avanzate disponibili su SurfaceEntity.

Applica sfumatura bordo

Ammorbidisci i bordi della superficie per integrarla meglio con l'ambiente impostando la proprietà 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)

Applicare una maschera alfa

Applica una maschera alfa per creare superfici non rettangolari o aggiungere effetti di trasparenza. Innanzitutto, carica un Texture da un asset, poi assegnalo alla proprietà 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
}

Riprodurre video spaziali utilizzando Jetpack Compose per XR

Se ti interessa scoprire come riprodurre video utilizzando Jetpack Compose per XR, scopri come aggiungere una superficie per contenuti di immagini o video.