TextureView

فئة 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 طبقة واجهة مستخدم التطبيق وجميع الطبقات الأخرى، بحيث يتم تجميع كل بكسل مرئي مرتين.

دراسة حالة: فيديو Play في Grafika

يتضمّن تطبيق Grafika لتشغيل الفيديو مشغّلَي فيديو، أحدهما مُطبَّق باستخدام TextureView والآخر مُطبَّق باستخدام SurfaceView. يُرسِل الجزء المعني بترميز الفيديو في النشاط لقطات من MediaCodec إلى سطح لكلٍّ من TextureView وSurfaceView. يتمثل أكبر فرق بين عمليات التنفيذ في الخطوات المطلوبة لعرض نسبة العرض إلى الارتفاع الصحيحة.

يتطلب تغيير حجم SurfaceView تنفيذًا مخصّصًا لإطار FrameLayout. يجب أن يرسل WindowManager موضع نافذة جديدًا وقيم حجم جديدة إلى SurfaceFlinger. يتطلّب تغيير حجم SurfaceTexture في TextureView ضبط ملف شخصي مصفوفة التحويل باستخدام TextureView#setTransform().

بعد عرض نسبة العرض إلى الارتفاع الصحيحة، يتّبع كلا التنفيذَين النمط نفسه. عندما تنشئ SurfaceView/TextureView مساحة العرض، يُفعِّل رمز التطبيق إمكانية التشغيل. عندما ينقر المستخدم على تشغيل، يبدأ سلسلة مهام لفك ترميز الفيديو، مع استخدام المساحة كهدف للإخراج. بعد ذلك، لا ينفِّذ رمز التطبيق أيّ إجراء، إذ يتم التعامل مع عملية التركيب والعرض من خلال SurfaceFlinger (لعرض SurfaceView) أو من خلال TextureView.

دراسة حالة: فك التشفير المزدوج في Grafika

يوضّح الترميز المزدوج في Grafika التلاعب بملف SurfaceTexture داخل TextureView.

يستخدم أسلوب "فك التشفير المزدوج" في Grafika زوجًا من عناصر TextureView لعرض فيديوهين يتم تشغيلهما جنبًا إلى جنب، ما يحاكي تطبيقًا لمكالمات الفيديو. وعندما يتغيّر اتجاه الشاشة ويتم إعادة تشغيل النشاط، لا تتوقف وحدات فك ترميز MediaCodec، ما يحاكي تشغيل بث فيديو في الوقت الفعلي. لتحسين الكفاءة، يجب أن يحافظ العميل على سطح العرض نشطًا. السطح هو معرّف لواجهة المنتج في BufferQueue في SurfaceTexture. بما أنّ TextureView يدير SurfaceTexture، يجب أن يحافظ العميل على SurfaceTexture نشطًا للحفاظ على Surface.

للحفاظ على SurfaceTexture، تحصل ميزة "فك التشفير المزدوج" في Grafika على إحالات إلى SurfaceTextures من عناصر TextureView وتحفظها في حقل ثابت. بعد ذلك، تُعيد ميزة "فك التشفير المزدوج" في Grafika false من TextureView.SurfaceTextureListener#onSurfaceTextureDestroyed() لمنع تدمير SurfaceTexture. بعد ذلك، يُرسِل TextureView ملف SurfaceTexture إلى onSurfaceTextureDestroyed() يمكنه الاحتفاظ به أثناء تغيير إعدادات النشاط، ويُرسِله العميل إلى TextureView الجديد من خلال setSurfaceTexture().

تدير سلاسل محادثات منفصلة كلّ وحدة فك ترميز فيديو. يُرسِل Mediaserver وحدات التخزين المؤقت مع الإخراج غير المشفَّر إلى SurfaceTextures، وهي مستخدِمو BufferQueue. تُجري عناصر TextureView عمليات التقديم والتنفيذ في سلسلة مهام واجهة المستخدم.

إنّ تنفيذ ميزة "فك التشفير المزدوج" من Grafika باستخدام SurfaceView أصعب من تنفيذها باستخدام TextureView لأنّ عناصر SurfaceView تُزيل مساحات العرض أثناء تغييرات الاتجاه. بالإضافة إلى ذلك، يؤدي استخدام عناصر SurfaceView إلى إضافة طبقتَين، ما ليس مثاليًا بسبب القيود المفروضة على عدد العناصر المتراكبة المتاحة على الجهاز.