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:
- Áudio nativo do Android baseado no OpenSL ES ou na AAudio
- android.media.SoundPool
- android.media.ToneGenerator
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.