La clase BufferQueue conecta componentes que generan buffers de datos gráficos ( productores ) con componentes que aceptan los datos para su visualización o procesamiento posterior ( consumidores ). Casi todo lo que mueve buffers de datos gráficos a través del sistema depende de BufferQueue.
El asignador de memoria Gralloc realiza asignaciones de búfer y se implementa a través de dos interfaces HIDL específicas del proveedor (consulte hardware/interfaces/graphics/allocator/
y hardware/interfaces/graphics/mapper/
). La función allocate()
toma los argumentos esperados (ancho, alto, formato de píxel), así como un conjunto de indicadores de uso.
Productores y consumidores de BufferQueue
Los consumidores crean y poseen la estructura de datos BufferQueue y pueden existir en procesos diferentes a los de sus productores. Cuando un productor necesita un búfer, solicita un búfer libre a BufferQueue llamando dequeueBuffer()
, especificando el ancho, alto, formato de píxel y indicadores de uso de los búferes. Luego, el productor llena el búfer y lo devuelve a la cola llamando queueBuffer()
. A continuación, el consumidor adquiere el búfer con acquireBuffer()
y utiliza el contenido del búfer. Cuando el consumidor termina, devuelve el búfer a la cola llamando releaseBuffer()
. El marco de sincronización controla cómo se mueven los buffers a través de la canalización de gráficos de Android.
Algunas características de BufferQueue, como el número máximo de buffers que puede contener, las determinan conjuntamente el productor y el consumidor. Sin embargo, BufferQueue asigna buffers cuando los necesita. Los buffers se retienen a menos que cambien las características; por ejemplo, si un productor solicita buffers con un tamaño diferente, los buffers antiguos se liberan y se asignan nuevos buffers según demanda.
BufferQueue nunca copia el contenido del búfer, ya que mover tanta información es ineficiente. En cambio, los buffers siempre se pasan mediante un identificador.
Seguimiento de BufferQueue con Systrace
Para comprender cómo se mueven los buffers de gráficos, use Systrace , una herramienta que registra la actividad del dispositivo durante un corto período de tiempo. El código de gráficos a nivel de sistema está bien instrumentado, al igual que gran parte del código del marco de la aplicación relevante.
Para usar Systrace, habilite las etiquetas gfx
, view
y sched
. Los objetos BufferQueue se muestran en el seguimiento. Como ejemplo, si realiza un seguimiento mientras se ejecuta el video Reproducir de Grafika (SurfaceView) , la fila denominada SurfaceView le indica cuántos buffers estaban en cola en un momento dado.
El valor aumenta mientras la aplicación está activa, lo que activa la representación de fotogramas por parte del decodificador MediaCodec. El valor disminuye mientras SurfaceFlinger está trabajando y consumiendo buffers. Cuando se muestra vídeo a 30 fps, el valor de la cola varía de 0 a 1 porque la pantalla de ~60 fps puede seguir el ritmo de la fuente. SurfaceFlinger se activa sólo cuando hay trabajo por hacer, no 60 veces por segundo. El sistema intenta evitar el trabajo y desactiva VSYNC si nada actualiza la pantalla.
Si cambia a Reproducir video de Grafika (TextureView) y toma un nuevo rastro, verá una fila etiquetada como com.android.grafika
/ com.android.grafika.PlayMovieActivity
. Esta es la capa principal de la interfaz de usuario, que es otro BufferQueue. Debido a que TextureView se representa en la capa de la interfaz de usuario en lugar de en una capa separada, todas las actualizaciones basadas en video se muestran aquí.
Gralloc
El asignador Gralloc HAL hardware/libhardware/include/hardware/gralloc.h
realiza asignaciones de búfer a través de indicadores de uso. Las marcas de uso incluyen atributos como:
- Con qué frecuencia se accederá a la memoria desde el software (CPU)
- Con qué frecuencia se accederá a la memoria desde el hardware (GPU)
- Si la memoria se utilizará como textura OpenGL ES (GLES)
- Si la memoria será utilizada por un codificador de video
Por ejemplo, si el formato del búfer de un productor especifica RGBA_8888
píxeles y el productor indica que se accederá al búfer desde el software (lo que significa que una aplicación tocará los píxeles en la CPU), Gralloc crea un búfer con 4 bytes por píxel en orden RGBA. Si, en cambio, un productor especifica que solo se accederá a su búfer desde el hardware y como una textura GLES, Gralloc puede hacer cualquier cosa que el controlador GLES desee, como pedidos BGRA, diseños swizzled no lineales y formatos de color alternativos. Permitir que el hardware utilice su formato preferido puede mejorar el rendimiento.
Algunos valores no se pueden combinar en determinadas plataformas. Por ejemplo, el indicador del codificador de video puede requerir píxeles YUV, por lo que falla agregar acceso al software y especificar RGBA_8888
.
El identificador devuelto por Gralloc se puede pasar entre procesos a través de Binder.
Buffers protegidos
El indicador de uso de Gralloc GRALLOC_USAGE_PROTECTED
permite que el búfer de gráficos se muestre solo a través de una ruta protegida por hardware. Estos planos de superposición son la única forma de mostrar contenido DRM (SurfaceFlinger o el controlador OpenGL ES no pueden acceder a los búferes protegidos por DRM).
El vídeo protegido con DRM sólo se puede presentar en un plano superpuesto. Los reproductores de vídeo que admitan contenido protegido deben implementarse con SurfaceView. El software que se ejecuta en hardware desprotegido no puede leer ni escribir en el búfer; las rutas protegidas por hardware deben aparecer en la superposición de Hardware Composer (es decir, los vídeos protegidos desaparecen de la pantalla si Hardware Composer cambia a composición OpenGL ES).
Para obtener detalles sobre el contenido protegido, consulte DRM .