SurfaceTexture
adalah kombinasi dari permukaan dan tekstur OpenGL ES (GLES) . SurfaceTexture
digunakan untuk menyediakan permukaan yang menghasilkan tekstur GLES.
SurfaceTexture
berisi instance BufferQueue
yang aplikasinya merupakan konsumen. onFrameAvailable()
memberi tahu aplikasi saat produser mengantre buffer baru. Kemudian, aplikasi memanggil updateTexImage()
, yang melepaskan buffer yang ditahan sebelumnya, memperoleh buffer baru dari antrean, dan membuat panggilan EGL untuk membuat buffer tersedia untuk GLES sebagai tekstur eksternal.
Tekstur GLES eksternal
Tekstur GLES eksternal ( GL_TEXTURE_EXTERNAL_OES
) berbeda dari tekstur GLES tradisional ( GL_TEXTURE_2D
) dalam hal berikut:
- Tekstur eksternal membuat poligon bertekstur langsung dari data yang diterima dari
BufferQueue
. - Perender tekstur eksternal dikonfigurasi secara berbeda dari perender tekstur GLES tradisional.
- Tekstur eksternal tidak dapat melakukan semua aktivitas tekstur GLES tradisional.
Manfaat utama tekstur eksternal adalah kemampuannya untuk merender langsung dari data BufferQueue
. SurfaceTexture
menyetel flag penggunaan konsumen ke GRALLOC_USAGE_HW_TEXTURE
saat membuat BufferQueue
untuk tekstur eksternal guna memastikan bahwa data dalam buffer dapat dikenali oleh GLES.
Karena instans SurfaceTexture
berinteraksi dengan konteks EGL, aplikasi hanya dapat memanggil metodenya sementara konteks EGL yang memiliki tekstur saat ini ada di utas panggilan. Untuk informasi selengkapnya, lihat dokumentasi kelas SurfaceTexture
.
Stempel waktu dan transformasi
SurfaceTexture
menyertakan metode getTimeStamp()
, yang mengambil stempel waktu, dan metode getTransformMatrix()
, yang mengambil matriks transformasi. Memanggil updateTexImage()
menyetel stempel waktu dan matriks transformasi. Setiap buffer yang dilewati BufferQueue
menyertakan parameter transformasi dan stempel waktu.
Parameter transformasi berguna untuk efisiensi. Dalam beberapa kasus, data sumber mungkin berada dalam orientasi yang salah bagi konsumen. Alih-alih memutar data sebelum mengirimnya ke konsumen, kirim data dalam orientasinya dengan transformasi yang memperbaikinya. Matriks transformasi dapat digabungkan dengan transformasi lain ketika data digunakan, meminimalkan overhead.
Stempel waktu berguna untuk sumber buffer yang bergantung pada waktu. Misalnya, ketika setPreviewTexture()
menghubungkan antarmuka produser ke output kamera, bingkai dari kamera dapat digunakan untuk membuat video. Setiap bingkai harus memiliki stempel waktu presentasi dari saat bingkai diambil, bukan dari saat aplikasi menerima bingkai. Kode kamera menyetel stempel waktu yang disediakan dengan buffer, menghasilkan rangkaian stempel waktu yang lebih konsisten.
Studi kasus: Pengambilan gambar Grafika yang berkelanjutan
Pengambilan gambar terus-menerus Grafika melibatkan perekaman bingkai dari kamera perangkat dan menampilkan bingkai tersebut di layar. Untuk merekam bingkai, buat permukaan dengan metode createInputSurface createInputSurface()
kelas MediaCodec dan teruskan permukaan ke kamera. Untuk menampilkan bingkai, buat instance SurfaceView
dan teruskan permukaan ke setPreviewDisplay()
. Perhatikan bahwa merekam bingkai dan menampilkannya pada saat yang sama adalah proses yang lebih rumit.
Aktivitas pengambilan terus menerus menampilkan video dari kamera saat video sedang direkam. Dalam hal ini, video yang dikodekan ditulis ke buffer melingkar di memori yang dapat disimpan ke disk kapan saja.
Aliran ini melibatkan tiga antrian buffer:
-
App
— Aplikasi menggunakan instansSurfaceTexture
untuk menerima bingkai dari kamera, mengonversinya menjadi tekstur GLES eksternal. -
SurfaceFlinger
— Aplikasi mendeklarasikan instanceSurfaceView
untuk menampilkan frame. -
MediaServer
— Mengonfigurasi encoderMediaCodec
dengan permukaan input untuk membuat video.
Pada gambar di bawah, panah menunjukkan propagasi data dari kamera. BufferQueue
berwarna (produsen berwarna teal, konsumen berwarna hijau).
Video H.264 yang dikodekan masuk ke buffer melingkar di RAM dalam proses aplikasi. Saat pengguna menekan tombol ambil, kelas MediaMuxer
menulis video yang disandikan ke file MP4 di disk.
Semua BufferQueue
ditangani dengan konteks EGL tunggal di aplikasi sementara operasi GLES dilakukan di thread UI. Penanganan data yang dikodekan (mengelola buffer melingkar dan menulisnya ke disk) dilakukan pada utas terpisah.
SurfaceView
, callback surfaceCreated()
membuat EGLContext
dan EGLSurface
untuk tampilan dan encoder video. Saat bingkai baru tiba, SurfaceTexture
melakukan empat aktivitas:- Memperoleh bingkai.
- Membuat bingkai tersedia sebagai tekstur GLES.
- Merender frame dengan perintah GLES.
- Meneruskan transformasi dan stempel waktu untuk setiap instance
EGLSurface
.
Utas encoder kemudian menarik output yang disandikan dari MediaCodec
dan menyimpannya di memori.
Pemutaran video tekstur aman
Android mendukung pemrosesan pasca GPU dari konten video yang dilindungi. Hal ini memungkinkan aplikasi menggunakan GPU untuk efek video nonlinier yang kompleks (seperti warps), memetakan konten video yang dilindungi ke tekstur untuk digunakan dalam adegan grafis umum (misalnya, menggunakan GLES), dan virtual reality (VR).
Dukungan diaktifkan menggunakan dua ekstensi berikut:
- Ekstensi EGL — (
EGL_EXT_protected_content
) Memungkinkan pembuatan konteks dan permukaan GL yang dilindungi, yang keduanya dapat beroperasi pada konten yang dilindungi. - Ekstensi GLES — (
GL_EXT_protected_textures
) Mengaktifkan penandaan tekstur sebagai dilindungi sehingga dapat digunakan sebagai lampiran tekstur framebuffer.
Android mengaktifkan SurfaceTexture
dan ACodec ( libstagefright.so
) untuk mengirim konten yang dilindungi meskipun permukaan jendela tidak mengantre ke SurfaceFlinger
dan menyediakan permukaan video yang dilindungi untuk digunakan dalam konteks yang dilindungi. Ini dilakukan dengan menyetel bit konsumen yang dilindungi ( GRALLOC_USAGE_PROTECTED
) pada permukaan yang dibuat dalam konteks yang dilindungi (diverifikasi oleh ACodec).
Pemutaran video tekstur yang aman menetapkan dasar untuk implementasi DRM yang kuat di lingkungan OpenGL ES. Tanpa implementasi DRM yang kuat, seperti Widevine Level 1, banyak penyedia konten tidak mengizinkan rendering konten bernilai tinggi mereka di lingkungan OpenGL ES, mencegah kasus penggunaan VR penting seperti menonton konten yang dilindungi DRM di VR.
AOSP menyertakan kode kerangka kerja untuk pemutaran video tekstur yang aman. Dukungan driver terserah OEM. Pelaksana perangkat harus menerapkan ekstensi EGL_EXT_protected_content
dan GL_EXT_protected_textures extensions
. Saat menggunakan pustaka codec Anda sendiri (untuk menggantikan libstagefright
), perhatikan perubahan di /frameworks/av/media/libstagefright/SurfaceUtils.cpp
yang memungkinkan buffer yang ditandai dengan GRALLOC_USAGE_PROTECTED
untuk dikirim ke ANativeWindow
(bahkan jika ANativeWindow
tidak mengantre langsung ke window composer) selama bit penggunaan konsumen mengandung GRALLOC_USAGE_PROTECTED
. Untuk dokumentasi terperinci tentang penerapan ekstensi, lihat registri Khronos ( EGL_EXT_protected_content
, dan GL_EXT_protected_textures
).