TextureView

کلاس TextureView یک شیء نمایشی است که یک نما را با SurfaceTexture ترکیب می‌کند.

پرداخت با OpenGL ES

یک شیء TextureView SurfaceTexture را می‌پوشاند، به callbackها پاسخ می‌دهد و بافرهای جدیدی را دریافت می‌کند. وقتی شیء TextureView میان‌گیرهای جدیدی به‌دست می‌آورد، TextureView درخواست باطل کردن نما را صادر می‌کند و بااستفاده از محتوای جدیدترین میان‌گیر به‌عنوان منبع داده‌اش، هرجا و هرطور که وضعیت نما نشان می‌دهد باید رندر شود، رندر می‌کند.

‫OpenGL ES (GLES) می‌تواند با انتقال SurfaceTexture به فراخوانی ایجاد EGL، روی شیء TextureView رندر کند، اما این کار مشکل ایجاد می‌کند. وقتی GLES روی TextureView رندر می‌کند، تولیدکنندگان و مصرف‌کنندگان BufferQueue در یک رشته قرار دارند که می‌تواند باعث توقف یا ناموفق شدن فراخوانی تعویض میان‌گیر شود. برای مثال، اگر تولیدکننده‌ای چند میان‌گیر را به‌سرعت و پشت‌سرهم از رشته میانای کاربر ارسال کند، فراخوانی تعویض میان‌گیر EGL باید میان‌گیری را از BufferQueue از صف خارج کند. اما چون مصرف‌کننده و تولیدکننده در یک رشته هستند، هیچ میان‌گیری دردسترس نخواهد بود و فراخوانی تعویض متوقف می‌شود یا ناموفق می‌ماند.

برای جلوگیری از توقف تعویض میان‌گیر، BufferQueue همیشه به یک میان‌گیر دردسترس برای صف‌زدایی نیاز دارد. برای انجام این کار، وقتی بافر جدیدی در صف قرار می‌گیرد، BufferQueue محتوای بافر قبلاً به‌دست‌آمده را دور می‌اندازد. همچنین محدودیت‌هایی را بر حداقل و حداکثر تعداد بافرها اعمال می‌کند تا از مصرف همه بافرها توسط مصرف‌کننده به‌طور هم‌زمان جلوگیری کند.

‫SurfaceView یا TextureView را انتخاب کنید

SurfaceView و TextureView نقش‌های مشابهی را ایفا می‌کنند و هر دو از اعضای سلسله‌مراتب نما هستند. بااین‌حال، SurfaceView و TextureView پیاده‌سازی‌های متفاوتی دارند. شیء SurfaceView همان پارامترهای نماهای دیگر را می‌گیرد، اما محتوای SurfaceView هنگام ارائه شفاف است.

‫TextureView در مدیریت چرخش و آلفا بهتر از SurfaceView عمل می‌کند، اما SurfaceView هنگام ترکیب عناصر میانای کاربر لایه‌بندی‌شده روی ویدیوها مزایای عملکردی دارد. وقتی مشتری با شیء SurfaceView پرداز می‌کند، SurfaceView لایه ترکیب جداگانه‌ای به مشتری ارائه می‌دهد. ‫SurfaceFlinger لایه جداگانه را به‌عنوان رونهاد سخت‌افزاری ترکیب می‌کند، البته اگر دستگاه از آن پشتیبانی کند. وقتی کارخواهی با TextureView پردازش می‌کند، جعبه‌ابزار واسط کاربر محتوای شیء TextureView را با واحد پردازش گرافیکی در سلسله‌مراتب نما ترکیب می‌کند. به‌روزرسانی‌های محتوا ممکن است باعث شود عناصر نمای دیگر دوباره ترسیم شوند، برای مثال، اگر نماهای دیگر در بالای TextureView قرار گرفته باشند. پس‌از تکمیل پرداز نمای دید، SurfaceFlinger لایه رابط کاربری برنامه و همه لایه‌های دیگر را ترکیب می‌کند، به‌طوری‌که هر پیکسل نمایان دو بار ترکیب می‌شود.

مطالعه موردی: ویدیو پخش Grafika

پخش ویدیو Grafika شامل یک جفت پخش‌کننده ویدیو است، یکی با TextureView و دیگری با SurfaceView پیاده‌سازی شده است. بخش رمزگشایی ویدیو در فعالیت، فریم‌ها را از MediaCodec به سطحی برای TextureView و SurfaceView ارسال می‌کند. بزرگ‌ترین تفاوت بین پیاده‌سازی‌ها مراحل لازم برای ارائه نسبت ابعادی صحیح است.

برای مقیاس‌بندی SurfaceView باید FrameLayout به‌صورت سفارشی پیاده‌سازی شود. ‫WindowManager باید موقعیت پنجره جدید و مقادیر اندازه جدید را به SurfaceFlinger ارسال کند. برای مقیاس‌بندی کردن SurfaceTexture شیء TextureView باید ماتریس تبدیل با TextureView#setTransform() پیکربندی شود.

پس‌از ارائه نسبت ابعادی صحیح، هر دو پیاده‌سازی از الگوی یکسانی پیروی می‌کنند. وقتی SurfaceView یا TextureView سطح را ایجاد می‌کند، کد برنامه پخش را فعال می‌کند. وقتی کاربر روی پخش ضربه می‌زند، رشته‌ای برای رمزگشایی ویدیو شروع می‌شود و سطح به‌عنوان هدف برونداد درنظر گرفته می‌شود. پس‌از آن، کد برنامه هیچ کاری انجام نمی‌دهد—ترکیب‌بندی و نمایش توسط SurfaceFlinger (برای SurfaceView) یا توسط TextureView انجام می‌شود.

مطالعه موردی: «رمزگشایی دوگانه» Grafika

Grafika's Double Decode دستکاری SurfaceTexture را در TextureView نشان می‌دهد.

‫Grafika's Double Decode از یک جفت شیء TextureView برای نمایش دو ویدیو در کنار هم استفاده می‌کند و یک برنامه کنفرانس ویدیویی را شبیه‌سازی می‌کند. وقتی جهت صفحه تغییر می‌کند و فعالیت دوباره شروع می‌شود، رمزگشاهای MediaCodec متوقف نمی‌شوند و پخش یک جریان ویدیویی هم‌زمان را شبیه‌سازی می‌کنند. برای بهبود کارایی، کارخواه باید سطح را فعال نگه دارد. سطح یک دستگیره برای رابط تولیدکننده در BufferQueue مربوط به SurfaceTexture است. ازآنجایی‌که شیء TextureView ‫SurfaceTexture را مدیریت می‌کند، مشتری باید SurfaceTexture را فعال نگه دارد تا سطح را فعال نگه دارد.

برای زنده نگه داشتن SurfaceTexture، «رمزگشایی دوگانه» Grafika از اشیای TextureView مرجع‌هایی به SurfaceTexture دریافت می‌کند و آن‌ها را در یک فیلد ایستا ذخیره می‌کند. سپس، «رمزگشایی دوگانه» Grafika مقدار false را از TextureView.SurfaceTextureListener#onSurfaceTextureDestroyed() برمی‌گرداند تا از تخریب SurfaceTexture جلوگیری کند. سپس TextureView یک SurfaceTexture به onSurfaceTextureDestroyed() منتقل می‌کند که می‌تواند درطول تغییر پیکربندی فعالیت حفظ شود و مشتری آن را ازطریق setSurfaceTexture() به شیء جدید TextureView منتقل می‌کند.

رشته‌های جداگانه هر رمزگشای ویدیو را هدایت می‌کنند. ‫Mediaserver بافرهای دارای برونداد کدبندی‌شده را به SurfaceTextures، مصرف‌کنندگان BufferQueue، ارسال می‌کند. اشیاء TextureView رندرینگ را انجام می‌دهند و در رشته UI اجرا می‌شوند.

پیاده‌سازی «رمزگشایی دوگانه» Grafika با SurfaceView سخت‌تر از پیاده‌سازی با TextureView است زیرا اشیاء SurfaceView سطوح را درطول تغییرات جهت‌گیری ازبین می‌برند. علاوه‌براین، استفاده از اشیاء SurfaceView دو لایه اضافه می‌کند که به‌دلیل محدودیت‌های تعداد هم‌پوشانی‌های دردسترس در سخت‌افزار، ایده‌آل نیست.