Пространственные внешние поверхности

Поддерживаемые XR-устройства
Это руководство поможет вам создавать продукты для таких XR-устройств.
XR-шлемы
Проводные XR-очки

SpatialExternalSurface – это composable-функция подпространства, которая создает Surface и управляет им. В этом элементе приложение может отрисовывать контент, например изображение или видео. SpatialExternalSurface поддерживает как стереоскопический, так и моноскопический контент.

Добавьте поверхность для изображений или видеоконтента

В примере ниже показано, как загрузить стереоскопическое видео в формате горизонтальной стереопары с помощью Media3 Exoplayer и 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() }
        }
    }
}

Важные сведения о коде

  • Задайте для параметра StereoMode значение Mono, SideBySide или TopBottom в зависимости от типа контента, который вы показываете:
    • Mono – изображение или кадр видео состоит из одного и того же изображения, которое показывается обоим глазам.
    • SideBySide: изображение или кадр видео содержит пару изображений или кадров видео, расположенных рядом, где изображение или кадр слева представляет вид для левого глаза, а изображение или кадр справа – вид для правого глаза.
    • TopBottom – изображение или кадр видео содержит пару изображений или кадров видео, расположенных вертикально, где изображение или кадр сверху представляет вид для левого глаза, а изображение или кадр снизу – вид для правого глаза.
  • SpatialExternalSurface поддерживает только прямоугольные поверхности.
  • Этот Surface не регистрирует события ввода.
  • Изменения StereoMode нельзя синхронизировать с отрисовкой приложения или декодированием видео.
  • Эта composable-функция не может отображаться перед другими панелями, поэтому не используйте MovePolicy, если в макете есть другие панели.

Как добавить поверхность для видеоконтента, защищенного DRM

SpatialExternalSurface также поддерживает воспроизведение видеопотоков, защищенных технологиями DRM. Для этого необходимо создать защищенную поверхность, которая будет отрисовываться в защищенных графических буферах. Это позволяет предотвратить запись экрана и доступ к контенту со стороны небезопасных компонентов системы.

Чтобы создать защищенную поверхность, задайте для параметра SpatialExternalSurfaceProtection значение SpatialExternalSurfaceProtection.Protected в composable-функции SpatialExternalSurface. Кроме того, вам нужно настроить Media3 Exoplayer, указав информацию о DRM, чтобы получать лицензии от сервера лицензирования.

В следующем примере показано, как настроить SpatialExternalSurface и ExoPlayer для воспроизведения видеопотока, защищенного технологиями 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() }
        }
    }
}

Важные сведения о коде

  • Защищенная поверхность. Настройка surfaceProtection = SpatialExternalSurfaceProtection.Protected в SpatialExternalSurface необходима, чтобы базовая Surface поддерживалась защищенными буферами, подходящими для контента с DRM.
  • Настройки DRM. Вам необходимо настроить MediaItem с помощью схемы DRM (например, C.WIDEVINE_UUID) и URI сервера лицензирования. ExoPlayer использует эту информацию для управления сеансом DRM.
  • Защищенный контент. При отрисовке на защищенной поверхности видеоконтент декодируется и показывается по защищенному пути, что помогает соблюдать требования лицензирования контента. Это также предотвращает появление контента на снимках экрана.