O SDK Jetpack XR é compatível com a reprodução de vídeos lado a lado estereoscópicos em superfícies planas. Com o vídeo estereoscópico, cada frame consiste em uma imagem para o olho esquerdo e outra para o direito, dando aos espectadores uma sensação de profundidade, também conhecida como estereopsia.
É 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 Jetpack SceneCore
Com o vídeo lado a lado, cada frame estereoscópico é apresentado como duas imagens organizadas horizontalmente adjacentes uma à 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 sim uma maneira de organizar frames estereoscópicos. Isso significa que ele pode ser codificado em qualquer um dos codecs compatíveis com o Android.
É possível carregar vídeos lado a lado usando o Exoplayer da Media3 e renderizar com o novo SurfaceEntity
. Para criar um SurfaceEntity
, chame
SurfaceEntity.create
, conforme mostrado no exemplo a seguir.
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()
Reproduzir vídeo MV-HEVC usando o Jetpack SceneCore
O padrão de codec MV-HEVC é otimizado e projetado para vídeo estereoscópico, permitindo que seu app reproduza vídeos imersivos com eficiência e alta qualidade. Os arquivos MV-HEVC têm um fluxo principal, geralmente o olho esquerdo, e um fluxo estéreo com o outro olho.
Assim como o vídeo lado a lado, você pode carregá-lo usando o Exoplayer da Media3 e
renderizá-lo usando o SurfaceEntity
. Você vai precisar especificar se o arquivo MV-HEVC é primário à esquerda ou à direita no parâmetro stereoMode
ao chamar 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()
Reproduzir vídeos em 180 e 360 graus usando o Jetpack SceneCore
O SurfaceEntity
é compatível com a reprodução de vídeos em 180° em superfícies hemisféricas e de vídeos em 360° em superfícies esféricas. O parâmetro radius
se refere ao tamanho radial das respectivas superfícies em metros por padrão.
O código a seguir mostra como configurar o 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 aproveitando a postura 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.
Controle avançado de SurfaceEntity
Para um controle mais avançado da renderização de vídeo e imagem, como a aplicação de efeitos de materiais personalizados, trabalhe diretamente com SurfaceEntity
na biblioteca SceneCore.
As seções a seguir descrevem alguns dos recursos avançados disponíveis no
SurfaceEntity
.
Aplicar difusão de borda
Suavize as bordas da superfície para ajudar a misturar com o ambiente definindo a propriedade 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)
Aplicar uma máscara alfa
Aplique uma máscara alfa para criar superfícies não retangulares ou adicionar efeitos de transparência. Primeiro, carregue um Texture
de um recurso e atribua-o à propriedade 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 }
Reproduzir vídeo espacial usando o Jetpack Compose para XR
Se quiser aprender a reproduzir vídeos usando o Jetpack Compose para XR, saiba como adicionar uma superfície para conteúdo de imagem ou vídeo.