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
هنگام ایجاد نمونههای BufferQueue
برای بافتهای خارجی، پرچمهای استفاده مصرفکننده را روی GRALLOC_USAGE_HW_TEXTURE
تنظیم میکنند تا اطمینان حاصل شود که دادههای بافر توسط GLES قابل تشخیص هستند.
از آنجا که نمونههای SurfaceTexture
با یک زمینه EGL تعامل دارند، یک برنامه فقط میتواند متدهای خود را فراخوانی کند در حالی که زمینه EGL که دارای بافت است در رشته فراخوانی جاری است. برای اطلاعات بیشتر به مستندات کلاس SurfaceTexture
مراجعه کنید.
مهرهای زمانی و تحولات
نمونه های SurfaceTexture
شامل متد getTimeStamp()
است که یک timestamp را بازیابی می کند و متد 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 روی رشته UI انجام میشود. مدیریت داده های رمزگذاری شده (مدیریت یک بافر دایره ای و نوشتن آن بر روی دیسک) در یک رشته جداگانه انجام می شود.
SurfaceView
، callback surfaceCreated()
نمونه های EGLContext
و EGLSurface
را برای نمایشگر و رمزگذار ویدیو ایجاد می کند. هنگامی که یک فریم جدید وارد می شود، SurfaceTexture
چهار فعالیت را انجام می دهد:- قاب را بدست می آورد.
- قاب را به صورت بافت GLES در دسترس قرار می دهد.
- فریم را با دستورات GLES رندر می کند.
- تبدیل و مهر زمانی را برای هر نمونه از
EGLSurface
ارسال می کند.
سپس رشته رمزگذار خروجی کدگذاری شده را از MediaCodec
می کشد و آن را در حافظه پنهان می کند.
پخش ویدئوی بافت امن
اندروید از پردازش پس از پردازش گرافیکی محتوای ویدیویی محافظت شده پشتیبانی می کند. این به برنامهها اجازه میدهد از 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 قرار می دهد. بدون اجرای DRM قوی، مانند Widevine Level 1، بسیاری از ارائه دهندگان محتوا اجازه رندر محتوای با ارزش خود را در محیط OpenGL ES نمی دهند و از موارد مهم استفاده از VR مانند تماشای محتوای محافظت شده با DRM در VR جلوگیری می کنند.
AOSP شامل کد فریمورک برای پخش ویدئوی بافت امن است. پشتیبانی درایور تا OEM ها است. پیادهکنندههای دستگاه باید پسوندهای EGL_EXT_protected_content
و GL_EXT_protected_textures extensions
را پیادهسازی کنند. هنگام استفاده از کتابخانه کدک خود (برای جایگزینی libstagefright
)، به تغییرات /frameworks/av/media/libstagefright/SurfaceUtils.cpp
توجه کنید که اجازه می دهد بافرهای علامت گذاری شده با GRALLOC_USAGE_PROTECTED
به ANativeWindow
ارسال شوند (حتی اگر ANativeWindow
مستقیماً در صف قرار نگیرد). window composer) تا زمانی که بیت های مصرف کننده حاوی GRALLOC_USAGE_PROTECTED
باشند. برای مستندات دقیق در مورد اجرای برنامههای افزودنی، به رجیستریهای Khronos ( EGL_EXT_protected_content
و GL_EXT_protected_textures
) مراجعه کنید.