SurfaceTexture
è una combinazione di una superficie e di una texture OpenGL ES (GLES). Le istanze SurfaceTexture
vengono utilizzate per fornire superfici da esportare nelle texture GLES.
SurfaceTexture
contiene un'istanza di BufferQueue
per cui
le app sono il consumatore. Il callback onFrameAvailable()
avvisa le app quando il produttore mette in coda un nuovo buffer. Successivamente, le app chiamano
updateTexImage()
, che rilascia il buffer precedentemente trattenuto,
acquisisce il nuovo buffer dalla coda ed effettua chiamate EGL per rendere il buffer disponibile per GLES come texture esterna.
Texture GLES esterne
Le texture GLES esterne (GL_TEXTURE_EXTERNAL_OES
) differiscono
dalle texture GLES tradizionali (GL_TEXTURE_2D
) nei seguenti modi:
- Le texture esterne rendono i poligoni con texture direttamente dai dati ricevuti da
BufferQueue
. - I renderer delle texture esterni sono configurati in modo diverso rispetto ai tradizionali renderer delle texture GLES.
- Le texture esterne non possono eseguire tutte le attività tradizionali delle texture GLES.
Il vantaggio principale delle texture esterne è la loro capacità di eseguire il rendering direttamente dai dati BufferQueue
. SurfaceTexture
le istanze impostano i flag di utilizzo dei consumatori su GRALLOC_USAGE_HW_TEXTURE
quando creano
BufferQueue
istanze per le texture esterne per garantire che i dati nel buffer siano
riconoscibili da GLES.
Poiché le istanze SurfaceTexture
interagiscono con un contesto EGL, un'app può chiamare i suoi metodi solo quando il contesto EGL proprietario della trama è corrente nel thread di chiamata. Per ulteriori informazioni, consulta la documentazione della classe SurfaceTexture
.
Timestamp e trasformazioni
Le istanze SurfaceTexture
includono il metodo getTimeStamp()
, che recupera un timestamp, e il metodo getTransformMatrix()
, che recupera una matrice di trasformazione. La chiamata a updateTexImage()
imposta sia il timestamp sia la matrice di trasformazione. Ogni buffer che
BufferQueue
passa include i parametri di trasformazione e un timestamp.
I parametri di trasformazione sono utili per l'efficienza. In alcuni casi, i dati dell'origine potrebbero essere nell'orientamento errato per il consumatore. Invece di ruotare i dati prima di inviarli al consumatore, inviali con il loro orientamento con una trasformazione che li corregge. La matrice di trasformazione può essere unita ad altre trasformazioni quando i dati vengono utilizzati, minimizzando il sovraccarico.
Il timestamp è utile per le origini buffer che dipendono dal tempo. Ad esempio, quando setPreviewTexture()
collega l'interfaccia del produttore all'uscita della videocamera, i frame della videocamera possono essere utilizzati per creare un video. Ogni frame deve avere un timestamp della presentazione dal momento in cui è stato acquisito, non dal momento in cui l'app lo ha ricevuto. Il codice della videocamera imposta il timestamp fornito con il buffer,
generando una serie di timestamp più coerente.
Case study: acquisizione continua di Grafika
L'acquisizione continua di Grafika prevede la registrazione di fotogrammi dalla fotocamera di un dispositivo e la loro visualizzazione sullo schermo.
Per registrare i frame, crea una superficie con il metodo createInputSurface()
della classe MediaCodec e passala alla videocamera. Per visualizzare i frame, crea un'istanza di SurfaceView
e passa la superficie a setPreviewDisplay()
. Tieni presente che registrare i frame e visualizzarli contemporaneamente è un processo più complesso.
L'attività di acquisizione continua mostra il video della videocamera durante la registrazione. In questo caso, il video codificato viene scritto in un buffer circolare in memoria che può essere salvato su disco in qualsiasi momento.
Questo flusso prevede tre code di buffer:
App
: l'app utilizza un'istanzaSurfaceTexture
per ricevere i frame dalla fotocamera, convertendoli in una texture GLES esterna.SurfaceFlinger
: l'app dichiara un'istanzaSurfaceView
per visualizzare i frame.MediaServer
: configura un codificatoreMediaCodec
con una superficie di input per creare il video.
Nella figura seguente, le frecce indicano la propagazione dei dati dalla videocamera.
Le istanze BufferQueue
sono a colori (i produttori sono verde acqua, i consumatori sono verdi).

Figura 1. Attività di acquisizione continua di Grafika
Il video codificato in H.264 viene inviato a un buffer circolare nella RAM nel processo dell'app.
Quando un utente preme il pulsante di acquisizione, la classe MediaMuxer
scrive il video codificato in un file MP4 su disco.
Tutte le istanze BufferQueue
vengono gestite con un unico contesto EGL nell'app, mentre le operazioni GLES vengono eseguite sul thread dell'interfaccia utente. La gestione dei dati codificati (gestione di un buffer circolare e scrittura su disco) viene eseguita su un thread separato.
SurfaceView
, il callback surfaceCreated()
crea le istanze EGLContext
e EGLSurface
per il display e il codificatore video. Quando arriva un nuovo frame, SurfaceTexture
esegue quattro attività:
- Acquisisce l'inquadratura.
- Rende il frame disponibile come texture GLES.
- Esegue il rendering del frame con i comandi GLES.
- Inoltra la trasformazione e il timestamp per ogni istanza di
EGLSurface
.
Il thread dell'encoder estrae quindi l'output codificato da MediaCodec
e lo memorizza.
Riproduzione video sicura delle texture
Android supporta il post-processing dei contenuti video protetti tramite GPU. In questo modo, le app possono utilizzare la GPU per effetti video complessi e non lineari (come le deformazioni), mappare i contenuti video protetti sulle texture per utilizzarli in scene grafiche generali (ad esempio utilizzando GLES) e nella realtà virtuale (VR).

Figura 2. Riproduzione video di texture sicura
Il supporto è abilitato utilizzando le due estensioni seguenti:
- Estensione EGL:
(
EGL_EXT_protected_content
) Consente la creazione di contesti e piattaforme GL protetti, che possono entrambi operare su contenuti protetti. - Estensione GLES:
(
GL_EXT_protected_textures
) Consente di contrassegnare le texture come protette in modo che possano essere utilizzate come framebuffer texture attachments.
Android consente a SurfaceTexture
e ACodec
(libstagefright.so
) di inviare contenuti protetti anche se
la superficie della finestra non è in coda per SurfaceFlinger
e fornisce una superficie video protetta da utilizzare in un contesto protetto. Per farlo, viene impostato il bit consumer protetto (GRALLOC_USAGE_PROTECTED
) sulle piattaforme create in un contesto protetto (verificato da ACodec).
La riproduzione video sicura delle texture getta le basi per un'implementazione solida del DRM nell'ambiente OpenGL ES. Senza un'implementazione DRM efficace, come Widevine Level 1, molti fornitori di contenuti non consentono il rendering dei loro contenuti di alto valore nell'ambiente OpenGL ES, impedendo importanti casi d'uso VR come la visione di contenuti protetti da DRM in VR.
AOSP include il codice del framework per la riproduzione video di texture sicura. Il supporto del driver è a carico degli OEM. Gli implementatori dei dispositivi devono implementare EGL_EXT_protected_content
e GL_EXT_protected_textures extensions
. Quando utilizzi la tua libreria di codec (per sostituire libstagefright
), tieni presente le modifiche in /frameworks/av/media/libstagefright/SurfaceUtils.cpp
che consentono di inviare i buffer contrassegnati con GRALLOC_USAGE_PROTECTED
a ANativeWindow
(anche se ANativeWindow
non mette in coda direttamente il compositore di finestre) purché i bit di utilizzo del consumatore contengano GRALLOC_USAGE_PROTECTED
. Per una documentazione dettagliata sull'implementazione delle estensioni, consulta i registry Khronos (EGL_EXT_protected_content
e GL_EXT_protected_textures
).