SurfaceTexture
es una combinación de una superficie y una textura de OpenGL ES (GLES).
Las instancias de SurfaceTexture
se usan para proporcionar superficies que generan texturas de GLES.
SurfaceTexture
contiene una instancia de BufferQueue
para la que las apps son el consumidor. La devolución de llamada de onFrameAvailable()
notifica a las apps cuando el productor pone en cola un búfer nuevo. Luego, las apps llaman a updateTexImage()
, que libera el búfer que se había mantenido, adquiere el nuevo búfer de la cola y realiza llamadas a EGL para que el búfer esté disponible para GLES como una textura externa.
Texturas GLES externas
Las texturas GLES externas (GL_TEXTURE_EXTERNAL_OES
) difieren de las texturas GLES estándar (GL_TEXTURE_2D
) de las siguientes maneras:
- Las texturas externas renderizan polígonos texturizados directamente a partir de los datos recibidos de
BufferQueue
. - Los renderizadores de texturas externos se configuran de manera diferente a los renderizadores de texturas GLES estándar.
- Las texturas externas no pueden realizar todas las actividades estándar de texturas de GLES.
El principal beneficio de las texturas externas es su capacidad de renderizar directamente desde datos de BufferQueue
. Las instancias de SurfaceTexture
establecen las marcas de uso del consumidor en GRALLOC_USAGE_HW_TEXTURE
cuando crean instancias de BufferQueue
para texturas externas, con el objetivo de verificar que GLES pueda reconocer los datos del búfer.
Debido a que las instancias de SurfaceTexture
interactúan con un contexto de EGL, una app solo puede llamar a sus métodos mientras el contexto de EGL que posee la textura sea actual en el subproceso de llamada. Para obtener más información, consulta la documentación de la clase
SurfaceTexture
.
Marcas de tiempo y transformaciones
Las instancias de SurfaceTexture
incluyen el método getTimeStamp()
, que recupera una marca de tiempo, y el método getTransformMatrix()
, que recupera una matriz de transformación. Cuando se llama a updateTexImage()
, se establecen tanto la marca de tiempo como la matriz de transformación. Cada búfer que pasa BufferQueue
incluye parámetros de transformación y una marca de tiempo.
Los parámetros de transformación son útiles para la eficiencia. En algunos casos, los datos de origen pueden tener una orientación incorrecta para el consumidor. En lugar de rotar los datos antes de enviarlos al consumidor, envíalos en su orientación con una transformación que los corrija. La matriz de transformación se puede combinar con otras transformaciones cuando se usan los datos, lo que minimiza la sobrecarga.
La marca de tiempo es útil para las fuentes de búfer que dependen del tiempo. Por ejemplo, cuando setPreviewTexture()
conecta la interfaz del productor a la salida de la cámara, se pueden usar los fotogramas de la cámara para crear un video. Cada fotograma debe tener una marca de tiempo de presentación del momento en que se capturó, no del momento en que la app lo recibió. El código de la cámara establece la marca de tiempo proporcionada con el búfer, lo que genera una serie más coherente de marcas de tiempo.
Caso de éxito: Captura continua de Grafika
La
captura continua de Grafika implica grabar fotogramas desde la cámara de un dispositivo y mostrarlos en la pantalla. Para grabar fotogramas, crea una superficie con el método createInputSurface()
de la clase
MediaCodec
y pasa la superficie a la cámara. Para mostrar fotogramas, crea una instancia de SurfaceView
y pasa la superficie a setPreviewDisplay()
.
Ten en cuenta que grabar fotogramas y mostrarlos al mismo tiempo es un proceso más complejo.
La actividad de captura continua muestra el video de la cámara mientras se graba. En este caso, el video codificado se escribe en un búfer circular en la memoria que se puede guardar en el disco en cualquier momento.
Este flujo incluye tres colas de búfer:
App
: La app usa una instancia deSurfaceTexture
para recibir fotogramas de la cámara y convertirlos en una textura GLES externa.SurfaceFlinger
: La app declara una instancia deSurfaceView
para mostrar los fotogramas.MediaServer
: Configura un codificadorMediaCodec
con una superficie de entrada para crear el video.
En la siguiente figura, las flechas indican la propagación de datos desde la cámara. Se muestran instancias de BufferQueue
, con indicadores visuales que distinguen a los productores (azul verdoso) de los consumidores (verde).

Figura 1: Actividad de captura continua de Grafika
El video H.264 codificado se dirige a un búfer circular en la RAM en el proceso de la app.
Cuando un usuario presiona el botón de captura, la clase MediaMuxer
escribe el video codificado en un archivo MP4 en el disco.
Todas las instancias de BufferQueue
se controlan con un solo contexto de EGL en la app, mientras que las operaciones de GLES se realizan en el subproceso de IU. El procesamiento de los datos codificados (administración de un búfer circular y escritura en el disco) se realiza en un subproceso independiente.
Cuando se usa la clase SurfaceView
, la devolución de llamada surfaceCreated()
crea las instancias EGLContext
y EGLSurface
para la pantalla y el codificador de video. Cuando llega un nuevo fotograma, SurfaceTexture
realiza cuatro actividades:
- Adquiere el fotograma.
- Hace que el fotograma esté disponible como una textura de GLES.
- Renderiza el fotograma con comandos de GLES.
- Reenvía la transformación y la marca de tiempo para cada instancia de
EGLSurface
.
Luego, el subproceso del codificador extrae el resultado codificado de MediaCodec
y lo almacena en la memoria.
Reproducción segura de videos de texturas
Android admite el posprocesamiento de GPU del contenido de video protegido. Esto permite que las apps usen la GPU para efectos de video complejos y no lineales (como deformaciones), asignar contenido de video protegido a texturas para usar en escenas de gráficos generales (por ejemplo, con GLES) y realidad virtual (RV).

Figura 2: Reproducción segura de videos de texturas
La compatibilidad se habilita con las siguientes dos extensiones:
- Extensión de EGL: (
EGL_EXT_protected_content
) Permite la creación de contextos y superficies de GL protegidos, que pueden operar en contenido protegido. - Extensión de GLES: (
GL_EXT_protected_textures
) Permite etiquetar texturas como protegidas para que se puedan usar como archivos adjuntos de texturas de búfer de fotogramas.
Android permite que SurfaceTexture
y ACodec (libstagefright.so
) envíen contenido protegido incluso si la superficie de la ventana no se pone en cola en SurfaceFlinger
y proporciona una superficie de video protegida para usarla en un contexto protegido. Para ello, se configura el bit de consumidor protegido (GRALLOC_USAGE_PROTECTED
) en las superficies creadas en un contexto protegido (verificado por ACodec).
La reproducción de video de texturas segura sienta las bases para una sólida implementación de la administración de derechos digitales (DRM) en el entorno de OpenGL ES. Sin una implementación sólida de DRM, como Widevine Level 1, muchos proveedores de contenido no permiten la renderización de su contenido valioso en el entorno de OpenGL ES, lo que impide casos de uso importantes de RV, como mirar contenido protegido por DRM en RV.
El Proyecto de código abierto de Android (AOSP) incluye código de framework para la reproducción segura de video con texturas. La compatibilidad con los controladores depende de los OEM. Los implementadores de dispositivos deben implementar las extensiones EGL_EXT_protected_content
y GL_EXT_protected_textures
. Cuando uses tu propia biblioteca de códecs (para reemplazar libstagefright
), ten en cuenta los cambios en /frameworks/av/media/libstagefright/SurfaceUtils.cpp
que permiten que los búferes marcados con GRALLOC_USAGE_PROTECTED
se envíen a ANativeWindow
(incluso si ANativeWindow
no pone en cola directamente al compositor de ventanas), siempre y cuando los bits de uso del consumidor contengan GRALLOC_USAGE_PROTECTED
. Para obtener documentación detallada sobre la implementación de las extensiones, consulta los registros de Khronos (
EGL_EXT_protected_content
) y (
GL_EXT_protected_textures
).