فئة TextureView هي عنصر عرض يجمع بين عرض وSurfaceTexture.
العرض باستخدام OpenGL ES
يغلّف عنصر TextureView عنصر SurfaceTexture، ويستجيب لعمليات معاودة الاتصال ويحصل على مخازن مؤقتة جديدة. عندما يحصل TextureView على مخازن مؤقتة جديدة، يرسل TextureView طلبًا بإبطال العرض ويرسم باستخدام محتويات أحدث مخزن مؤقت كمصدر بيانات، ويعرض في أي مكان وبأي طريقة يشير إليها حالة العرض.
يمكن OpenGL ES (GLES) عرض المحتوى على TextureView من خلال تمرير SurfaceTexture إلى طلب إنشاء EGL، ولكن يؤدي ذلك إلى حدوث مشكلة. عندما يتم عرض GLES على TextureView، يكون منتجو ومستهلكو BufferQueue في سلسلة المحادثات نفسها، ما قد يؤدي إلى توقّف أو تعذُّر عملية تبديل المخزن المؤقت. على سبيل المثال، إذا أرسل منتج عدة مخازن مؤقتة على التوالي بسرعة من سلسلة UI، يجب أن يستخرج استدعاء تبديل المخزن المؤقت EGL مخزنًا مؤقتًا من BufferQueue. ومع ذلك، بما أنّ المستهلك والمنتج يعملان على سلسلة المحادثات نفسها، لن تتوفّر أي مخازن مؤقتة، وسيتعذّر تنفيذ عملية التبديل أو ستتوقف.
لمنع توقّف تبديل المخزن المؤقت، يجب أن يتوفّر دائمًا مخزن مؤقت في BufferQueue لإزالة البيانات من قائمة الانتظار. ولإجراء ذلك، تتجاهل BufferQueue محتويات المخزن المؤقت الذي تم الحصول عليه سابقًا عند وضع مخزن مؤقت جديد في قائمة الانتظار. ويفرض أيضًا قيودًا على الحد الأدنى والحد الأقصى لعدد المخازن المؤقتة لمنع المستهلك من استخدام جميع المخازن المؤقتة في وقت واحد.
اختيار SurfaceView أو TextureView
تؤدي كلّ من SurfaceView وTextureView أدوارًا مشابهة، وهما جزء من بنية العرض الهرمية. ومع ذلك، يختلف تنفيذ SurfaceView عن تنفيذ TextureView. تتلقّى SurfaceView المَعلمات نفسها التي تتلقّاها طرق العرض الأخرى، ولكن تكون محتويات SurfaceView شفافة عند عرضها.
تتفوّق TextureView على SurfaceView في معالجة القنوات الشفافة والتدوير، ولكن تتفوّق SurfaceView في الأداء عند دمج عناصر واجهة المستخدم التي يتم عرضها فوق الفيديوهات. عندما يعرض العميل المحتوى باستخدام SurfaceView، يوفّر SurfaceView للعميل طبقة تركيب منفصلة. تجمع خدمة SurfaceFlinger الطبقة المنفصلة كطبقة متراكبة للأجهزة إذا كان الجهاز يتيح ذلك. عندما يعرض أحد العملاء المحتوى باستخدام TextureView، تدمج حزمة أدوات واجهة المستخدم محتوى TextureView في بنية العرض الهرمية باستخدام وحدة معالجة الرسومات. قد تؤدي التعديلات على المحتوى إلى إعادة رسم عناصر العرض الأخرى، مثلاً، إذا كانت طرق العرض الأخرى موضوعة فوق TextureView. بعد اكتمال عرض طريقة العرض، يدمج SurfaceFlinger طبقة واجهة مستخدم التطبيق وجميع الطبقات الأخرى، بحيث يتم دمج كل بكسل مرئي مرتين.
دراسة حالة: "تشغيل الفيديو" من Grafika
يتضمّن تطبيق Grafika's Play Video زوجًا من مشغّلات الفيديو، أحدهما تم تنفيذه باستخدام TextureView والآخر باستخدام SurfaceView. يرسل جزء فك ترميز الفيديو من النشاط إطارات من MediaCodec إلى مساحة عرض لكل من TextureView وSurfaceView. ويتمثل الاختلاف الأكبر بين عمليات التنفيذ في الخطوات المطلوبة لعرض نسبة العرض إلى الارتفاع الصحيحة.
يتطلّب تغيير حجم SurfaceView تنفيذًا مخصّصًا لـ FrameLayout.
يحتاج WindowManager إلى إرسال قيم جديدة لموضع النافذة وحجمها إلى SurfaceFlinger. يتطلّب تغيير حجم SurfaceTexture الخاص بـ TextureView ضبط مصفوفة تحويل باستخدام TextureView#setTransform().
بعد عرض نسبة العرض إلى الارتفاع الصحيحة، يتّبع كلا التنفيذين النمط نفسه. عندما تنشئ SurfaceView/TextureView مساحة العرض، يفعّل رمز التطبيق التشغيل. عندما ينقر المستخدم على تشغيل، يبدأ سلسلة تعليمات لفك ترميز الفيديو، مع تحديد السطح كهدف الإخراج. بعد ذلك، لا ينفّذ رمز التطبيق أي إجراء، بل يتولّى SurfaceFlinger (بالنسبة إلى SurfaceView) أو TextureView عملية الإنشاء والعرض.
دراسة حالة: ميزة "فك الترميز المزدوج" من Grafika
يوضّح تطبيق Grafika's Double Decode كيفية التلاعب في SurfaceTexture داخل TextureView.
يستخدم Double Decode من Grafika زوجًا من عناصر TextureView لعرض فيديوهَين يتم تشغيلهما جنبًا إلى جنب، ما يحاكي تطبيقًا لعقد اجتماعات الفيديو. وعندما تتغير اتجاه الشاشة ويتم إعادة تشغيل النشاط، لا تتوقف برامج الترميز MediaCodec، ما يحاكي تشغيل بث فيديو في الوقت الفعلي. لتحسين الكفاءة، يجب أن يبقي العميل السطح نشطًا. السطح هو أداة معالجة لواجهة المنتج في BufferQueue الخاصة بـ SurfaceTexture. وبما أنّ TextureView يدير SurfaceTexture، على العميل إبقاء SurfaceTexture نشطًا لإبقاء السطح نشطًا.
لإبقاء SurfaceTexture نشطًا، يحصل Double Decode في Grafika على مراجع إلى SurfaceTexture من عناصر TextureView ويحفظها في حقل ثابت.
بعد ذلك، تعرض وظيفة Double Decode في Grafika القيمة false من
TextureView.SurfaceTextureListener#onSurfaceTextureDestroyed() لمنع إتلاف SurfaceTexture. بعد ذلك، تمرِّر TextureView عنصر SurfaceTexture إلى onSurfaceTextureDestroyed() الذي يمكن الاحتفاظ به عند تغيير إعدادات النشاط، والذي يمرِّره العميل إلى TextureView الجديد من خلال setSurfaceTexture().
تتولّى سلاسل المحادثات المنفصلة تشغيل كل أداة لفك ترميز الفيديو. يرسل Mediaserver المخازن المؤقتة التي تتضمّن الناتج الذي تم فك ترميزه إلى SurfaceTextures، أي مستهلكي BufferQueue. تنفّذ عناصر TextureView عملية العرض وتعمل على سلسلة التعليمات الخاصة بواجهة المستخدم.
يصعب تنفيذ ميزة "فك الترميز المزدوج" في Grafika باستخدام SurfaceView مقارنةً بتنفيذها باستخدام TextureView، لأنّ عناصر SurfaceView تتلف الأسطح عند تغيير اتجاه الشاشة. بالإضافة إلى ذلك، يؤدي استخدام عناصر SurfaceView إلى إضافة طبقتَين، وهو أمر غير مثالي بسبب القيود المفروضة على عدد التراكبات المتاحة على الجهاز.