Jetpack XR SDK поддерживает воспроизведение стереоскопического видео в режиме «бок о бок» на плоских поверхностях. В стереоскопическом видео каждый кадр состоит из изображений для левого и правого глаза, что создаёт у зрителей ощущение глубины, также известное как стереопсис .
Вы можете визуализировать нестереоскопическое 2D-видео в приложениях Android XR с помощью стандартных API-интерфейсов мультимедиа, используемых для разработки Android на устройствах других форм-факторов.
Воспроизведение параллельного видео с помощью Jetpack SceneCore
При параллельном видео каждый стереокадр представлен двумя изображениями, расположенными рядом друг с другом по горизонтали. Верхний и нижний видеокадры расположены рядом друг с другом по вертикали.
Видео «бок о бок» — это не кодек, а скорее способ организации стереокадров, то есть его можно кодировать в любом из кодеков, поддерживаемых Android .
Вы можете загрузить параллельное видео с помощью Media3 Exoplayer , а затем отрендерить его с помощью нового SurfaceEntity
. Чтобы создать SurfaceEntity
, вызовите SurfaceEntity.create
, как показано в следующем примере.
val stereoSurfaceEntity = SurfaceEntity.create( xrSession, SurfaceEntity.StereoMode.SIDE_BY_SIDE, Pose(Vector3(0.0f, 0.0f, -1.5f)), SurfaceEntity.CanvasShape.Quad(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
. Вам нужно будет указать, является ли ваш файл MV-HEVC основным левым или правым, в параметре stereoMode
при вызове SurfaceEntity.create
.
// Create the SurfaceEntity with the StereoMode corresponding to the MV-HEVC content val stereoSurfaceEntity = SurfaceEntity.create( xrSession, SurfaceEntity.StereoMode.MULTIVIEW_LEFT_PRIMARY, Pose(Vector3(0.0f, 0.0f, -1.5f)), SurfaceEntity.CanvasShape.Quad(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)), canvasShape = SurfaceEntity.CanvasShape.Quad(1.0f, 1.0f), contentSecurityLevel = SurfaceEntity.ContentSecurityLevel.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()
Более подробный обзор платформы Android Media DRM можно найти в документации Media DRM на source.android.com .
Воспроизведение 180-градусного и 360-градусного видео с помощью Jetpack SceneCore
SurfaceEntity
поддерживает воспроизведение видео 180° на полусферических поверхностях и видео 360° на сферических поверхностях. Параметр radius
по умолчанию определяет радиальный размер соответствующих поверхностей в метрах.
Следующий код показывает, как настроить SurfaceEntity
для воспроизведения на полусфере с обзором 180° и сфере с обзором 360°. При использовании этих форм холста расположите поверхность, используя положение головы пользователя, чтобы создать эффект погружения.
// Set up the surface for playing a 180° video on a hemisphere. val hemisphereStereoSurfaceEntity = SurfaceEntity.create( xrSession, SurfaceEntity.StereoMode.SIDE_BY_SIDE, xrSession.scene.spatialUser.head?.transformPoseTo( Pose.Identity, xrSession.scene.activitySpace )!!, SurfaceEntity.CanvasShape.Vr180Hemisphere(1.0f), ) // ... and use the surface for playing the media.
// Set up the surface for playing a 360° video on a sphere. val sphereStereoSurfaceEntity = SurfaceEntity.create( xrSession, SurfaceEntity.StereoMode.TOP_BOTTOM, xrSession.scene.spatialUser.head?.transformPoseTo( Pose.Identity, xrSession.scene.activitySpace )!!, SurfaceEntity.CanvasShape.Vr360Sphere(1.0f), ) // ... and use the surface for playing the media.
Расширенное управление SurfaceEntity
Для более расширенного управления рендерингом видео и изображений, например, для применения пользовательских эффектов материалов, вы можете работать напрямую с SurfaceEntity
из библиотеки SceneCore.
В следующих разделах описываются некоторые расширенные функции, доступные в SurfaceEntity
.
Применить растушевку краев
Смягчите края поверхности, чтобы она лучше сочеталась с окружающей средой, установив свойство edgeFeather
.
// 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.edgeFeather = SurfaceEntity.EdgeFeatheringParams.SmoothFeather(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"), TextureSampler.create() ) // 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, узнайте, как добавить поверхность для изображений или видеоконтента .