BufferQueue e Gralloc

A classe BufferQueue conecta componentes que geram buffers de dados gráficos ( produtores ) a componentes que aceitam os dados para exibição ou processamento posterior ( consumidores ). Quase tudo que move buffers de dados gráficos pelo sistema depende do BufferQueue.

O alocador de memória Gralloc realiza alocações de buffer e é implementado por meio de duas interfaces HIDL específicas do fornecedor (consulte hardware/interfaces/graphics/allocator/ e hardware/interfaces/graphics/mapper/ ). A função allocate() recebe argumentos esperados (largura, altura, formato de pixel), bem como um conjunto de sinalizadores de uso.

Produtores e consumidores de BufferQueue

Os consumidores criam e possuem a estrutura de dados BufferQueue e podem existir em processos diferentes dos seus produtores. Quando um produtor precisa de um buffer, ele solicita um buffer livre de BufferQueue chamando dequeueBuffer() , especificando a largura, altura, formato de pixel e sinalizadores de uso dos buffers. O produtor então preenche o buffer e o retorna para a fila chamando queueBuffer() . Em seguida, o consumidor adquire o buffer com acquireBuffer() e utiliza o conteúdo do buffer. Quando o consumidor termina, ele retorna o buffer para a fila chamando releaseBuffer() . A estrutura de sincronização controla como os buffers se movem pelo pipeline gráfico do Android.

Algumas características do BufferQueue, como o número máximo de buffers que ele pode conter, são determinadas em conjunto pelo produtor e pelo consumidor. No entanto, o BufferQueue aloca buffers conforme necessário. Os buffers são retidos, a menos que as características mudem; por exemplo, se um produtor solicitar buffers com tamanho diferente, os buffers antigos serão liberados e novos buffers serão alocados sob demanda.

O conteúdo do buffer nunca é copiado pelo BufferQueue, pois mover tantos dados é ineficiente. Em vez disso, os buffers são sempre passados ​​por um identificador.

Rastreie BufferQueue com Systrace

Para entender como os buffers gráficos se movimentam, use o Systrace , uma ferramenta que registra a atividade do dispositivo durante um curto período de tempo. O código gráfico no nível do sistema é bem instrumentado, assim como grande parte do código da estrutura do aplicativo relevante.

Para usar o Systrace, habilite as tags gfx , view e sched . Os objetos BufferQueue são exibidos no rastreamento. Por exemplo, se você fizer um rastreamento enquanto o vídeo Play do Grafika (SurfaceView) estiver em execução, a linha chamada SurfaceView informa quantos buffers foram enfileirados em um determinado momento.

O valor aumenta enquanto o aplicativo está ativo, o que aciona a renderização de quadros pelo decodificador MediaCodec. O valor diminui enquanto o SurfaceFlinger está funcionando e consumindo buffers. Ao exibir vídeo a 30 fps, o valor da fila varia de 0 a 1 porque a exibição de ~60 fps pode acompanhar a fonte. O SurfaceFlinger é ativado apenas quando há trabalho a ser feito, e não 60 vezes por segundo. O sistema tenta evitar o trabalho e desabilita o VSYNC se nada estiver atualizando a tela.

Se você mudar para o Play video do Grafika (TextureView) e pegar um novo traço, você verá uma linha chamada com.android.grafika / com.android.grafika.PlayMovieActivity . Esta é a camada principal da UI, que é outro BufferQueue. Como o TextureView é renderizado na camada de UI em vez de em uma camada separada, todas as atualizações baseadas em vídeo são exibidas aqui.

Gralloc

O alocador HAL hardware/libhardware/include/hardware/gralloc.h Gralloc executa alocações de buffer por meio de sinalizadores de uso. Os sinalizadores de uso incluem atributos como:

  • Com que frequência a memória será acessada pelo software (CPU)
  • Com que frequência a memória será acessada pelo hardware (GPU)
  • Se a memória será usada como textura OpenGL ES (GLES)
  • Se a memória será usada por um codificador de vídeo

Por exemplo, se o formato de buffer de um produtor especificar RGBA_8888 pixels, e o produtor indicar que o buffer será acessado pelo software (o que significa que um aplicativo tocará pixels na CPU), Gralloc criará um buffer com 4 bytes por pixel na ordem RGBA. Se, em vez disso, um produtor especificar que seu buffer será acessado apenas pelo hardware e como uma textura GLES, o Gralloc poderá fazer qualquer coisa que o driver GLES desejar, como ordenação BGRA, layouts swizzled não lineares e formatos de cores alternativos. Permitir que o hardware use seu formato preferido pode melhorar o desempenho.

Alguns valores não podem ser combinados em determinadas plataformas. Por exemplo, o sinalizador do codificador de vídeo pode exigir pixels YUV, portanto, adicionar acesso de software e especificar RGBA_8888 falha.

O identificador retornado pelo Gralloc pode ser passado entre processos por meio do Binder.

Buffers protegidos

O sinalizador de uso Gralloc GRALLOC_USAGE_PROTECTED permite que o buffer gráfico seja exibido apenas através de um caminho protegido por hardware. Esses planos de sobreposição são a única maneira de exibir conteúdo DRM (buffers protegidos por DRM não podem ser acessados ​​pelo SurfaceFlinger ou pelo driver OpenGL ES).

O vídeo protegido por DRM só pode ser apresentado em um plano de sobreposição. Os players de vídeo que oferecem suporte a conteúdo protegido devem ser implementados com o SurfaceView. O software executado em hardware desprotegido não consegue ler ou gravar no buffer; caminhos protegidos por hardware devem aparecer na sobreposição do Hardware Composer (ou seja, os vídeos protegidos desaparecem da exibição se o Hardware Composer alternar para a composição OpenGL ES).

Para obter detalhes sobre conteúdo protegido, consulte DRM .