Extensões de câmera

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

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

Nesta página, descrevemos como implementar e ativar a biblioteca do fornecedor OEM em dispositivos.

Arquitetura

O diagrama a seguir descreve a arquitetura da interface Camera Extensions ou extensions-interface: Arquitetura

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

Como mostrado no diagrama, para oferecer suporte às extensões de câmera, é necessário implementar o extensions-interface fornecido pela biblioteca do fornecedor OEM. A 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 extensões do fornecedor.

Implementar a biblioteca do fornecedor OEM

Para implementar a biblioteca do fornecedor OEM, copie os arquivos camera-extensions-stub para um projeto de biblioteca do sistema. Esses arquivos definem a interface Camera Extensions.

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

Arquivos essenciais da interface (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 for compatível)

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

Classes de extensão noturna (implemente se a extensão noturna for compatível)

  • 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 for compatível)

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

Classes de extensão de retoque facial (implemente se a extensão de retoque facial for compatível)

  • 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 Extender correspondentes. As APIs Camera2 e CameraX Extensions informam ao app que a extensão não está disponível.

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

Mainflow

Figura 2. Implementação da extensão noturna

  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 compatíveis do Camera2/X.

  2. Inicialização da biblioteca do fornecedor:

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

  3. Instancie classes Extender:

    Instancia as classes Extender para a extensão. Há dois tipos de Extender: Basic Extender e Advanced Extender. É necessário implementar um tipo de extensor para todas as extensões. Para mais informações, consulte Extensor básico x Extensor avançado.

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

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

    • NightImageCaptureExtenderImpl.java
    • NightPreviewExtenderImpl.java

    E para o tipo Advanced Extender:

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

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

  5. Inicialize o Extender com informações da câmera:

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

  6. Informações da consulta:

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

  7. Ative a extensão no Extender:

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

    Para o tipo de extensor avançado, o Camera2/X interage com SessionProcessorImpl para ativar a extensão. O Camera2/X recupera a instância 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, o Camera2/X verifica se a biblioteca é compatível com a versão do 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 principal e secundária são usadas durante a verificação.

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

Compatibilidade com versões principais

Se as versões principais da interface de extensão 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 futuras do 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, convém ativar as extensões a partir de uma determinada versão. Nesse caso, retorne a versão extensions-interface compatível quando a versão da biblioteca Camera2/X atender aos requisitos. Se as versões do Camera2/X não forem compatíveis, retorne 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 do extensions-interface implementada pela biblioteca do OEM, a Camera2/X inicia o processo de inicialização. O método InitializerImpl.init() sinaliza para a biblioteca do OEM que um app está tentando usar extensões.

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

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

Extensor básico x Extensor avançado

Há dois tipos de implementação do extensions-interface: Basic Extender e Advanced Extender. O Advanced Extender tem suporte desde extensions-interface 1.2.0.

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

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

Confira a tabela a seguir para a comparação:

Extensor básico Extensor avançado
Configurações de transmissão Corrigido
Prévia: PRIVATE ou YUV_420_888 (se o processador existir)
Captura estática: JPEG ou YUV_420_888 (se o processador existir)
Personalizável pelo OEM.
Enviando 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, o Camera2/X pode enviar várias solicitações de captura e enviar todas as imagens e resultados de captura para o processador. Uma instância RequestProcessorImpl é fornecida para você executar a solicitação de captura da Camera2 e receber resultados e imagens.

O Camera2/X invoca startRepeating e startCapture em SessionProcessorImpl para sinalizar ao OEM que inicie a solicitação repetida de visualização e a sequência de captura de fotos, respectivamente.

Hooks no pipeline da câmera
  • O onPresetSession fornece parâmetros de sessão.
  • onEnableSession envia uma única solicitação logo após a configuração de CameraCaptureSession.
  • O onDisableSession envia uma única solicitação antes que o CameraCaptureSession seja fechado.
  • initSession inicializa e retorna uma configuração de sessão camera2 personalizada 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.
Adequado 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 de stream personalizada, como um stream RAW.
  • Precisa de uma sequência de captura interativa.
Versão da API compatível Extensões do Camera2: Android 13 ou versões mais recentes
Extensões do CameraX: camera-extensions 1.1.0 ou versões mais recentes
Extensões do 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 apps e as chamadas de 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 descrevemos em mais detalhes em uma seção posterior.

Extensões do Camera2 Extensões do CameraX
Disponibilidade da extensã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.

Visualizar e capturar imagens estáticas com a extensão ativada CameraDevice. createExtensionSession

cameraExtensionsSession. setRepeatingRequest

cameraExtensionsSession. capture

val cameraSelector = ExtensionsManager. getExtensionEnabledCameraSelector

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

Extensor básico

A interface Basic Extender fornece hooks em vários lugares no pipeline da câmera. Cada tipo de extensão tem classes Extender correspondentes que os OEMs precisam implementar.

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

Classes de extensão para implementar
Noite NightPreviewExtenderImpl.java

NightImageCaptureExtenderImpl.java

HDR HdrPreviewExtenderImpl.java

HdrImageCaptureExtenderImpl.java

Automóveis AutoPreviewExtenderImpl.java

AutoImageCaptureExtenderImpl.java

Bokeh BokehPreviewExtenderImpl.java

BokehImageCaptureExtenderImpl.java

Retoque facial BeautyPreviewExtenderImpl.java

BeautyImageCaptureExtenderImpl.java

Usamos PreviewExtenderImpl e ImageCaptureExtenderImpl como marcadores no exemplo a seguir. Substitua esses nomes pelos nomes dos arquivos reais que você está implementando.

O Basic Extender tem os seguintes recursos:

  • Injete parâmetros de sessão ao configurar CameraCaptureSession (onPresetSession).
  • Notificar você sobre os eventos de início e encerramento da sessão de captura e enviar uma única solicitação para notificar o HAL com os parâmetros retornados (onEnableSession, onDisableSession).
  • Injete parâmetros de captura para a solicitação (PreviewExtenderImpl.getCaptureStage, ImageCaptureExtenderImpl.getCaptureStages).
  • Adicione processadores para prévia e captura de imagens estáticas capazes de processar o fluxo YUV_420_888.

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

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

BasicExtenderAppFlow1

Figura 3. Fluxo de app 1 no Basic Extender

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

Essa é geralmente a primeira etapa para os apps verificarem se o tipo de extensão especificado é compatível com um determinado ID de câmera antes de ativar a extensão. Isso ocorre porque algumas extensões são compatíveis apenas com determinados IDs de câmera.

Fluxo do app 2: informações da consulta

BasicExtenderAppFlow2

Figura 4. Fluxo de app 2 no Basic Extender

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

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

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

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

    • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys
    • ImageCaptureExtenderImpl.getAvailableCapturetResultKeys

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

Fluxo do app 3: captura de prévia/imagem estática com extensão ativada (implementação da HAL)

BasicExtenderAppFlow3

Figura 5. Fluxo de app 3 no Basic Extender

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

Nesse fluxo, o Camera2/X primeiro chama init() e depois onInit, que notifica você que uma sessão de câmera está prestes a começar com as extensões especificadas. Você pode fazer a inicialização pesada em onInit().

Ao configurar CameraCaptureSession, o 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 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, o Camera2/X invoca onDisableSession e envia uma única solicitação com os parâmetros de captura retornados.

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

Por fim, o Camera2/X invoca onDeInit() depois que a sessão da câmera é concluída. Você pode liberar recursos em onDeinit().

Processador de visualização

Além da HAL da câmera, também é possível 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. PreviewExtenderImpl.getCaptureStage() também precisa refletir o resultado do processamento e retornar o CaptureStageImpl mais recente.

  • PROCESSOR_TYPE_IMAGE_PROCESSOR:esse tipo permite 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 PreviewImageProcessorImpl em PreviewExtenderImpl.getProcessor. O processador é responsável por processar imagens de entrada YUV_420_888. Ele precisa gravar a saída no formato PRIVATE da prévia. O Camera2/X usa uma superfície YUV_420_888 em vez de PRIVATE para configurar o CameraCaptureSession para visualização.

    Confira a ilustração a seguir para o fluxo:

PreviewProcessor

Figura 6. Fluxo de prévia 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 pixel, 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ó pode ser YUV_420_888.

Processador de captura de imagem

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

Você pode presumir que a prévia 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. Ainda capture o fluxo com CaptureProcessorImpl

  1. O Camera2/X usa uma superfície de formato YUV_420_888 para captura de imagens estáticas e configurar a sessão de captura. O 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 enviará três solicitações de captura com 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 resultante (formato YUV_420_888) na superfície de saída especificada pela chamada onOutputSurface(). O Camera2/X a converte em imagens JPEG, se necessário.

Aceitar 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 um toque para focar. Esses parâmetros podem não ser compatíveis com a implementação da extensão.

Os seguintes métodos 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 sua implementação.
  • ImageCaptureExtenderImpl.getAvailableCaptureResultKeys() retorna as chaves de resultado da 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. No extensions-interface 1.3.0 ou versões mais recentes, 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 oferecer suporte às seguintes chaves para solicitação e resultado de 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 será compatível com o app, enquanto o toque para foco, o flash e a compensação de exposição não serão permitidos.

Extensor avançado

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

  • Configuração de stream personalizada:configure streams personalizadas, como a RAW, ou tenha várias streams para diferentes IDs de câmera física.

  • Capacidade de enviar solicitações da Camera2:compatibilidade com uma lógica de interação complicada que pode enviar solicitações de captura com parâmetros baseados nos resultados de solicitações anteriores.

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

Arquivos para implementar

Para mudar para a implementação do Advanced Extender, o método isAdvancedExtenderImplemented() em ExtensionVersionImpl precisa retornar true. Para cada tipo de extensão, os OEMs precisam implementar as classes Extender 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óveis advanced/AutoAdvancedExtenderImpl.java
Bokeh advanced/BokehAdvancedExtenderImpl.java
Retoque facial advanced/BeautyAdvancedExtenderImpl.java

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

Vamos ver como o Camera2/X invoca o extensions-interface para alcançar os três fluxos de apps.

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

AdvancedAppFlow1

Figura 8. Fluxo de app 1 no Advanced Extender

Primeiro, o app verifica se a extensão especificada é compatível.

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 seguintes informações em AdvancedExtenderImpl:

  • Latência estimada de captura estática:o AdvancedExtenderImpl.getEstimatedCaptureLatencyRange() retorna o intervalo da latência de captura para que o app avalie se é adequado 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 da imagem para a lista de tamanhos compatíveis com o formato e o tamanho da superfície de visualização. Os OEMs precisam ser compatíveis com pelo menos o formato PRIVATE.

    • AdvancedExtenderImpl.getSupportedCaptureOutputResolutions() retorna o formato e os tamanhos compatíveis para a superfície de captura de imagens estáticas. Os OEMs precisam oferecer suporte à saída nos formatos JPEG e YUV_420_888.

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

  • Chaves/resultados de solicitação de captura disponíveis (adicionado no extensions-interface 1.3.0): o Camera2/X invoca os seguintes métodos para recuperar as chaves de solicitação de captura e de resultado compatíveis da sua 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: captura de prévia/imagem estática com extensão ativada

AdvancedAppFlow3

Figura 10. Fluxo de app 3 no Advanced Extender

O diagrama acima mostra o fluxo principal para iniciar a prévia e a captura de imagem para o tipo de extensor avançado. Vamos analisar cada etapa.

  1. Instância do SessionProcessorImpl

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

  2. initSession

    SessionProcessorImpl.initSession() inicializa a sessão para a 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 de superfície de saída para prévia, captura de imagem estática 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 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 gerar as imagens corretas da câmera 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 a CameraCaptureSession com uma implementação de SurfaceOutputConfigImpl. Isso configura a superfície de saída fornecida para o pipeline da câmera e permite que a HAL da câmera processe a imagem.
    • Processamento da superfície intermediária ImageReader (RAW, YUV etc.): adicione as superfícies intermediárias ImageReader ao CameraCaptureSession com uma instância ImageReaderOutputConfigImpl.

      É necessário processar as imagens intermediárias e gravar a imagem resultante 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 recuperar a imagem de ImageReaderOutputConfigImpl.

  3. onCaptureSessionStart e RequestProcessorImpl

    Quando CameraCaptureSession é iniciado e o framework Camera 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 Camera2 CameraCaptureSession em termos de execução de solicitações. As diferenças são:

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

    Você pode chamar RequestProcessorImpl.setImageProcessor() com um ID Camera2OutputConfigImpl especificado para registrar uma instância ImageProcessorImpl e 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 Advanced Extender, é possível enviar solicitações de captura pela interface RequestProcessorImpl. O 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. Envie solicitações de captura para atender a essas solicitações de prévia e captura de imagem.

    A Camera2/X também define os parâmetros de solicitação de captura usando SessionProcessorImpl#setParameters. Você precisa definir esses parâmetros de solicitação (se compatíveis) nas solicitações únicas e repetidas.

    É preciso oferecer suporte a pelo menos CaptureRequest.JPEG_ORIENTATION e CaptureRequest.JPEG_QUALITY. O extensions-interface 1.3.0 é compatível com 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 gatilho, como CaptureRequest.CONTROL_AF_TRIGGER e CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER. Você pode ignorar as chaves de solicitação de captura que não foram anunciadas em AdvancedExtenderImpl.getAvailableCaptureRequestKeys().

    O startTrigger() é compatível desde o extensions-interface 1.3.0. Ele permite que os apps implementem o toque para foco e o flash com extensões.

  6. Limpar

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

Suporte para prévia, captura de imagens estáticas e análise de imagens

Você precisa aplicar a extensão para os casos de uso de visualização e captura de imagens estáticas. No entanto, se a latência for muito alta para mostrar a prévia sem problemas, você poderá aplicar a extensão apenas para captura de imagens estáticas.

Para o tipo de extensão básica, independente 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 streams de visualização, captura de fotos e um stream YUV_420_888 para configurar CameraCaptureSession. Isso significa que, se você implementar um processador, precisará oferecer suporte à combinação de fluxo de três fluxos YUV_420_888.

Para o Advanced Extender, o Camera2/X transmite três superfícies de saída para a chamada SessionProcessorImpl.initSession(). Essas superfícies de saída são para visualização , captura de imagens estáticas e análise de imagens, respectivamente. Verifique se as superfícies de saída de prévia e captura de imagens mostram a saída válida. No entanto, para a superfície de saída da análise de imagem, verifique se ela está funcionando apenas quando não é nula. Se a implementação não puder oferecer suporte ao fluxo de análise de imagens, retorne uma lista vazia em AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions(). Isso garante que a superfície 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 imagens estáticas. 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 da prévia.

Estamos investigando a compatibilidade com plataformas MediaCodec e MediaRecorder.

Metadados específicos da extensão

No Android 14 e em versões mais recentes, os metadados específicos da extensão permitem que os clientes de extensão de 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 de 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 ativada.

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 da captura correspondente inclui o valor de intensidade padrão se esse parâmetro não for definido explicitamente pelo cliente. Esse parâmetro pode ser aplicado da seguinte forma para esses tipos de extensão:

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

O intervalo compatível para o parâmetro EXTENSION_STRENGTH é entre 0 e 100. 0 indica que não há processamento de extensão ou passagem simples, e 100 indica a intensidade máxima da extensão do efeito de processamento.

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

Capturar resultados

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

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 de câmera podem consultar estimativas de latência de captura estática em tempo real com base nas condições de cena e ambiente usando getRealtimeStillCaptureLatency(). Esse método oferece 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 da extensão ou mostrar uma indicação para notificar os usuários sobre uma operação de longa duração.

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:

Callbacks de progresso do processamento de captura

No Android 14 e versões mais recentes, os clientes de extensão de câmera podem receber callbacks para o progresso de operações de processamento de captura de imagens estáticas 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 prévia) usando setPostviewOutputConfiguration. Para melhorar a experiência do usuário, os apps podem mostrar uma imagem de pós-visualização como um marcador de posição quando uma extensão está com maior latência de processamento e substituir a imagem quando a final estiver disponível. Os apps podem configurar e emitir solicitações de captura pós-visualização 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 imagens estáticas pós-visualização, a implementação do fornecedor precisa implementar o seguinte:

Suporte de 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 performance registrando uma instância SurfaceView para saída de visualização em solicitações repetidas.

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

Tipos de sessão específicos do fornecedor

O recurso permite que as implementações de extensão do fornecedor selecionem um tipo de sessão específico do fornecedor que será definido na sessão interna de captura 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 nas 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 Camera Extension. Sempre implemente a biblioteca do fornecedor com a versão mais recente.

Versão Recursos adicionados
1.0.0
  • Verificação de versão
    • ExtensionVersionImpl
  • Extensor básico
    • PreviewExtenderImpl
    • ImageCaptureExtenderImpl
    • Processor
      • PreviewImageProcessorImpl
      • CaptureProcessorImpl
      • RequestUpdateProcessorImpl
1.1.0
  • Inicialização da biblioteca
    • InitializerImpl
  • Expor 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
  • Expor chaves de solicitação de captura/chaves de resultados compatíveis
    • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys e getAvailableCaptureResultKeys
    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys e getAvailableCaptureResultKeys
    • Nova chamada de process() que usa 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 dinâmicas de latência de captura estática
  • Callbacks de progresso do processamento de captura
  • 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 biblioteca de fornecedores OEM de referência estão disponíveis em frameworks/ex.

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

  • sample: uma implementação básica do Basic Extender.

  • 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 da câmera para as APIs Camera2 e CameraX Extensions que implementa Extensions-Interface. Ele funciona como uma transmissão 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 está ativado por padrão. Para ativar o Basic Extender, mude ExtensionsVersionImpl#isAdvancedExtenderImplemented para retornar false.

    • extensions_service: Uma implementação de amostra 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 obrigatórios para tornar Image e TotalCaptureResult parceláveis.

Configurar a biblioteca do fornecedor em um dispositivo

A biblioteca do fornecedor OEM não é integrada a um app. Ela é carregada do dispositivo no tempo de 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 ambiente de 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 durante a 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. O 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 é exigido pela 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 real do arquivo no dispositivo.
  2. Use o exemplo abaixo para adicionar as informações necessárias ao arquivo.

    • name precisa ser androidx.camera.extensions.impl, já que é a biblioteca que o CameraX procura.
    • file é o caminho absoluto do arquivo que contém a implementação das 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 ou versões mais recentes, os dispositivos com suporte a extensões CameraX precisam definir a propriedade ro.camerax.extensions.enabled como true, o que possibilita consultar se um dispositivo oferece suporte a extensões. Para fazer isso, adicione a seguinte linha ao arquivo de criação do dispositivo:

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

Validação

Para testar sua implementação da biblioteca do fornecedor OEM durante a etapa de desenvolvimento, use o app de exemplo em androidx-main/camera/integration-tests/extensionstestapp/, que passa por 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 estendido x extensões de câmera

Para a extensão de bokeh, além de expor usando extensões de câmera, você pode expor a extensão usando o modo de cena estendido, 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 estendido em uma instância CameraCaptureSession comum que oferece suporte a combinações flexíveis de streams e parâmetros de solicitação de captura. Em contrapartida, as extensões de câmera só oferecem suporte a um conjunto fixo de tipos de stream e têm suporte limitado para parâmetros de solicitação de captura.

Uma desvantagem do modo de cena estendido é 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 efeito bokeh usando o modo de cena estendido e as extensões do CameraX, porque os apps podem preferir usar uma API específica para ativar o efeito. Recomendamos usar primeiro o modo de cena estendido, porque essa é a maneira mais flexível para os apps ativarem a extensão de desfoque. Em seguida, implemente a interface de extensões de câmera com base no modo de cena estendido. Se for difícil implementar o efeito bokeh na HAL da câmera, por exemplo, porque ele exige um pós- processador em execução na camada do app para processar imagens, recomendamos implementar a extensão bokeh usando a interface Camera Extensions.

Perguntas frequentes

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

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