SurfaceTexture

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

הלכידה הרציפה של Grafika כוללת הקלטת פריימים מהמצלמה של המכשיר והצגת הפריימים האלה על המסך. כדי להקליט פריימים, צריך ליצור משטח באמצעות השיטה createInputSurface() של המחלקה MediaCodec ולהעביר את המשטח למצלמה. כדי להציג פריימים, יוצרים מופע של SurfaceView ומעבירים את השטח אל setPreviewDisplay(). שימו לב שתהליך ההקלטה של פריימים והצגתם בו-זמנית הוא מורכב יותר.

בפעילות הקלטה רציפה מוצג סרטון מהמצלמה בזמן ההקלטה. במקרה הזה, הסרטון המקודד נכתב למאגר זמני בזיכרון, שאפשר לשמור בדיסק בכל שלב.

התהליך הזה כולל שלושה תורים של מאגרים:

  • App — האפליקציה משתמשת במופע SurfaceTexture כדי לקבל פריימים מהמצלמה, ולהמיר אותם לטקסטורה חיצונית של GLES.
  • SurfaceFlinger — האפליקציה מצהירה על מופע SurfaceView להצגת המסגרות.
  • MediaServer — מגדירים מקודד MediaCodec עם משטח קלט כדי ליצור את הסרטון.

באיור הבא, החצים מציינים את העברת הנתונים מהמצלמה. מוצגים BufferQueue מקרים, עם אינדיקטורים חזותיים שמבחינים בין יצרנים (תכלת) לבין צרכנים (ירוק).

פעילות של Grafika continuous
capture

איור 1. פעילות של Grafika ללכידה רציפה

סרטון בקידוד H.264 מועבר למאגר זמני מעגלי ב-RAM בתהליך של האפליקציה. כשמשתמש לוחץ על לחצן הצילום, המחלקה MediaMuxer כותבת את הסרטון המקודד לקובץ MP4 בדיסק.

כל המקרים של BufferQueue מטופלים באמצעות הקשר EGL יחיד באפליקציה, בזמן שפעולות GLES מבוצעות בשרשור ממשק המשתמש. הטיפול בנתונים מקודדים (ניהול של מאגר זמני מעגלי וכתיבה שלו לדיסק) מתבצע בשרשור נפרד.

כשמשתמשים במחלקה SurfaceView, פונקציית הקריאה החוזרת surfaceCreated() יוצרת את המופעים EGLContext ו-EGLSurface של המקודד של התצוגה ושל הסרטון. כשמגיע פריים חדש,‏ SurfaceTexture מבצע ארבע פעולות:

  1. המסגרת נרכשת.
  2. הופך את הפריים לזמין כטקסטורה של GLES.
  3. המסגרת מוצגת באמצעות פקודות GLES.
  4. מעביר את הטרנספורמציה ואת חותמת הזמן לכל מופע של EGLSurface.

אחר כך, השרשור של המקודד שולף את הפלט המקודד מ-MediaCodec ומאחסן אותו בזיכרון.

הפעלה מאובטחת של סרטונים עם טקסטורה

מערכת Android תומכת בעיבוד שלאחר ההפקה (post-processing) של תוכן וידאו מוגן באמצעות GPU. האפשרות הזו מאפשרת לאפליקציות להשתמש במעבד הגרפי לאפקטים מורכבים ולא לינאריים של וידאו (כמו עיוותים), למיפוי של תוכן וידאו מוגן על גבי טקסטורות לשימוש בסצנות גרפיות כלליות (לדוגמה, באמצעות GLES) ובמציאות מדומה (VR).

הפעלה מאובטחת של סרטונים עם טקסטורה

איור 2. הפעלה מאובטחת של סרטונים עם טקסטורה

התמיכה מופעלת באמצעות שני התוספים הבאים:

  • תוסף EGL — (EGL_EXT_protected_content) מאפשר ליצור הקשרים ומשטחים מוגנים של GL, ששניהם יכולים לפעול על תוכן מוגן.
  • GLES extension — (GL_EXT_protected_textures) מאפשר לתייג טקסטורות כמוגנות כדי שאפשר יהיה להשתמש בהן כקבצים מצורפים של טקסטורות של מאגר מסגרות.

‫Android מאפשרת ל-SurfaceTexture ול-ACodec (libstagefright.so) לשלוח תוכן מוגן גם אם פני השטח של החלון לא מתווספים לתור של SurfaceFlinger, ומספקת פני שטח מוגנים של וידאו לשימוש בהקשר מוגן. הפעולה הזו מתבצעת על ידי הגדרת הביט של הצרכן המוגן (GRALLOC_USAGE_PROTECTED) בממשקים שנוצרו בהקשר מוגן (מאומת על ידי ACodec).

ההפעלה המאובטחת של סרטוני טקסטורה מהווה בסיס ליישום חזק של ניהול זכויות דיגיטלי (DRM) בסביבת OpenGL ES. בלי הטמעה חזקה של DRM, כמו Widevine Level 1, הרבה ספקי תוכן לא מאפשרים עיבוד של התוכן בעל הערך הגבוה שלהם בסביבת OpenGL ES, מה שמונע תרחישי שימוש חשובים ב-VR, כמו צפייה בתוכן שמוגן באמצעות DRM ב-VR.

פרויקט הקוד הפתוח של Android‏ (AOSP) כולל קוד של מסגרת להפעלה מאובטחת של סרטונים עם טקסטורה. התמיכה במנהלי התקנים היא באחריות יצרני הציוד המקורי (OEM). מפתחים שמטמיעים את המכשיר צריכים להטמיע את התוספים EGL_EXT_protected_content ו-GL_EXT_protected_textures. כשמשתמשים בספריית קודקים משלכם (כדי להחליף את libstagefright), חשוב לשים לב לשינויים ב-/frameworks/av/media/libstagefright/SurfaceUtils.cpp שמאפשרים לשלוח מאגרי נתונים זמניים שמסומנים ב-GRALLOC_USAGE_PROTECTED אל ANativeWindow (גם אם ANativeWindow לא מוסיף אותם ישירות לתור של מנהל החלונות), כל עוד הביטים של השימוש בצרכן מכילים GRALLOC_USAGE_PROTECTED. למסמכי תיעוד מפורטים על הטמעת התוספים, אפשר לעיין במאגרי המידע של Khronos‏ ( EGL_EXT_protected_content) ו- GL_EXT_protected_textures).