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إذا كانت هناك لوحات أخرى في التنسيق.
إضافة مساحة عرض لمحتوى الفيديو المحمي بنظام "إدارة الحقوق الرقمية"
يتيح SpatialExternalSurface أيضًا تشغيل فيديوهات البث المباشر المحمية بموجب "إدارة الحقوق الرقمية". لتفعيل هذه الميزة، يجب إنشاء مساحة عرض آمنة يتم عرضها في
مخازن مؤقتة للرسومات المحمية. يمنع ذلك تسجيل الشاشة أو وصول مكوّنات النظام غير الآمنة إلى المحتوى.
لإنشاء سطح آمن، اضبط المَعلمة SpatialExternalSurfaceProtection على SpatialExternalSurfaceProtection.Protected في الدالة المركّبة SpatialExternalSurface. بالإضافة إلى ذلك، يجب ضبط
Media3 Exoplayer باستخدام معلومات إدارة الحقوق الرقمية المناسبة للتعامل مع عملية الحصول على الترخيص
من خادم الترخيص.
يوضّح المثال التالي كيفية ضبط SpatialExternalSurface وExoPlayer لتشغيل بث فيديو محمي بموجب إدارة الحقوق الرقمية:
@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: Setting
surfaceProtection = SpatialExternalSurfaceProtection.ProtectedonSpatialExternalSurfaceis essential so that the underlyingSurfaceis backed by secure buffers suitable for DRM content. - إعدادات إدارة الحقوق الرقمية: يجب ضبط
MediaItemباستخدام نظام إدارة الحقوق الرقمية (على سبيل المثال،C.WIDEVINE_UUID) ومعرّف الموارد المنتظم (URI) لخادم الترخيص. يستخدم ExoPlayer هذه المعلومات لإدارة جلسة إدارة الحقوق الرقمية. - المحتوى الآمن: عند العرض على سطح محمي، يتم فك ترميز محتوى الفيديو وعرضه على مسار آمن، ما يساعد في تلبية متطلبات ترخيص استخدام المحتوى. يؤدي ذلك أيضًا إلى منع ظهور المحتوى في لقطات الشاشة.