앱에 공간 동영상 추가

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를 사용하여 DRM으로 보호된 공간 동영상 재생

Jetpack XR SDK는 Android의 내장 디지털 권한 관리 (DRM) 프레임워크를 사용하여 암호화된 동영상 스트림의 재생을 지원합니다. DRM은 안전한 배포를 지원하고 무단 복사 또는 재생을 방지하여 콘텐츠를 보호합니다.

이 프로세스에는 미디어 플레이어 애플리케이션이 라이선스 서버에 연락하여 복호화 키를 획득하는 과정이 포함됩니다. Android에서는 이 프로세스가 안전하게 관리되며 복호화된 동영상 프레임은 시스템이나 다른 애플리케이션에서 액세스할 수 없는 보호된 그래픽 버퍼에 렌더링되어 화면 캡처를 방지합니다.

Jetpack SceneCore로 DRM 보호 동영상을 재생하려면 다음이 필요합니다.

  1. 보호된 노출 영역을 요청하도록 SurfaceEntity을 구성합니다.
  2. 키 교환을 처리하는 데 필요한 DRM 정보로 Media3 Exoplayer를 구성합니다.
  3. 플레이어의 출력을 SurfaceEntity의 표면으로 설정합니다.

다음 예시에서는 DRM으로 보호된 스트림을 재생하고 SurfaceEntity에 렌더링하도록 ExoPlayer를 구성하는 방법을 보여줍니다.

// 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의 미디어 DRM 프레임워크에 관한 자세한 개요는 source.android.com의 미디어 DRM 문서를 참고하세요.

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을 사용하여 동영상을 재생하는 방법을 알아보려면 이미지 또는 동영상 콘텐츠용 서페이스를 추가하는 방법을 알아보세요.