SurfaceTexture
adalah kombinasi permukaan dan tekstur OpenGL ES (GLES) . Instance SurfaceTexture
digunakan untuk menyediakan permukaan yang menghasilkan tekstur GLES.
SurfaceTexture
berisi instance BufferQueue
yang aplikasinya adalah konsumennya. Callback onFrameAvailable()
memberi tahu aplikasi saat produsen mengantri buffer baru. Kemudian, aplikasi memanggil updateTexImage()
, yang melepaskan buffer yang disimpan sebelumnya, mengambil buffer baru dari antrean, dan melakukan panggilan EGL agar buffer tersebut tersedia bagi 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 merender poligon bertekstur langsung dari data yang diterima dari
BufferQueue
. - Perender tekstur eksternal dikonfigurasi secara berbeda dibandingkan 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
. Instans SurfaceTexture
menyetel tanda penggunaan konsumen ke GRALLOC_USAGE_HW_TEXTURE
saat membuat instance BufferQueue
untuk tekstur eksternal guna memastikan bahwa data dalam buffer dapat dikenali oleh GLES.
Karena instance SurfaceTexture
berinteraksi dengan konteks EGL, aplikasi hanya dapat memanggil metodenya saat konteks EGL yang memiliki tekstur tersebut ada di thread pemanggil. Untuk informasi selengkapnya lihat dokumentasi kelas SurfaceTexture
.
Stempel waktu dan transformasi
Instance SurfaceTexture
mencakup 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, sumber data mungkin berada pada orientasi yang salah bagi konsumen. Daripada memutar data sebelum mengirimkannya ke konsumen, kirimkan data sesuai orientasinya dengan transformasi yang memperbaikinya. Matriks transformasi dapat digabungkan dengan transformasi lain saat data digunakan, sehingga 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 frame harus memiliki stempel waktu presentasi sejak frame diambil, bukan sejak aplikasi menerima frame. Kode kamera menyetel stempel waktu yang disediakan bersama buffer, sehingga menghasilkan rangkaian stempel waktu yang lebih konsisten.
Studi kasus: Pengambilan gambar secara terus-menerus di Grafika
Pengambilan berkelanjutan Grafika melibatkan perekaman bingkai dari kamera perangkat dan menampilkan bingkai tersebut di layar. Untuk merekam bingkai, buat permukaan dengan metode createInputSurface()
kelas MediaCodec dan teruskan permukaan tersebut ke kamera. Untuk menampilkan bingkai, buat instance SurfaceView
dan teruskan permukaannya ke setPreviewDisplay()
. Perhatikan bahwa merekam bingkai dan menampilkannya pada saat yang sama merupakan proses yang lebih rumit.
Aktivitas pengambilan berkelanjutan 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 instanceSurfaceTexture
untuk menerima bingkai dari kamera, mengubahnya menjadi tekstur GLES eksternal. -
SurfaceFlinger
— Aplikasi mendeklarasikan instanceSurfaceView
untuk menampilkan bingkai. -
MediaServer
— Konfigurasikan encoderMediaCodec
dengan permukaan input untuk membuat video.
Pada gambar di bawah, panah menunjukkan propagasi data dari kamera. Instance 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 instance BufferQueue
ditangani dengan satu konteks EGL di aplikasi sementara operasi GLES dilakukan di thread UI. Penanganan data yang dikodekan (mengelola buffer melingkar dan menulisnya ke disk) dilakukan pada thread terpisah.
SurfaceView
, callback surfaceCreated()
membuat instance EGLContext
dan EGLSurface
untuk tampilan dan encoder video. Saat frame baru tiba, SurfaceTexture
melakukan empat aktivitas:- Mengakuisisi bingkai.
- Menjadikan bingkai tersedia sebagai tekstur GLES.
- Merender bingkai dengan perintah GLES.
- Meneruskan transformasi dan stempel waktu untuk setiap instance
EGLSurface
.
Thread encoder kemudian menarik output yang dikodekan dari MediaCodec
dan menyimpannya di memori.
Pemutaran video tekstur yang aman
Android mendukung pasca-pemrosesan GPU untuk konten video yang dilindungi. Hal ini memungkinkan aplikasi menggunakan GPU untuk efek video nonlinier yang kompleks (seperti warp), 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 mengantri ke SurfaceFlinger
dan menyediakan permukaan video yang dilindungi untuk digunakan dalam konteks yang dilindungi. Hal ini dilakukan dengan mengatur bit konsumen yang dilindungi ( GRALLOC_USAGE_PROTECTED
) pada permukaan yang dibuat dalam konteks terlindungi (diverifikasi oleh ACodec).
Pemutaran video tekstur yang aman menetapkan landasan bagi penerapan DRM yang kuat di lingkungan OpenGL ES. Tanpa penerapan DRM yang kuat, seperti Widevine Level 1, banyak penyedia konten tidak mengizinkan rendering konten bernilai tinggi mereka di lingkungan OpenGL ES, sehingga mencegah kasus penggunaan VR yang 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 GL_EXT_protected_textures extensions
EGL_EXT_protected_content
dan GL_EXT_protected_textures . Saat menggunakan pustaka codec Anda sendiri (untuk menggantikan libstagefright
), perhatikan perubahan di /frameworks/av/media/libstagefright/SurfaceUtils.cpp
yang memungkinkan buffer bertanda GRALLOC_USAGE_PROTECTED
dikirim ke ANativeWindow
(walaupun ANativeWindow
tidak mengantri langsung ke window composer) selama bit penggunaan konsumen mengandung GRALLOC_USAGE_PROTECTED
. Untuk dokumentasi mendetail tentang penerapan ekstensi, lihat registri Khronos ( EGL_EXT_protected_content
, dan GL_EXT_protected_textures
).