Jetpack XR SDK поддерживает воспроизведение стереоскопического видео в формате Side-by-Side на плоских поверхностях. В стереоскопическом видео каждый кадр состоит из двух изображений – для левого и правого глаза. Это позволяет создать ощущение глубины, или стереоэффект.
Для рендеринга нестереоскопического 2D-видео в приложениях Android XR можно использовать стандартные Media API, которые применяются при разработке для Android на других типах устройств.
Как воспроизводить видео в режиме Side-by-Side с помощью 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 укажите в параметре stereoMode, какой ракурс в файле MV-HEVC является основным – левый или правый.
// 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
Jetpack XR SDK поддерживает воспроизведение зашифрованных видеопотоков с помощью встроенной в Android платформы управления цифровыми правами (DRM). Технологии DRM защищают контент, обеспечивая его безопасное распространение и предотвращая несанкционированное копирование или воспроизведение.
Для этого проигрыватель обращается к серверу лицензий, чтобы получить ключи расшифровки. На устройствах Android этот процесс защищен, а расшифрованные кадры видео передаются в защищенный графический буфер, к которому нет доступа у системы и других приложений. Это предотвращает запись экрана.
Чтобы воспроизводить видео, защищенное DRM, с помощью Jetpack SceneCore, выполните следующие действия:
- Настройте
SurfaceEntity, чтобы запрашивать защищенную поверхность. - Настройте Media3 Exoplayer, указав необходимую информацию о DRM для обмена ключами.
- Настройте вывод проигрывателя на поверхность
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()
Подробную информацию о фреймворке Media DRM для Android можно найти в документации на сайте source.android.com.
Как воспроизводить панорамные видео с помощью Jetpack SceneCore
SurfaceEntity поддерживает воспроизведение видео 180° на полусферических поверхностях и панорамного видео на сферических поверхностях. Параметр 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, прочитайте статью о том, как добавить поверхность для изображений или видеоконтента.