Fluxos de saída
O subsistema de câmera opera apenas no pipeline baseado em ANativeWindow para todas as resoluções e formatos de saída. Vários streams podem ser configurados de uma só vez para enviar um único frame a vários destinos, como a GPU, o codificador de vídeo, o RenderScript, ou buffers visíveis para o app (Bayer RAW, buffers YUV processados ou buffers codificados em JPEG).
Como uma otimização, esses fluxos de saída precisam ser configurados com antecedência, e apenas um número limitado pode existir por vez. Isso permite a pré-alocação de buffers de memória e a configuração do hardware da câmera. Assim, quando as solicitações são enviadas com vários pipelines de saída ou pipelines variados, não há atrasos ou latência no atendimento da solicitação.
Para mais informações sobre as combinações de saída de stream garantidas
que dependem do nível de hardware compatível, consulte
createCaptureSession()
.
Recorte
O corte da matriz de pixels completa (para zoom digital e outros casos de uso em que um FOV menor é desejável) é comunicado pela configuração ANDROID_SCALER_CROP_REGION. Essa é uma configuração por solicitação, que pode mudar de acordo com cada solicitação, o que é fundamental para implementar um zoom digital suave.
A região é definida como um retângulo (x, y, largura, altura), com (x, y) descrevendo o canto superior esquerdo do retângulo. O retângulo é definido no sistema de coordenadas da matriz de pixels ativos do sensor, sendo (0,0) o pixel superior esquerdo da matriz. Portanto, a largura e a altura não podem ser maiores do que as dimensões informadas no campo de informações estáticas ANDROID_SENSOR_ACTIVE_PIXEL_ARRAY. A largura e a altura mínimas permitidas são informadas pela HAL pelo campo de informações estáticas ANDROID_SCALER_MAX_DIGITAL_ZOOM, que descreve o fator de zoom máximo compatível. Portanto, a largura e a altura mínimas da região de corte são:
{width, height} = { floor(ANDROID_SENSOR_ACTIVE_PIXEL_ARRAY[0] / ANDROID_SCALER_MAX_DIGITAL_ZOOM), floor(ANDROID_SENSOR_ACTIVE_PIXEL_ARRAY[1] / ANDROID_SCALER_MAX_DIGITAL_ZOOM) }
Se a região de corte precisar atender a requisitos específicos (por exemplo, começar em coordenadas pares e ter largura/altura par), a HAL precisará fazer o arredondamento necessário e gravar a região de corte final usada nos metadados do resultado da saída. Da mesma forma, se a HAL implementar a estabilização de vídeo, ela precisará ajustar a região de corte do resultado para descrever a região realmente incluída na saída após a aplicação da estabilização de vídeo. Em geral, um app que usa a câmera precisa determinar o campo de visão que está recebendo com base na região de corte, nas dimensões do sensor de imagem e na distância focal da lente.
Como a região de corte se aplica a todos os streams, que podem ter proporções diferentes da região de corte, a região exata do sensor usada para cada stream pode ser menor do que a região de corte. Especificamente, cada stream precisa manter pixels quadrados e a proporção cortando minimamente mais a região de corte definida. Se a proporção da transmissão for maior que a região de corte, ela deverá ser cortada mais verticalmente. Se a proporção da transmissão for menor que a região de corte, ela deverá ser cortada mais horizontalmente.
Em todos os casos, o corte do stream precisa estar centralizado na região de corte completa, e cada stream só pode ser cortado horizontal ou verticalmente em relação à região de corte completa, nunca os dois.
Por exemplo, se duas transmissões forem definidas, uma de 640 x 480 (proporção 4:3) e outra de 1280 x 720 (proporção 16:9), o exemplo abaixo mostra as regiões de saída esperadas para cada transmissão em algumas regiões de corte de amostra, em um sensor hipotético de 3 MP (matriz de pixels de 2000 x 1500).
Região de corte: (500, 375, 1000, 750) (proporção de 4:3)
Corte de stream 640 x 480: (500, 375, 1000, 750) (igual à região de corte)
Corte de stream 1280 x 720: (500, 469, 1000, 562)

Figura 1. Proporção de 4:3
Região de corte: (500, 375, 1333, 750) (proporção de 16:9)
Corte de stream 640x480: (666, 375, 1000, 750)
Corte de stream 1280x720: (500, 375, 1333, 750) (igual à região de corte)

Figura 2. Proporção de 16:9
Região de corte: (500, 375, 750, 750) (proporção de 1:1)
Corte de stream 640 x 480: (500, 469, 750, 562)
Corte de stream 1280 x 720: (500, 543, 750, 414)

Figura 3. Proporção 1:1
E um exemplo final, uma transmissão com proporção quadrada de 1024x1024 em vez da transmissão de 480p:
Região de corte: (500, 375, 1000, 750) (proporção de 4:3)
Corte da transmissão de 1024x1024: (625, 375, 750, 750)
Corte da transmissão de 1280x720: (500, 469, 1000, 562)

Figura 4. Proporção 4:3, quadrada
Reprocessamento
O suporte adicional para arquivos de imagem brutos é fornecido pelo suporte ao reprocessamento de dados RAW Bayer. Esse suporte permite que o pipeline da câmera processe um buffer RAW e metadados capturados anteriormente (um frame inteiro gravado antes) para produzir uma nova saída YUV ou JPEG renderizada.
Zoom
Em dispositivos com Android 11 ou mais recente, um app pode usar o zoom de uma câmera
(digital e óptico) pela configuração ANDROID_CONTROL_ZOOM_RATIO
.
A proporção de zoom é definida como um fator de ponto flutuante. Em vez de usar ANDROID_SCALER_CROP_REGION
para corte e zoom, um app pode usar ANDROID_CONTROL_ZOOM_RATIO
para controlar o nível de zoom e ANDROID_SCALER_CROP_REGION
para corte horizontal e vertical, alcançando proporções diferentes do sensor de câmera nativo.
Um sistema de várias câmeras pode ter mais de uma lente com diferentes distâncias focais, e o usuário pode usar o zoom óptico trocando de lente.
O uso de ANDROID_CONTROL_ZOOM_RATIO
tem benefícios nos cenários abaixo:
- Ao aumentar o zoom de uma lente grande-angular para uma telefoto: uma proporção de ponto flutuante oferece melhor precisão em comparação com valores inteiros de
ANDROID_SCALER_CROP_REGION
. - Diminuir o zoom de uma lente grande angular para uma ultra grande angular:
ANDROID_CONTROL_ZOOM_RATIO
aceita diminuir o zoom (<1.0f), masANDROID_SCALER_CROP_REGION
não.
Proporção de zoom: 2,0; 1/4 do campo de visão original
Região de corte: (0, 0, 2000, 1500) (proporção de 4:3)
Corte de stream de 640 x 480: (0, 0, 2000, 1500) (igual à região de corte)
Corte de stream de 1280 x 720: (0, 187, 2000, 1125)

Figura 5. Zoom de 2,0, proporção 4:3
Proporção de zoom: 2,0; 1/4 do campo de visão original
Região de corte: (0, 187, 2000, 1125) (proporção de 16:9)
Corte de stream de 640 x 480: (250, 187, 1500, 1125) (pillarbox)
Corte de stream de 1280 x 720: (0, 187, 2000, 1125) (igual à região de corte)

Figura 6. Zoom de 2,0, proporção de 16:9
Proporção de zoom: 0,5; 4x do campo de visão original (mudança de lente grande-angular para ultragrande-angular)
Região de corte: (250, 0, 1500, 1500) (proporção de 1:1)
Corte de stream 640 x 480: (250, 187, 1500, 1125) (com efeito letterbox)
Corte de stream 1280 x 720: (250, 328, 1500, 844) (com efeito letterbox)

Figura 7. Zoom de 0,5, proporção 1:1
Como mostrado nos gráficos acima, o sistema de coordenadas da região de corte muda para o campo de visão efetivo após o zoom e é representado pelo retângulo com as seguintes dimensões: (0
, 0
, activeArrayWith
, activeArrayHeight
). O mesmo se aplica às regiões e rostos de AE/AWB/AF. Essa mudança no sistema de coordenadas não se aplica à captura RAW e aos metadados relacionados, como intrinsicCalibration
e lensShadingMap
.
Usando o mesmo exemplo hipotético acima e supondo que o stream de saída nº 1 (640 x 480) seja o stream do visor, é possível alcançar um zoom de 2, 0x de duas maneiras:
zoomRatio = 2.0
,scaler.cropRegion = (0, 0, 2000, 1500)
zoomRatio = 1.0
(padrão),scaler.cropRegion = (500, 375, 1000, 750)
Para que um app defina android.control.aeRegions
como o quarto superior esquerdo do campo de visão do visor, defina android.control.aeRegions
como (0, 0, 1000, 750)
com android.control.zoomRatio
definido como 2.0
. Como alternativa, o app pode definir android.control.aeRegions
como a região equivalente de (500, 375, 1000, 750)
para android.control.zoomRatio
de 1.0
.