L'SDK Jetpack XR supporta la riproduzione di video stereoscopici side-by-side video su superfici piane. Con i video stereoscopici, ogni frame è composto da un'immagine per l'occhio sinistro e un'immagine 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 di Android su altri fattori di forma.
Riprodurre video side-by-side utilizzando Jetpack SceneCore
Con i video side-by-side, ogni frame stereoscopico viene presentato come due immagini disposte orizzontalmente una accanto all'altra. I frame video top-and-bottom sono disposti verticalmente uno accanto all'altro.
Il video side-by-side non è un codec, ma un modo per organizzare i frame stereoscopici , il che significa che può essere codificato in uno qualsiasi dei codec supportati da Android.
Puoi caricare video side-by-side 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( session = xrSession, stereoMode = SurfaceEntity.StereoMode.SIDE_BY_SIDE, pose = Pose(Vector3(0.0f, 0.0f, -1.5f)), shape = SurfaceEntity.Shape.Quad(FloatSize2d(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 alta qualità. I file MV-HEVC hanno uno stream principale, in genere l'occhio sinistro, e uno stream stereo con l'altro occhio.
Come per i video side-by-side, puoi caricarli utilizzando Media3 Exoplayer ed
eseguirne il rendering 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( session = xrSession, stereoMode = SurfaceEntity.StereoMode.MULTIVIEW_LEFT_PRIMARY, pose = Pose(Vector3(0.0f, 0.0f, -1.5f)), shape = SurfaceEntity.Shape.Quad(FloatSize2d(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 spaziali protetti da DRM utilizzando Jetpack SceneCore
L'SDK Jetpack XR supporta la riproduzione di stream video criptati utilizzando il framework Digital Rights Management (DRM) integrato di Android's. DRM protegge i tuoi contenuti consentendo la distribuzione sicura e impedendo la copia o la riproduzione non autorizzata.
La procedura prevede che l'applicazione del media player contatti un server di licenze per ottenere le chiavi di decriptaggio. Su Android, questa procedura viene gestita in modo sicuro e i frame video decriptati vengono sottoposti a rendering in un buffer grafico protetto a cui il sistema o altre applicazioni non possono accedere, impedendo l'acquisizione dello schermo.
Per riprodurre video protetti da DRM con Jetpack SceneCore:
- Configura
SurfaceEntityper richiedere una superficie protetta. - Configura Media3 Exoplayer con le informazioni DRM necessarie per gestire lo scambio di chiavi.
- Imposta l'output del player sulla superficie di
SurfaceEntity.
L'esempio seguente mostra come configurare ExoPlayer per riprodurre uno stream protetto da DRM
ed eseguirne il rendering su un SurfaceEntity:
// Create a SurfaceEntity with DRM content // Define the URI for your DRM-protected content and license server. val videoUri = "https://your-content-provider.com/video.mpd" val drmLicenseUrl = "https://your-license-server.com/license" // Create the SurfaceEntity with the PROTECTED content security level. val protectedSurfaceEntity = SurfaceEntity.create( session = xrSession, stereoMode = SurfaceEntity.StereoMode.SIDE_BY_SIDE, pose = Pose(Vector3(0.0f, 0.0f, -1.5f)), shape = SurfaceEntity.Shape.Quad(FloatSize2d(1.0f, 1.0f)), surfaceProtection = SurfaceEntity.SurfaceProtection.PROTECTED ) // Build a MediaItem with the necessary DRM configuration. val mediaItem = MediaItem.Builder() .setUri(videoUri) .setDrmConfiguration( MediaItem.DrmConfiguration.Builder(C.WIDEVINE_UUID) .setLicenseUri(drmLicenseUrl) .build() ) .build() // Initialize ExoPlayer and set the protected surface. val exoPlayer = ExoPlayer.Builder(this).build() exoPlayer.setVideoSurface(protectedSurfaceEntity.getSurface()) // Set the media item and start playback. exoPlayer.setMediaItem(mediaItem) exoPlayer.prepare() exoPlayer.play()
Per una panoramica più dettagliata del framework DRM multimediale di Android, consulta la documentazione DRM su source.android.com.
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. Per impostazione predefinita, il parametro radius si riferisce alla dimensione radiale delle rispettive superfici in metri.
Il seguente codice mostra come configurare SurfaceEntity per la riproduzione su un emisfero a 180° e una sfera a 360°. Quando utilizzi queste forme di canvas, posiziona la superficie sfruttando la posa della testa dell'utente per offrire un'esperienza immersiva.
val devicePose = ArDevice.getInstance(xrSession).state.value.devicePose val activitySpacePose = xrSession.scene.perceptionSpace.transformPoseTo(devicePose, xrSession.scene.activitySpace) // Set up the surface for playing a 180° video on a hemisphere. val hemisphereStereoSurfaceEntity = SurfaceEntity.create( session = xrSession, stereoMode = SurfaceEntity.StereoMode.SIDE_BY_SIDE, pose = activitySpacePose, shape = SurfaceEntity.Shape.Hemisphere(1.0f), ) // ... and use the surface for playing the media.
val devicePose = ArDevice.getInstance(xrSession).state.value.devicePose val activitySpacePose = xrSession.scene.perceptionSpace.transformPoseTo(devicePose, xrSession.scene.activitySpace) // Set up the surface for playing a 360° video on a sphere. val sphereStereoSurfaceEntity = SurfaceEntity.create( session = xrSession, stereoMode = SurfaceEntity.StereoMode.TOP_BOTTOM, pose = activitySpacePose, shape = SurfaceEntity.Shape.Sphere(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 di materiale personalizzati, puoi lavorare direttamente con SurfaceEntity dalla libreria SceneCore.
Le sezioni seguenti descrivono alcune delle funzionalità avanzate disponibili su SurfaceEntity.
Applicare la sfumatura dei bordi
Attenua i bordi della superficie per aiutarla a integrarsi con l'ambiente impostando la proprietà edgeFeatheringParams.
// 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.edgeFeatheringParams = SurfaceEntity.EdgeFeatheringParams.RectangleFeather(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, quindi assegnale la 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"), ) // 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 for XR
Se ti interessa scoprire come riprodurre video utilizzando Jetpack Compose per XR, scopri come aggiungere una superficie per contenuti di immagini o video.