Thêm video không gian vào ứng dụng

SDK Jetpack XR hỗ trợ phát video cạnh nhau âm thanh nổi trên các bề mặt phẳng. Với video 3D, mỗi khung hình bao gồm một hình ảnh mắt trái và một hình ảnh mắt phải để mang đến cho người xem cảm giác về chiều sâu.

Bạn có thể kết xuất video 2D không lập thể trên các ứng dụng Android XR bằng API đa phương tiện tiêu chuẩn dùng để phát triển Android trên các hệ số hình dạng khác.

Phát video cạnh nhau bằng SDK Jetpack XR

Với video cạnh nhau, mỗi khung hình ba chiều được trình bày dưới dạng hai hình ảnh được sắp xếp cạnh nhau theo chiều ngang. Các khung hình video trên cùng và dưới cùng được sắp xếp theo chiều dọc cạnh nhau.

Video cạnh nhau không phải là một bộ mã hoá và giải mã mà là một cách sắp xếp các khung hình ba chiều, tức là video này có thể được mã hoá bằng bất kỳ bộ mã hoá và giải mã nào mà Android hỗ trợ.

Jetpack SceneCore

Bạn có thể tải video cạnh nhau bằng Media3 Exoplayer, sau đó hiển thị video đó bằng SurfaceEntity mới. Để tạo SurfaceEntity, hãy gọi SurfaceEntity.create như trong ví dụ sau.

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

Jetpack Compose cho XR

Alpha04 trở lên

Kể từ Phiên bản 1.0.0-alpha04, Jetpack Compose cho XR cung cấp một cách khác để tải và kết xuất video cạnh nhau. Sử dụng SpatialExternalSurface, một thành phần kết hợp không gian con tạo và quản lý Surface mà ứng dụng có thể vẽ nội dung, chẳng hạn như hình ảnh hoặc video. Để biết thêm thông tin chi tiết về SpatialExternalSurface, hãy xem hướng dẫn Phát triển giao diện người dùng bằng Compose cho XR.

Ví dụ này minh hoạ cách tải video cạnh nhau bằng Media3 ExoplayerSpatialExternalSurface.

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

Phát video 180 độ và 360 độ bằng SDK Jetpack XR

SurfaceEntity hỗ trợ phát video 180° trên bề mặt hình bán cầu và video 360° trên bề mặt hình cầu. Nếu video là 3D, thì các tệp phải ở định dạng cạnh nhau.

Mã sau đây cho biết cách thiết lập SurfaceEntity để phát trên một bán cầu 180° và một hình cầu 360°. Khi sử dụng các hình dạng canvas này, hãy định vị bề mặt bằng cách tận dụng tư thế đầu của người dùng để mang lại trải nghiệm sống động.

// 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.