Комплект разработчика 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 вам необходимо:
- Настройте
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()
Более подробный обзор системы 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, узнайте, как добавить поверхность для изображения или видеоконтента .