SurfaceTexture

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 رنگی هستند (تولیدکنندگان سبز رنگ هستند، مصرف‌کنندگان سبز هستند).

فعالیت ضبط مداوم Grafika

شکل 1. فعالیت ضبط مداوم Grafika

ویدیوی کدگذاری شده H.264 در فرآیند برنامه به یک بافر دایره ای در RAM می رود. هنگامی که کاربر دکمه ضبط را فشار می دهد، کلاس MediaMuxer ویدیوی کدگذاری شده را روی یک فایل MP4 روی دیسک می نویسد.

تمام نمونه‌های BufferQueue با یک زمینه EGL در برنامه مدیریت می‌شوند در حالی که عملیات GLES روی رشته UI انجام می‌شود. مدیریت داده های رمزگذاری شده (مدیریت یک بافر دایره ای و نوشتن آن بر روی دیسک) در یک رشته جداگانه انجام می شود.

هنگام استفاده از کلاس SurfaceView ، callback surfaceCreated() نمونه های EGLContext و EGLSurface را برای نمایشگر و رمزگذار ویدیو ایجاد می کند. هنگامی که یک فریم جدید وارد می شود، SurfaceTexture چهار فعالیت را انجام می دهد:
  1. قاب را بدست می آورد.
  2. قاب را به صورت بافت GLES در دسترس قرار می دهد.
  3. فریم را با دستورات GLES رندر می کند.
  4. تبدیل و مهر زمانی را برای هر نمونه از EGLSurface ارسال می کند.

سپس رشته رمزگذار خروجی کدگذاری شده را از MediaCodec می کشد و آن را در حافظه پنهان می کند.

پخش ویدئوی بافت امن

اندروید از پردازش پس از پردازش گرافیکی محتوای ویدیویی محافظت شده پشتیبانی می کند. این به برنامه‌ها اجازه می‌دهد از GPU برای جلوه‌های ویدیویی پیچیده و غیرخطی (مانند پیچ‌خوردگی)، نگاشت محتوای ویدیویی محافظت‌شده روی بافت‌ها برای استفاده در صحنه‌های گرافیکی عمومی (مثلاً استفاده از GLES) و واقعیت مجازی (VR) استفاده کنند.

پخش فیلم بافت امن

شکل 2. پخش ویدئوی بافت ایمن

پشتیبانی با استفاده از دو پسوند زیر فعال می شود:

  • پسوند 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 ) مراجعه کنید.