Tampilan Tekstur

Kelas TextureView adalah objek tampilan yang menggabungkan tampilan dengan SurfaceTexture.

Render dengan OpenGL ES

Objek TextureView membungkus SurfaceTexture, merespons callback dan memperoleh buffer baru. Saat TextureView memperoleh buffer baru, TextureView mengeluarkan permintaan pembatalan tampilan dan menggambar menggunakan konten buffer terbaru sebagai sumber datanya, merender di mana pun dan bagaimanapun status tampilan menunjukkannya.

OpenGL ES (GLES) dapat merender pada TextureView dengan meneruskan SurfaceTexture ke panggilan pembuatan EGL, tetapi ini menimbulkan masalah. Saat GLES dirender pada TextureView, produsen dan konsumen BufferQueue berada di utas yang sama, yang dapat menyebabkan panggilan swap buffer terhenti atau gagal. Misalnya, jika produser mengirimkan beberapa buffer secara berurutan dari thread UI, 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 hang atau gagal.

Untuk memastikan bahwa buffer swap tidak terhenti, BufferQueue selalu membutuhkan buffer yang tersedia untuk di-dequeued. Untuk mengimplementasikan ini, BufferQueue membuang isi buffer yang diperoleh sebelumnya ketika buffer baru sedang diantrekan dan membatasi jumlah buffer minimum dan maksimum untuk mencegah konsumen mengkonsumsi semua buffer sekaligus.

Memilih SurfaceView atau TextureView

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

TextureView memiliki penanganan alfa dan rotasi yang lebih baik daripada SurfaceView, tetapi SurfaceView memiliki keunggulan kinerja saat mengomposisi elemen UI berlapis di atas video. Saat klien merender dengan SurfaceView, SurfaceView menyediakan klien dengan lapisan komposisi terpisah. SurfaceFlinger menyusun lapisan terpisah sebagai overlay perangkat keras jika didukung oleh perangkat. Saat klien merender dengan TextureView, toolkit UI menggabungkan konten TextureView ke dalam hierarki tampilan dengan GPU. Pembaruan 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 dikomposisikan dua kali.

Studi Kasus: Video Putar Grafika

Video Putar Grafika menyertakan sepasang pemutar video, satu diimplementasikan dengan TextureView dan satu lagi diimplementasikan dengan SurfaceView. Bagian decoding video dari aktivitas mengirimkan bingkai dari MediaCodec ke permukaan untuk TextureView dan SurfaceView. Perbedaan terbesar antara implementasi adalah langkah-langkah yang diperlukan untuk menyajikan rasio aspek yang benar.

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

Setelah menyajikan rasio aspek yang benar, kedua implementasi mengikuti pola yang sama. Saat SurfaceView/TextureView membuat permukaan, kode aplikasi mengaktifkan pemutaran. Saat pengguna mengetuk putar , itu memulai utas dekode video, dengan permukaan sebagai target keluaran. Setelah itu, kode aplikasi tidak melakukan apa-apa—komposisi dan tampilan ditangani oleh SurfaceFlinger (untuk SurfaceView) atau oleh TextureView.

Studi Kasus: Dekode Ganda Grafika

Decode Ganda Grafika menunjukkan manipulasi SurfaceTexture di dalam TextureView.

Dekode Ganda Grafika menggunakan sepasang objek TextureView untuk menampilkan dua video yang diputar berdampingan, mensimulasikan aplikasi konferensi video. Saat orientasi layar berubah dan aktivitas dimulai ulang, dekoder MediaCodec tidak berhenti, mensimulasikan pemutaran aliran video waktu nyata. Untuk meningkatkan efisiensi, klien harus menjaga permukaan tetap hidup. Permukaan adalah pegangan untuk antarmuka produsen di BufferQueue SurfaceTexture. Karena TextureView mengelola SurfaceTexture, klien perlu menjaga SurfaceTexture tetap hidup agar permukaan tetap hidup.

Untuk menjaga SurfaceTexture tetap hidup, Decode Ganda Grafika memperoleh referensi ke SurfaceTextures dari objek TextureView dan menyimpannya dalam bidang statis. Kemudian, Dekode Ganda Grafika mengembalikan 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() .

Utas terpisah menggerakkan setiap dekoder video. Mediaserver mengirimkan buffer dengan output yang didekodekan ke SurfaceTextures, konsumen BufferQueue. Objek TextureView melakukan rendering dan eksekusi pada thread UI.

Menerapkan Decode Ganda Grafika dengan SurfaceView lebih sulit daripada menerapkan dengan TextureView karena objek SurfaceView menghancurkan permukaan selama perubahan orientasi. Selain itu, menggunakan objek SurfaceView menambahkan dua lapisan, yang tidak ideal karena keterbatasan jumlah overlay yang tersedia pada perangkat keras.