SurfaceTexture ترکیبی از یک سطح و یک بافت OpenGL ES (GLES) است.
از SurfaceTexture نمونه برای ارائه سطوحی که به بافتهای GLES بروند استفاده میشود.
SurfaceTexture حاوی نمونهای از BufferQueue است
که برنامهها مصرفکننده آن هستند. وقتی تولیدکننده میانگیر جدیدی را در صف قرار میدهد،
onFrameAvailable() callback به برنامهها اطلاع میدهد. سپس، برنامهها updateTexImage() را فرا میخوانند که بافر قبلی را آزاد میکند، بافر جدید را از صف دریافت میکند، و برای دردسترس قرار دادن بافر برای GLES بهعنوان بافت خارجی، فراخوانیهای EGL انجام میدهد.
بافتهای خارجی 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
ویدیو H.264 کدبندیشده به یک بافر حلقوی در RAM در فرایند برنامه میرود.
وقتی کاربر دکمه ضبط را فشار میدهد، کلاس MediaMuxer ویدیو کدبندیشده را در فایل MP4 روی دیسک مینویسد.
همه نمونههای BufferQueue با یک بافت EGL در برنامه مدیریت میشوند،
درحالیکه عملیات GLES در رشته میانای کاربر انجام میشود. مدیریت دادههای کدبندیشده (مدیریت بافر حلقوی و نوشتن آن روی دیسک) در رشتهای جداگانه انجام میشود.
هنگام استفاده از کلاس SurfaceView،
surfaceCreated() تابع برگشتی نمونههای EGLContext و EGLSurface
را برای نمایشگر و کدبند ویدیو ایجاد میکند. وقتی قاب جدیدی میرسد،
SurfaceTexture چهار فعالیت انجام میدهد:
- قاب را بهدست میآورد.
- قاب را بهعنوان بافت GLES دردسترس قرار میدهد.
- قاب را با فرمانهای GLES پرداز میکند.
- تبدیل و مُهر زمان را برای هر نمونه از
EGLSurfaceبازارسال میکند.
سپس رشته کدبند خروجی کدبندیشده را از MediaCodec
میکشد و آن را در حافظه ذخیره میکند.
بازپخش ویدیو بافت ایمن
Android از پسپردازش واحد پردازش گرافیکی محتوای ویدیویی محافظتشده پشتیبانی میکند. این کار به برنامهها اجازه میدهد از 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 جلوگیری میکند.
«پروژه منبع باز Android» (AOSP) شامل کد چارچوب برای بازپخش ویدیو با بافت امن است. پشتیبانی از درایور برعهده سازندگان اصلی محصول است. پیادهسازان دستگاه باید
افزونههای 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) مراجعه کنید.