Saída de streams, corte e zoom

Esta página descreve a operação e a otimização da câmera, incluindo streams de saída, corte, reprocessamento e zoom.

Streams de saída

O subsistema da 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 muitos destinos, como a GPU, o codificador de vídeo, RenderScript, ou buffers visíveis do app (RAW Bayer, buffers YUV processados ou buffers codificados em JPEG).

Como otimização, esses streams de saída precisam ser configurados com antecedência, e apenas um número limitado pode existir de uma só 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 listados ou variáveis, 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.

Corte

O corte da matriz de pixels completa (para zoom digital e outros casos de uso em que um campo de visão menor é desejável) é comunicado pela ANDROID_SCALER_CROP_REGION configuração. Essa é uma configuração por solicitação e pode mudar de acordo com a 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 ativa do sensor, com (0,0) sendo o pixel superior esquerdo da matriz de pixels ativa. Portanto, a largura e a altura não podem ser maiores que as dimensões informadas no ANDROID_SENSOR_ACTIVE_PIXEL_ARRAY campo de informações estáticas. A largura e a altura mínimas permitidas são informadas pelo HAL no 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, precisar começar em coordenadas pares e ter largura/altura pares), o 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 o HAL implementar a estabilização de vídeo, ele 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 que a região de corte. Especificamente, cada stream precisa manter pixels quadrados e a proporção, cortando ainda mais a região de corte definida. Se a proporção do stream for maior que a região de corte, o stream precisará ser cortado verticalmente. Se a proporção do stream for menor que a região de corte, o stream precisará ser cortado horizontalmente.

Em todos os casos, o corte do stream precisa ser centralizado na região de corte completa, e cada stream é cortado apenas horizontal ou verticalmente em relação à região de corte completa, nunca ambos.

Por exemplo, se dois streams forem definidos, um stream de 640 x 480 (proporção de 4:3) e um stream de 1280 x 720 (proporção de 16:9), abaixo demonstra as regiões de saída esperadas para cada stream 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 de 640 x 480: (500, 375, 1000, 750) (igual à região de corte)
Corte de stream de 1280 x 720: (500, 469, 1000, 562)

crop-region-43-ratio

Figura 1. Proporção de 4:3

Região de corte: (500, 375, 1333, 750) (proporção de 16:9)
Corte de stream de 640 x 480: (666, 375, 1000, 750)
Corte de stream de 1280 x 720: (500, 375, 1333, 750) (igual à região de corte)

crop-region-169-ratio

Figura 2. Proporção de 16:9

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

crop-region-11-ratio

Figura 3. Proporção de 1:1

E um exemplo final, um stream de proporção quadrada de 1024 x 1024 em vez do stream de 480p stream:
Região de corte: (500, 375, 1000, 750) (proporção de 4:3)
Corte de stream de 1024 x 1024: (625, 375, 750, 750)
Corte de stream de 1280 x 720: (500, 469, 1000, 562)

crop-region-43-square-ratio

Figura 4. Proporção de 4:3, quadrada

Reprocessamento

O suporte adicional para arquivos de imagem bruta é fornecido pelo suporte de reprocessamento para dados RAW Bayer. Esse suporte permite que o pipeline da câmera processe um buffer RAW e metadados capturados anteriormente (um frame inteiro gravado anteriormente) para produzir uma nova saída YUV ou JPEG renderizada.

Zoom

Em dispositivos com o 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 para alcançar proporções diferentes do sensor de câmera nativo.

Um sistema de várias câmeras pode conter mais de uma lente com distâncias focais diferentes, e o usuário pode usar o zoom óptico alternando entre as lentes. O uso de ANDROID_CONTROL_ZOOM_RATIO tem benefícios nos cenários abaixo:

  • Zoom de uma lente grande angular para uma lente telefoto: uma proporção de ponto flutuante oferece melhor precisão em comparação com valores inteiros de ANDROID_SCALER_CROP_REGION.
  • Zoom de uma lente grande angular para uma lente ultra grande angular: ANDROID_CONTROL_ZOOM_RATIO oferece suporte para zoom out (<1.0f), enquanto ANDROID_SCALER_CROP_REGION não.

Para ilustrar, confira vários cenários de diferentes proporções de zoom, regiões de corte e streams de saída, usando a mesma câmera hipotética definida na seção anterior.

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)

zoom-ratio-2-crop-43

Figura 5. Zoom de 2,0, proporção de 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) (pillarboxed)
Corte de stream de 1280 x 720: (0, 187, 2000, 1125) (igual à região de corte)

zoom-ratio-2-crop-169

Figura 6. Zoom de 2,0, proporção de 16:9

Proporção de zoom: 0,5; 4x do campo de visão original (alternado de lente grande angular para lente ultra grande angular)
Região de corte: (250, 0, 1500, 1500) (proporção de 1:1)
Corte de stream de 640 x 480: (250, 187, 1500, 1125) (letterboxed)
Corte de stream de 1280 x 720: (250, 328, 1500, 844) (letterboxed)

images/zoom-ratio-0.5-crop-11

Figura 7. Zoom de 0,5, proporção de 1:1

Como visto 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 a regiões e faces 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, o zoom de 2, 0x pode ser alcançado de uma das 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.