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
ملونة (المنتجون باللون الأزرق المخضر، والمستهلكون باللون الأخضر).
ينتقل فيديو H.264 المشفر إلى مخزن مؤقت دائري في ذاكرة الوصول العشوائي (RAM) أثناء عملية التطبيق. عندما يضغط المستخدم على زر الالتقاط، تقوم فئة MediaMuxer
بكتابة الفيديو المشفر إلى ملف MP4 على القرص.
تتم معالجة جميع مثيلات BufferQueue
باستخدام سياق EGL واحد في التطبيق أثناء تنفيذ عمليات GLES على مؤشر ترابط واجهة المستخدم. تتم معالجة البيانات المشفرة (إدارة المخزن المؤقت الدائري وكتابتها على القرص) في موضوع منفصل.
SurfaceView
، يقوم رد الاتصال surfaceCreated()
بإنشاء مثيلات EGLContext
و EGLSurface
للشاشة وبرنامج تشفير الفيديو. عند وصول إطار جديد، يقوم SurfaceTexture
بتنفيذ أربعة أنشطة:- يكتسب الإطار.
- يجعل الإطار متاحًا كنسيج GLES.
- يعرض الإطار باستخدام أوامر GLES.
- إعادة توجيه التحويل والطابع الزمني لكل مثيل لـ
EGLSurface
.
يقوم خيط التشفير بعد ذلك بسحب الإخراج المشفر من MediaCodec
ويخزنه في الذاكرة.
تأمين تشغيل الفيديو الملمس
يدعم Android المعالجة اللاحقة لوحدة معالجة الرسومات (GPU) لمحتوى الفيديو المحمي. يتيح ذلك للتطبيقات استخدام وحدة معالجة الرسومات (GPU) لتأثيرات الفيديو المعقدة وغير الخطية (مثل الإعوجاج)، وتعيين محتوى الفيديو المحمي على مواد لاستخدامها في مشاهد الرسومات العامة (على سبيل المثال، باستخدام GLES)، والواقع الافتراضي (VR).
يتم تمكين الدعم باستخدام الامتدادين التاليين:
- ملحق 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
).