SpatialExternalSurface 是子空間可組合項,可建立及管理 Surface,讓應用程式在其中繪製內容,例如圖片或影片。SpatialExternalSurface 支援立體或單視內容。
新增圖片或影片內容的介面
以下範例說明如何使用 Media3 Exoplayer 和 SpatialExternalSurface 載入並排立體影片:
@OptIn(ExperimentalComposeApi::class) @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() } } } }
程式碼重點
- 根據您要顯示的內容類型,將
StereoMode設為Mono、SideBySide或TopBottom:Mono:圖片或影片影格由單一、相同的圖片組成,雙眼看到的內容相同。SideBySide:圖片或影片影格包含一組並排排列的圖片或影片影格,其中左側的圖片或影格代表左眼視圖,右側的圖片或影格代表右眼視圖。TopBottom:圖片或影片影格包含一組垂直堆疊的圖片或影片影格,其中頂端的圖片或影格代表左眼視圖,底部的圖片或影格代表右眼視圖。
SpatialExternalSurface僅支援矩形表面。- 這個
Surface不會擷取輸入事件。 - 無法將
StereoMode變更與應用程式轉譯或影片解碼同步。 - 這個可組合項無法在其他面板前方算繪,因此如果版面配置中有其他面板,請勿使用
MovePolicy。
為受 DRM 保護的影片內容新增途徑
SpatialExternalSurface 也支援播放受 DRM 保護的影片串流。如要啟用這項功能,您必須建立安全途徑,轉譯為受保護的圖形緩衝區。這樣可防止內容遭到螢幕錄影,或由不安全的系統元件存取。
如要建立安全途徑,請將 SpatialExternalSurface 可組合項目的 SpatialExternalSurfaceProtection 參數設為 SpatialExternalSurfaceProtection.Protected。此外,您必須使用適當的 DRM 資訊設定 Media3 Exoplayer,以便處理從授權伺服器取得授權。
以下範例說明如何設定 SpatialExternalSurface 和 ExoPlayer,播放受 DRM 保護的影片串流:
@OptIn(ExperimentalComposeApi::class) @Composable fun DrmSpatialVideoPlayer() { val context = LocalContext.current Subspace { SpatialExternalSurface( modifier = SubspaceModifier .width(1200.dp) .height(676.dp), stereoMode = StereoMode.SideBySide, surfaceProtection = SpatialExternalSurfaceProtection.Protected ) { val exoPlayer = remember { ExoPlayer.Builder(context).build() } // 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" // 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() onSurfaceCreated { surface -> // The created surface is secure and can be used by the player. exoPlayer.setVideoSurface(surface) exoPlayer.setMediaItem(mediaItem) exoPlayer.prepare() exoPlayer.play() } onSurfaceDestroyed { exoPlayer.release() } } } }
程式碼重點
- 受保護的 Surface:必須在
SpatialExternalSurface上設定surfaceProtection = SpatialExternalSurfaceProtection.Protected,基礎Surface才能由適合 DRM 內容的安全緩衝區支援。 - DRM 設定:您必須使用 DRM 配置 (例如
C.WIDEVINE_UUID) 和授權伺服器的 URI 設定MediaItem。ExoPlayer 會使用這項資訊管理 DRM 工作階段。 - 安全內容:在受保護的介面上算繪時,影片內容會解碼並顯示在安全路徑上,有助於滿足內容授權需求。這也能防止內容出現在螢幕擷取畫面中。