Projetar para reduzir a latência

A versão do Android 4.1 introduziu mudanças internas do framework para um caminho de saída de áudio de menor latência. Houve mudanças mínimas na API de cliente público ou na API HAL. Este documento descreve o design inicial, que continuou a evoluir ao longo do tempo. Ter um bom entendimento desse design ajuda os OEMs de dispositivos e os fornecedores de SoC a implementar o design corretamente nos dispositivos e chipsets específicos. Este artigo não é destinado a desenvolvedores de aplicativos.

Criação de faixa

O cliente pode definir o bit AUDIO_OUTPUT_FLAG_FAST no parâmetro audio_output_flags_t do construtor AudioTrack C++ ou AudioTrack::set(). Atualmente, os únicos clientes que fazem isso são:

A implementação do AudioTrack em C++ analisa a solicitação AUDIO_OUTPUT_FLAG_FAST e pode recusá-la, se necessário, no nível do cliente. Se ele decidir transmitir a solicitação, ele fará isso usando o bit TRACK_FAST do parâmetro track_flags_t do método de fábrica IAudioTrack IAudioFlinger::createTrack().

O servidor de áudio AudioFlinger analisa a solicitação TRACK_FAST e pode recusar a solicitação no nível do servidor. Ele informa ao cliente se a solicitação foi aceita ou não, pelo bit CBLK_FAST do bloco de controle de memória compartilhada.

Os fatores que afetam a decisão incluem:

  • Presença de uma linha de execução de mixer rápida para essa saída (confira abaixo)
  • Taxa de amostragem da faixa
  • Presença de uma linha de execução do cliente para executar gerenciadores de callback para essa faixa
  • Tamanho do buffer de faixa
  • Vagas disponíveis para a faixa rápida (confira abaixo)

Se a solicitação do cliente for aceita, ela será chamada de "pista rápida". Caso contrário, é chamada de "faixa normal".

Linhas de execução do mixer

Quando o AudioFlinger cria uma linha de execução de mixer normal, ele decide se também criará ou não uma linha de execução de mixer rápida. O mixer normal e o mixer rápido não estão associados a uma faixa específica, mas a um conjunto de faixas. Sempre há uma linha de mesclador normal. A linha de execução do mixer rápido, se existir, é subordinada à linha de execução normal do mixer e age sob o controle dela.

Misturador rápido

Recursos

A linha de execução do mixer rápido oferece estes recursos:

  • Mistura da submix do mixer normal e até sete faixas rápidas do cliente
  • Atenuação por faixa

Recursos omitidos:

  • Conversão da taxa de amostragem por faixa
  • Efeitos por faixa
  • Por efeitos de mixagem

Período

O mixer rápido é executado periodicamente, com um período recomendado de dois a três milissegundos (ms) ou um período ligeiramente maior de cinco ms, se necessário para a estabilidade da programação. Esse número foi escolhido para que, considerando o pipeline de buffer completo, a latência total ficasse na ordem de 10 ms. Valores menores são possíveis, mas podem resultar em aumento do consumo de energia e chance de falhas, dependendo da previsibilidade da programação da CPU. Valores maiores são possíveis, até 20 ms, mas resultam em latência total degradada e, portanto, devem ser evitados.

Programação

O mixer rápido é executado com prioridade SCHED_FIFO elevada. Ele precisa de muito pouco tempo de CPU, mas precisa ser executado com frequência e com baixo jitter de programação. O jitter expressa a variação no tempo de ciclo: é a diferença entre o tempo de ciclo real e o esperado. A execução muito tardia resultará em falhas devido ao underrun. A execução muito cedo resultará em falhas devido à extração de uma faixa rápida antes que ela forneça dados.

Bloqueia o conteúdo

O ideal é que a linha de execução do mixer rápido nunca seja bloqueada, exceto no HAL write(). Outras ocorrências de bloqueio no mixer rápido são consideradas bugs. Especificamente, os mutexes são evitados. Em vez disso, são usados algoritmos sem bloqueio, também conhecidos como algoritmos sem bloqueio. Consulte Como evitar a inversão de prioridade para saber mais sobre esse assunto.

Relação com outros componentes

O mixer rápido tem pouca interação direta com os clientes. Em particular, ele não identifica operações no nível do vinculamento, mas acessa o bloco de controle de memória compartilhada do cliente.

O mixer rápido recebe comandos do mixer normal por uma fila de estado.

Além de extrair dados de faixas, a interação com os clientes é feita pelo mixer normal.

O sink principal do mixer rápido é o HAL de áudio.

Mixer normal

Recursos

Todos os recursos estão ativados:

  • Até 32 faixas
  • Atenuação por faixa
  • Conversão da taxa de amostragem por faixa
  • Processamento de efeitos

Período

O período é calculado para ser o primeiro múltiplo integral do período do mixer rápido que é >= 20 ms.

Programação

O mixer normal é executado com prioridade SCHED_OTHER elevada.

Bloqueia o conteúdo

O mixer normal pode bloquear e, geralmente, faz isso em vários mutexes e em um pipe de bloqueio para gravar o submix.

Relação com outros componentes

O mixer normal interage extensivamente com o mundo externo, incluindo linhas de execução de vinculação, gerenciador de políticas de áudio, linha de execução de mixer rápido e faixas de cliente.

O sink do mixer normal é um pipe de bloqueio para a faixa 0 do mixer rápido.

Flags

O bit AUDIO_OUTPUT_FLAG_FAST é uma dica. Não há garantia de que a solicitação será atendida.

AUDIO_OUTPUT_FLAG_FAST é um conceito no nível do cliente. Ele não aparece no servidor.

TRACK_FAST é um conceito de cliente para servidor.