Zewnętrzne powierzchnie przestrzenne

Odpowiednie urządzenia z XR
Te wskazówki pomogą Ci tworzyć treści na te typy urządzeń z XR.
Gogle XR
Przewodowe okulary XR

SpatialExternalSurface to funkcja kompozycyjna podprzestrzeni, która tworzy Surface i nim zarządza. Twoja aplikacja może w nim rysować treści, takie jak obraz czy film. SpatialExternalSurface obsługuje treści stereoskopowe i monoskopowe.

Dodawanie powierzchni na obrazy lub treści wideo

Ten przykład pokazuje, jak wczytać stereoskopowy film side-by-side za pomocą Media3 Exoplayer i SpatialExternalSurface:

@OptIn(ExperimentalComposeApi::class)
@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() }
        }
    }
}

Najważniejsze informacje o kodzie

  • Ustaw StereoMode na Mono, SideBySide lub TopBottom w zależności od tego, jaki typ treści renderujesz:
    • Mono: klatka obrazu lub filmu składa się z jednego, identycznego obrazu wyświetlanego dla obu oczu.
    • SideBySide: obraz lub klatka wideo zawiera parę obrazów lub klatek wideo ułożonych obok siebie, przy czym obraz lub klatka po lewej stronie przedstawia widok dla lewego oka, a obraz lub klatka po prawej stronie przedstawia widok dla prawego oka.
    • TopBottom: obraz lub klatka filmu zawiera parę obrazów lub klatek filmu ułożonych pionowo, przy czym obraz lub klatka na górze przedstawia widok dla lewego oka, a obraz lub klatka na dole przedstawia widok dla prawego oka.
  • SpatialExternalSurface obsługuje tylko powierzchnie prostokątne.
  • Ten element Surface nie rejestruje zdarzeń wejściowych.
  • Nie można zsynchronizować zmian StereoMode z renderowaniem aplikacji ani dekodowaniem wideo.
  • Tego elementu kompozycyjnego nie można renderować przed innymi panelami, więc nie należy używać elementu MovePolicy, jeśli w układzie są inne panele.

Dodawanie platformy na potrzeby treści wideo chronionych DRM

SpatialExternalSurface obsługuje też odtwarzanie strumieni wideo chronionych przez DRM. Aby to umożliwić, musisz utworzyć bezpieczną powierzchnię, która renderuje do chronionych buforów graficznych. Zapobiega to nagrywaniu treści na ekranie i uzyskiwaniu do nich dostępu przez niezabezpieczone komponenty systemu.

Aby utworzyć bezpieczną platformę, ustaw parametr SpatialExternalSurfaceProtection na SpatialExternalSurfaceProtection.Protected w funkcji kompozycyjnej SpatialExternalSurface. Dodatkowo musisz skonfigurować Media3 Exoplayer, podając odpowiednie informacje DRM, aby umożliwić pobieranie licencji z serwera licencji.

Poniższy przykład pokazuje, jak skonfigurować SpatialExternalSurface i ExoPlayer, aby odtwarzać strumień wideo chroniony przez DRM:

@OptIn(ExperimentalComposeApi::class)
@Composable
fun DrmSpatialVideoPlayer() {
    val context = LocalContext.current
    Subspace {
        SpatialExternalSurface(
            modifier = SubspaceModifier
                .width(1200.dp)
                .height(676.dp),
            stereoMode = StereoMode.SideBySide,
            surfaceProtection = SpatialExternalSurfaceProtection.Protected
        ) {
            val exoPlayer = remember { ExoPlayer.Builder(context).build() }

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

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

            onSurfaceCreated { surface ->
                // The created surface is secure and can be used by the player.
                exoPlayer.setVideoSurface(surface)
                exoPlayer.setMediaItem(mediaItem)
                exoPlayer.prepare()
                exoPlayer.play()
            }

            onSurfaceDestroyed { exoPlayer.release() }
        }
    }
}

Najważniejsze informacje o kodzie

  • Protected Surface: ustawienie surfaceProtection = SpatialExternalSurfaceProtection.Protected na SpatialExternalSurface jest niezbędne, aby podstawowy Surface był obsługiwany przez bezpieczne buforowanie odpowiednie dla treści DRM.
  • Konfiguracja DRM: musisz skonfigurować MediaItem za pomocą schematu DRM (np. C.WIDEVINE_UUID) i identyfikatora URI serwera licencji. ExoPlayer używa tych informacji do zarządzania sesją DRM.
  • Bezpieczne treści: podczas renderowania na chronionej powierzchni treści wideo są dekodowane i wyświetlane na bezpiecznej ścieżce, co pomaga spełnić wymagania dotyczące licencji na treści. Zapobiega to też wyświetlaniu treści na zrzutach ekranu.