TextureView

Class TextureView adalah objek tampilan yang menggabungkan tampilan dengan SurfaceTexture.

Merender dengan OpenGL ES

Objek TextureView membungkus SurfaceTexture, merespons callback, dan mendapatkan buffer baru. Saat mendapatkan buffer baru, TextureView mengirimkan permintaan invalidasi tampilan dan menggambar menggunakan konten buffer terbaru sebagai sumber datanya, merender di mana pun dan bagaimana pun kondisi tampilan menunjukkannya.

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

Untuk mencegah jeda pertukaran buffer, BufferQueue selalu memerlukan buffer yang tersedia untuk penghapusan dari antrean. Untuk melakukannya, BufferQueue akan membuang konten buffer yang diperoleh sebelumnya saat buffer baru diantrekan. Hal ini juga memberikan batasan pada jumlah buffer minimum dan maksimum untuk mencegah konsumen menggunakan semua buffer sekaligus.

Memilih SurfaceView atau TextureView

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

TextureView memiliki penanganan alfa dan rotasi yang lebih baik daripada SurfaceView, tetapi SurfaceView memiliki keunggulan performa saat menggabungkan elemen UI yang disusun di atas video. Saat merender dengan SurfaceView, SurfaceView akan memberikan lapisan komposisi terpisah kepada klien. SurfaceFlinger menyusun lapisan terpisah sebagai overlay hardware jika didukung oleh perangkat. Saat merender dengan TextureView, toolkit UI 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 menggabungkan lapisan UI aplikasi dan semua lapisan lainnya, sehingga setiap piksel yang terlihat digabungkan dua kali.

Studi Kasus: Putar Video Grafika

Grafika's Play Video mencakup sepasang pemutar video, satu diimplementasikan dengan TextureView dan satu lagi diimplementasikan dengan SurfaceView. Bagian decoding video dari aktivitas mengirimkan frame dari MediaCodec ke permukaan untuk TextureView dan SurfaceView. Perbedaan terbesar antara implementasi adalah langkah-langkah yang diperlukan untuk menampilkan rasio aspek yang benar.

Menskalakan SurfaceView memerlukan implementasi FrameLayout kustom. WindowManager perlu mengirimkan posisi jendela baru dan nilai ukuran baru ke SurfaceFlinger. Menskalakan SurfaceTexture TextureView memerlukan konfigurasi matriks transformasi dengan TextureView#setTransform().

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

Studi Kasus: Double Decode Grafika

Grafika's Double Decode menunjukkan manipulasi SurfaceTexture di dalam TextureView.

Double Decode Grafika menggunakan sepasang objek TextureView untuk menampilkan dua video yang diputar secara berdampingan, yang menyimulasikan aplikasi konferensi video. Saat orientasi layar berubah dan aktivitas dimulai ulang, dekoder MediaCodec tidak berhenti, yang menyimulasikan pemutaran streaming video real-time. Untuk meningkatkan efisiensi, klien harus menjaga agar platform tetap aktif. Permukaan 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, Dekode Ganda 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().

Setiap dekoder video didorong oleh thread terpisah. Mediaserver mengirim buffer dengan output yang didekode ke SurfaceTexture, konsumen BufferQueue. Objek TextureView melakukan rendering dan dieksekusi di UI thread.

Menerapkan Dekode Ganda Grafika dengan SurfaceView lebih sulit daripada menerapkan dengan TextureView karena objek SurfaceView menghancurkan permukaan selama perubahan orientasi. Selain itu, penggunaan objek SurfaceView menambahkan dua lapisan, yang tidak ideal karena batasan jumlah overlay yang tersedia di hardware.