SurfaceTexture

SurfaceTexture adalah kombinasi platform dan tekstur OpenGL ES (GLES). Instance SurfaceTexture digunakan untuk menyediakan platform yang menghasilkan output ke tekstur GLES.

SurfaceTexture berisi instance BufferQueue yang aplikasinya adalah konsumen. Callback onFrameAvailable() memberi tahu aplikasi saat produsen mengantrekan buffer baru. Kemudian, aplikasi memanggil updateTexImage(), yang melepaskan buffer yang sebelumnya disimpan, mendapatkan buffer baru dari antrean, dan melakukan panggilan EGL untuk membuat buffer tersedia untuk GLES sebagai tekstur eksternal.

Tekstur GLES eksternal

Tekstur GLES eksternal (GL_TEXTURE_EXTERNAL_OES) berbeda dengan tekstur GLES tradisional (GL_TEXTURE_2D) dengan cara berikut:

  • Tekstur eksternal merender poligon bertekstur langsung dari data yang diterima dari BufferQueue.
  • Perender tekstur eksternal dikonfigurasi secara berbeda dengan 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. Instance SurfaceTexture menetapkan flag penggunaan konsumen ke GRALLOC_USAGE_HW_TEXTURE saat membuat instance BufferQueue untuk tekstur eksternal guna memastikan bahwa data dalam buffering dapat dikenali oleh GLES.

Karena instance SurfaceTexture berinteraksi dengan konteks EGL, aplikasi hanya dapat memanggil metodenya saat konteks EGL yang memiliki tekstur saat ini berada di thread panggilan. Untuk informasi selengkapnya, lihat dokumentasi class SurfaceTexture.

Stempel waktu dan transformasi

Instance SurfaceTexture mencakup metode getTimeStamp(), yang mengambil stempel waktu, dan metode getTransformMatrix(), yang mengambil matriks transformasi. Memanggil updateTexImage() akan menetapkan stempel waktu dan matriks transformasi. Setiap buffering yang diteruskan BufferQueue menyertakan parameter transformasi dan stempel waktu.

Parameter transformasi berguna untuk efisiensi. Dalam beberapa kasus, data sumber mungkin memiliki orientasi yang salah untuk konsumen. Daripada memutar data sebelum mengirimkannya ke konsumen, kirim data dalam orientasinya dengan transformasi yang mengoreksinya. Matriks transformasi dapat digabungkan dengan transformasi lain saat data digunakan, sehingga meminimalkan overhead.

Stempel waktu berguna untuk sumber buffering yang bergantung pada waktu. Misalnya, saat setPreviewTexture() menghubungkan antarmuka produsen ke output kamera, frame dari kamera dapat digunakan untuk membuat video. Setiap frame harus memiliki stempel waktu presentasi sejak frame diambil, bukan sejak aplikasi menerima frame. Kode kamera menetapkan stempel waktu yang disediakan dengan buffering, sehingga menghasilkan serangkaian stempel waktu yang lebih konsisten.

Studi kasus: Perekaman berkelanjutan Grafika

Perekaman berkelanjutan Grafika melibatkan perekaman frame dari kamera perangkat dan menampilkan frame tersebut di layar. Untuk merekam frame, buat platform dengan metode createInputSurface() class MediaCodec dan teruskan platform ke kamera. Untuk menampilkan frame, buat instance SurfaceView dan teruskan platform ke setPreviewDisplay(). Perhatikan bahwa merekam frame dan menampilkannya secara bersamaan adalah proses yang lebih rumit.

Aktivitas perekaman berkelanjutan menampilkan video dari kamera saat video direkam. Dalam hal ini, video yang dienkode ditulis ke buffer melingkar dalam memori yang dapat disimpan ke disk kapan saja.

Alur ini melibatkan tiga antrean buffering:

  • App — Aplikasi menggunakan instance SurfaceTexture untuk menerima frame dari kamera, mengonversinya menjadi tekstur GLES eksternal.
  • SurfaceFlinger — Aplikasi mendeklarasikan instance SurfaceView untuk menampilkan frame.
  • MediaServer — Mengonfigurasi encoder MediaCodec dengan platform input untuk membuat video.

Pada gambar di bawah, panah menunjukkan penyebaran data dari kamera. Instance BufferQueue berwarna (produser berwarna hijau kebiruan, konsumen berwarna hijau).

Grafik aktivitas pengambilan berkelanjutan

Gambar 1. Aktivitas pengambilan berkelanjutan Grafika

Video H.264 yang dienkode akan masuk ke buffer melingkar di RAM dalam proses aplikasi. Saat pengguna menekan tombol rekam, class MediaMuxer akan menulis video yang dienkode ke file MP4 di disk.

Semua instance BufferQueue ditangani dengan satu konteks EGL dalam aplikasi saat operasi GLES dilakukan pada thread UI. Penanganan data yang dienkode (mengelola buffer melingkar dan menulisnya ke disk) dilakukan di thread terpisah.

Saat menggunakan class SurfaceView, callback surfaceCreated() akan membuat instance EGLContext dan EGLSurface untuk encoder layar dan video. Saat frame baru tiba, SurfaceTexture akan melakukan empat aktivitas:
  1. Mendapatkan frame.
  2. Membuat frame tersedia sebagai tekstur GLES.
  3. Merender frame dengan perintah GLES.
  4. Meneruskan transformasi dan stempel waktu untuk setiap instance EGLSurface.

Thread encoder kemudian mengambil output yang dienkode dari MediaCodec dan menyimpannya dalam memori.

Pemutaran video tekstur yang aman

Android mendukung pascapemrosesan GPU untuk konten video yang dilindungi. Hal ini memungkinkan aplikasi menggunakan GPU untuk efek video non-linear yang kompleks (seperti warp), memetakan konten video yang dilindungi ke tekstur untuk digunakan dalam tampilan grafis umum (misalnya, menggunakan GLES), dan virtual reality (VR).

Pemutaran Video Tekstur yang Aman

Gambar 2. Pemutaran video tekstur yang aman

Dukungan diaktifkan menggunakan dua ekstensi berikut:

  • Ekstensi EGL — (EGL_EXT_protected_content) Memungkinkan pembuatan konteks dan platform GL yang dilindungi, yang dapat beroperasi pada konten yang dilindungi.
  • Ekstensi GLES — (GL_EXT_protected_textures) Memungkinkan pemberian tag pada tekstur sebagai dilindungi sehingga dapat digunakan sebagai lampiran tekstur framebuffer.

Android memungkinkan SurfaceTexture dan ACodec (libstagefright.so) mengirim konten yang dilindungi meskipun permukaan jendela tidak mengantre ke SurfaceFlinger dan menyediakan platform video yang dilindungi untuk digunakan dalam konteks yang dilindungi. Tindakan ini dilakukan dengan menetapkan bit konsumen yang dilindungi (GRALLOC_USAGE_PROTECTED) pada platform yang dibuat dalam konteks yang dilindungi (diverifikasi oleh ACodec).

Pemutaran video tekstur yang aman menetapkan fondasi 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, sehingga mencegah kasus penggunaan VR yang penting seperti menonton konten yang dilindungi DRM di VR.

AOSP menyertakan kode framework untuk pemutaran video tekstur yang aman. Dukungan driver bergantung pada OEM. Implementator perangkat harus mengimplementasikan EGL_EXT_protected_content dan GL_EXT_protected_textures extensions. Saat menggunakan library codec Anda sendiri (untuk mengganti libstagefright), perhatikan perubahan dalam /frameworks/av/media/libstagefright/SurfaceUtils.cpp yang memungkinkan buffer yang ditandai dengan GRALLOC_USAGE_PROTECTED dikirim ke ANativeWindow (meskipun ANativeWindow tidak mengantre langsung ke composer jendela) selama bit penggunaan konsumen berisi GRALLOC_USAGE_PROTECTED. Untuk dokumentasi mendetail tentang cara menerapkan ekstensi, lihat registry Khronos (EGL_EXT_protected_content, dan GL_EXT_protected_textures).