APIs de gerenciamento de buffer HAL3 da câmera

O Android 10 apresenta APIs opcionais de gerenciamento de buffer HAL3 de câmera que permitem implementar a lógica de gerenciamento de buffer para obter diferentes compensações de memória e latência de captura em implementações de HAL de câmera.

A câmera HAL requer N solicitações (onde N é igual à profundidade do pipeline ) enfileiradas em seu pipeline, mas geralmente não requer todos os N conjuntos de buffers de saída ao mesmo tempo.

Por exemplo, o HAL pode ter oito solicitações enfileiradas no pipeline, mas requer apenas buffers de saída para as duas solicitações nos últimos estágios do pipeline. Em dispositivos com Android 9 e inferior, a estrutura da câmera aloca buffers quando a solicitação é enfileirada no HAL, portanto, pode haver seis conjuntos de buffers no HAL que não estão em uso. No Android 10, as APIs de gerenciamento de buffer HAL3 da câmera permitem o desacoplamento dos buffers de saída para liberar os seis conjuntos de buffers. Isso pode levar a centenas de megabytes de economia de memória em dispositivos de última geração e também pode ser benéfico para dispositivos com pouca memória.

A Figura 1 mostra um diagrama da interface HAL da câmera para dispositivos com Android 9 e inferior. A Figura 2 mostra a interface HAL da câmera no Android 10 com as APIs de gerenciamento de buffer HAL3 da câmera implementadas.

Gerenciamento de buffer em 9 ou inferior

Figura 1. Interface HAL da câmera no Android 9 e inferior

Gerenciamento de buffer no Android 10

Figura 2. Interface HAL da câmera no Android 10 usando as APIs de gerenciamento de buffer

Implementando as APIs de gerenciamento de buffer

Para implementar as APIs de gerenciamento de buffer, a câmera HAL deve:

A câmera HAL usa os métodos requestStreamBuffers e returnStreamBuffers em ICameraDeviceCallback.hal para solicitar e retornar buffers. O HAL também deve implementar o método signalStreamFlush em ICameraDeviceSession.hal para sinalizar o HAL da câmera para retornar buffers.

requestStreamBuffers

Use o método requestStreamBuffers para solicitar buffers da estrutura da câmera. Ao usar as APIs de gerenciamento de buffer da câmera HAL3, as solicitações de captura da estrutura da câmera não contêm buffers de saída, ou seja, o campo bufferId em StreamBuffer é 0 . Portanto, a câmera HAL deve usar requestStreamBuffers para solicitar buffers da estrutura da câmera.

O método requestStreamBuffers permite que o chamador solicite vários buffers de vários fluxos de saída em uma única chamada, permitindo menos chamadas HIDL IPC. No entanto, as chamadas levam mais tempo quando mais buffers são solicitados ao mesmo tempo e isso pode afetar negativamente a latência total da solicitação para o resultado. Além disso, como as chamadas para requestStreamBuffers são serializadas no serviço da câmera, é recomendável que o HAL da câmera use um thread dedicado de alta prioridade para solicitar buffers.

Se uma solicitação de buffer falhar, o HAL da câmera deve ser capaz de lidar adequadamente com erros não fatais. A lista a seguir descreve os motivos comuns pelos quais as solicitações de buffer falham e como elas devem ser tratadas pelo HAL da câmera.

  • O aplicativo se desconecta do fluxo de saída: este é um erro não fatal. A câmera HAL deve enviar ERROR_REQUEST para qualquer solicitação de captura direcionada a um fluxo desconectado e estar pronta para processar solicitações subsequentes normalmente.
  • Tempo limite: isso pode ocorrer quando um aplicativo está ocupado fazendo processamento intensivo enquanto mantém alguns buffers. A câmera HAL deve enviar ERROR_REQUEST para solicitações de captura que não podem ser atendidas devido a um erro de tempo limite e estar pronta para processar solicitações subsequentes normalmente.
  • A estrutura da câmera está preparando uma nova configuração de fluxo: A câmera HAL deve aguardar até que a próxima chamada configureStreams seja concluída antes de chamar requestStreamBuffers novamente.
  • A câmera HAL atingiu seu limite de buffer (o campo maxBuffers ): A câmera HAL deve esperar até retornar pelo menos um buffer do fluxo antes de chamar requestStreamBuffers novamente.

returnStreamBuffers

Use o método returnStreamBuffers para retornar buffers extras para a estrutura da câmera. O HAL da câmera normalmente retorna buffers para a estrutura da câmera por meio do método processCaptureResult , mas só pode levar em conta as solicitações de captura que foram enviadas para o HAL da câmera. Com o método requestStreamBuffers , é possível que a implementação HAL da câmera retenha mais buffers do que o solicitado pela estrutura da câmera. É quando o método returnStreamBuffers deve ser usado. Se a implementação HAL nunca tiver mais buffers do que o solicitado, a implementação HAL da câmera não precisará chamar o método returnStreamBuffers .

sinalStreamFlush

O método signalStreamFlush é chamado pela estrutura da câmera para notificar o HAL da câmera para retornar todos os buffers disponíveis. Isso normalmente é chamado quando a estrutura da câmera está prestes a chamar configureStreams e deve drenar o pipeline de captura da câmera. Semelhante ao método returnStreamBuffers , se uma implementação HAL de câmera não contém mais buffers do que o solicitado, é possível que haja uma implementação vazia deste método.

Depois que a estrutura da câmera chama signalStreamFlush , a estrutura para de enviar novas solicitações de captura para o HAL da câmera até que todos os buffers tenham retornado à estrutura da câmera. Quando todos os buffers são retornados, as chamadas do método requestStreamBuffers falham e a estrutura da câmera pode continuar seu trabalho em um estado limpo. A estrutura da câmera então chama o método configureStreams ou processCaptureRequest . Se a estrutura da câmera chamar o método configureStreams , o HAL da câmera poderá começar a solicitar buffers novamente depois que a chamada configureStreams retornar com êxito. Se a estrutura da câmera chamar o método processCaptureRequest , a HAL da câmera poderá começar a solicitar buffers durante a chamada processCaptureRequest .

A semântica é diferente para o método signalStreamFlush e o método flush . Quando o método flush é chamado, o HAL pode abortar solicitações de captura pendentes com ERROR_REQUEST para drenar o pipeline o mais rápido possível. Quando o método signalStreamFlush é chamado, o HAL deve finalizar todas as requisições de captura pendentes normalmente e devolver todos os buffers para o framework da câmera.

Outra diferença entre o método signalStreamFlush e outros métodos é que signalStreamFlush é um método HIDL unidirecional , o que significa que a estrutura da câmera pode chamar outras APIs de bloqueio antes que o HAL receba a chamada signalStreamFlush . Isso significa que o método signalStreamFlush e outros métodos (especificamente o método configureStreams ) podem chegar ao HAL da câmera em uma ordem diferente daquela em que foram chamados na estrutura da câmera. Para resolver esse problema de assincronia, o campo streamConfigCounter foi adicionado a StreamConfiguration e adicionado como um argumento ao método signalStreamFlush . A implementação HAL da câmera deve usar o argumento streamConfigCounter para determinar se uma chamada signalStreamFlush chega depois de sua chamada configureStreams correspondente. Consulte a Figura 3 para obter um exemplo.

Lidando com chamadas que chegam atrasadas

Figura 3. Como o HAL da câmera deve detectar e tratar as chamadas signalStreamFlush que chegam atrasadas

Alterações de comportamento ao implementar as APIs de gerenciamento de buffer

Ao usar as APIs de gerenciamento de buffer para implementar a lógica de gerenciamento de buffer, considere as seguintes possíveis alterações de comportamento na câmera e na implementação HAL da câmera:

  • As solicitações de captura chegam ao HAL da câmera com mais rapidez e frequência: sem APIs de gerenciamento de buffer, a estrutura da câmera solicita buffers de saída para cada solicitação de captura antes de enviar uma solicitação de captura ao HAL da câmera. Ao usar as APIs de gerenciamento de buffer, a estrutura da câmera não precisa mais esperar por buffers e pode, portanto, enviar solicitações de captura para o HAL da câmera mais cedo.

    Além disso, sem APIs de gerenciamento de buffer, a estrutura da câmera para de enviar solicitações de captura se um dos fluxos de saída da solicitação de captura atingir o número máximo de buffers que o HAL pode conter por vez (esse valor é designado pelo HAL da câmera no campo HalStream::maxBuffers no valor de retorno de uma chamada configureStreams ). Com as APIs de gerenciamento de buffer, esse comportamento de limitação não existe mais e a implementação do HAL da câmera não deve aceitar chamadas processCaptureRequest quando o HAL tem muitas solicitações de captura na fila.

  • A latência da chamada requestStreamBuffers varia significativamente: há muitos motivos pelos quais uma chamada requestStreamBuffers pode levar mais tempo do que a média. Por exemplo:

    • Para os primeiros buffers de um fluxo recém-criado, as chamadas podem demorar mais porque o dispositivo precisa alocar memória.
    • A latência esperada aumenta proporcionalmente ao número de buffers solicitados em cada chamada.
    • O aplicativo está retendo buffers e está ocupado processando. Isso pode fazer com que as solicitações de buffer diminuam ou atinjam um tempo limite devido à falta de buffers ou a uma CPU ocupada.

Estratégias de gerenciamento de buffer

As APIs de gerenciamento de buffer permitem a implementação de diferentes tipos de estratégias de gerenciamento de buffer. Alguns exemplos são:

  • Compatível com versões anteriores: o HAL solicita buffers para uma solicitação de captura durante a chamada processCaptureRequest . Essa estratégia não fornece nenhuma economia de memória, mas pode servir como a primeira implementação das APIs de gerenciamento de buffer, exigindo muito poucas alterações de código no HAL da câmera existente.
  • Economia de memória maximizada: O HAL da câmera solicita apenas buffers de saída imediatamente antes de precisar preencher um. Essa estratégia permite economia de memória maximizada. A desvantagem potencial é mais instabilidade no pipeline da câmera quando as solicitações de buffer demoram muito tempo para serem concluídas.
  • Em cache: o HAL da câmera armazena em cache alguns buffers para que seja menos provável que seja afetado por uma solicitação ocasional de buffer lento.

A câmera HAL pode adotar estratégias diferentes para casos de uso específicos, por exemplo, usando a estratégia de economia de memória maximizada para casos de uso que usam muita memória e usando a estratégia compatível com versões anteriores para outros casos de uso.

Exemplo de implementação na câmera externa HAL

A câmera externa HAL foi introduzida no Android 9 e pode ser encontrada na árvore de origem em hardware/interfaces/camera/device/3.5/ . No Android 10, ele foi atualizado para incluir ExternalCameraDeviceSession.cpp , uma implementação da API de gerenciamento de buffer. Esta HAL de câmera externa implementa a estratégia de economia de memória maximizada mencionada em Estratégias de gerenciamento de buffer em algumas centenas de linhas de código C++.

,

O Android 10 apresenta APIs opcionais de gerenciamento de buffer HAL3 de câmera que permitem implementar a lógica de gerenciamento de buffer para obter diferentes compensações de memória e latência de captura em implementações de HAL de câmera.

A câmera HAL requer N solicitações (onde N é igual à profundidade do pipeline ) enfileiradas em seu pipeline, mas geralmente não requer todos os N conjuntos de buffers de saída ao mesmo tempo.

Por exemplo, o HAL pode ter oito solicitações enfileiradas no pipeline, mas requer apenas buffers de saída para as duas solicitações nos últimos estágios do pipeline. Em dispositivos com Android 9 e inferior, a estrutura da câmera aloca buffers quando a solicitação é enfileirada no HAL, portanto, pode haver seis conjuntos de buffers no HAL que não estão em uso. No Android 10, as APIs de gerenciamento de buffer HAL3 da câmera permitem o desacoplamento dos buffers de saída para liberar os seis conjuntos de buffers. Isso pode levar a centenas de megabytes de economia de memória em dispositivos de última geração e também pode ser benéfico para dispositivos com pouca memória.

A Figura 1 mostra um diagrama da interface HAL da câmera para dispositivos com Android 9 e inferior. A Figura 2 mostra a interface HAL da câmera no Android 10 com as APIs de gerenciamento de buffer HAL3 da câmera implementadas.

Gerenciamento de buffer em 9 ou inferior

Figura 1. Interface HAL da câmera no Android 9 e inferior

Gerenciamento de buffer no Android 10

Figura 2. Interface HAL da câmera no Android 10 usando as APIs de gerenciamento de buffer

Implementando as APIs de gerenciamento de buffer

Para implementar as APIs de gerenciamento de buffer, a câmera HAL deve:

A câmera HAL usa os métodos requestStreamBuffers e returnStreamBuffers em ICameraDeviceCallback.hal para solicitar e retornar buffers. O HAL também deve implementar o método signalStreamFlush em ICameraDeviceSession.hal para sinalizar o HAL da câmera para retornar buffers.

requestStreamBuffers

Use o método requestStreamBuffers para solicitar buffers da estrutura da câmera. Ao usar as APIs de gerenciamento de buffer da câmera HAL3, as solicitações de captura da estrutura da câmera não contêm buffers de saída, ou seja, o campo bufferId em StreamBuffer é 0 . Portanto, a câmera HAL deve usar requestStreamBuffers para solicitar buffers da estrutura da câmera.

O método requestStreamBuffers permite que o chamador solicite vários buffers de vários fluxos de saída em uma única chamada, permitindo menos chamadas HIDL IPC. No entanto, as chamadas levam mais tempo quando mais buffers são solicitados ao mesmo tempo e isso pode afetar negativamente a latência total da solicitação para o resultado. Além disso, como as chamadas para requestStreamBuffers são serializadas no serviço da câmera, é recomendável que o HAL da câmera use um thread dedicado de alta prioridade para solicitar buffers.

Se uma solicitação de buffer falhar, o HAL da câmera deve ser capaz de lidar adequadamente com erros não fatais. A lista a seguir descreve os motivos comuns pelos quais as solicitações de buffer falham e como elas devem ser tratadas pelo HAL da câmera.

  • O aplicativo se desconecta do fluxo de saída: este é um erro não fatal. A câmera HAL deve enviar ERROR_REQUEST para qualquer solicitação de captura direcionada a um fluxo desconectado e estar pronta para processar solicitações subsequentes normalmente.
  • Tempo limite: isso pode ocorrer quando um aplicativo está ocupado fazendo processamento intensivo enquanto mantém alguns buffers. A câmera HAL deve enviar ERROR_REQUEST para solicitações de captura que não podem ser atendidas devido a um erro de tempo limite e estar pronta para processar solicitações subsequentes normalmente.
  • A estrutura da câmera está preparando uma nova configuração de fluxo: A câmera HAL deve aguardar até que a próxima chamada configureStreams seja concluída antes de chamar requestStreamBuffers novamente.
  • A câmera HAL atingiu seu limite de buffer (o campo maxBuffers ): A câmera HAL deve esperar até retornar pelo menos um buffer do fluxo antes de chamar requestStreamBuffers novamente.

returnStreamBuffers

Use o método returnStreamBuffers para retornar buffers extras para a estrutura da câmera. O HAL da câmera normalmente retorna buffers para a estrutura da câmera por meio do método processCaptureResult , mas só pode levar em conta as solicitações de captura que foram enviadas para o HAL da câmera. Com o método requestStreamBuffers , é possível que a implementação HAL da câmera retenha mais buffers do que o solicitado pela estrutura da câmera. É quando o método returnStreamBuffers deve ser usado. Se a implementação HAL nunca tiver mais buffers do que o solicitado, a implementação HAL da câmera não precisará chamar o método returnStreamBuffers .

sinalStreamFlush

O método signalStreamFlush é chamado pela estrutura da câmera para notificar o HAL da câmera para retornar todos os buffers disponíveis. Isso normalmente é chamado quando a estrutura da câmera está prestes a chamar configureStreams e deve drenar o pipeline de captura da câmera. Semelhante ao método returnStreamBuffers , se uma implementação HAL de câmera não contém mais buffers do que o solicitado, é possível que haja uma implementação vazia deste método.

Depois que a estrutura da câmera chama signalStreamFlush , a estrutura para de enviar novas solicitações de captura para o HAL da câmera até que todos os buffers tenham retornado à estrutura da câmera. Quando todos os buffers são retornados, as chamadas do método requestStreamBuffers falham e a estrutura da câmera pode continuar seu trabalho em um estado limpo. A estrutura da câmera então chama o método configureStreams ou processCaptureRequest . Se a estrutura da câmera chamar o método configureStreams , o HAL da câmera poderá começar a solicitar buffers novamente depois que a chamada configureStreams retornar com êxito. Se a estrutura da câmera chamar o método processCaptureRequest , a HAL da câmera poderá começar a solicitar buffers durante a chamada processCaptureRequest .

A semântica é diferente para o método signalStreamFlush e o método flush . Quando o método flush é chamado, o HAL pode abortar solicitações de captura pendentes com ERROR_REQUEST para drenar o pipeline o mais rápido possível. Quando o método signalStreamFlush é chamado, o HAL deve finalizar todas as requisições de captura pendentes normalmente e devolver todos os buffers para o framework da câmera.

Outra diferença entre o método signalStreamFlush e outros métodos é que signalStreamFlush é um método HIDL unidirecional , o que significa que a estrutura da câmera pode chamar outras APIs de bloqueio antes que o HAL receba a chamada signalStreamFlush . Isso significa que o método signalStreamFlush e outros métodos (especificamente o método configureStreams ) podem chegar ao HAL da câmera em uma ordem diferente daquela em que foram chamados na estrutura da câmera. Para resolver esse problema de assincronia, o campo streamConfigCounter foi adicionado a StreamConfiguration e adicionado como um argumento ao método signalStreamFlush . A implementação HAL da câmera deve usar o argumento streamConfigCounter para determinar se uma chamada signalStreamFlush chega depois de sua chamada configureStreams correspondente. Consulte a Figura 3 para obter um exemplo.

Lidando com chamadas que chegam atrasadas

Figura 3. Como o HAL da câmera deve detectar e tratar as chamadas signalStreamFlush que chegam atrasadas

Alterações de comportamento ao implementar as APIs de gerenciamento de buffer

Ao usar as APIs de gerenciamento de buffer para implementar a lógica de gerenciamento de buffer, considere as seguintes possíveis alterações de comportamento na câmera e na implementação HAL da câmera:

  • As solicitações de captura chegam ao HAL da câmera com mais rapidez e frequência: sem APIs de gerenciamento de buffer, a estrutura da câmera solicita buffers de saída para cada solicitação de captura antes de enviar uma solicitação de captura para o HAL da câmera. Ao usar as APIs de gerenciamento de buffer, a estrutura da câmera não precisa mais esperar por buffers e pode, portanto, enviar solicitações de captura para o HAL da câmera mais cedo.

    Além disso, sem APIs de gerenciamento de buffer, a estrutura da câmera para de enviar solicitações de captura se um dos fluxos de saída da solicitação de captura atingir o número máximo de buffers que o HAL pode conter por vez (esse valor é designado pelo HAL da câmera no campo HalStream::maxBuffers no valor de retorno de uma chamada configureStreams ). Com as APIs de gerenciamento de buffer, esse comportamento de limitação não existe mais e a implementação do HAL da câmera não deve aceitar chamadas processCaptureRequest quando o HAL tem muitas solicitações de captura na fila.

  • A latência da chamada requestStreamBuffers varia significativamente: há muitos motivos pelos quais uma chamada requestStreamBuffers pode levar mais tempo do que a média. Por exemplo:

    • Para os primeiros buffers de um fluxo recém-criado, as chamadas podem demorar mais porque o dispositivo precisa alocar memória.
    • A latência esperada aumenta proporcionalmente ao número de buffers solicitados em cada chamada.
    • O aplicativo está retendo buffers e está ocupado processando. Isso pode fazer com que as solicitações de buffer diminuam ou atinjam um tempo limite devido à falta de buffers ou a uma CPU ocupada.

Estratégias de gerenciamento de buffer

As APIs de gerenciamento de buffer permitem a implementação de diferentes tipos de estratégias de gerenciamento de buffer. Alguns exemplos são:

  • Compatível com versões anteriores: o HAL solicita buffers para uma solicitação de captura durante a chamada processCaptureRequest . Essa estratégia não fornece nenhuma economia de memória, mas pode servir como a primeira implementação das APIs de gerenciamento de buffer, exigindo muito poucas alterações de código no HAL da câmera existente.
  • Economia de memória maximizada: O HAL da câmera solicita apenas buffers de saída imediatamente antes de precisar preencher um. Essa estratégia permite economia de memória maximizada. A desvantagem potencial é mais instabilidade no pipeline da câmera quando as solicitações de buffer demoram muito tempo para serem concluídas.
  • Em cache: o HAL da câmera armazena em cache alguns buffers para que seja menos provável que seja afetado por uma solicitação ocasional de buffer lento.

A câmera HAL pode adotar estratégias diferentes para casos de uso específicos, por exemplo, usando a estratégia de economia de memória maximizada para casos de uso que usam muita memória e usando a estratégia compatível com versões anteriores para outros casos de uso.

Exemplo de implementação na câmera externa HAL

A câmera externa HAL foi introduzida no Android 9 e pode ser encontrada na árvore de origem em hardware/interfaces/camera/device/3.5/ . No Android 10, ele foi atualizado para incluir ExternalCameraDeviceSession.cpp , uma implementação da API de gerenciamento de buffer. Esta HAL de câmera externa implementa a estratégia de economia de memória maximizada mencionada em Estratégias de gerenciamento de buffer em algumas centenas de linhas de código C++.

,

O Android 10 apresenta APIs opcionais de gerenciamento de buffer HAL3 de câmera que permitem implementar a lógica de gerenciamento de buffer para obter diferentes compensações de memória e latência de captura em implementações de HAL de câmera.

A câmera HAL requer N solicitações (onde N é igual à profundidade do pipeline ) enfileiradas em seu pipeline, mas geralmente não requer todos os N conjuntos de buffers de saída ao mesmo tempo.

Por exemplo, o HAL pode ter oito solicitações enfileiradas no pipeline, mas requer apenas buffers de saída para as duas solicitações nos últimos estágios do pipeline. Em dispositivos com Android 9 e inferior, a estrutura da câmera aloca buffers quando a solicitação é enfileirada no HAL, portanto, pode haver seis conjuntos de buffers no HAL que não estão em uso. No Android 10, as APIs de gerenciamento de buffer HAL3 da câmera permitem o desacoplamento dos buffers de saída para liberar os seis conjuntos de buffers. Isso pode levar a centenas de megabytes de economia de memória em dispositivos de última geração e também pode ser benéfico para dispositivos com pouca memória.

A Figura 1 mostra um diagrama da interface HAL da câmera para dispositivos com Android 9 e inferior. A Figura 2 mostra a interface HAL da câmera no Android 10 com as APIs de gerenciamento de buffer HAL3 da câmera implementadas.

Gerenciamento de buffer em 9 ou inferior

Figura 1. Interface HAL da câmera no Android 9 e inferior

Gerenciamento de buffer no Android 10

Figura 2. Interface HAL da câmera no Android 10 usando as APIs de gerenciamento de buffer

Implementando as APIs de gerenciamento de buffer

Para implementar as APIs de gerenciamento de buffer, a câmera HAL deve:

A câmera HAL usa os métodos requestStreamBuffers e returnStreamBuffers em ICameraDeviceCallback.hal para solicitar e retornar buffers. O HAL também deve implementar o método signalStreamFlush em ICameraDeviceSession.hal para sinalizar o HAL da câmera para retornar buffers.

requestStreamBuffers

Use o método requestStreamBuffers para solicitar buffers da estrutura da câmera. Ao usar as APIs de gerenciamento de buffer da câmera HAL3, as solicitações de captura da estrutura da câmera não contêm buffers de saída, ou seja, o campo bufferId em StreamBuffer é 0 . Portanto, a câmera HAL deve usar requestStreamBuffers para solicitar buffers da estrutura da câmera.

O método requestStreamBuffers permite que o chamador solicite vários buffers de vários fluxos de saída em uma única chamada, permitindo menos chamadas HIDL IPC. No entanto, as chamadas levam mais tempo quando mais buffers são solicitados ao mesmo tempo e isso pode afetar negativamente a latência total da solicitação para o resultado. Além disso, como as chamadas para requestStreamBuffers são serializadas no serviço da câmera, é recomendável que o HAL da câmera use um thread dedicado de alta prioridade para solicitar buffers.

Se uma solicitação de buffer falhar, o HAL da câmera deve ser capaz de lidar adequadamente com erros não fatais. A lista a seguir descreve os motivos comuns pelos quais as solicitações de buffer falham e como elas devem ser tratadas pelo HAL da câmera.

  • O aplicativo se desconecta do fluxo de saída: este é um erro não fatal. A câmera HAL deve enviar ERROR_REQUEST para qualquer solicitação de captura direcionada a um fluxo desconectado e estar pronta para processar solicitações subsequentes normalmente.
  • Tempo limite: isso pode ocorrer quando um aplicativo está ocupado fazendo processamento intensivo enquanto mantém alguns buffers. A câmera HAL deve enviar ERROR_REQUEST para solicitações de captura que não podem ser atendidas devido a um erro de tempo limite e estar pronta para processar solicitações subsequentes normalmente.
  • A estrutura da câmera está preparando uma nova configuração de fluxo: A câmera HAL deve aguardar até que a próxima chamada configureStreams seja concluída antes de chamar requestStreamBuffers novamente.
  • A câmera HAL atingiu seu limite de buffer (o campo maxBuffers ): A câmera HAL deve esperar até retornar pelo menos um buffer do fluxo antes de chamar requestStreamBuffers novamente.

returnStreamBuffers

Use o método returnStreamBuffers para retornar buffers extras para a estrutura da câmera. O HAL da câmera normalmente retorna buffers para a estrutura da câmera por meio do método processCaptureResult , mas só pode levar em conta as solicitações de captura que foram enviadas para o HAL da câmera. Com o método requestStreamBuffers , é possível que a implementação HAL da câmera retenha mais buffers do que o solicitado pela estrutura da câmera. É quando o método returnStreamBuffers deve ser usado. Se a implementação HAL nunca tiver mais buffers do que o solicitado, a implementação HAL da câmera não precisará chamar o método returnStreamBuffers .

sinalStreamFlush

O método signalStreamFlush é chamado pela estrutura da câmera para notificar o HAL da câmera para retornar todos os buffers disponíveis. Isso normalmente é chamado quando a estrutura da câmera está prestes a chamar configureStreams e deve drenar o pipeline de captura da câmera. Semelhante ao método returnStreamBuffers , se uma implementação HAL de câmera não contém mais buffers do que o solicitado, é possível que haja uma implementação vazia deste método.

Depois que a estrutura da câmera chama signalStreamFlush , a estrutura para de enviar novas solicitações de captura para o HAL da câmera até que todos os buffers tenham retornado à estrutura da câmera. Quando todos os buffers são retornados, as chamadas do método requestStreamBuffers falham e a estrutura da câmera pode continuar seu trabalho em um estado limpo. A estrutura da câmera então chama o método configureStreams ou processCaptureRequest . Se a estrutura da câmera chamar o método configureStreams , o HAL da câmera poderá começar a solicitar buffers novamente depois que a chamada configureStreams retornar com êxito. Se a estrutura da câmera chamar o método processCaptureRequest , a HAL da câmera poderá começar a solicitar buffers durante a chamada processCaptureRequest .

A semântica é diferente para o método signalStreamFlush e o método flush . Quando o método flush é chamado, o HAL pode abortar solicitações de captura pendentes com ERROR_REQUEST para drenar o pipeline o mais rápido possível. Quando o método signalStreamFlush é chamado, o HAL deve finalizar todas as requisições de captura pendentes normalmente e devolver todos os buffers para o framework da câmera.

Outra diferença entre o método signalStreamFlush e outros métodos é que signalStreamFlush é um método HIDL unidirecional , o que significa que a estrutura da câmera pode chamar outras APIs de bloqueio antes que o HAL receba a chamada signalStreamFlush . Isso significa que o método signalStreamFlush e outros métodos (especificamente o método configureStreams ) podem chegar ao HAL da câmera em uma ordem diferente daquela em que foram chamados na estrutura da câmera. Para resolver esse problema de assincronia, o campo streamConfigCounter foi adicionado a StreamConfiguration e adicionado como um argumento ao método signalStreamFlush . A implementação HAL da câmera deve usar o argumento streamConfigCounter para determinar se uma chamada signalStreamFlush chega depois de sua chamada configureStreams correspondente. Consulte a Figura 3 para obter um exemplo.

Lidando com chamadas que chegam atrasadas

Figura 3. Como o HAL da câmera deve detectar e tratar as chamadas signalStreamFlush que chegam atrasadas

Alterações de comportamento ao implementar as APIs de gerenciamento de buffer

Ao usar as APIs de gerenciamento de buffer para implementar a lógica de gerenciamento de buffer, considere as seguintes possíveis alterações de comportamento na câmera e na implementação HAL da câmera:

  • As solicitações de captura chegam ao HAL da câmera com mais rapidez e frequência: sem APIs de gerenciamento de buffer, a estrutura da câmera solicita buffers de saída para cada solicitação de captura antes de enviar uma solicitação de captura para o HAL da câmera. Ao usar as APIs de gerenciamento de buffer, a estrutura da câmera não precisa mais esperar por buffers e pode, portanto, enviar solicitações de captura para o HAL da câmera mais cedo.

    Além disso, sem APIs de gerenciamento de buffer, a estrutura da câmera para de enviar solicitações de captura se um dos fluxos de saída da solicitação de captura atingir o número máximo de buffers que o HAL pode conter por vez (esse valor é designado pelo HAL da câmera no campo HalStream::maxBuffers no valor de retorno de uma chamada configureStreams ). Com as APIs de gerenciamento de buffer, esse comportamento de limitação não existe mais e a implementação do HAL da câmera não deve aceitar chamadas processCaptureRequest quando o HAL tem muitas solicitações de captura na fila.

  • A latência da chamada requestStreamBuffers varia significativamente: há muitos motivos pelos quais uma chamada requestStreamBuffers pode levar mais tempo do que a média. Por exemplo:

    • Para os primeiros buffers de um fluxo recém-criado, as chamadas podem demorar mais porque o dispositivo precisa alocar memória.
    • A latência esperada aumenta proporcionalmente ao número de buffers solicitados em cada chamada.
    • O aplicativo está retendo buffers e está ocupado processando. Isso pode fazer com que as solicitações de buffer diminuam ou atinjam um tempo limite devido à falta de buffers ou a uma CPU ocupada.

Estratégias de gerenciamento de buffer

As APIs de gerenciamento de buffer permitem a implementação de diferentes tipos de estratégias de gerenciamento de buffer. Alguns exemplos são:

  • Compatível com versões anteriores: o HAL solicita buffers para uma solicitação de captura durante a chamada processCaptureRequest . Essa estratégia não oferece nenhuma economia de memória, mas pode servir como a primeira implementação das APIs de gerenciamento de buffer, exigindo muito poucas alterações de código no HAL da câmera existente.
  • Economia de memória maximizada: O HAL da câmera solicita apenas buffers de saída imediatamente antes de precisar preencher um. Essa estratégia permite economia de memória maximizada. A desvantagem potencial é mais instabilidade no pipeline da câmera quando as solicitações de buffer demoram muito tempo para serem concluídas.
  • Em cache: o HAL da câmera armazena em cache alguns buffers para que seja menos provável que seja afetado por uma solicitação ocasional de buffer lento.

A câmera HAL pode adotar estratégias diferentes para casos de uso específicos, por exemplo, usando a estratégia de economia de memória maximizada para casos de uso que usam muita memória e usando a estratégia compatível com versões anteriores para outros casos de uso.

Exemplo de implementação na câmera externa HAL

A câmera externa HAL foi introduzida no Android 9 e pode ser encontrada na árvore de origem em hardware/interfaces/camera/device/3.5/ . In Android 10, it has been updated to include ExternalCameraDeviceSession.cpp , an implementation of the buffer management API. This external camera HAL implements the maximized memory savings strategy mentioned in Buffer management strategies in a few hundred lines of C++ code.