SpatialExternalSurface คือคอมโพสิเบิลของ Subspace ที่สร้างและจัดการ 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: เฟรมรูปภาพหรือเฟรมวิดีโอประกอบด้วยรูปภาพเดียวที่เหมือนกันซึ่งแสดงต่อตาทั้ง 2 ข้างSideBySide: รูปภาพหรือเฟรมวิดีโอมีรูปภาพหรือเฟรมวิดีโอคู่หนึ่งจัดเรียงเคียงข้างกัน โดยรูปภาพหรือเฟรมทางด้านซ้ายแสดงมุมมองตาซ้าย และรูปภาพหรือเฟรมทางด้านขวาแสดงมุมมองตาขวาTopBottom: รูปภาพหรือเฟรมวิดีโอมีรูปภาพหรือเฟรมวิดีโอคู่หนึ่งซ้อนกันในแนวตั้ง โดยรูปภาพหรือเฟรมด้านบนแสดงมุมมองตาซ้าย และรูปภาพหรือเฟรมด้านล่างแสดงมุมมองตาขวา
SpatialExternalSurfaceรองรับเฉพาะพื้นผิวสี่เหลี่ยมผืนผ้าเท่านั้นSurfaceนี้ไม่บันทึกเหตุการณ์การป้อนข้อมูล- ไม่สามารถซิงค์การเปลี่ยนแปลง
StereoModeกับการแสดงผลแอปพลิเคชันหรือการถอดรหัสวิดีโอ - คอมโพสิเบิลนี้ไม่สามารถแสดงผลที่ด้านหน้าของแผงอื่นๆ ดังนั้นคุณจึงไม่ควรใช้
MovePolicyหากมีแผงอื่นๆ ในเลย์เอาต์
เพิ่มแพลตฟอร์มสำหรับเนื้อหาวิดีโอที่ได้รับการคุ้มครองโดย DRM
SpatialExternalSurface ยังรองรับการเล่นสตรีมวิดีโอที่ได้รับการคุ้มครองด้วย DRM ด้วย หากต้องการเปิดใช้ฟีเจอร์นี้ คุณต้องสร้างแพลตฟอร์มที่ปลอดภัยซึ่งแสดงผลไปยังบัฟเฟอร์กราฟิกที่มีการป้องกัน ซึ่งจะป้องกันไม่ให้มีการบันทึกหน้าจอเนื้อหาหรือเข้าถึงเนื้อหาโดยคอมโพเนนต์ของระบบที่ไม่ปลอดภัย
หากต้องการสร้างแพลตฟอร์มที่ปลอดภัย ให้ตั้งค่าพารามิเตอร์ SpatialExternalSurfaceProtection เป็น SpatialExternalSurfaceProtection.Protected ใน SpatialExternalSurface Composable นอกจากนี้ คุณต้องกำหนดค่า Media3 Exoplayer ด้วยข้อมูล DRM ที่เหมาะสมเพื่อจัดการการรับใบอนุญาตจากเซิร์ฟเวอร์ใบอนุญาต
ตัวอย่างต่อไปนี้แสดงวิธีกำหนดค่า 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() } } } }
ประเด็นสำคัญเกี่ยวกับโค้ด
- Protected Surface: การตั้งค่า
surfaceProtection = SpatialExternalSurfaceProtection.ProtectedในSpatialExternalSurfaceเป็นสิ่งสำคัญเพื่อให้Surfaceที่สำคัญได้รับการสนับสนุนโดยบัฟเฟอร์ที่ปลอดภัยซึ่งเหมาะสำหรับเนื้อหา DRM - การกำหนดค่า DRM: คุณต้องกำหนดค่า
MediaItemด้วยรูปแบบ DRM (เช่นC.WIDEVINE_UUID) และ URI ของเซิร์ฟเวอร์ใบอนุญาต ExoPlayer จะใช้ข้อมูลนี้เพื่อจัดการเซสชัน DRM - เนื้อหาที่ปลอดภัย: เมื่อแสดงผลบนพื้นผิวที่มีการป้องกัน เนื้อหาวิดีโอจะได้รับการถอดรหัสและแสดงในเส้นทางที่ปลอดภัย ซึ่งช่วยให้เป็นไปตามข้อกำหนดของใบอนุญาตการใช้เนื้อหา นอกจากนี้ยังป้องกันไม่ให้เนื้อหาปรากฏในการจับภาพหน้าจอด้วย