TampilanTekstur

Kelas TextureView adalah objek tampilan yang menggabungkan tampilan dengan SurfaceTexture.

Merender dengan OpenGL ES

Objek TextureView membungkus SurfaceTexture, merespons panggilan balik dan memperoleh buffer baru. Saat TextureView memperoleh buffer baru, TextureView mengeluarkan permintaan tampilan yang tidak valid dan menggambar menggunakan konten buffer terbaru sebagai sumber datanya, merender di mana pun dan bagaimanapun kondisi tampilan menunjukkan hal tersebut seharusnya.

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

Untuk memastikan bahwa buffer swap tidak terhenti, BufferQueue selalu membutuhkan buffer yang tersedia untuk di-dequeued. Untuk mengimplementasikan hal ini, BufferQueue membuang konten buffer yang diperoleh sebelumnya ketika buffer baru dimasukkan ke dalam antrian dan membatasi jumlah buffer minimum dan maksimum untuk mencegah konsumen menggunakan semua buffer sekaligus.

Memilih SurfaceView atau TextureView

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

TextureView memiliki penanganan alfa dan rotasi yang lebih baik daripada SurfaceView, namun SurfaceView memiliki keunggulan kinerja saat menyusun elemen UI yang dilapisi video. Saat klien merender dengan SurfaceView, SurfaceView menyediakan lapisan komposisi terpisah kepada klien. 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 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: Video Putar Grafika

Putar Video Grafika mencakup 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 penerapannya adalah langkah-langkah yang diperlukan untuk menyajikan rasio aspek yang benar.

Penskalaan SurfaceView memerlukan implementasi khusus FrameLayout. WindowManager perlu mengirimkan posisi jendela baru dan nilai ukuran baru ke SurfaceFlinger. Penskalaan SurfaceTexture 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 , rangkaian decoding video akan dimulai, dengan permukaan sebagai target keluaran. Setelah itu, kode aplikasi tidak melakukan apa pun—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, menyimulasikan aplikasi konferensi video. Saat orientasi layar berubah dan aktivitas dimulai ulang, decoder MediaCodec tidak berhenti, menyimulasikan pemutaran streaming video real-time. 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.

Agar SurfaceTexture tetap hidup, Dekode 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 selama perubahan konfigurasi aktivitas, yang diteruskan klien ke TextureView baru melalui setSurfaceTexture() .

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

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