نسيج السطح

SurfaceTexture عبارة عن مزيج من السطح وملمس OpenGL ES (GLES) . يتم استخدام مثيلات SurfaceTexture لتوفير الأسطح التي يتم إخراجها إلى مواد GLES.

يحتوي SurfaceTexture على مثيل BufferQueue الذي تعتبر التطبيقات المستهلك له. يقوم رد الاتصال onFrameAvailable() بإعلام التطبيقات عندما يقوم المنتج بوضع مخزن مؤقت جديد في قائمة الانتظار. بعد ذلك، تستدعي التطبيقات updateTexImage() ، الذي يحرر المخزن المؤقت المحتجز مسبقًا، ويحصل على المخزن المؤقت الجديد من قائمة الانتظار، ويقوم باستدعاءات EGL لجعل المخزن المؤقت متاحًا لـ GLES كنسيج خارجي.

قوام GLES الخارجي

تختلف أنسجة GLES الخارجية ( GL_TEXTURE_EXTERNAL_OES ) عن أنسجة GLES التقليدية ( GL_TEXTURE_2D ) بالطرق التالية:

  • تعرض الأنسجة الخارجية مضلعات منسقة مباشرةً من البيانات الواردة من BufferQueue .
  • يتم تكوين أجهزة عرض النسيج الخارجية بشكل مختلف عن أجهزة عرض نسيج GLES التقليدية.
  • لا يمكن للأنسجة الخارجية تنفيذ جميع أنشطة نسيج GLES التقليدية.

الميزة الرئيسية للأنسجة الخارجية هي قدرتها على العرض مباشرة من بيانات BufferQueue . تقوم مثيلات SurfaceTexture بتعيين إشارات استخدام المستهلك إلى GRALLOC_USAGE_HW_TEXTURE عندما تقوم بإنشاء مثيلات BufferQueue للأنسجة الخارجية للتأكد من إمكانية التعرف على البيانات الموجودة في المخزن المؤقت بواسطة GLES.

نظرًا لأن مثيلات SurfaceTexture تتفاعل مع سياق EGL، فيمكن للتطبيق استدعاء أساليبه فقط بينما يكون سياق EGL الذي يمتلك المادة موجودًا في مؤشر ترابط الاستدعاء. لمزيد من المعلومات، راجع وثائق فئة SurfaceTexture .

الطوابع الزمنية والتحولات

تتضمن مثيلات SurfaceTexture أسلوب getTimeStamp() ، الذي يسترد طابعًا زمنيًا، وأسلوب getTransformMatrix() ، الذي يسترد مصفوفة تحويل. يؤدي استدعاء updateTexImage() إلى تعيين الطابع الزمني ومصفوفة التحويل. يتضمن كل مخزن مؤقت يمرره BufferQueue معلمات تحويل وطابع زمني.

معلمات التحويل مفيدة لتحقيق الكفاءة. في بعض الحالات، قد تكون بيانات المصدر في الاتجاه غير الصحيح بالنسبة للمستهلك. بدلاً من تدوير البيانات قبل إرسالها إلى المستهلك، أرسل البيانات في اتجاهها مع تحويل يصححها. يمكن دمج مصفوفة التحويل مع تحويلات أخرى عند استخدام البيانات، مما يقلل من الحمل الزائد.

يعد الطابع الزمني مفيدًا للمصادر المؤقتة التي تعتمد على الوقت. على سبيل المثال، عندما يقوم setPreviewTexture() بتوصيل واجهة المنتج بمخرج الكاميرا، يمكن استخدام الإطارات من الكاميرا لإنشاء فيديو. يجب أن يكون لكل إطار طابع زمني للعرض التقديمي من وقت التقاط الإطار، وليس من وقت استلام التطبيق للإطار. يقوم رمز الكاميرا بتعيين الطابع الزمني المقدم مع المخزن المؤقت، مما يؤدي إلى سلسلة أكثر اتساقًا من الطوابع الزمنية.

دراسة الحالة: الالتقاط المستمر لـ Grafika

يتضمن الالتقاط المستمر لـ Grafika تسجيل الإطارات من كاميرا الجهاز وعرض تلك الإطارات على الشاشة. لتسجيل الإطارات، قم بإنشاء سطح باستخدام طريقة createInputSurface() الخاصة بفئة MediaCodec وتمرير السطح إلى الكاميرا. لعرض الإطارات، قم بإنشاء مثيل لـ SurfaceView وتمرير السطح إلى setPreviewDisplay() . لاحظ أن تسجيل الإطارات وعرضها في نفس الوقت يعد عملية أكثر تعقيدًا.

يعرض نشاط الالتقاط المستمر الفيديو من الكاميرا أثناء تسجيل الفيديو. في هذه الحالة، يتم كتابة الفيديو المشفر إلى مخزن مؤقت دائري في الذاكرة يمكن حفظه على القرص في أي وقت.

يتضمن هذا التدفق ثلاث قوائم انتظار مؤقتة:

  • App - يستخدم التطبيق مثيل SurfaceTexture لتلقي الإطارات من الكاميرا، وتحويلها إلى نسيج GLES خارجي.
  • SurfaceFlinger — يعلن التطبيق عن مثيل SurfaceView لعرض الإطارات.
  • MediaServer — قم بتكوين برنامج تشفير MediaCodec بسطح إدخال لإنشاء الفيديو.

في الشكل أدناه، تشير الأسهم إلى انتشار البيانات من الكاميرا. تكون مثيلات BufferQueue ملونة (المنتجون باللون الأزرق المخضر، والمستهلكون باللون الأخضر).

نشاط التقاط Grafika المستمر

الشكل 1. نشاط الالتقاط المستمر لـ Grafika

ينتقل فيديو H.264 المشفر إلى مخزن مؤقت دائري في ذاكرة الوصول العشوائي (RAM) أثناء عملية التطبيق. عندما يضغط المستخدم على زر الالتقاط، تقوم فئة MediaMuxer بكتابة الفيديو المشفر إلى ملف MP4 على القرص.

تتم معالجة جميع مثيلات BufferQueue باستخدام سياق EGL واحد في التطبيق أثناء تنفيذ عمليات GLES على مؤشر ترابط واجهة المستخدم. تتم معالجة البيانات المشفرة (إدارة المخزن المؤقت الدائري وكتابتها على القرص) في موضوع منفصل.

عند استخدام فئة SurfaceView ، يقوم رد الاتصال surfaceCreated() بإنشاء مثيلات EGLContext و EGLSurface للشاشة وبرنامج تشفير الفيديو. عند وصول إطار جديد، يقوم SurfaceTexture بتنفيذ أربعة أنشطة:
  1. يكتسب الإطار.
  2. يجعل الإطار متاحًا كنسيج GLES.
  3. يعرض الإطار باستخدام أوامر GLES.
  4. إعادة توجيه التحويل والطابع الزمني لكل مثيل لـ EGLSurface .

يقوم خيط التشفير بعد ذلك بسحب الإخراج المشفر من MediaCodec ويخزنه في الذاكرة.

تأمين تشغيل الفيديو الملمس

يدعم Android المعالجة اللاحقة لوحدة معالجة الرسومات (GPU) لمحتوى الفيديو المحمي. يتيح ذلك للتطبيقات استخدام وحدة معالجة الرسومات (GPU) لتأثيرات الفيديو المعقدة وغير الخطية (مثل الإعوجاج)، وتعيين محتوى الفيديو المحمي على مواد لاستخدامها في مشاهد الرسومات العامة (على سبيل المثال، باستخدام GLES)، والواقع الافتراضي (VR).

تشغيل آمن للفيديو

الشكل 2. تشغيل الفيديو بشكل آمن

يتم تمكين الدعم باستخدام الامتدادين التاليين:

  • ملحق EGL — ( EGL_EXT_protected_content ) يتيح إنشاء سياقات وأسطح GL محمية، والتي يمكن أن تعمل على المحتوى المحمي.
  • ملحق GLES — ( GL_EXT_protected_textures ) يتيح وضع علامات على الأنسجة باعتبارها محمية بحيث يمكن استخدامها كمرفقات نسيج مخزن الإطارات المؤقت.

يمكّن Android SurfaceTexture وACodec ( libstagefright.so ) من إرسال محتوى محمي حتى لو لم يكن سطح النافذة في قائمة الانتظار لـ SurfaceFlinger ويوفر سطح فيديو محميًا للاستخدام ضمن سياق محمي. يتم ذلك عن طريق تعيين بت المستهلك المحمي ( GRALLOC_USAGE_PROTECTED ) على الأسطح التي تم إنشاؤها في سياق محمي (تم التحقق منه بواسطة ACodec).

يضع تشغيل الفيديو الآمن الأساس لتطبيق إدارة الحقوق الرقمية (DRM) القوي في بيئة OpenGL ES. بدون تطبيق قوي لإدارة الحقوق الرقمية، مثل Widevine Level 1، لا يسمح العديد من موفري المحتوى بعرض المحتوى عالي القيمة الخاص بهم في بيئة OpenGL ES، مما يمنع حالات استخدام VR المهمة مثل مشاهدة المحتوى المحمي بموجب إدارة الحقوق الرقمية في الواقع الافتراضي.

يتضمن AOSP رمز إطار عمل لتشغيل الفيديو بشكل آمن. دعم برامج التشغيل متروك لمصنعي المعدات الأصلية. يجب على منفذي الأجهزة تنفيذ ملحقات EGL_EXT_protected_content و GL_EXT_protected_textures extensions . عند استخدام مكتبة برامج الترميز الخاصة بك (لاستبدال libstagefright )، لاحظ التغييرات في /frameworks/av/media/libstagefright/SurfaceUtils.cpp التي تسمح بإرسال المخازن المؤقتة المميزة بـ GRALLOC_USAGE_PROTECTED إلى ANativeWindow (حتى إذا لم يكن ANativeWindow في قائمة الانتظار مباشرة إلى مؤلف النافذة) طالما أن بتات استخدام المستهلك تحتوي على GRALLOC_USAGE_PROTECTED . للحصول على وثائق مفصلة حول تنفيذ الامتدادات، راجع سجلات Khronos ( EGL_EXT_protected_content و GL_EXT_protected_textures ).