앱에 공간 동영상 추가

Jetpack XR SDK는 평면 표면에 나란히 배치된 동영상의 스테레오스코피 재생을 지원합니다. 입체 동영상의 각 프레임은 왼쪽 눈 이미지와 오른쪽 눈 이미지로 구성되어 시청자에게 깊이감(입체시라고도 함)을 제공합니다.

다른 폼 팩터에서 Android 개발에 사용되는 표준 미디어 API를 사용하여 Android XR 앱에서 비스테레오 2D 동영상을 렌더링할 수 있습니다.

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

Jetpack SceneCore를 사용하여 MV-HEVC 동영상 재생

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

Jetpack SceneCore를 사용하여 180도 및 360도 동영상 재생

SurfaceEntity은 반구형 표면에서 180도 동영상을 재생하고 구형 표면에서 360도 동영상을 재생하는 것을 지원합니다. radius 매개변수는 기본적으로 해당 표면의 반지름 크기를 미터 단위로 나타냅니다.

다음 코드는 180° 반구와 360° 구체에서 재생할 SurfaceEntity를 설정하는 방법을 보여줍니다. 이러한 캔버스 모양을 사용할 때는 사용자의 머리 포즈를 활용하여 서피스를 배치하여 몰입도 높은 환경을 제공하세요.

// 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 제어

맞춤 소재 효과 적용과 같은 동영상 및 이미지 렌더링을 더 고급으로 제어하려면 SceneCore 라이브러리에서 SurfaceEntity를 직접 사용하면 됩니다.

다음 섹션에서는 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
}

XR용 Jetpack Compose를 사용하여 공간 동영상 재생

Jetpack Compose for XR을 사용하여 동영상을 재생하는 방법을 알아보려면 이미지 또는 동영상 콘텐츠용 서페이스를 추가하는 방법을 알아보세요.