O SDK Jetpack XR oferece suporte à reprodução de vídeo lado a lado estereoscópico em superfícies planas. Com o vídeo estereoscópico, cada frame consiste em uma imagem do olho esquerdo e uma do olho direito para dar aos espectadores uma sensação de profundidade.
É possível renderizar vídeos 2D não estereoscópicos em apps Android XR com as APIs de mídia padrão usadas para desenvolvimento do Android em outros formatos.
Reproduzir vídeos lado a lado usando o SDK Jetpack XR
No vídeo lado a lado, cada frame estereoscópico é apresentado como duas imagens organizadas horizontalmente uma ao lado da outra. Os frames de vídeo de cima e de baixo são organizados verticalmente, um ao lado do outro.
O vídeo lado a lado não é um codec, mas uma maneira de organizar frames estereoscópicos, o que significa que ele pode ser codificado em qualquer um dos codecs compatíveis com o Android.
Jetpack SceneCore
É possível carregar vídeos lado a lado usando o Exoplayer da Media3 e renderizá-los
usando o novo SurfaceEntity
. Para criar um
SurfaceEntity
, chame SurfaceEntity.create
, conforme mostrado no
exemplo abaixo.
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()
Jetpack Compose para XR
Alpha04 e mais recentes
A partir da versão 1.0.0-alpha04
, o Jetpack Compose para XR oferece outra maneira
de carregar e renderizar vídeos lado a lado. Use SpatialExternalSurface
, um
combinável de subespaço que cria e gerencia o
Surface
em que o app pode desenhar conteúdo, como uma imagem ou
vídeo. Para mais detalhes sobre SpatialExternalSurface
, consulte o guia Desenvolver interface com
o Compose para XR.
Este exemplo demonstra como carregar vídeos lado a lado
usando o Media3 Exoplayer e o
SpatialExternalSurface
.
@Composable fun SpatialExternalSurfaceContent() { val context = LocalContext.current Subspace { SpatialExternalSurface( modifier = SubspaceModifier .width(1200.dp) // Default width is 400.dp if no width modifier is specified .height(676.dp), // Default height is 400.dp if no height modifier is specified // Use StereoMode.Mono, StereoMode.SideBySide, or StereoMode.TopBottom, depending // upon which type of content you are rendering: monoscopic content, side-by-side stereo // content, or top-bottom stereo content stereoMode = StereoMode.SideBySide, ) { val exoPlayer = remember { ExoPlayer.Builder(context).build() } val videoUri = Uri.Builder() .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE) // Represents a side-by-side stereo video, where each frame contains a pair of // video frames arranged side-by-side. The frame on the left represents the left // eye view, and the frame on the right represents the right eye view. .path("sbs_video.mp4") .build() val mediaItem = MediaItem.fromUri(videoUri) // onSurfaceCreated is invoked only one time, when the Surface is created onSurfaceCreated { surface -> exoPlayer.setVideoSurface(surface) exoPlayer.setMediaItem(mediaItem) exoPlayer.prepare() exoPlayer.play() } // onSurfaceDestroyed is invoked when the SpatialExternalSurface composable and its // associated Surface are destroyed onSurfaceDestroyed { exoPlayer.release() } } } }
Reproduzir vídeos de 180 e 360 graus usando o SDK do Jetpack XR
O SurfaceEntity
oferece suporte à reprodução de vídeos em 180° em
superfícies hemisféricas e em 360° em superfícies esféricas. Se os vídeos forem
estereoscópicos, os arquivos precisam estar em um formato lado a lado.
O código a seguir mostra como configurar SurfaceEntity
para reprodução em um
hemisfério de 180° e uma esfera de 360°. Ao usar essas formas de tela, posicione a
superfície usando a pose da cabeça do usuário para oferecer uma experiência imersiva.
// 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.