Os fabricantes de dispositivos podem expor extensões como bokeh, modo noturno e HDR para desenvolvedores terceirizados por meio da interface de extensões de câmera fornecida pela biblioteca do fornecedor 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 obter uma lista de extensões suportadas, que é a mesma em Camera2 e CameraX, consulte API de extensões CameraX . Se você quiser adicionar uma extensão, registre 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 Camera Extensions ou extensions-interface
:
Figura 1. Diagrama de arquitetura de extensões de câmera
Conforme mostrado no diagrama, para oferecer suporte a extensões de câmera, você precisa implementar a extensions-interface
fornecida pela biblioteca do fornecedor OEM. Sua biblioteca de fornecedores OEM permite duas APIs: CameraX Extensions API e Camera2 Extensions API , que são usadas pelos aplicativos CameraX e Camera2, respectivamente, para acessar extensões de fornecedores.
Implementar a biblioteca de fornecedores 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 extensoras de Bokeh (implemente-as se a extensão Bokeh for suportada)
-
BokehImageCaptureExtenderImpl.java
-
BokehPreviewExtenderImpl.java
-
advanced/BokehAdvancedExtenderImpl.java
Classes extensoras noturnas (implemente-as se a extensão noturna for suportada)
-
NightImageCaptureExtenderImpl.java
-
NightPreviewExtenderImpl.java
-
advanced/NightAdvancedExtenderImpl.java
Classes de extensão automática (implemente-as se a extensão automática for suportada)
-
AutoImageCaptureExtenderImpl.java
-
AutoPreviewExtenderImpl.java
-
advanced/AutoAdvancedExtenderImpl.java
Classes de extensor HDR (implemente-as se a extensão HDR for suportada)
-
HdrImageCaptureExtenderImpl.java
-
HdrPreviewExtenderImpl.java
-
advanced/HdrAdvancedExtenderImpl.java
Classes extensoras de Retoque Facial (implemente-as se a extensão Retoque Facial for suportada)
-
BeautyImageCaptureExtenderImpl.java
-
BeautyPreviewExtenderImpl.java
-
advanced/BeautyAdvancedExtenderImpl.java
Utilitários (opcional, pode ser excluído)
-
advanced/Camera2OutputConfigImplBuilder.java
-
advanced/Camera2SessionConfigImplBuilder.java
Você não é obrigado a fornecer uma implementação para cada extensão. Se você não implementar uma extensão, configure isExtensionAvailable()
para retornar false
ou remova as classes Extender correspondentes. As APIs de extensões Camera2 e CameraX informam ao aplicativo que a extensão não está disponível.
Vejamos como as APIs de extensões Camera2 e CameraX interagem com a biblioteca do fornecedor para habilitar uma extensão. O diagrama a seguir ilustra o fluxo ponta a ponta usando a extensão Night como exemplo:
Figura 2. Implementação da extensão noturna
Verificação de versão:
Camera2/X chama
ExtensionVersionImpl.checkApiVersion()
para garantir que a versãoextensions-interface
implementada pelo OEM seja compatível com as versões suportadas por Camera2/X.Inicialização da biblioteca do fornecedor:
InitializerImpl
possui um métodoinit()
que inicializa a biblioteca do fornecedor. Camera2/X conclui a inicialização antes de acessar as classes do Extender.Instanciar classes do Extender:
Instancia as classes Extender para a extensão. Existem dois tipos de Extender: Extender Básico e Extender Avançado. Você deve implementar um tipo de extensor para todas as extensões. Para obter mais informações, consulte Extender Básico versus Extender Avançado .
Camera2/X instancia e interage com as classes Extender para recuperar informações e ativar a extensão. Para uma determinada extensão, Camera2/X pode instanciar as classes Extender várias vezes. Como resultado, não faça inicialização pesada 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 quandoonInit()
é chamado no Basic Extender ouinitSession()
é chamado no Advanced Extender.Para a extensão Night, as seguintes classes Extender são instanciadas para o tipo Basic Extender:
-
NightImageCaptureExtenderImpl.java
-
NightPreviewExtenderImpl.java
E para o tipo Advanced Extender:
-
NightAdvancedExtenderImpl.java
-
Verifique a disponibilidade da extensão:
Antes de habilitar a extensão,
isExtensionAvailable()
verifica se a extensão está disponível no ID da câmera especificada por meio da instância do Extender.Inicialize o Extender com informações da câmera:
Camera2/X chama
init()
na instância do Extender e passa a ela o ID da câmera eCameraCharacteristics
.Informações de consulta:
Invoca a classe Extender para recuperar informações como resoluções suportadas, ainda capturar a latência estimada e capturar chaves de solicitação do Extender em preparação para habilitar a extensão.
Habilite a extensão no Extender:
A classe Extender fornece todas as interfaces necessárias para habilitar a classe. Ele oferece um mecanismo para conectar a implementação OEM ao pipeline Camera2, como injetar parâmetros de solicitação de captura ou ativar um pós-processador.
Para o tipo Advanced Extender, Camera2/X interage com
SessionProcessorImpl
para ativar a extensão. Camera2/X recupera a instânciaSessionProcessorImpl
chamandocreateSessionProcessor()
no Extender.
As seções a seguir descrevem o fluxo de extensão com mais detalhes.
Verificação de versão
Ao carregar a biblioteca do fornecedor OEM do dispositivo em tempo de execução, Camera2/X verifica se a biblioteca é compatível com a versão extensions-interface
. A extensions-interface
usa controle de versão semântico, ou MAJOR.MINOR.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, Camera2/X chama ExtensionVersionImpl.checkApiVersion()
com a versão extensions-interface
suportada. Camera2/X então usa a versão relatada pela biblioteca OEM para determinar se a extensão pode ser habilitada e quais recursos ela deve invocar.
Compatibilidade de versão principal
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
Contanto que a versão principal seja idêntica, o Camera2/X garante compatibilidade retroativa com bibliotecas de fornecedores OEM construídas com versões anteriores extensions-interface
. Por exemplo, se Camera2/X suportar 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 extension-interface
futura.
Compatibilidade futura
A compatibilidade futura com bibliotecas de fornecedores de extensions-interface
mais recentes depende de você, o OEM. Se precisar de alguns recursos para implementar as extensões, você pode querer habilitá-las a partir de uma determinada versão. Nesse caso, você pode retornar a versão extensions-interface
suportada quando a versão da biblioteca Camera2/X atender aos requisitos. Se as versões Camera2/X não forem suportadas, você poderá retornar uma versão incompatível, como 99.0.0, para desativar as extensões.
Inicialização da biblioteca do fornecedor
Após verificar a versão extensions-interface
implementada pela biblioteca OEM, Camera2/X inicia o processo de inicialização. O método InitializerImpl.init()
sinaliza à biblioteca OEM que um aplicativo está tentando usar extensões.
Camera2/X não faz outras chamadas para a biblioteca OEM (além da verificação de versão) até que a biblioteca do fornecedor OEM chame OnExtensionsInitializedCallback.onSuccess()
para notificar a conclusão da inicialização.
Você deve implementar InitializerImpl
a partir da extensions-interface
1.1.0. Camera2/X ignora a etapa de inicialização da biblioteca se a biblioteca do fornecedor OEM implementar extensions-interface
1.0.0.
Extensor Básico versus Extensor Avançado
Existem dois tipos de implementação extensions-interface
: Basic Extender e Advanced Extender. Advanced Extender é suportado desde 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 stream Camera2 e enviar solicitações de captura conforme necessário.
Veja a tabela a seguir para comparação:
Extensor Básico | Extensor Avançado | |
---|---|---|
Configurações de fluxo | Fixo Pré-visualização: PRIVATE ou YUV_420_888 (se existir processador)Captura de imagem: JPEG ou YUV_420_888 (se existir processador) | Customizável por OEM. |
Enviando solicitação de captura | Somente Camera2/X pode enviar solicitações de captura. Você pode definir os parâmetros para essas solicitações. Quando o processador é fornecido para captura de imagem, Camera2/X pode enviar múltiplas solicitações de captura e enviar todas as imagens e resultados de captura para o processador. | Uma instância RequestProcessorImpl é fornecida a você para executar a solicitação de captura camera2 e obter resultados e imagem. Camera2/X invoca |
Ganchos no pipeline da câmera |
|
|
Adequado para | Extensões implementadas no HAL da câmera ou em um processador que processa imagens YUV. |
|
Versão da API suportada | Extensões Camera2: Android 13 ou superior Extensões CameraX: camera-extensions 1.1.0 ou superior | Extensões Camera2: Android 12L ou superior Extensões CameraX: camera-extensions 1.2.0-alpha03 ou superior |
Fluxos de aplicativos
A tabela a seguir mostra três tipos de fluxos de aplicativos e suas chamadas de API de extensões de câmera correspondentes. Embora Camera2/X forneça essas APIs, você deve implementar adequadamente a biblioteca do fornecedor para dar suporte a esses fluxos, que descreveremos com mais detalhes em uma seção posterior.
Extensões da câmera2 | Extensões CameraX | |
---|---|---|
Disponibilidade da extensão de consulta | CameraExtensionCharacteristics . getSupportedExtensions | ExtensionsManager. isExtensionAvailable |
Consultar informações | CameraExtensionCharacteristics. getExtensionSupportedSizes CameraExtensionCharacteristics. getEstimatedCaptureLatencyRangeMillis CameraExtensionCharacteristics. getAvailableCaptureRequestKeys CameraExtensionCharacteristics. getAvailableCaptureResultKeys | ExtensionsManager. getEstimatedCaptureLatencyRange CameraX lida com o restante das informações da biblioteca. |
Visualizar e capturar imagens com extensão habilitada | CameraDevice. createExtensionSession | val cameraSelector = ExtensionsManager. getExtensionEnabledCameraSelector bindToLifecycle(lifecycleOwner, cameraSelector, visualização, ...) |
Extensor Básico
A interface do Basic Extender fornece ganchos em vários locais do pipeline da câmera. Cada tipo de extensão possui classes Extender correspondentes que os OEMs precisam implementar.
A tabela a seguir lista as classes Extender que os OEMS precisam implementar para cada extensão:
Classes extensoras para implementar | |
---|---|
Noite | NightPreviewExtenderImpl.java |
HDR | HdrPreviewExtenderImpl.java |
Auto | AutoPreviewExtenderImpl.java |
Bokeh | BokehPreviewExtenderImpl.java |
Retoque facial | BeautyPreviewExtenderImpl.java |
Usamos PreviewExtenderImpl
e ImageCaptureExtenderImpl
como espaços reservados no exemplo a seguir. Substitua-os pelos nomes dos arquivos reais que você está implementando.
O Extender Básico possui os seguintes recursos:
- Injete parâmetros de sessão ao configurar
CameraCaptureSession
(onPresetSession
). - Notificá-lo sobre os eventos de início e fechamento 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 visualização e captura que sejam capazes de processar o fluxo
YUV_420_888
.
Vamos ver como Camera2/X invoca a extensions-interface
para atingir os três fluxos de aplicativos mencionados acima.
Fluxo de aplicativo 1: verificar a disponibilidade da extensão
Figura 3. Fluxo de aplicativo 1 no Basic Extender
Neste fluxo, Camera2/X chama diretamente o método isExtensionAvailable()
de PreviewExtenderImpl
e ImageCaptureExtenderImpl
sem chamar init()
. Ambas as classes Extender devem retornar true
para ativar as extensões.
Geralmente, essa é a primeira etapa para os aplicativos verificarem se o tipo de extensão fornecido é compatível com um determinado ID de câmera antes de ativar a extensão. Isso ocorre porque algumas extensões são suportadas apenas em determinados IDs de câmera.
Fluxo de aplicativo 2: consultar informações
Figura 4. Fluxo de aplicativo 2 no Basic Extender
Depois de determinar se a extensão está disponível, os aplicativos devem consultar as informações a seguir antes de ativar a extensão.
Ainda intervalo de latência de captura:
ImageCaptureExtenderImpl.getEstimatedCaptureLatencyRange
retorna o intervalo de latência de captura para o aplicativo avaliar se é apropriado habilitar a extensão para o cenário atual.Tamanhos suportados para a superfície de visualização e captura:
ImageCaptureExtenderImpl.getSupportedResolutions
ePreviewExtenderImpl.getSupportedResolutions
retornam uma lista de formatos de imagem e os tamanhos que são suportados para formato e tamanho de superfície.Chaves de solicitação e resultado suportadas: Camera2/X invoca os seguintes métodos para recuperar as chaves de solicitação de captura e chaves de resultado suportadas de sua implementação:
-
ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys
-
ImageCaptureExtenderImpl.getAvailableCapturetResultKeys
-
Camera2/X sempre chama init()
primeiro nessas classes do Extender antes de consultar mais informações.
Fluxo de aplicativo 3: visualização/captura estática com extensão habilitada (implementação HAL)
Figura 5. Fluxo de aplicativo 3 no Basic Extender
O diagrama acima ilustra o fluxo principal de ativação da visualização e ainda da captura com uma extensão sem qualquer processador. Isso significa que a câmera HAL processa a extensão.
Nesse fluxo, Camera2/X primeiro chama init()
e depois onInit
, que notifica que uma sessão de câmera está prestes a começar com as extensões especificadas. Você pode fazer uma inicialização pesada em onInit()
.
Ao configurar CameraCaptureSession
, Camera2/X invoca onPresetSession
para obter os parâmetros da sessão. Depois que a sessão de captura for configurada com sucesso, Camera2/X invoca onEnableSession
retornando uma instância CaptureStageImpl
que contém os parâmetros de captura. Camera2/X envia imediatamente uma única solicitação com esses parâmetros de captura para notificar o HAL. Da mesma forma, antes que a sessão de captura seja fechada, Camera2/X invoca onDisableSession
e envia uma única solicitação com os parâmetros de captura retornados.
A solicitação repetida acionada por Camera2/X contém os parâmetros de solicitação retornados por PreviewExtenderImpl.getCaptureStage()
. Além disso, a solicitação de captura estática contém os parâmetros retornados por ImageCaptureExtenderImpl.getCaptureStages()
.
Finalmente, Camera2/X invoca onDeInit()
após o término da sessão da câmera. Você pode liberar recursos em onDeinit()
.
Processador de visualização
Além do 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
: Sem processador. As imagens são processadas na câmera HAL.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 noTotalCaptureResult
mais recente.PreviewExtenderImpl.getProcessor
deve retornar uma instânciaRequestUpdateProcessorImpl
que processa a instânciaTotalCaptureResult
e retorna uma instânciaCaptureStageImpl
para atualizar a solicitação repetida.PreviewExtenderImpl.getCaptureStage()
também deve refletir o resultado do processamento e retornar oCaptureStageImpl
mais recente.PROCESSOR_TYPE_IMAGE_PROCESSOR
: Este tipo permite implementar um processador para processar imagensYUV_420_888
e gravar a saída em uma superfíciePRIVATE
.Você precisa implementar e retornar uma instância
PreviewImageProcessorImpl
emPreviewExtenderImpl.getProcessor
. O processador é responsável pelo processamento das imagens de entradaYUV_420_888
. Deve gravar a saída no formatoPRIVATE
de visualização. Camera2/X usa uma superfícieYUV_420_888
em vez dePRIVATE
para configurarCameraCaptureSession
para visualização.Veja a ilustração a seguir para o fluxo:
Figura 6. Fluxo de visualização com PreviewImageProcessorImpl
A interface PreviewImageProcessorImpl
estende ProcessImpl
e possui três métodos importantes:
onOutputSurface(Surface surface, int imageFormat)
define a superfície de saída para o processador. ParaPreviewImageProcessorImpl
,imageFormat
é um formato de pixel comoPixelFormat.RGBA_8888
.onResolutionUpdate(Size size)
define o tamanho da imagem de entrada.onImageFormatUpdate(int imageFormat)
define o formato da imagem de entrada. Atualmente, só pode serYUV_420_888
.
Processador de captura de imagem
Para captura estática, você pode 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 assumir com segurança que a visualização está habilitada e em execução antes de enviar a solicitação de captura estática.
Veja o fluxo no diagrama abaixo:
Figura 7. Fluxo de captura contínua com CaptureProcessorImpl
Camera2/X usa uma superfície de formato
YUV_420_888
para captura estática para configurar a sessão de captura. Camera2/X preparaCaptureProcessorImpl
chamando:-
CaptureProcessorImpl.onImageFormatUpdate()
comYUV_420_888
. -
CaptureProcessorImpl.onResolutionUpdate()
pelo tamanho da imagem de entrada. -
CaptureProcessorImpl.onOutputSurface()
com uma superfície de saídaYUV_420_888
.
-
ImageCaptureExtenderImpl.getCaptureStages
retorna uma lista deCaptureStageImpl
, onde cada elemento é mapeado para uma instânciaCaptureRequest
com parâmetros de captura que são enviados por Camera2/X. Por exemplo, se retornar uma lista de três instânciasCaptureStageImpl
, Camera2/X enviará três solicitações de captura com parâmetros de captura correspondentes usando a APIcaptureBurst
.As imagens recebidas e as instâncias
TotalCaptureResult
são agrupadas e enviadas aoCaptureProcessorImpl
para processamento.CaptureProcessorImpl
grava a imagem resultante (formatoYUV_420_888
) na superfície de saída especificada pela chamadaonOutputSurface()
. Camera2/X converte-o em imagens JPEG, se necessário.
Chaves e resultados de solicitação de captura de suporte
Além da visualização e captura da câmera, os aplicativos 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 sua extensão.
Os métodos a seguir foram adicionados ao extensions-interface
1.3.0 para permitir que você exponha os parâmetros suportados pela sua implementação:
-
ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys()
retorna as chaves de solicitação de captura suportadas pela sua implementação. -
ImageCaptureExtenderImpl.getAvailableCaptureResultKeys()
retorna as chaves do resultado da captura que estão contidas no resultado da captura.
Se o HAL da câmera processar a extensão, Camera2/X recuperará os resultados da captura em CameraCaptureSession.CaptureCallback
. No entanto, se o processador for implementado, o Camera2/X recupera os resultados da captura em ProcessResultImpl
, que é passado para o método process()
em PreviewImageProcessorImpl
e CaptureProcessorImpl
. Você é responsável por relatar o resultado da captura por meio ProcessResultImpl
para Camera2/X.
Consulte a definição da interface CaptureProcessorImpl
abaixo como exemplo. Na extensions-interface
1.3.0 ou superior, 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 de câmera, como zoom, toque para focar, flash e compensação de exposição, recomendamos oferecer suporte às seguintes teclas para solicitação e resultado de captura:
- Ampliação:
-
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
-
- Clarão:
-
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 versões 1.2.0 ou anteriores, a API CameraX Extensions suporta explicitamente todas as chaves acima. Para extensions-interface
1.3.0, tanto CameraX quanto Camera2 respeitam a lista retornada e suportam apenas as 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 aplicativo, enquanto o toque para focar, o flash e a compensação de exposição não são permitidos.
Extensor Avançado
Advanced Extender é um tipo de implementação de fornecedor baseado na API Camera2. Este tipo de Extender foi adicionado na extensions-interface
1.2.0. Dependendo do fabricante do dispositivo, as extensões podem ser implementadas na camada do aplicativo, o que depende dos seguintes fatores:
Configuração de stream personalizada: configure streams personalizados como stream RAW ou tenha vários streams para diferentes IDs de câmera física.
Capacidade de enviar solicitações Camera2: Suporta 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 fornece um wrapper, ou uma camada intermediária, para que você possa customizar a configuração do fluxo 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
deve retornar true
. Para cada tipo de extensão, os OEMs devem implementar as classes Extender correspondentes. Os arquivos de implementação do Advanced Extender estão no pacote avançado .
Classes extensoras para implementar | |
---|---|
Noite | advanced/NightAdvancedExtenderImpl.java |
HDR | advanced/HdrAdvancedExtenderImpl.java |
Auto | advanced/AutoAdvancedExtenderImpl.java |
Bokeh | advanced/BokehAdvancedExtenderImpl.java |
Retoque facial | advanced/BeautyAdvancedExtenderImpl.java |
Usamos AdvancedExtenderImpl
como espaço reservado no exemplo a seguir. Substitua-o pelo nome do arquivo Extender da extensão que você está implementando.
Vamos ver como Camera2/X invoca a extensions-interface
para atingir os três fluxos de aplicativo.
Fluxo de aplicativo 1: verificar a disponibilidade de extensões
Figura 8. Fluxo de aplicativo 1 no Advanced Extender
Primeiro, o aplicativo verifica se a extensão fornecida é compatível.
Fluxo de aplicativo 2: consultar informações
Figura 9. Fluxo de aplicativo 2 no Advanced Extender
Depois de chamar AdvancedExtenderImpl.init()
, o aplicativo pode consultar as seguintes informações em AdvancedExtenderImpl
:
Latência estimada de captura ainda:
AdvancedExtenderImpl.getEstimatedCaptureLatencyRange()
retorna o intervalo de latência de captura para o aplicativo avaliar se é apropriado habilitar a extensão para o cenário atual.Resoluções suportadas para visualização e captura:
AdvancedExtenderImpl.getSupportedPreviewOutputResolutions()
retorna um mapa de formato de imagem para a lista de tamanhos que são suportados para formato e tamanho de superfície de visualização. Os OEMs devem suportar pelo menos o formatoPRIVATE
.AdvancedExtenderImpl.getSupportedCaptureOutputResolutions()
retorna o formato e os tamanhos suportados para a superfície de captura estática. Os OEMs devem oferecer suporte à saída no formatoJPEG
eYUV_420_888
.AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions()
retorna os tamanhos suportados para um fluxoYUV_420_888
extra para análise de imagem. Se a superfície YUV de análise de imagem não for compatível,getSupportedYuvAnalysisResolutions()
deverá retornarnull
ou uma lista vazia.
Chaves/resultados de solicitação de captura disponíveis (adicionados na
extensions-interface
1.3.0): Camera2/X invoca os seguintes métodos para recuperar as chaves de solicitação de captura e chaves de resultado suportadas de sua implementação:-
AdvancedExtenderImpl.getAvailableCaptureRequestKeys
-
AdvancedExtenderImpl.getAvailableCaptureResultKeys
-
Para obter mais informações, consulte Chaves e resultados de solicitação de captura de suporte .
Fluxo de aplicativo 3: visualização/captura estática com extensão ativada
Figura 10. Fluxo de aplicativo 3 no Advanced Extender
O diagrama acima mostra o fluxo principal para iniciar a visualização e capturar imagens para o tipo Advanced Extender. Vamos percorrer cada etapa.
Instância
SessionProcessorImpl
A implementação principal do Advanced Extender está em
SessionProcessorImpl
, que é responsável por fornecer configuração de sessão customizada e enviar solicitações de captura para iniciar a visualização e ainda a solicitação de captura.AdvancedExtenderImpl.createSessionProcessor()
é invocado para retornar a instânciaSessionProcessorImpl
.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 umaCameraCaptureSession
.Para os parâmetros de entrada, Camera2/X especifica as configurações da superfície de saída para visualização, captura estática e uma análise de imagem YUV opcional. Esta 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 emAdvancedExtenderImpl
:-
getSupportedPreviewOutputResolutions()
-
getSupportedCaptureOutputResolutions()
-
getSupportedYuvAnalysisResolutions()
Você deve retornar uma instância
Camera2SessionConfigImpl
, que consiste em uma lista de instânciasCamera2OutputConfigImpl
e os parâmetros de sessão usados para configurarCameraCaptureSession
. Você é responsável por enviar as imagens corretas da câmera para as superfícies de saída transmitidas pela Camera2/X. Aqui estão algumas opções para ativar a saída:- Processamento na câmera HAL: você pode adicionar diretamente as superfícies de saída ao
CameraCaptureSession
com uma implementaçãoSurfaceOutputConfigImpl
. Isso configura a superfície de saída fornecida ao pipeline da câmera e permite que o HAL da câmera processe a imagem. Processando superfície
ImageReader
intermediária (RAW, YUV, etc): Adicione as superfíciesImageReader
intermediárias aoCameraCaptureSession
com uma instânciaImageReaderOutputConfigImpl
.Você precisa processar as imagens intermediárias e gravar a imagem resultante na superfície de saída.
- Use o compartilhamento de superfície Camera2: use o compartilhamento de superfície com outra superfície adicionando qualquer instância
Camera2OutputConfigImpl
ao métodogetSurfaceSharingOutputConfigs()
de outra instânciaCamera2OutputConfigImpl
. O formato e tamanho da superfície devem ser idênticos.
Todos
Camera2OutputConfigImpl
incluindoSurfaceOutputConfigImpl
eImageReaderOutputConfigImpl
devem ter um ID exclusivo (getId()
), que é usado para especificar a superfície de destino e recuperar a imagem deImageReaderOutputConfigImpl
.-
onCaptureSessionStart
eRequestProcessorImpl
Quando
CameraCaptureSession
é iniciado e a estrutura Camera invocaonConfigured()
, Camera2/X invocaSessionProcessorImpl.onCaptureSessionStart()
com o wrapper de solicitação Camera2RequestProcessImpl
. Camera2/X implementaRequestProcessImpl
, que permite executar as solicitações de captura e recuperar imagens seImageReaderOutputConfigImpl
for usado.As APIs
RequestProcessImpl
são semelhantes às APIs Camera2CameraCaptureSession
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
.
Você pode chamar
RequestProcessorImpl.setImageProcessor()
com um IDCamera2OutputConfigImpl
especificado para registrar uma instânciaImageProcessorImpl
para receber imagens.A instância
RequestProcessImpl
torna-se inválida depois que Camera2/X chamaSessionProcessorImpl.onCaptureSessionEnd()
.- A superfície de destino é especificada pelo ID da instância
Inicie a visualização e tire uma foto
Na implementação do Advanced Extender, é possível enviar solicitações de captura por meio da interface
RequestProcessorImpl
. Camera2/X notifica você para iniciar a solicitação repetida de visualização ou a sequência de captura estática chamandoSessionProcessorImpl#startRepeating
eSessionProcessorImpl#startCapture
respectivamente. Você deve enviar solicitações de captura para atender a essas solicitações de visualização e captura ainda.Camera2/X também define os parâmetros de solicitação de captura por meio de
SessionProcessorImpl#setParameters
. Você deve definir esses parâmetros de solicitação (se os parâmetros forem suportados) nas solicitações repetidas e únicas.Você deve oferecer suporte a pelo menos
CaptureRequest.JPEG_ORIENTATION
eCaptureRequest.JPEG_QUALITY
.extensions-interface
1.3.0 suporta 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
, você deve ativar os parâmetros e garantir que o resultado da captura contenha as chaves na listagetAvailableCaptureResultKeys
.-
startTrigger
SessionProcessorImpl.startTrigger()
é invocado para iniciar o gatilho comoCaptureRequest.CONTROL_AF_TRIGGER
eCaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER
. Você pode desconsiderar quaisquer chaves de solicitação de captura que não foram anunciadas emAdvancedExtenderImpl.getAvailableCaptureRequestKeys()
.startTrigger()
é suportado desdeextensions-interface
1.3.0. Ele permite que os aplicativos implementem toque para focar e flash com extensões.Limpar
Ao finalizar uma sessão de captura,
SessionProcessorImpl.onCaptureSessionEnd()
é invocado antes do fechamento deCameraCaptureSession
. Após o encerramento da sessão de captura,deInitSession()
executa a limpeza.
Suporte para visualização, captura estática e análise de imagens
Você deve aplicar a extensão para casos de uso de visualização e ainda de captura. 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 estática.
Para o tipo Basic Extender, independentemente de ativar a extensão para visualização, você deve implementar ImageCaptureExtenderImpl
e PreviewExtenderImpl
para uma determinada extensão. Freqüentemente, um aplicativo também usa um fluxo YUV para analisar o conteúdo da imagem, como encontrar códigos QR ou texto. Para suportar melhor esse caso de uso, você deve suportar a combinação de fluxo de visualização, ainda captura e um fluxo YUV_420_888
para configurar CameraCaptureSession
. Isso significa que, se você implementar um processador, precisará suportar a combinação de fluxos de três fluxos YUV_420_888
.
Para o Avançado Extender, o Camera2/X passa três superfícies de saída para a chamada SessionProcessorImpl.initSession()
. Essas superfícies de saída são para visualização, ainda captura e análise de imagem, respectivamente. Você deve garantir que a visualização e ainda capture as superfícies de saída mostrem a saída válida. No entanto, para a superfície da saída de análise de imagem, verifique se está funcionando apenas quando não é nulo. Se a sua implementação não puder suportar o fluxo de análise de imagem, você poderá retornar uma lista vazia no AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions()
. Isso garante que a superfície de saída da análise de imagem seja sempre nula no SessionProcessorImpl.initSession()
.
Suporte a captura de vídeo
A arquitetura atual de extensão da câmera suporta apenas a visualização e ainda captura casos de uso. Não apoiamos as superfícies da extensão nas superfícies MediaCodec
ou MediaRecorder
para gravar o vídeo. No entanto, é possível para os aplicativos gravarem a saída de visualização.
Superfícies de apoio ao MediaCodec
e MediaRecorder
está sob investigação.
Metadados específicos de extensão
Para o Android 14 e Metadados específicos de extensão, permite que os clientes de extensão da câmera definam e recebam configurações e resultados de solicitação de captura específicos. Especificamente, os clientes de extensão da câmera podem usar o parâmetro EXTENSION_STRENGTH
Capture Solicy para controlar a força 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 força do efeito pós-processamento de extensão. O resultado de captura correspondente inclui o valor de força padrão se este parâmetro não for definido explicitamente pelo cliente. Este parâmetro pode ser aplicado da seguinte maneira para esses tipos de extensão:
-
BOKEH
: controla a quantidade de desfoque. -
HDR
eNIGHT
: controla a quantidade de imagens fundidas e o brilho da imagem final. -
FACE_RETOUCH
: Controla a quantidade de aprimoramento cosmético e suavização da pele.
O intervalo suportado para o parâmetro EXTENSION_STRENGTH
está entre 0
e 100
, com 0
indicando nenhum processamento de extensão ou passagem simples e 100
indicando a força máxima de extensão do efeito de processamento.
Para adicionar suporte para EXTENSION_STRENGTH
, use as APIs de parâmetro específicas do fornecedor introduzidas na versão 1.3.0 da interface da biblioteca de extensão. Para obter mais informações, consulte getAvailableCaptureRequestKeys()
.
Capture resultados
O resultado da captura EXTENSION_CURRENT_TYPE
permite que as implementações de extensão notifiquem os clientes sobre o tipo de extensão ativa.
Como as extensões usando o tipo AUTO
alternam dinamicamente os tipos de extensão, como HDR
e NIGHT
, dependendo das condições da cena, os aplicativos de extensões da câmera podem usar EXTENSION_CURRENT_TYPE
para exibir informações sobre a extensão atual selecionada pela extensão AUTO
.
Em tempo real ainda captura a estimativa de latência
Para o Android 14 e superior, os clientes de extensão de câmera podem consultar as estimativas de latência ainda em tempo real com base nas condições de cena e ambiente usando getRealtimeStillCaptureLatency()
. Este método fornece estimativas mais precisas do que o método estático getEstimatedCaptureLatencyRangeMillis()
. Com base na estimativa de latência, os aplicativos podem decidir pular o processamento de extensão ou exibir uma indicação para notificar os usuários sobre uma operação de longa execuçã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 apoiar as estimativas de latência ainda em tempo real, implemente o seguinte:
- Extensões básicas:
ImageCaptureExtenderImpl.getRealtimeCaptureLatency()
- Extensões avançadas:
SessionProcessorImpl.getRealtimeCaptureLatency
Capture o processamento de retornos de chamada de progresso
Para o Android 14 e superior, os clientes de extensão de câmera podem receber retornos de chamada para o progresso das operações de processamento de captura ainda mais longa. Os aplicativos podem exibir o progresso atual para os usuários para melhorar a experiência geral do usuário.
Os aplicativos 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 apoiar os retornos de chamada do Progresso do Processamento do Processamento, a implementação do seu fornecedor de extensão deve chamar os seguintes retornos de chamada com o valor de progresso atual:
- Extensões básicas:
ProcessResultImpl.onCaptureProcessProgressed()
- Extensões avançadas:
CaptureCallback.onCaptureProcessProgressed()
PostView ainda captura
Para o Android 14 e superior, as extensões da câmera podem fornecer um pós -visualização (imagem de visualização) usando setPostviewOutputConfiguration
. Para melhorar a experiência do usuário, os aplicativos podem exibir uma imagem pós -visão como um espaço reservado quando uma extensão está experimentando maior latência de processamento e substituir a imagem quando a imagem final estiver disponível. Os aplicativos podem configurar e emitir solicitações de captura de pós -visã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 apoiar o PostView Still Capture, sua implementação de fornecedor deve implementar o seguinte:
Extensões básicas:
CaptureProcessorImpl.onPostviewOutputSurface
eCaptureProcessorImpl.processWithPostview
Extensões avançadas:
SessionProcessorImpl.startCaptureWithPostview
Suporte SurfaceView Saída
Para o Android 14 e superior, os clientes de extensão de câmera podem usar os caminhos de renderização de visualização otimizados de energia e desempenho, registrando uma instância SurfaceView
para a saída de visualização para repetições de solicitações.
Para suportar a saída SurfaceView
, a implementação da sua extensão de fornecedor deve ser capaz de transmitir e sair de saída para instâncias SurfaceView
. Para verificar se isso é suportado, execute o módulo CTS SurfaceViewExtensionPreviewTest.java
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 de captura de câmera interna em vez do valor padrão.
O recurso funciona inteiramente dentro da pilha de estruturas e fornecedores e não possui impacto da API visível 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
Extensões do histórico da versão da interface
A tabela a seguir mostra o histórico da versão da interface de extensão da câmera. Você sempre deve implementar a biblioteca de fornecedores com a versão mais recente.
Versão | Recursos adicionados |
---|---|
1.0.0 |
|
1.1.0 |
|
1.2.0 |
|
1.3.0 |
|
1.4.0 |
|
Implementação de referência
As seguintes implementações da biblioteca de fornecedores de OEM de referência estão disponíveis em frameworks/ex
.
advancedSample
: uma implementação básica do extensor avançado.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 umService
. Esta implementação contém os seguintes componentes:oem_library
: uma biblioteca OEM de extensões de câmera para APIs de Extensões Camera2 e Camerax que implementaExtensions-Interface
. Isso atua como uma passagem que encaminha as chamadas daExtensions-Interface
para o serviço. Esta biblioteca também fornece arquivos AIDL e classes de wrapper para se comunicar com o serviço.O Avançado Extender é ativado por padrão. Para ativar o extensor básico, altere
ExtensionsVersionImpl#isAdvancedExtenderImplemented
para retornarfalse
.extensions_service
: uma amostra 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 doIAdvancedExtenderImpl.Stub
executa as mesmas operações que oAdvancedExtenderImpl
.ImageWrapper
eTotalCaptureResultWrapper
são necessários para criarImage
eTotalCaptureResult
Parcelable.
Configure a biblioteca de fornecedores em um dispositivo
A biblioteca de fornecedores OEM não está incorporada a um aplicativo; É carregado do dispositivo em tempo de execução por câmera2/x. No Camerax, a tag <uses-library>
declara que a biblioteca androidx.camera.extensions.impl
, que é definida no arquivo AndroidManifest.xml
da biblioteca camera-extensions
, é uma dependência do Camerax e deve ser carregado no tempo de execução. Na câmera2, a estrutura carrega um serviço de extensões que também declara que a <uses-library>
carrega o mesmo androidx.camera.extensions.impl
biblioteca em tempo de execução.
Isso permite que aplicativos de terceiros usando extensões para carregar automaticamente a biblioteca de fornecedores OEM. A biblioteca OEM é marcada como opcional para que os aplicativos possam ser executados em dispositivos que não possuem a biblioteca no dispositivo. A câmera2/x lida com esse comportamento automaticamente quando um aplicativo tenta usar uma extensão da câmera, desde que o fabricante do dispositivo coloque a biblioteca OEM no dispositivo para que possa ser descoberto pelo aplicativo.
Para configurar a biblioteca OEM em um dispositivo, faça o seguinte:
- Adicione um arquivo de permissão, exigido pela tag
<uses-library>
, usando o seguinte formato:/etc/permissions/ ANY_FILENAME .xml
. Por exemplo,/etc/permissions/camera_extensions.xml
. Os arquivos neste diretório fornecem um mapeamento da biblioteca nomeada em<uses-library>
para o caminho real do arquivo no dispositivo. Use o exemplo abaixo para adicionar as informações necessárias ao arquivo.
-
name
deve serandroidx.camera.extensions.impl
como essa é a biblioteca que a 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 ou superior, os dispositivos que suportam as extensões de camerax devem ter a propriedade ro.camerax.extensions.enabled
Property definido como true
, o que permite consultar se um dispositivo suporta extensões. Para fazer isso, adicione a seguinte linha no dispositivo Faça o arquivo:
PRODUCT_VENDOR_PROPERTIES += \
ro.camerax.extensions.enabled=true \
Validação
Para testar sua implementação da biblioteca de fornecedores OEM durante o estágio de desenvolvimento, use o aplicativo de exemplo em androidx-main/camera/integration-tests/extensionstestapp/
, que percorre várias extensões de fornecedores.
Depois de concluir sua implementação, use a ferramenta de validação de extensões da câmera para executar testes automatizados e manuais para verificar se a biblioteca de fornecedores foi implementada corretamente.
Modo de cena estendido versus extensões de câmera
Para a extensão do bokeh, além de expor -o usando extensões da câmera, você pode expor a extensão usando o modo de cena estendido, que é ativado através da tecla CONTROL_EXTENDED_SCENE_MODE
. Para mais detalhes da implementação, consulte a câmera Bokeh .
O modo de cena estendido tem menos restrições em comparação com as extensões da câmera para aplicativos Camera2. Por exemplo, você pode ativar o modo de cena estendida em uma instância regular CameraCaptureSession
que suporta combinações flexíveis de fluxo e capturar parâmetros de solicitação. Por outro lado, as extensões da câmera suportam apenas um conjunto fixo de tipos de fluxo e têm suporte limitado para parâmetros de solicitação de captura.
Uma desvantagem do modo de cena estendida é que você pode implementá -lo apenas na câmera HAL, o que significa que ela deve ser verificada para funcionar em todos os controles ortogonais disponíveis para os desenvolvedores de aplicativos.
Recomendamos expor o bokeh usando o modo de cena estendido e as extensões da câmera, porque os aplicativos podem preferir usar uma API específica para ativar o bokeh. Recomendamos primeiro usar o modo de cena estendida, porque essa é a maneira mais flexível para os aplicativos ativarem a extensão do bokeh. Em seguida, você pode implementar a interface das extensões da câmera com base no modo de cena estendido. Se a implementação do bokeh na câmera Hal for difícil, por exemplo, porque exige que um pós -processador seja executado na camada de aplicativos para processar imagens, recomendamos a implementação da extensão do bokeh usando a interface das extensões da câmera.
Perguntas frequentes (perguntas frequentes)
Existem restrições aos níveis de API?
Sim. Isso depende do conjunto de recursos Android API necessário pela implementação da Biblioteca de Vendor OEM. Por exemplo, ExtenderStateListener.onPresetSession()
usa a chamada SessionConfiguration.setSessionParameters()
para definir um conjunto de tags de linha de base. Esta chamada está disponível apenas no nível de API 28 e superior. Para detalhes sobre métodos específicos de interface, consulte a documentação de referência da API .