Добавьте пространственное видео в свое приложение

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

Комплект разработчика Jetpack XR SDK поддерживает воспроизведение стереоскопического видео в режиме «бок о бок» на плоских поверхностях. В стереоскопическом видео каждый кадр состоит из изображения для левого и правого глаза, что создает у зрителей ощущение глубины — также известное как стереоскопическое зрение .

В приложениях Android XR можно отображать нестереоскопическое 2D-видео с помощью стандартных медиа-API, используемых для разработки под Android на других форм-факторах.

Воспроизводите видео в режиме параллельного просмотра с помощью Jetpack SceneCore.

При показе видео в режиме «бок о бок» каждый стереоскопический кадр представляется в виде двух изображений, расположенных горизонтально рядом друг с другом. Верхний и нижний кадры видео располагаются вертикально рядом друг с другом.

Видео в режиме "бок о бок" — это не кодек, а способ организации стереоскопических кадров, что означает, что его можно закодировать любым из кодеков, поддерживаемых Android .

С помощью Media3 Exoplayer можно загружать видео в режиме параллельного воспроизведения, а затем отображать его с помощью нового SurfaceEntity . Для создания SurfaceEntity вызовите метод SurfaceEntity.create , как показано в следующем примере.

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

Воспроизведение видео MV-HEVC с помощью Jetpack SceneCore

Стандарт кодека MV-HEVC оптимизирован и разработан для стереоскопического видео, что позволяет вашему приложению эффективно воспроизводить захватывающие видеоролики в отличном качестве. Файлы MV-HEVC имеют основной поток, обычно для левого глаза, и стереопоток для левого глаза.

Аналогично видео в режиме "бок о бок", вы можете загрузить его с помощью Media3 Exoplayer и отрендерить с помощью SurfaceEntity . При вызове метода SurfaceEntity.create вам потребуется указать, является ли ваш MV-HEVC-файл основным для левого или правого канала, в параметре 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()

Воспроизводите пространственное видео с защитой DRM с помощью Jetpack SceneCore.

SDK Jetpack XR поддерживает воспроизведение зашифрованных видеопотоков с использованием встроенной в Android системы управления цифровыми правами (DRM) . DRM защищает ваш контент, обеспечивая безопасное распространение и предотвращая несанкционированное копирование или воспроизведение.

Процесс включает в себя обращение вашего медиаплеера к серверу лицензий для получения ключей расшифровки. На Android этот процесс осуществляется безопасно, и расшифрованные видеокадры отображаются в защищенном графическом буфере, недоступном для системы или других приложений, что предотвращает захват экрана.

Для воспроизведения видео с защитой DRM с помощью Jetpack SceneCore вам необходимо:

  1. Настройте SurfaceEntity таким образом, чтобы он запрашивал защищенную поверхность.
  2. Настройте Media3 Exoplayer , указав необходимую информацию DRM для обработки обмена ключами.
  3. Настройте вывод плеера на поверхность объекта SurfaceEntity .

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

Более подробный обзор системы DRM для мультимедиа в Android можно найти в документации по DRM для мультимедиа на сайте source.android.com .

Воспроизводите видео в формате 180 и 360 градусов с помощью Jetpack SceneCore.

SurfaceEntity поддерживает воспроизведение видео 180° на полусферических поверхностях и видео 360° на сферических поверхностях. Параметр radius по умолчанию обозначает радиальный размер соответствующих поверхностей в метрах.

Приведенный ниже код показывает, как настроить SurfaceEntity для воспроизведения на полусфере с углом обзора 180° и сфере с углом обзора 360°. При использовании этих форм холста позиционируйте поверхность, используя положение головы пользователя, чтобы обеспечить эффект полного погружения.

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.

Расширенное управление SurfaceEntity

Для более продвинутого управления рендерингом видео и изображений, например, для применения пользовательских эффектов материалов, вы можете работать непосредственно с SurfaceEntity из библиотеки SceneCore.

В следующих разделах описаны некоторые расширенные функции, доступные в SurfaceEntity .

Примените технику сглаживания краев.

Чтобы поверхность лучше сливалась с окружающей средой, смягчите её края, установив свойство 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)

Примените альфа-маску.

Примените альфа-маску для создания непрямоугольных поверхностей или добавления эффектов прозрачности. Сначала загрузите Texture из ресурса, затем назначьте её свойству 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
}

Воспроизводите пространственное видео с помощью Jetpack Compose для XR.

Если вас интересует, как воспроизводить видео с помощью Jetpack Compose для XR, узнайте, как добавить поверхность для изображения или видеоконтента .