SurfaceTexture
הוא שילוב של משטח ומרקם OpenGL ES (GLES) . מופעי SurfaceTexture
משמשים כדי לספק משטחים שיוצאים למרקמי GLES.
SurfaceTexture
מכיל מופע של BufferQueue
שעבורו אפליקציות הן הצרכן. ה- onFrameAvailable()
callback מודיע לאפליקציות כאשר המפיק מעמיד בתור מאגר חדש. לאחר מכן, יישומים קוראים ל- 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 כולל הקלטת פריימים ממצלמה של מכשיר והצגת הפריימים האלה על המסך. כדי להקליט פריימים, צור משטח עם שיטת createInputSurface()
של מחלקה MediaCodec והעבירו את המשטח למצלמה. כדי להציג מסגרות, צור מופע של SurfaceView
והעביר את המשטח ל- setPreviewDisplay()
. שימו לב שהקלטת מסגרות והצגתן בו-זמנית היא תהליך מעורב יותר.
פעילות הלכידה הרציפה מציגה וידאו מהמצלמה תוך כדי הקלטת וידאו. במקרה זה, וידאו מקודד נכתב למאגר עגול בזיכרון שניתן לשמור בדיסק בכל עת.
זרימה זו כוללת שלושה תורי חיץ:
-
App
- האפליקציה משתמשת במופעSurfaceTexture
כדי לקבל פריימים מהמצלמה, וממירה אותם למרקם GLES חיצוני. -
SurfaceFlinger
- האפליקציה מכריזה על מופעSurfaceView
כדי להציג את הפריימים. -
MediaServer
- הגדר מקודדMediaCodec
עם משטח קלט ליצירת הווידאו.
באיור למטה, החצים מציינים את התפשטות הנתונים מהמצלמה. מופעי BufferQueue
הם בצבע (יצרנים הם צהבהבים, הצרכנים ירוקים).
וידאו מקודד H.264 עובר למאגר עגול ב-RAM בתהליך האפליקציה. כאשר משתמש לוחץ על לחצן הלכידה, מחלקת MediaMuxer
כותבת את הסרטון המקודד לקובץ MP4 בדיסק.
כל מופעי BufferQueue
מטופלים עם הקשר EGL יחיד באפליקציה בזמן שפעולות ה-GLES מבוצעות בשרשור ממשק המשתמש. הטיפול בנתונים מקודדים (ניהול מאגר מעגלי וכתיבתו לדיסק) נעשה על שרשור נפרד.
SurfaceView
, ה-callback surfaceCreated()
יוצר את המופעים EGLContext
ו- EGLSurface
עבור התצוגה ומקודד הווידאו. כאשר מגיעה מסגרת חדשה, SurfaceTexture
מבצעת ארבע פעילויות:- רוכש את המסגרת.
- הופך את המסגרת לזמינה כמרקם GLES.
- מעבד את המסגרת עם פקודות GLES.
- מעביר את ההמרה וחותמת הזמן עבור כל מופע של
EGLSurface
.
לאחר מכן חוט המקודד מושך את הפלט המקודד מ- MediaCodec
ומאחסן אותו בזיכרון.
השמעת וידאו במרקם מאובטח
אנדרואיד תומכת בעיבוד לאחר עיבוד גרפי של תוכן וידאו מוגן. זה מאפשר לאפליקציות להשתמש ב-GPU עבור אפקטים מורכבים ולא ליניאריים של וידאו (כגון עיוותים), מיפוי תוכן וידאו מוגן על טקסטורות לשימוש בסצנות גרפיות כלליות (לדוגמה, שימוש ב-GLES), ומציאות מדומה (VR).
התמיכה מופעלת באמצעות שתי ההרחבות הבאות:
- הרחבת EGL — (
EGL_EXT_protected_content
) מאפשרת יצירת הקשרים ומשטחים מוגנים של GL, שיכולים לפעול שניהם על תוכן מוגן. - תוסף GLES — (
GL_EXT_protected_textures
) מאפשר תיוג מרקמים כמוגנים כך שניתן להשתמש בהם כקבצים מצורפים של טקסטורת מסגרת מאיץ.
אנדרואיד מאפשר SurfaceTexture
ו-ACodec ( libstagefright.so
) לשלוח תוכן מוגן גם אם משטח החלון אינו עומד בתור ל- SurfaceFlinger
ומספק משטח וידאו מוגן לשימוש בהקשר מוגן. זה נעשה על ידי הגדרת ביט הצרכן המוגן ( GRALLOC_USAGE_PROTECTED
) על משטחים שנוצרו בהקשר מוגן (אומת על ידי ACodec).
השמעת וידאו בטקסטורה מאובטחת מציבה את הבסיס ליישום DRM חזק בסביבת OpenGL ES. ללא יישום DRM חזק, כגון Widevine Level 1, ספקי תוכן רבים אינם מאפשרים עיבוד של התוכן בעל הערך הגבוה שלהם בסביבת OpenGL ES, ומונעים מקרי שימוש חשובים ב-VR כגון צפייה בתוכן מוגן DRM ב-VR.
AOSP כולל קוד מסגרת להפעלת וידאו במרקם מאובטח. תמיכת מנהלי התקנים היא עד יצרני OEM. מיישמי מכשירים חייבים ליישם GL_EXT_protected_textures extensions
EGL_EXT_protected_content
ו-GL_EXT_protected_textures . כאשר אתה משתמש בספריית ה-codec שלך (כדי להחליף libstagefright
), שים לב לשינויים ב- /frameworks/av/media/libstagefright/SurfaceUtils.cpp
av/media/libstagefright/SurfaceUtils.cpp המאפשרים שליחת מאגרים המסומנים ב- GRALLOC_USAGE_PROTECTED
אל ANativeWindow
(גם אם ANativeWindow
לא עומד בתור ישירות ל- יוצר חלון) כל עוד סיביות השימוש לצרכן מכילות GRALLOC_USAGE_PROTECTED
. לתיעוד מפורט על הטמעת ההרחבות, עיין ברישום של Khronos ( EGL_EXT_protected_content
ו- GL_EXT_protected_textures
).