SpatialExternalSurface adalah composable subruang yang membuat dan
mengelola Surface tempat aplikasi Anda dapat menggambar konten, seperti
gambar atau video. SpatialExternalSurface mendukung konten stereoskopis atau monoskopis.
Menambahkan platform untuk konten gambar atau video
Contoh ini menunjukkan cara memuat video stereoskopis berdampingan menggunakan
Media3 Exoplayer dan 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() } } } }
Poin penting tentang kode
- Tetapkan
StereoModekeMono,SideBySide, atauTopBottom, bergantung pada jenis konten yang Anda render:Mono: Frame gambar atau video terdiri dari satu gambar identik yang ditampilkan ke kedua mata.SideBySide: Gambar atau frame video berisi sepasang gambar atau frame video yang disusun berdampingan, dengan gambar atau frame di sebelah kiri mewakili tampilan mata kiri, dan gambar atau frame di sebelah kanan mewakili tampilan mata kanan.TopBottom: Frame gambar atau video berisi sepasang gambar atau frame video yang ditumpuk secara vertikal, dengan gambar atau frame di bagian atas mewakili tampilan mata kiri, dan gambar atau frame di bagian bawah mewakili tampilan mata kanan.
SpatialExternalSurfacehanya mendukung platform persegi panjang.Surfaceini tidak merekam peristiwa input.- Perubahan
StereoModetidak dapat disinkronkan dengan rendering aplikasi atau decoding video. - Composable ini tidak dapat dirender di depan panel lain, jadi Anda tidak boleh menggunakan
MovePolicyjika ada panel lain dalam tata letak.
Menambahkan platform untuk konten video yang dilindungi DRM
SpatialExternalSurface juga mendukung pemutaran streaming video yang dilindungi DRM. Untuk mengaktifkannya, Anda harus membuat platform aman yang merender ke
buffer grafis yang dilindungi. Tindakan ini mencegah konten direkam di layar
atau diakses oleh komponen sistem yang tidak aman.
Untuk membuat platform yang aman, tetapkan parameter SpatialExternalSurfaceProtection
ke SpatialExternalSurfaceProtection.Protected pada
composable SpatialExternalSurface. Selain itu, Anda harus mengonfigurasi
Media3 Exoplayer dengan informasi DRM yang sesuai untuk menangani akuisisi
lisensi dari server lisensi.
Contoh berikut menunjukkan cara mengonfigurasi SpatialExternalSurface dan
ExoPlayer untuk memutar streaming video yang dilindungi 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() } } } }
Poin penting tentang kode
- Platform yang Dilindungi: Menyetel
surfaceProtection = SpatialExternalSurfaceProtection.ProtecteddiSpatialExternalSurfacesangat penting agarSurfaceyang mendasarinya didukung oleh buffer aman yang sesuai untuk konten DRM. - Konfigurasi DRM: Anda harus mengonfigurasi
MediaItemdengan skema DRM (misalnya,C.WIDEVINE_UUID) dan URI server lisensi Anda. ExoPlayer menggunakan informasi ini untuk mengelola sesi DRM. - Konten Aman: Saat dirender ke platform yang dilindungi, konten video didekode dan ditampilkan di jalur yang aman, yang membantu memenuhi persyaratan lisensi konten. Hal ini juga mencegah konten muncul dalam screenshot.