TextureView

Class TextureView adalah objek tampilan yang menggabungkan tampilan dengan SurfaceTexture.

Rendering dengan OpenGL ES

Objek TextureView menggabungkan SurfaceTexture, merespons callback, dan mendapatkan buffering baru. Saat TextureView memperoleh buffering baru, TextureView akan mengeluarkan permintaan pembatalan validasi tampilan dan menggambar menggunakan konten buffering terbaru sebagai sumber datanya, yang dirender di mana pun dan bagaimanapun status tampilan menunjukkannya.

OpenGL ES (GLES) dapat merender di TextureView dengan meneruskan SurfaceTexture ke panggilan pembuatan EGL, tetapi hal ini menimbulkan masalah. Saat GLES dirender di TextureView, produsen dan konsumen BufferQueue berada di thread yang sama, yang dapat menyebabkan panggilan swap buffer terhenti atau gagal. Misalnya, jika produser mengirimkan beberapa buffer secara berurutan dari UI thread, panggilan pertukaran buffer EGL perlu menghapus buffer dari BufferQueue. Namun, karena konsumen dan produsen berada di thread yang sama, tidak akan ada buffer yang tersedia dan panggilan swap akan berhenti berfungsi atau gagal.

Untuk memastikan bahwa pertukaran buffering tidak terhenti, BufferQueue selalu memerlukan buffer yang tersedia untuk dihapus dari antrean. Untuk menerapkannya, BufferQueue akan menghapus konten buffer yang diperoleh sebelumnya saat buffer baru diantrekan dan menetapkan batasan pada jumlah buffer minimum dan maksimum untuk mencegah konsumen menggunakan semua buffer sekaligus.

Memilih SurfaceView atau TextureView

SurfaceView dan TextureView mengisi peran yang serupa dan keduanya merupakan bagian dari hierarki tampilan. Namun, SurfaceView dan TextureView memiliki implementasi yang berbeda. SurfaceView menggunakan parameter yang sama dengan tampilan lainnya, tetapi konten SurfaceView transparan saat dirender.

TextureView memiliki penanganan alfa dan rotasi yang lebih baik daripada SurfaceView, tetapi SurfaceView memiliki keunggulan performa saat mengomposisi elemen UI yang dilapisi di atas video. Saat klien merender dengan SurfaceView, SurfaceView akan menyediakan lapisan komposisi terpisah untuk klien. SurfaceFlinger menyusun lapisan terpisah sebagai overlay hardware jika didukung oleh perangkat. Saat klien merender dengan TextureView, toolkit UI akan menggabungkan konten TextureView ke dalam hierarki tampilan dengan GPU. Pembaruan pada konten dapat menyebabkan elemen tampilan lain digambar ulang, misalnya, jika tampilan lain diposisikan di atas TextureView. Setelah rendering tampilan selesai, SurfaceFlinger akan menggabungkan lapisan UI aplikasi dan semua lapisan lainnya, sehingga setiap piksel yang terlihat digabungkan dua kali.

Studi Kasus: Video Play Grafika

Play Video Grafika menyertakan sepasang pemutar video, satu diimplementasikan dengan TextureView dan satu lagi diimplementasikan dengan SurfaceView. Bagian decoding video dari aktivitas mengirim frame dari MediaCodec ke platform untuk TextureView dan SurfaceView. Perbedaan terbesar antara penerapan adalah langkah-langkah yang diperlukan untuk menampilkan rasio aspek yang benar.

Penskalaan SurfaceView memerlukan implementasi FrameLayout kustom. WindowManager perlu mengirim posisi jendela baru dan nilai ukuran baru ke SurfaceFlinger. Untuk menskalakan SurfaceTexture TextureView, Anda harus mengonfigurasi matriks transformasi dengan TextureView#setTransform().

Setelah menampilkan rasio aspek yang benar, kedua implementasi mengikuti pola yang sama. Saat SurfaceView/TextureView membuat platform, kode aplikasi akan mengaktifkan pemutaran. Saat pengguna mengetuk putar, tindakan ini akan memulai thread decoding video, dengan platform sebagai target output. Setelah itu, kode aplikasi tidak melakukan apa pun—komposisi dan tampilan ditangani oleh SurfaceFlinger (untuk SurfaceView) atau oleh TextureView.

Studi Kasus: Dekode Ganda Grafika

Double Decode Grafika menunjukkan manipulasi SurfaceTexture di dalam TextureView.

Dekode Ganda Grafika menggunakan sepasang objek TextureView untuk menampilkan dua video yang diputar berdampingan, menyimulasikan aplikasi konferensi video. Saat orientasi layar berubah dan aktivitas dimulai ulang, dekoder MediaCodec tidak berhenti, menyimulasikan pemutaran streaming video real-time. Untuk meningkatkan efisiensi, klien harus menjaga agar platform tetap aktif. Platform adalah handle ke antarmuka produsen di BufferQueue SurfaceTexture. Karena TextureView mengelola SurfaceTexture, klien harus menjaga SurfaceTexture tetap aktif agar permukaan tetap aktif.

Agar SurfaceTexture tetap aktif, Double Decode Grafika mendapatkan referensi ke SurfaceTexture dari objek TextureView dan menyimpannya di kolom statis. Kemudian, Double Decode Grafika menampilkan false dari TextureView.SurfaceTextureListener#onSurfaceTextureDestroyed() untuk mencegah penghancuran SurfaceTexture. TextureView kemudian meneruskan SurfaceTexture ke onSurfaceTextureDestroyed() yang dapat dipertahankan di seluruh perubahan konfigurasi aktivitas, yang diteruskan klien ke TextureView baru melalui setSurfaceTexture().

Thread terpisah mendorong setiap decoder video. Mediaserver mengirim buffering dengan output yang didekode ke SurfaceTextures, konsumen BufferQueue. Objek TextureView melakukan rendering dan dieksekusi di UI thread.

Mengimplementasikan Double Decode Grafika dengan SurfaceView lebih sulit daripada mengimplementasikan dengan TextureView karena objek SurfaceView menghancurkan platform selama perubahan orientasi. Selain itu, penggunaan objek SurfaceView akan menambahkan dua lapisan, yang tidak ideal karena batasan jumlah overlay yang tersedia di hardware.