فئة TextureView هي كائن عرض يجمع بين العرض وSurfaceTexture.
التقديم باستخدام OpenGL ES
يقوم كائن TextureView بتغليف SurfaceTexture، والاستجابة لعمليات الاسترجاعات والحصول على مخازن مؤقتة جديدة. عندما يكتسب TextureView مخازن مؤقتة جديدة، يصدر TextureView عرضًا يبطل الطلب ويرسم باستخدام محتويات المخزن المؤقت الأحدث كمصدر بياناته، مما يعرض أينما وكيفما تشير حالة العرض إلى ذلك.
يمكن لـ OpenGL ES (GLES) العرض على TextureView عن طريق تمرير SurfaceTexture إلى استدعاء إنشاء EGL، ولكن هذا يخلق مشكلة. عندما يتم عرض GLES على TextureView، يكون المنتجون والمستهلكون في BufferQueue في نفس مؤشر الترابط، مما قد يتسبب في توقف استدعاء مبادلة المخزن المؤقت أو فشله. على سبيل المثال، إذا أرسل منتج العديد من المخازن المؤقتة في تتابع سريع من مؤشر ترابط واجهة المستخدم، فإن استدعاء مبادلة المخزن المؤقت 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.
يستخدم برنامج Grafika Double Decode زوجًا من كائنات TextureView لعرض مقطعي فيديو يتم تشغيلهما جنبًا إلى جنب، لمحاكاة تطبيق مؤتمرات الفيديو. عندما يتغير اتجاه الشاشة ويتم إعادة تشغيل النشاط، لا تتوقف أجهزة فك ترميز MediaCodec، مما يحاكي تشغيل دفق الفيديو في الوقت الفعلي. لتحسين الكفاءة، يجب على العميل الحفاظ على السطح حيًا. السطح عبارة عن مؤشر لواجهة المنتج في BufferQueue الخاص بـ SurfaceTexture. نظرًا لأن TextureView يدير SurfaceTexture، يحتاج العميل إلى إبقاء SurfaceTexture حيًا لإبقاء السطح حيًا.
للحفاظ على SurfaceTexture حيًا، يحصل برنامج Grafika's Double Decode على مراجع إلى SurfaceTextures من كائنات TextureView ويحفظها في حقل ثابت. بعد ذلك، يقوم Double Decode الخاص بـ Grafika بإرجاع false
من TextureView.SurfaceTextureListener#onSurfaceTextureDestroyed()
لمنع تدمير SurfaceTexture. يقوم TextureView بعد ذلك بتمرير SurfaceTexture إلى onSurfaceTextureDestroyed()
الذي يمكن الحفاظ عليه عبر تغيير تكوين النشاط، والذي يمرره العميل إلى TextureView الجديد من خلال setSurfaceTexture()
.
تعمل الخيوط المنفصلة على تشغيل كل وحدة فك ترميز فيديو. يرسل Mediaserver مخازن مؤقتة ذات مخرجات تم فك تشفيرها إلى SurfaceTextures، ومستهلكي BufferQueue. تقوم كائنات TextureView بالعرض والتنفيذ على مؤشر ترابط واجهة المستخدم.
يعد تنفيذ فك التشفير المزدوج لـ Grafika باستخدام SurfaceView أصعب من التنفيذ باستخدام TextureView لأن كائنات SurfaceView تدمر الأسطح أثناء تغييرات الاتجاه. بالإضافة إلى ذلك، يؤدي استخدام كائنات SurfaceView إلى إضافة طبقتين، وهو أمر غير مثالي بسبب القيود المفروضة على عدد التراكبات المتوفرة على الجهاز.