Räumliche Außenflächen

XR‑Geräte, für die der Leitfaden gilt
Dieser Leitfaden hilft Ihnen dabei, Erlebnisse für die folgenden Arten von XR-Geräten zu entwickeln.
XR-Headsets
Kabelgebundene XR-Datenbrille

Ein SpatialExternalSurface ist ein Subspace-Composable, das die Surface erstellt und verwaltet, in die Ihre App Inhalte wie ein Bild oder ein Video zeichnen kann. SpatialExternalSurface unterstützt entweder stereoskopische oder monoskopische Inhalte.

Oberfläche für Bild- oder Videoinhalte hinzufügen

In diesem Beispiel wird gezeigt, wie Sie ein stereoskopisches Side-by-Side-Video mit Media3 Exoplayer und SpatialExternalSurface laden:

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

Wichtige Punkte zum Code

  • Legen Sie StereoMode je nach Art des zu rendernden Inhalts auf Mono, SideBySide oder TopBottom fest:
    • Mono: Das Bild oder der Videoframe besteht aus einem einzelnen, identischen Bild, das für beide Augen angezeigt wird.
    • SideBySide: Das Bild oder der Videoframe enthält ein Paar Bilder oder Videoframes, die nebeneinander angeordnet sind. Das Bild oder der Frame auf der linken Seite stellt die Ansicht für das linke Auge dar, das Bild oder der Frame auf der rechten Seite die Ansicht für das rechte Auge.
    • TopBottom: Das Bild oder der Videoframe enthält ein Paar vertikal gestapelter Bilder oder Videoframes, wobei das Bild oder der Frame oben die Ansicht für das linke Auge und das Bild oder der Frame unten die Ansicht für das rechte Auge darstellt.
  • SpatialExternalSurface unterstützt nur rechteckige Oberflächen.
  • Dieses Surface erfasst keine Eingabeereignisse.
  • Es ist nicht möglich, StereoMode-Änderungen mit dem Anwendungsrendering oder der Videodecodierung zu synchronisieren.
  • Dieses Compose-Element kann nicht vor anderen Bereichen gerendert werden. Sie sollten also kein MovePolicy verwenden, wenn das Layout andere Bereiche enthält.

Oberfläche für DRM-geschützte Videoinhalte hinzufügen

SpatialExternalSurface unterstützt auch die Wiedergabe von DRM-geschützten Videostreams. Dazu musst du eine sichere Oberfläche erstellen, die in geschützten Grafikpuffern gerendert wird. Dadurch wird verhindert, dass der Inhalt per Bildschirmaufzeichnung aufgenommen oder von unsicheren Systemkomponenten abgerufen wird.

Wenn Sie eine sichere Oberfläche erstellen möchten, setzen Sie den Parameter SpatialExternalSurfaceProtection in der zusammensetzbaren Funktion SpatialExternalSurface auf SpatialExternalSurfaceProtection.Protected. Außerdem musst du Media3 Exoplayer mit den entsprechenden DRM-Informationen konfigurieren, um den Lizenzerwerb von einem Lizenzserver zu verarbeiten.

Im folgenden Beispiel wird gezeigt, wie Sie SpatialExternalSurface und ExoPlayer für die Wiedergabe eines DRM-geschützten Videostreams konfigurieren:

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

Wichtige Punkte zum Code

  • Geschützte Oberfläche: Die Einstellung surfaceProtection = SpatialExternalSurfaceProtection.Protected für SpatialExternalSurface ist wichtig, damit die zugrunde liegende Surface durch sichere Puffer unterstützt wird, die für DRM-Inhalte geeignet sind.
  • DRM-Konfiguration: Du musst die MediaItem mit dem DRM-Schema (z. B. C.WIDEVINE_UUID) und dem URI deines Lizenzservers konfigurieren. ExoPlayer verwendet diese Informationen, um die DRM-Sitzung zu verwalten.
  • Sicherer Inhalt: Beim Rendern auf einer geschützten Oberfläche wird der Videoinhalt decodiert und auf einem sicheren Pfad angezeigt, was zur Erfüllung der Anforderungen an die Inhaltslizenzierung beiträgt. Dadurch wird auch verhindert, dass der Inhalt in Bildschirmaufnahmen angezeigt wird.