La clase BufferQueue conecta componentes que generan búferes de datos gráficos ( productores ) con componentes que aceptan los datos para su visualización o procesamiento posterior ( consumidores ). Casi todo lo que mueve búferes de datos gráficos a través del sistema se basa en 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 (ver 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 de BufferQueue y pueden existir en diferentes procesos que sus productores. Cuando un productor necesita un búfer, solicita un búfer libre de BufferQueue llamando a dequeueBuffer()
, especificando el ancho, la altura, el formato de píxel y las marcas de uso de los búferes. Luego, el productor llena el búfer y lo devuelve a la cola llamando a queueBuffer()
. A continuación, el consumidor adquiere el búfer con acquireBuffer()
y hace uso del contenido del búfer. Cuando el consumidor termina, devuelve el búfer a la cola llamando a releaseBuffer()
. El marco de sincronización controla cómo se mueven los búferes a través de la canalización de gráficos de Android.
Algunas características de BufferQueue, como el número máximo de búferes que puede contener, las determinan conjuntamente el productor y el consumidor. Sin embargo, BufferQueue asigna búferes a medida que los necesita. Los tampones se conservan a menos que cambien las características; por ejemplo, si un productor solicita búferes con un tamaño diferente, los búferes antiguos se liberan y se asignan nuevos a pedido.
BufferQueue nunca copia el contenido del búfer, ya que mover tantos datos es ineficiente. En su lugar, los búferes siempre se pasan mediante un identificador.
Seguimiento de BufferQueue con Systrace
Para comprender cómo se mueven los búferes de gráficos, utilice Systrace , una herramienta que registra la actividad del dispositivo durante un breve período de tiempo. El código de gráficos a nivel del sistema está bien instrumentado, al igual que gran parte del código de marco de aplicación relevante.
Para usar Systrace, habilite las gfx
, view
y sched
. Los objetos BufferQueue se muestran en el seguimiento. Como ejemplo, si realiza un seguimiento mientras se ejecuta Play video (SurfaceView) de Grafika , la fila etiquetada como SurfaceView le indica cuántos búferes 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á funcionando y consumiendo búferes. Cuando se muestra video 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 solo cuando hay trabajo por hacer, no 60 veces por segundo. El sistema intenta evitar el trabajo y deshabilita VSYNC si nada actualiza la pantalla.
Si cambia a Grafika's Play video (TextureView) y toma un nuevo seguimiento, verá una fila etiquetada como com.android.grafika
/ com.android.grafika.PlayMovieActivity
. Esta es la capa principal de la interfaz de usuario, que es otra 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 de Gralloc HAL hardware/libhardware/include/hardware/gralloc.h
realiza asignaciones de búfer a través de indicadores de uso. Los indicadores 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 usará como una textura OpenGL ES (GLES)
- Si la memoria será utilizada por un codificador de video
Por ejemplo, si el formato de 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á píxeles en la CPU), Gralloc crea un búfer con 4 bytes por píxel en orden RGBA. Si, por el contrario, 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 desee el controlador GLES, como el pedido 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 ciertas plataformas. Por ejemplo, la bandera del codificador de video puede requerir píxeles YUV, por lo que falla la adición de acceso de software y la especificación RGBA_8888
.
El identificador devuelto por Gralloc se puede pasar entre procesos a través de Binder.
Búferes protegidos
El indicador de uso de 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 superpuestos son la única forma de mostrar contenido DRM (los búferes protegidos por DRM no pueden ser accedidos por SurfaceFlinger o el controlador OpenGL ES).
El video protegido por DRM solo se puede presentar en un plano superpuesto. Los reproductores de video que admitan contenido protegido deben implementarse con SurfaceView. El software que se ejecuta en hardware sin protección 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 videos protegidos desaparecen de la pantalla si Hardware Composer cambia a composición OpenGL ES).
Para obtener detalles sobre el contenido protegido, consulte DRM .