Extensões de câmera

Os fabricantes de dispositivos podem expor extensões, como bokeh, modo noturno e HDR, a desenvolvedores de terceiros pela interface de extensões da câmera fornecida pela biblioteca OEM. Os desenvolvedores podem usar a API Camera2 Extensions e a API CameraX Extensions para acessar as extensões implementadas na biblioteca do fornecedor OEM.

Para conferir uma lista de extensões com suporte, que é a mesma para o Camera2 e o CameraX, consulte API Extensions do CameraX. Se você quiser adicionar uma extensão, informe um bug no Issue Tracker.

Esta página descreve como implementar e ativar a biblioteca do fornecedor OEM em dispositivos.

Arquitetura

O diagrama a seguir descreve a arquitetura da interface das extensões da câmera ou extensions-interface: Arquitetura

Figura 1. Diagrama da arquitetura das extensões de câmera

Conforme mostrado no diagrama, para oferecer suporte às extensões de câmera, é necessário implementar o extensions-interface fornecido pela biblioteca do fornecedor OEM. Sua biblioteca do fornecedor OEM ativa duas APIs: API Extensions do CameraX e API Extensions do Camera2, que são usadas pelos apps CameraX e Camera2, respectivamente, para acessar as extensões do fornecedor.

Implementar a biblioteca de fornecedor OEM

Para implementar a biblioteca do fornecedor OEM, copie os arquivos camera-extensions-stub em um projeto de biblioteca do sistema. Esses arquivos definem a interface das extensões da câmera.

Os arquivos camera-extensions-stub são divididos nas seguintes categorias:

Arquivos de interface essenciais (não modifique)

  • PreviewExtenderImpl.java
  • ImageCaptureExtenderImpl.java
  • ExtenderStateListener.java
  • ProcessorImpl.java
  • PreviewImageProcessorImpl.java
  • CaptureProcessorImpl.java
  • CaptureStageImpl.java
  • RequestUpdateProcessorImpl.java
  • ProcessResultImpl.java
  • advanced/AdvancedExtenderImpl.java
  • advanced/Camera2OutputConfigImpl.java
  • advanced/Camera2SessionConfigImpl.java
  • advanced/ImageProcessorImpl.java
  • advanced/ImageReaderOutputConfigImpl.java
  • advanced/ImageReferenceImpl.java
  • advanced/MultiResolutionImageReaderOutputConfigImpl.java
  • advanced/OutputSurfaceImpl.java
  • advanced/RequestProcessorImpl.java
  • advanced/SessionProcessorImpl.java
  • advanced/SurfaceOutputConfigImpl.java

Implementações obrigatórias (adicione sua implementação)

  • ExtensionVersionImpl.java
  • InitializerImpl.java

Classes de extensão do Bokeh (implemente se a extensão do Bokeh tiver suporte)

  • BokehImageCaptureExtenderImpl.java
  • BokehPreviewExtenderImpl.java
  • advanced/BokehAdvancedExtenderImpl.java

Classes de extensão noturna (implemente se a extensão noturna tiver suporte)

  • NightImageCaptureExtenderImpl.java
  • NightPreviewExtenderImpl.java
  • advanced/NightAdvancedExtenderImpl.java

Classes de extensão automática (implemente se a extensão automática for compatível)

  • AutoImageCaptureExtenderImpl.java
  • AutoPreviewExtenderImpl.java
  • advanced/AutoAdvancedExtenderImpl.java

Classes de extensão de HDR (implemente se a extensão de HDR tiver suporte)

  • HdrImageCaptureExtenderImpl.java
  • HdrPreviewExtenderImpl.java
  • advanced/HdrAdvancedExtenderImpl.java

Classes de extensão do retoque facial (implemente se a extensão do retoque facial tiver suporte)

  • BeautyImageCaptureExtenderImpl.java
  • BeautyPreviewExtenderImpl.java
  • advanced/BeautyAdvancedExtenderImpl.java

Utilitários (opcional, pode ser excluído)

  • advanced/Camera2OutputConfigImplBuilder.java
  • advanced/Camera2SessionConfigImplBuilder.java

Não é necessário fornecer uma implementação para cada extensão. Se você não implementar uma extensão, defina isExtensionAvailable() para retornar false ou remova as classes de extensão correspondentes. As APIs de extensões do Camera2 e CameraX informam ao app que a extensão está indisponível.

Vamos mostrar como as APIs Camera2 e CameraX Extensions interagem com a biblioteca do fornecedor para ativar uma extensão. O diagrama a seguir ilustra o fluxo completo usando a extensão Night como exemplo:

Mainflow

Figura 2. Implementação da extensão do Modo noturno

  1. Verificação de versão:

    O Camera2/X chama ExtensionVersionImpl.checkApiVersion() para garantir que a versão extensions-interface implementada pelo OEM seja compatível com as versões com suporte do Camera2/X.

  2. Inicialização da biblioteca do fornecedor:

    InitializerImpl tem um método init() que inicializa a biblioteca do fornecedor. A Camera2/X conclui a inicialização antes de acessar as classes do extensor.

  3. Criar instâncias de classes de extensão:

    Cria instâncias das classes de extensão para a extensão. Há dois tipos de extensor: básico e avançado. É necessário implementar um tipo de extensor para todas as extensões. Para mais informações, consulte Extensão básica e avançada.

    O Camera2/X instancia e interage com as classes de extensão para extrair informações e ativar a extensão. Para uma determinada extensão, o Camera2/X pode instanciar as classes de extensão várias vezes. Como resultado, não faça a inicialização de tarefas pesadas no construtor ou na chamada init(). Faça o trabalho pesado somente quando a sessão da câmera estiver prestes a começar, como quando onInit() for chamado no Basic Extender ou initSession() for chamado no Advanced Extender.

    Para a extensão Night, as seguintes classes de extensão são instanciadas para o tipo de extensão básica:

    • NightImageCaptureExtenderImpl.java
    • NightPreviewExtenderImpl.java

    E para o tipo de extensor avançado:

    • NightAdvancedExtenderImpl.java
  4. Confira a disponibilidade da extensão:

    Antes de ativar a extensão, isExtensionAvailable() verifica se ela está disponível no ID da câmera especificado pela instância do extensor.

  5. Inicializar o extensor com informações da câmera:

    O Camera2/X chama init() na instância do extensor e transmite o ID da câmera e CameraCharacteristics.

  6. Informações da consulta:

    Invoca a classe de extensor para extrair informações, como resoluções compatíveis, ainda capturar a latência estimada e capturar chaves de solicitação do extensão em preparação para ativar a extensão.

  7. Ativar a extensão no extensor:

    A classe Extender fornece todas as interfaces necessárias para ativar a classe. Ele oferece um mecanismo para vincular a implementação do OEM ao pipeline da Camera2, como injetar parâmetros de solicitação de captura ou ativar um pós-processador.

    Para o tipo de extensor avançado, o Camera2/X interage com SessionProcessorImpl para ativar a extensão. A Camera2/X recupera a instância de SessionProcessorImpl chamando createSessionProcessor() no Extender.

As seções a seguir descrevem o fluxo de extensão em mais detalhes.

Verificação de versão

Ao carregar a biblioteca do fornecedor OEM do dispositivo no ambiente de execução, a Camera2/X verifica se a biblioteca é compatível com a versão extensions-interface. O extensions-interface usa o controle de versões semântico ou PRINCIPAL.SECUNDÁRIA.PATCH, por exemplo, 1.1.0 ou 1.2.0. No entanto, apenas as versões principais e secundárias são usadas durante a verificação de versão.

Para verificar a versão, o Camera2/X chama ExtensionVersionImpl.checkApiVersion() com a versão extensions-interface com suporte. A Camera2/X usa a versão informada pela biblioteca OEM para determinar se a extensão pode ser ativada e quais recursos ela precisa invocar.

Compatibilidade com a versão principal

Se as versões principais da extension-interface forem diferentes entre Camera2/X e a biblioteca do fornecedor, ela será considerada incompatível e a extensão será desativada.

Compatibilidade com versões anteriores

Desde que a versão principal seja idêntica, o Camera2/X garante compatibilidade com versões anteriores com bibliotecas de fornecedores OEM criadas com versões extensions-interface anteriores. Por exemplo, se o Camera2/X for compatível com extensions-interface 1.3.0, as bibliotecas do fornecedor OEM que implementaram 1.0.0, 1.1.0 e 1.2.0 ainda serão compatíveis. Isso também significa que, depois de implementar uma versão específica da biblioteca do fornecedor, o Camera2/X garante que a biblioteca seja compatível com versões anteriores de extension-interface.

Compatibilidade com versões futuras

A compatibilidade futura com bibliotecas de fornecedores de extensions-interface mais recentes depende de você, o OEM. Se você precisar de alguns recursos para implementar as extensões, ative as extensões a partir de uma determinada versão. Nesse caso, você pode retornar a versão extensions-interface com suporte quando a versão da biblioteca Camera2/X atender aos requisitos. Se as versões Camera2/X não tiverem suporte, você poderá retornar uma versão incompatível, como 99.0.0, para desativar as extensões.

Inicialização da biblioteca do fornecedor

Depois de verificar a versão extensions-interface implementada pela biblioteca OEM, a Camera2/X inicia o processo de inicialização. O método InitializerImpl.init() sinaliza para a biblioteca OEM que um app está tentando usar extensões.

A Camera2/X não faz outras chamadas para a biblioteca OEM (exceto a verificação de versão) até que a biblioteca do fornecedor OEM chame OnExtensionsInitializedCallback.onSuccess() para notificar a conclusão da inicialização.

É necessário implementar InitializerImpl a partir da extensions-interface 1.1.0. O Camera2/X pula a etapa de inicialização da biblioteca se a biblioteca do fornecedor OEM implementar extensions-interface 1.0.0.

Extensor básico x Extensor avançado

Há dois tipos de implementação de extensions-interface: extensor básico e extensão avançada. O suporte para o Advanced Extender está disponível desde a extensions-interface 1.2.0.

Implemente o Basic Extender para extensões que processam imagens no HAL da câmera ou use um pós-processador capaz de processar fluxos YUV.

Implemente o Advanced Extender para extensões que precisam personalizar a configuração do fluxo da Camera2 e enviar solicitações de captura conforme necessário.

Confira a comparação na tabela a seguir:

Extensor básico Extensor avançado
Configurações de transmissão Corrigido
Pré-visualização: PRIVATE ou YUV_420_888 (se o processador existir)
Captura de imagem: JPEG ou YUV_420_888 (se o processador existir)
Personalizável pelo OEM.
Enviar solicitação de captura Somente o Camera2/X pode enviar solicitações de captura. É possível definir os parâmetros para essas solicitações. Quando o processador é fornecido para captura de imagem, a Camera2/X pode enviar várias solicitações de captura e enviar todas as imagens e capturar os resultados para o processador. Uma instância RequestProcessorImpl é fornecida para executar a solicitação de captura da camera2 e receber resultados e imagens.

A Camera2/X invoca startRepeating e startCapture em SessionProcessorImpl para sinalizar o OEM para iniciar a solicitação repetida de visualização e iniciar a sequência de captura de fotos estáticas, respectivamente.

Ganchos no pipeline da câmera
  • onPresetSession fornece parâmetros de sessão.
  • O onEnableSession envia uma única solicitação logo após a configuração do CameraCaptureSession.
  • O onDisableSession envia uma única solicitação antes que o CameraCaptureSession seja fechado.
  • initSession inicializa e retorna uma configuração de sessão personalizada da Camera2 para criar a sessão de captura.
  • O onCaptureSessionStart é invocado logo após a configuração do CameraCaptureSession.
  • onCaptureSessionEnd é invocado antes de CameraCaptureSession ser fechado.
Indicado para Extensões implementadas na HAL da câmera ou em um processador que processa imagens YUV.
  • Tem implementações baseadas na Camera2 para as extensões.
  • Precisa de uma configuração personalizada, como o fluxo RAW.
  • Precisa de uma sequência de captura interativa.
Versão da API com suporte Extensões da Camera2: Android 13 ou mais recente
Extensões da CameraX: camera-extensions 1.1.0 ou mais recente
Extensões da Camera2: Android 12L ou mais recente
Extensões do CameraX: camera-extensions 1.2.0-alpha03 ou mais recente

Fluxos de apps

A tabela a seguir mostra três tipos de fluxos de app e as chamadas da API Camera Extensions correspondentes. Embora o Camera2/X forneça essas APIs, é necessário implementar corretamente a biblioteca do fornecedor para oferecer suporte a esses fluxos, que serão descritos em mais detalhes em uma seção posterior.

Extensões do Camera2 Extensões do CameraX
Disponibilidade da expansão de consulta CameraExtensionCharacteristics .getSupportedExtensions ExtensionsManager. isExtensionAvailable
Informações da consulta CameraExtensionCharacteristics. getExtensionSupportedSizes CameraExtensionCharacteristics. getEstimatedCaptureLatencyRangeMillis CameraExtensionCharacteristics. getAvailableCaptureRequestKeys CameraExtensionCharacteristics. getAvailableCaptureResultKeys ExtensionsManager. getEstimatedCaptureLatencyRange

O CameraX processa o restante das informações na biblioteca.

Visualização e captura de fotos com a extensão ativada CameraDevice. createExtensionSession

cameraExtensionsSession. setRepeatingRequest

cameraExtensionsSession. capture

val cameraSelector = ExtensionsManager. getExtensionEnabledCameraSelector

bindToLifecycle(lifecycleOwner, cameraSelector, preview, ...)

Extensor básico

A interface do extensor básico oferece ganchos em vários lugares no pipeline da câmera. Cada tipo de extensão tem classes correspondentes que os OEMs precisam implementar.

A tabela a seguir lista as classes de extensor que os OEMs precisam implementar para cada extensão:

Classes de extensão a serem implementadas
Noite NightPreviewExtenderImpl.java

NightImageCaptureExtenderImpl.java

HDR HdrPreviewExtenderImpl.java

HdrImageCaptureExtenderImpl.java

Automático AutoPreviewExtenderImpl.java

AutoImageCaptureExtenderImpl.java

Bokeh BokehPreviewExtenderImpl.java

BokehImageCaptureExtenderImpl.java

Retoque facial BeautyPreviewExtenderImpl.java

BeautyImageCaptureExtenderImpl.java

Usamos PreviewExtenderImpl e ImageCaptureExtenderImpl como marcadores de posição no exemplo abaixo. Substitua esses nomes pelos nomes dos arquivos que você está implementando.

O extensor básico tem os seguintes recursos:

  • Injete parâmetros de sessão ao configurar CameraCaptureSession ( onPresetSession).
  • Notifica você sobre os eventos de início e encerramento da sessão de captura e envia uma única solicitação para notificar a HAL com os parâmetros retornados (onEnableSession, onDisableSession).
  • Injete parâmetros de captura para a solicitação (PreviewExtenderImpl.getCaptureStage, ImageCaptureExtenderImpl.getCaptureStages).
  • Adicione processadores para visualização e capture ainda capaz de processar o stream YUV_420_888.

Vamos conferir como o Camera2/X invoca o extensions-interface para alcançar os três fluxos de app mencionados acima.

Fluxo do app 1: verificar a disponibilidade da extensão

BasicExtenderAppFlow1

Figura 3. Fluxo de app 1 no extensor básico

Nesse fluxo, o Camera2/X chama diretamente o método isExtensionAvailable() de PreviewExtenderImpl e ImageCaptureExtenderImpl sem chamar init(). Ambas as classes de extensão precisam retornar true para ativar as extensões.

Essa é geralmente a primeira etapa para que os apps verifiquem se o tipo de extensão oferece suporte a um determinado ID de câmera antes de ativar a extensão. Isso ocorre porque algumas extensões têm suporte apenas para determinados IDs de câmera.

Fluxo do app 2: informações da consulta

BasicExtenderAppFlow2

Figura 4. Fluxo de app 2 no extensor básico

Depois de determinar se a extensão está disponível, os apps precisam consultar as informações a seguir antes de ativar a extensão.

  • Intervalo de latência de captura estática:ImageCaptureExtenderImpl.getEstimatedCaptureLatencyRange retorna o intervalo de latência de captura para que o app avalie se é apropriado ativar a extensão para o cenário atual.

  • Tamanhos compatíveis para a visualização e a superfície de captura:ImageCaptureExtenderImpl.getSupportedResolutions e PreviewExtenderImpl.getSupportedResolutions retornam uma lista de formatos de imagem e os tamanhos compatíveis com o formato e o tamanho da superfície.

  • Chaves de solicitação e resultado compatíveis:a Camera2/X invoca os seguintes métodos para extrair as chaves de solicitação de captura e as chaves de resultado compatíveis da sua implementação:

    • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys
    • ImageCaptureExtenderImpl.getAvailableCapturetResultKeys

O Camera2/X sempre chama init() primeiro nessas classes de extensão antes de consultar para mais informações.

Fluxo do app 3: visualização/captura de foto com extensão ativada (implementação do HAL)

BasicExtenderAppFlow3

Figura 5. Fluxo de app 3 no extensor básico

O diagrama acima ilustra o fluxo principal de ativação da visualização e da captura de fotos com uma extensão sem processador. Isso significa que o HAL da câmera processa a extensão.

Nesse fluxo, a Camera2/X chama primeiro init() e depois onInit, que notifica que uma sessão da câmera está prestes a começar com as extensões especificadas. É possível fazer a inicialização de tarefas pesadas em onInit().

Ao configurar CameraCaptureSession, a Camera2/X invoca onPresetSession para receber os parâmetros da sessão. Depois que a sessão de captura é configurada, o Camera2/X invoca onEnableSession, retornando uma instância de CaptureStageImpl que contém os parâmetros de captura. O Camera2/X envia imediatamente uma única solicitação com esses parâmetros de captura para notificar o HAL. Da mesma forma, antes de a sessão de captura ser fechada, a Camera2/X invoca onDisableSession e envia uma única solicitação com os parâmetros de captura retornados.

A solicitação repetida acionada pela Camera2/X contém os parâmetros de solicitação retornados por PreviewExtenderImpl.getCaptureStage(). Além disso, a solicitação de captura de imagem contendo os parâmetros retornados por ImageCaptureExtenderImpl.getCaptureStages().

Por fim, o Camera2/X invoca onDeInit() após a sessão da câmera terminar. Você pode liberar recursos em onDeinit().

Pré-visualizar o processador

Além da HAL da câmera, você também pode implementar extensões em um processador.

Implemente PreviewExtenderImpl.getProcessorType para especificar o tipo de processador, conforme explicado abaixo:

  • PROCESSOR_TYPE_NONE:nenhum processador. As imagens são processadas no HAL da câmera.

  • PROCESSOR_TYPE_REQUEST_UPDATE_ONLY:o tipo de processador permite atualizar a solicitação repetida com novos parâmetros de solicitação de captura com base no TotalCaptureResult mais recente.

    PreviewExtenderImpl.getProcessor precisa retornar uma instância RequestUpdateProcessorImpl que processa a instância TotalCaptureResult e retorna uma instância CaptureStageImpl para atualizar a solicitação repetida. O PreviewExtenderImpl.getCaptureStage() também precisa refletir o resultado do processamento e retornar o CaptureStageImpl mais recente.

  • PROCESSOR_TYPE_IMAGE_PROCESSOR:com esse tipo, é possível implementar um processador para processar imagens YUV_420_888 e gravar a saída em uma superfície PRIVATE.

    Você precisa implementar e retornar uma instância de PreviewImageProcessorImpl em PreviewExtenderImpl.getProcessor. O processador é responsável pelo processamento de imagens de entrada YUV_420_888. Ele precisa gravar a saída no formato PRIVATE da visualização. O Camera2/X usa uma plataforma YUV_420_888 em vez de PRIVATE para configurar o CameraCaptureSession para visualização.

    Confira a ilustração a seguir do fluxo:

PreviewProcessor

Figura 6. Fluxo de visualização com PreviewImageProcessorImpl

A interface PreviewImageProcessorImpl estende ProcessImpl e tem três métodos importantes:

  • onOutputSurface(Surface surface, int imageFormat) define a superfície de saída para o processador. Para PreviewImageProcessorImpl, imageFormat é um formato de pixels, como PixelFormat.RGBA_8888.

  • onResolutionUpdate(Size size) define o tamanho da imagem de entrada.

  • onImageFormatUpdate(int imageFormat) define o formato da imagem de entrada. No momento, só é possível usar YUV_420_888.

Processador de captura de imagem

Para capturas de tela, é possível implementar um processador retornando uma instância de CaptureProcessorImpl usando ImageCaptureExtenderImpl.getCaptureProcessor. O processador é responsável por processar uma lista de imagens YUV_420_888 e instâncias TotalCaptureResult capturadas e gravar a saída em uma superfície YUV_420_888.

Você pode presumir que a visualização está ativada e em execução antes de enviar a solicitação de captura de imagem estática.

Confira o fluxo no diagrama abaixo:

CaptureProcessor

Figura 7. Fluxo de captura de fotos com CaptureProcessorImpl

  1. O Camera2/X usa uma superfície de formato YUV_420_888 para a captura de fotos estáticas para configurar a sessão de captura. A Camera2/X prepara CaptureProcessorImpl chamando:

    • CaptureProcessorImpl.onImageFormatUpdate() com YUV_420_888.
    • CaptureProcessorImpl.onResolutionUpdate() com o tamanho da imagem de entrada.
    • CaptureProcessorImpl.onOutputSurface() com uma superfície de saída YUV_420_888.
  2. ImageCaptureExtenderImpl.getCaptureStages retorna uma lista de CaptureStageImpl, em que cada elemento é mapeado para uma instância CaptureRequest com parâmetros de captura enviados pelo Camera2/X. Por exemplo, se ele retornar uma lista de três instâncias CaptureStageImpl, o Camera2/X vai enviar três solicitações de captura com os parâmetros de captura correspondentes usando a API captureBurst.

  3. As imagens recebidas e as instâncias de TotalCaptureResult são agrupadas e enviadas para CaptureProcessorImpl para processamento.

  4. CaptureProcessorImpl grava a imagem do resultado (formato YUV_420_888) na superfície de saída especificada pela chamada onOutputSurface(). O Camera2/X as converte em imagens JPEG, se necessário.

Suporte a chaves e resultados de solicitações de captura

Além da visualização e captura da câmera, os apps podem definir zoom, parâmetros de flash ou acionar o recurso de tocar para focar. Esses parâmetros podem não ser compatíveis com a implementação da extensão.

Os métodos a seguir foram adicionados ao extensions-interface 1.3.0 para permitir que você exponha os parâmetros compatíveis com sua implementação:

  • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys() retorna as chaves de solicitação de captura compatíveis com a implementação.
  • ImageCaptureExtenderImpl.getAvailableCaptureResultKeys() retorna as chaves de resultado de captura contidas no resultado da captura.

Se a HAL da câmera processar a extensão, o Camera2/X vai recuperar os resultados da captura em CameraCaptureSession.CaptureCallback. No entanto, se o processador for implementado, o Camera2/X vai recuperar os resultados da captura em ProcessResultImpl, que é transmitido para o método process() em PreviewImageProcessorImpl e CaptureProcessorImpl. Você é responsável por informar o resultado da captura usando ProcessResultImpl para Camera2/X.

Confira a definição da interface CaptureProcessorImpl abaixo como exemplo. Na extensions-interface 1.3.0 ou mais recente, a segunda chamada process() é invocada:

Interface CaptureProcessorImpl extends ProcessorImpl {
    // invoked when extensions-interface version < 1.3.0
    void process(Map<Integer, Pair<Image, TotalCaptureResult>> results);
    // invoked when extensions-interface version >= 1.3.0
    void process(Map<Integer, Pair<Image, TotalCaptureResult>> results,
            ProcessResultImpl resultCallback, Executor executor);
}

Para operações comuns da câmera, como zoom, toque para focar, flash e compensação de exposição, recomendamos o suporte às seguintes chaves para a solicitação de captura e o resultado da captura:

  • Zoom:
    • CaptureRequest#CONTROL_ZOOM_RATIO
    • CaptureRequest#SCALER_CROP_REGION
  • Toque para focar:
    • CaptureRequest#CONTROL_AF_MODE
    • CaptureRequest#CONTROL_AF_TRIGGER
    • CaptureRequest#CONTROL_AF_REGIONS
    • CaptureRequest#CONTROL_AE_REGIONS
    • CaptureRequest#CONTROL_AWB_REGIONS
  • Flash:
    • CaptureRequest#CONTROL_AE_MODE
    • CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
    • CaptureRequest#FLASH_MODE
  • Compensação de exposição:
    • CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION

Para extensores básicos que implementam a versão 1.2.0 ou anterior, a API CameraX Extensions oferece suporte explícito a todas as chaves acima. Para extensions-interface 1.3.0, o CameraX e o Camera2 respeitam a lista retornada e oferecem suporte apenas às chaves contidas nela. Por exemplo, se você decidir retornar apenas CaptureRequest#CONTROL_ZOOM_RATIO e CaptureRequest#SCALER_CROP_REGION na implementação 1.3.0, isso significa que apenas o zoom é compatível com o app, enquanto o toque para focar, o flash e a compensação de exposição não são permitidos.

Extensor avançado

O Advanced Extender é um tipo de implementação do fornecedor baseada na API Camera2. Esse tipo de extensor foi adicionado na extensions-interface 1.2.0. Dependendo do fabricante do dispositivo, as extensões podem ser implementadas na camada do app, o que depende dos seguintes fatores:

  • Configuração de fluxo personalizado:configure fluxos personalizados, como o fluxo RAW, ou tenha vários fluxos para diferentes IDs de câmera física.

  • Capacidade de enviar solicitações da Camera2:ofereça suporte a uma lógica de interação complicada que possa enviar solicitações de captura com parâmetros com base nos resultados de solicitações anteriores.

O Advanced Extender fornece um wrapper, ou uma camada intermediária, para que você possa personalizar a configuração do stream e enviar solicitações de captura sob demanda.

Arquivos a implementar

Para alternar para a implementação do extensor avançado, o método isAdvancedExtenderImplemented() em ExtensionVersionImpl precisa retornar true. Para cada tipo de extensão, os OEMs precisam implementar as classes de extensor correspondentes. Os arquivos de implementação do Advanced Extender estão no pacote advanced.

Classes de extensão a serem implementadas
Noite advanced/NightAdvancedExtenderImpl.java
HDR advanced/HdrAdvancedExtenderImpl.java
Automático advanced/AutoAdvancedExtenderImpl.java
Bokeh advanced/BokehAdvancedExtenderImpl.java
Retocar rosto advanced/BeautyAdvancedExtenderImpl.java

Usamos AdvancedExtenderImpl como marcador de posição no exemplo a seguir. Substitua pelo nome do arquivo do extensor da extensão que você está implementando.

Vamos conferir como o Camera2/X invoca o extensions-interface para alcançar os três fluxos do app.

Fluxo do app 1: verificar a disponibilidade das extensões

AdvancedAppFlow1

Figura 8. Fluxo de app 1 no Advanced Extender

Primeiro, o app verifica se a extensão tem suporte.

Fluxo do app 2: informações da consulta

AdvancedAppFlow2

Figura 9. Fluxo de app 2 no Advanced Extender

Depois de chamar AdvancedExtenderImpl.init(), o app pode consultar as informações em AdvancedExtenderImpl:

  • Latência de captura estática estimada:AdvancedExtenderImpl.getEstimatedCaptureLatencyRange() retorna o intervalo de latência de captura para que o app avalie se é apropriado ativar a extensão para o cenário atual.

  • Resoluções compatíveis para visualização e captura estática:

    • AdvancedExtenderImpl.getSupportedPreviewOutputResolutions() retorna um mapa do formato de imagem para a lista de tamanhos que têm suporte para o formato e o tamanho da superfície de visualização. Os OEMs precisam oferecer suporte a pelo menos o formato PRIVATE.

    • AdvancedExtenderImpl.getSupportedCaptureOutputResolutions() retorna o formato e os tamanhos aceitos para a superfície de captura de fotos. Os OEMs precisam oferecer suporte à saída de formato JPEG e YUV_420_888.

    • AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions() retorna os tamanhos aceitos para um fluxo YUV_420_888 extra para análise de imagem. Se a análise de imagem não tiver suporte à superfície YUV, getSupportedYuvAnalysisResolutions() vai retornar null ou uma lista vazia.

  • Chaves/resultados de solicitação de captura disponíveis (adicionadas na extensions-interface 1.3.0): o Camera2/X invoca os seguintes métodos para extrair as chaves de solicitação de captura e de resultado compatíveis da implementação:

    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys
    • AdvancedExtenderImpl.getAvailableCaptureResultKeys

Para mais informações, consulte Suporte a chaves e resultados de solicitação de captura.

Fluxo do app 3: visualização/captura de foto com extensão ativada

AdvancedAppFlow3

Figura 10. Fluxo de app 3 no Advanced Extender

O diagrama acima mostra o fluxo principal para iniciar a visualização e a captura de imagem estática para o tipo de extensor avançado. Vamos analisar cada etapa.

  1. Instância SessionProcessorImpl

    A implementação principal do Advanced Extender está em SessionProcessorImpl, que é responsável por fornecer a configuração personalizada da sessão e enviar solicitações de captura para iniciar a visualização e a captura. AdvancedExtenderImpl.createSessionProcessor() é invocado para retornar a instância SessionProcessorImpl.

  2. initSession

    SessionProcessorImpl.initSession() inicializa a sessão da extensão. É aqui que você aloca recursos e retorna uma configuração de sessão para preparar um CameraCaptureSession.

    Para os parâmetros de entrada, o Camera2/X especifica as configurações da superfície de saída para visualização, captura de imagens e uma análise de imagem YUV opcional. Essa configuração de superfície de saída (OutputSurfaceImpl) contém a superfície, o tamanho e o formato da imagem que são recuperados pelos seguintes métodos em AdvancedExtenderImpl:

    • getSupportedPreviewOutputResolutions()
    • getSupportedCaptureOutputResolutions()
    • getSupportedYuvAnalysisResolutions()

    É necessário retornar uma instância Camera2SessionConfigImpl, que consiste em uma lista de instâncias Camera2OutputConfigImpl e os parâmetros de sessão usados para configurar CameraCaptureSession. Você é responsável por enviar as imagens da câmera corretas para as superfícies de saída transmitidas por Camera2/X. Confira algumas opções para ativar a saída:

    • Processamento na HAL da câmera:é possível adicionar diretamente as superfícies de saída ao CameraCaptureSession com uma implementação SurfaceOutputConfigImpl. Isso configura a superfície de saída fornecida para o pipeline da câmera e permite que o HAL da câmera processe a imagem.
    • Processamento de superfície ImageReader intermediária (RAW, YUV etc.): adicione as superfícies ImageReader intermediárias ao CameraCaptureSession com uma instância ImageReaderOutputConfigImpl.

      Você precisa processar as imagens intermediárias e gravar a imagem do resultado na superfície de saída.

    • Usar o compartilhamento de superfície do Camera2:use o compartilhamento de superfície com outra superfície adicionando qualquer instância Camera2OutputConfigImpl ao método getSurfaceSharingOutputConfigs() de outra instância Camera2OutputConfigImpl. O formato e o tamanho da superfície precisam ser idênticos.

    Todos os Camera2OutputConfigImpl, incluindo SurfaceOutputConfigImpl e ImageReaderOutputConfigImpl, precisam ter um ID exclusivo (getId()), que é usado para especificar a superfície de destino e extrair a imagem de ImageReaderOutputConfigImpl.

  3. onCaptureSessionStart e RequestProcessorImpl

    Quando CameraCaptureSession é iniciado e o framework da câmera invoca onConfigured(), o Camera2/X invoca SessionProcessorImpl.onCaptureSessionStart() com o wrapper de solicitação RequestProcessImpl do Camera2. O Camera2/X implementa RequestProcessImpl, que permite executar as solicitações de captura e recuperar imagens se ImageReaderOutputConfigImpl for usado.

    As APIs RequestProcessImpl são semelhantes às APIs CameraCaptureSession da Camera2 em termos de execução de solicitações. As diferenças são:

    • A superfície de destino é especificada pelo ID da instância Camera2OutputConfigImpl.
    • A capacidade de recuperar a imagem do ImageReader.

    É possível chamar RequestProcessorImpl.setImageProcessor() com um ID Camera2OutputConfigImpl especificado para registrar uma instância ImageProcessorImpl para receber imagens.

    A instância RequestProcessImpl se torna inválida depois que o Camera2/X chama SessionProcessorImpl.onCaptureSessionEnd().

  4. Iniciar a visualização e tirar uma foto

    Na implementação do extensor avançado, é possível enviar solicitações de captura pela interface RequestProcessorImpl. A Camera2/X notifica você para iniciar a solicitação repetida de visualização ou a sequência de captura de fotos chamando SessionProcessorImpl#startRepeating e SessionProcessorImpl#startCapture, respectivamente. Você precisa enviar solicitações de captura para atender a essas solicitações de visualização e captura de fotos.

    A Camera2/X também define os parâmetros de solicitação de captura usando SessionProcessorImpl#setParameters. Defina esses parâmetros de solicitação (se houver suporte) nas solicitações únicas e recorrentes.

    É necessário oferecer suporte a pelo menos CaptureRequest.JPEG_ORIENTATION e CaptureRequest.JPEG_QUALITY. O extensions-interface 1.3.0 oferece suporte a chaves de solicitação e resultado, que são expostas pelos seguintes métodos:

    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys()
    • AdvancedExtenderImpl.getAvailableCaptureResultKeys()

    Quando os desenvolvedores definem as chaves na lista getAvailableCaptureRequestKeys, é necessário ativar os parâmetros e garantir que o resultado da captura contenha as chaves na lista getAvailableCaptureResultKeys.

  5. startTrigger

    SessionProcessorImpl.startTrigger() é invocado para iniciar o acionador, como CaptureRequest.CONTROL_AF_TRIGGER e CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER. Desconsidere as chaves de solicitação de captura que não foram anunciadas em AdvancedExtenderImpl.getAvailableCaptureRequestKeys().

    O startTrigger() tem suporte desde a versão 1.3.0 do extensions-interface. Ele permite que os apps implementem o toque para focar e o flash com extensões.

  6. Limpeza

    Ao terminar uma sessão de captura, SessionProcessorImpl.onCaptureSessionEnd() é invocado antes de fechar CameraCaptureSession. Depois que a sessão de captura é fechada, deInitSession() faz a limpeza.

Oferecer suporte a visualização, captura de fotos e análise de imagens

Aplique a extensão para os casos de uso de visualização e captura de fotos. No entanto, se a latência for muito alta para mostrar a visualização sem problemas, você poderá aplicar a extensão apenas para captura de fotos.

Para o tipo de extensor básico, independentemente de ativar a extensão para visualização, é necessário implementar ImageCaptureExtenderImpl e PreviewExtenderImpl para uma determinada extensão. Muitas vezes, um app também usa um stream YUV para analisar o conteúdo da imagem, como encontrar códigos QR ou texto. Para oferecer melhor suporte a esse caso de uso, é necessário oferecer suporte à combinação de fluxo de visualização, captura de fotos e um fluxo YUV_420_888 para configurar CameraCaptureSession. Isso significa que, se você implementar um processador, precisará oferecer suporte à combinação de três streams YUV_420_888.

Para o Advanced Extender, o Camera2/X transmite três superfícies de saída para a chamada SessionProcessorImpl.initSession(). Essas plataformas de saída são para visualização, captura de fotos e análise de imagens, respectivamente. É necessário garantir que a visualização e as superfícies de saída de captura mostrem a saída válida. No entanto, para a superfície de saída da análise de imagem, verifique se ela funciona apenas quando não é nula. Se a implementação não oferecer suporte ao fluxo de análise de imagem, você poderá retornar uma lista vazia em AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions(). Isso garante que a plataforma de saída da análise de imagem seja sempre nula em SessionProcessorImpl.initSession().

Suporte para captura de vídeo

A arquitetura atual da extensão da câmera oferece suporte apenas aos casos de uso de visualização e captura de fotos. Não é possível ativar a extensão nas plataformas MediaCodec ou MediaRecorder para gravar o vídeo. No entanto, é possível que os apps gravem a saída de visualização.

A compatibilidade com as plataformas MediaCodec e MediaRecorder está em investigação.

Metadados específicos da extensão

No Android 14 e versões mais recentes, os metadados específicos da extensão permitem que os clientes de extensão da câmera definam e recebam configurações e resultados de solicitação de captura específicos da extensão. Especificamente, os clientes de extensão da câmera podem usar o parâmetro de solicitação de captura EXTENSION_STRENGTH para controlar a intensidade da extensão e o resultado da captura EXTENSION_CURRENT_TYPE para indicar o tipo de extensão ativado.

Capturar solicitações

O parâmetro de solicitação de captura EXTENSION_STRENGTH controla a intensidade do efeito de pós-processamento da extensão. O resultado de captura correspondente inclui o valor de força padrão se esse parâmetro não for definido explicitamente pelo cliente. Esse parâmetro pode ser aplicado da seguinte forma para estes tipos de extensão:

  • BOKEH: controla a quantidade de desfoque.
  • HDR e NIGHT: controlam a quantidade de imagens mescladas e o brilho da imagem final.
  • FACE_RETOUCH: controla a quantidade de melhoria cosmética e suavização da pele.

O intervalo com suporte para o parâmetro EXTENSION_STRENGTH fica entre 0 e 100, com 0 indicando nenhum processamento de extensão ou passagem simples e 100 indicando a intensidade máxima de extensão do efeito de processamento.

Para adicionar suporte a EXTENSION_STRENGTH, use as APIs de parâmetro específicos do fornecedor introduzidas na versão 1.3.0 da interface da biblioteca de extensão. Para mais informações, consulte getAvailableCaptureRequestKeys():

Capturar resultados

O resultado da captura de EXTENSION_CURRENT_TYPE permite que as implementações de extensão notifiquem os clientes sobre o tipo de extensão ativo.

Como as extensões que usam o tipo AUTO alternam dinamicamente entre tipos de extensão como HDR e NIGHT, dependendo das condições da cena, os apps de extensões de câmera podem usar EXTENSION_CURRENT_TYPE para mostrar informações sobre a extensão atual selecionada pela extensão AUTO.

Estimativa de latência de captura estática em tempo real

No Android 14 e versões mais recentes, os clientes de extensão da câmera podem consultar estimativas de latência de captura estática em tempo real com base nas condições da cena e do ambiente usando getRealtimeStillCaptureLatency(). Esse método fornece estimativas mais precisas do que o método estático getEstimatedCaptureLatencyRangeMillis(). Com base na estimativa de latência, os apps podem decidir pular o processamento de extensões ou mostrar uma indicação para notificar os usuários sobre uma operação demorada.

CameraExtensionSession.StillCaptureLatency latency;

latency = extensionSession.getRealtimeStillCaptureLatency();

// The capture latency from ExtensionCaptureCallback#onCaptureStarted() until ExtensionCaptureCallback#onCaptureProcessStarted().

latency.getCaptureLatency();

// The processing latency from  ExtensionCaptureCallback#onCaptureProcessStarted() until  the processed frame returns to the client.

latency.getProcessingLatency();

Para oferecer suporte a estimativas de latência de captura estática em tempo real, implemente o seguinte:

Capturar callbacks de progresso do processamento

No Android 14 e versões mais recentes, os clientes de extensão da câmera podem receber callbacks para o progresso de operações de processamento de captura de fotos de longa duração. Os apps podem mostrar o progresso atual aos usuários para melhorar a experiência geral.

Os apps podem usar o seguinte código para integrar esse recurso:

import android.hardware.camera2.CameraExtensionSession.
ExtensionCaptureCallback;

{
…
  class AppCallbackImpl extends ExtensionCaptureCallback {
…
    @Override
    public void onCaptureProcessProgressed(
      @NonNull CameraExtensionSession session,
      @NonNull CaptureRequest request,
      @IntRange(from = 0, to = 100) int progress) {
      // Update app UI with current progress
    }
  }
…
}

Para oferecer suporte a callbacks de progresso do processamento de captura, a implementação do fornecedor da extensão precisa chamar os seguintes callbacks com o valor de progresso atual:

Captura estática de PostView

No Android 14 e versões mais recentes, as extensões de câmera podem fornecer uma pós-visualização (imagem de visualização) usando setPostviewOutputConfiguration. Para melhorar a experiência do usuário, os apps podem mostrar uma imagem pós-visualização como um marcador de posição quando uma extensão estiver com latência de processamento aumentada e substituir a imagem quando a imagem final estiver disponível. Os apps podem configurar e emitir solicitações de captura de postview usando o seguinte código de referência:

{
…
if (!CameraExtensionCharacteristics.isPostviewAvailable()) {
    continue;
}
…
ExtensionSessionConfiguration extensionConfiguration = new
        ExtensionSessionConfiguration(
                CameraExtensionCharacteristics.EXTENSION_NIGHT,
                outputConfig,
                backgroundExecutor,
                extensionSessionStateCallback
    );

extensionConfiguration.setPostviewOutputConfiguration(
    postviewImageOutput);
…
CaptureRequest.Builder captureRequestBuilder =
    cameraDevice.createCaptureRequest(
        CameraDevice.TEMPLATE_STILL_CAPTURE);
captureRequestBuilder.addTarget(stillImageReader.getSurface());
captureRequestBuilder.addTarget(postviewImageSurface);

CaptureRequest captureRequest = captureRequestBuilder.build();
…
}

Para oferecer suporte à captura de imagem estática pós-visualização, a implementação do fornecedor precisa implementar o seguinte:

Suporte à saída SurfaceView

No Android 14 e versões mais recentes, os clientes de extensão da câmera podem usar caminhos de renderização de visualização otimizados para energia e desempenho registrando uma instância SurfaceView para a saída de visualização de solicitações repetidas.

Para oferecer suporte à saída SurfaceView, a implementação da extensão do fornecedor precisa ser capaz de transmitir e gerar a prévia para instâncias SurfaceView. Para verificar se há suporte, execute o módulo CTS SurfaceViewExtensionPreviewTest.java.

Tipos de sessão específicos do fornecedor

O recurso permite que as implementações de extensões de fornecedores selecionem um tipo de sessão específico do fornecedor que será definido na sessão de captura interna da câmera em vez do valor padrão.

O recurso funciona totalmente dentro do framework e da pilha do fornecedor e não tem impacto na API visível para o cliente/público.

Para selecionar um tipo de sessão específico do fornecedor, implemente o seguinte para suas bibliotecas de extensão: * ExtenderStateListener.onSessionType() para extensões básicas * Camera2SessionConfigImpl.getSessionType() para extensões avançadas

Histórico de versões da interface das Extensões

A tabela a seguir mostra o histórico de versões da interface da extensão da câmera. Você sempre deve implementar a biblioteca do fornecedor com a versão mais recente.

Versão Recursos adicionados
1.0.0
  • Verificação de versão
    • ExtensionVersionImpl
  • Extensão básica
    • PreviewExtenderImpl
    • ImageCaptureExtenderImpl
    • Processor
      • PreviewImageProcessorImpl
      • CaptureProcessorImpl
      • RequestUpdateProcessorImpl
1.1.0
  • Inicialização da biblioteca
    • InitializerImpl
  • Exibir resoluções compatíveis
    • PreviewExtenderImpl.getSupportedResolutions
    • ImageCaptureExtenderImpl.getSupportedResolutions
1.2.0
  • AdvancedExtender
    • AdvancedExtenderImpl
    • SessionProcessorImpl
  • Receber a latência de captura estimada
    • ImageCaptureExtenderImpl.getEstimatedCaptureLatencyRange
1.3.0
  • Exposição de chaves de solicitação de captura/resultados compatíveis
    • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys e getAvailableCaptureResultKeys
    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys e getAvailableCaptureResultKeys
    • Nova chamada process() que recebe ProcessResultImpl em PreviewImageProcessorImpl e CaptureProcessorImpl
    • Solicitação de tipo de gatilho de suporte
      • AdvancedExtenderImpl.startTrigger
1.4.0
  • Metadados específicos da extensão
  • Estimativas de latência de captura estática dinâmica
  • Capturar callbacks de progresso do processamento
  • Captura estática de PostView
  • Suporte para saída SurfaceView
  • Tipos de sessão específicos do fornecedor

Implementação de referência

As seguintes implementações de referência da biblioteca do fornecedor OEM estão disponíveis em frameworks/ex.

  • advancedSample: uma implementação básica do Advanced Extender.

  • sample: uma implementação básica do extensor básico.

  • service_based_sample: uma implementação que demonstra como hospedar extensões de câmera em um Service. Essa implementação contém os seguintes componentes:

    • oem_library: uma biblioteca OEM de extensões de câmera para as APIs Camera2 e CameraX Extensions que implementa Extensions-Interface. Isso funciona como um encaminhamento que encaminha chamadas de Extensions-Interface para o serviço. Essa biblioteca também fornece arquivos AIDL e classes wrapper para se comunicar com o serviço.

      O Advanced Extender é ativado por padrão. Para ativar o extensor básico, mude ExtensionsVersionImpl#isAdvancedExtenderImplemented para retornar false.

    • extensions_service: um exemplo de implementação do serviço de extensões. Adicione sua implementação aqui. A interface a ser implementada no serviço é semelhante à Extensions-Interface. Por exemplo, a implementação de IAdvancedExtenderImpl.Stub executa as mesmas operações que AdvancedExtenderImpl. ImageWrapper e TotalCaptureResultWrapper são necessários para tornar Image e TotalCaptureResult parceláveis.

Configurar a biblioteca do fornecedor em um dispositivo

A biblioteca do fornecedor OEM não está integrada a um app. Ela é carregada do dispositivo no momento da execução pelo Camera2/X. No CameraX, a tag <uses-library> declara que a biblioteca androidx.camera.extensions.impl, definida no arquivo AndroidManifest.xml da biblioteca camera-extensions, é uma dependência do CameraX e precisa ser carregada no momento da execução. No Camera2, o framework carrega um serviço de extensões que também declara que o <uses-library> carrega a mesma biblioteca androidx.camera.extensions.impl no momento de execução.

Isso permite que apps de terceiros que usam extensões carreguem automaticamente a biblioteca do fornecedor OEM. A biblioteca do OEM é marcada como opcional para que os apps possam ser executados em dispositivos que não têm a biblioteca. A Camera2/X processa esse comportamento automaticamente quando um app tenta usar uma extensão de câmera, desde que o fabricante do dispositivo coloque a biblioteca OEM no dispositivo para que ela possa ser descoberta pelo app.

Para configurar a biblioteca do OEM em um dispositivo, faça o seguinte:

  1. Adicione um arquivo de permissão, que é necessário para a tag <uses-library>, usando o seguinte formato: /etc/permissions/ANY_FILENAME.xml. Por exemplo, /etc/permissions/camera_extensions.xml. Os arquivos nesse diretório fornecem um mapeamento da biblioteca nomeada em <uses-library> para o caminho de arquivo real no dispositivo.
  2. Use o exemplo abaixo para adicionar as informações necessárias ao arquivo.

    • name precisa ser androidx.camera.extensions.impl, porque essa é a biblioteca que o CameraX procura.
    • file é o caminho absoluto do arquivo que contém a implementação de extensões (por exemplo, /system/framework/androidx.camera.extensions.impl.jar).
    <?xml version="1.0" encoding="utf-8"?>
    <permissions>
        <library name="androidx.camera.extensions.impl"
                 file="OEM_IMPLEMENTED_JAR" />
    </permissions>
    

No Android 12 e versões mais recentes, os dispositivos com suporte a extensões CameraX precisam definir a propriedade ro.camerax.extensions.enabled como true, o que permite consultar se um dispositivo oferece suporte a extensões. Para fazer isso, adicione a seguinte linha no arquivo de fabricação do dispositivo:

PRODUCT_VENDOR_PROPERTIES += \
    ro.camerax.extensions.enabled=true \

Validação

Para testar a implementação da biblioteca do fornecedor OEM durante o estágio de desenvolvimento, use o app de exemplo em androidx-main/camera/integration-tests/extensionstestapp/, que é executado em várias extensões do fornecedor.

Depois de concluir a implementação, use a ferramenta de validação de extensões de câmera para executar testes automatizados e manuais e verificar se a biblioteca do fornecedor foi implementada corretamente.

Modo de cena estendida x extensões de câmera

Para a extensão de bokeh, além de expor usando extensões da câmera, você pode expor a extensão usando o modo de cena estendida, que é ativado pela chave CONTROL_EXTENDED_SCENE_MODE. Para mais detalhes de implementação, consulte Bokeh da câmera.

O modo de cena estendido tem menos restrições em comparação com as extensões de câmera para apps camera2. Por exemplo, é possível ativar o modo de cena estendida em uma instância CameraCaptureSession regular que oferece suporte a combinações de fluxo flexíveis e captura de parâmetros de solicitação. Em contraste, as extensões de câmera oferecem suporte apenas a um conjunto fixo de tipos de streaming e têm suporte limitado para parâmetros de solicitação de captura.

Uma desvantagem do modo de cena estendida é que ele só pode ser implementado no HAL da câmera, o que significa que ele precisa ser verificado para funcionar em todos os controles ortogonais disponíveis para desenvolvedores de apps.

Recomendamos expor o bokeh usando o modo de cena estendida e as extensões da câmera, porque os apps podem preferir usar uma API específica para ativar o bokeh. Recomendamos usar primeiro o modo de cena estendida, porque essa é a maneira mais flexível de ativar a extensão de bokeh em apps. Em seguida, é possível implementar a interface de extensões da câmera com base no modo de cena estendido. Se a implementação do bokeh na HAL da câmera for difícil, por exemplo, porque exige um pós- processador em execução na camada do app para processar imagens, recomendamos implementar a extensão de bokeh usando a interface de extensões da câmera.

Perguntas frequentes

Há alguma restrição nos níveis da API?

Sim. Isso depende do conjunto de recursos da API do Android que é necessário para a implementação da biblioteca do fornecedor OEM. Por exemplo, ExtenderStateListener.onPresetSession() usa a chamada SessionConfiguration.setSessionParameters() para definir um conjunto de referência de tags. Essa chamada está disponível apenas no nível 28 da API e versões mais recentes. Para detalhes sobre métodos de interface específicos, consulte a documentação de referência da API.