Cámara2 con un SurfaceView
Estoy tratando de obtener el nuevo Camera2 trabajando con un simple SurfaceView y estoy teniendo algunos problemas con la vista previa en vivo. En algunos dispositivos, la imagen se estira de proporciones mientras se ve bien en otros.
He configurado un SurfaceView que programo ajustar para caber el tamaño del tamaño de la secuencia de vista previa.
- Android: reproduce el mismo video en varias vistas
- Cómo dibujo Bitmap en TextureView
- Textura transparente semi-transparente no funciona
- Obtener Bitmap de TextureView eficientemente
- Reproducción de un video después de que un video en TextureView de Android tenga problemas
En Nexus 5 esto se ve bien, pero uno de los dispositivos de Samsung está lejos. También los dispositivos Samsung tienen un borde negro en la parte derecha de la vista previa.
¿Realmente no es posible trabajar con SurfaceView o es el momento de cambiar a TextureView?
- SurfaceView vs TextureView para la cámara?
- ¿Cómo es que una vista previa de la cámara en una vista de textura es mucho más borrosa que en una vista de superficie?
- Realice un ajuste de vídeo en un TextureView (Partes de él están fuera (no visibles)) con MediaPlayer
- Reproducir vídeo en la vista de lista de Android
- Cómo tomar la instantánea de RTSP streaming con LibVLC para Android
- Añadir etiquetas de texto en el archivo de salida de vídeo utilizando la API de la cámara2
- Vista previa de la cámara de corte para TextureView
- ¿Cómo determino la orientación predeterminada de los marcos de previsualización de la cámara?
Sí, ciertamente es posible. Tenga en cuenta que el SurfaceView
y su Surface
asociada son dos cosas diferentes, y cada uno puede / debe tener asignado un tamaño.
La Surface
es el búfer de memoria real que mantendrá la salida de la cámara, y por lo tanto la configuración de su tamaño dicta el tamaño de la imagen real que obtendrá de cada marco. Para cada formato disponible de la cámara, hay un pequeño conjunto de posibles tamaños (exactos) que puede hacer este búfer.
SurfaceView
es lo que hace la visualización de esta imagen cuando está disponible, y básicamente puede ser de cualquier tamaño en su diseño. Estirará sus datos de imagen asociados subyacentes para adaptarse a cualquier tamaño de diseño, pero tenga en cuenta que este tamaño de pantalla es diferente del tamaño de los datos: Android cambiará el tamaño de los datos de la imagen para que se muestren automáticamente. Esto es lo que probablemente está causando su estiramiento.
Por ejemplo, puede crear una SurfaceView
de SurfaceView
basada en SurfaceView similar a AutoFitTextureView de la camera2basic de la siguiente manera (esto es lo que uso):
import android.content.Context; import android.util.AttributeSet; import android.view.SurfaceView; public class AutoFitSurfaceView extends SurfaceView { private int mRatioWidth = 0; private int mRatioHeight = 0; public AutoFitSurfaceView(Context context) { this(context, null); } public AutoFitSurfaceView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public AutoFitSurfaceView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } /** * Sets the aspect ratio for this view. The size of the view will be measured based on the ratio * calculated from the parameters. Note that the actual sizes of parameters don't matter, that * is, calling setAspectRatio(2, 3) and setAspectRatio(4, 6) make the same result. * * @param width Relative horizontal size * @param height Relative vertical size */ public void setAspectRatio(int width, int height) { if (width < 0 || height < 0) { throw new IllegalArgumentException("Size cannot be negative."); } mRatioWidth = width; mRatioHeight = height; requestLayout(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); if (0 == mRatioWidth || 0 == mRatioHeight) { setMeasuredDimension(width, height); } else { if (width < height * mRatioWidth / mRatioHeight) { setMeasuredDimension(width, width * mRatioHeight / mRatioWidth); } else { setMeasuredDimension(height * mRatioWidth / mRatioHeight, height); } } } }
En los documentos para createCaptureSession se dice
Para dibujar a un SurfaceView: Una vez que se crea la Superfície de SurfaceView, defina el tamaño de Surface con setFixedSize (int, int) como uno de los tamaños devueltos por getOutputSizes (SurfaceHolder.class)
Nunca he trabajado con Camera2 (pero muy interesante en la nueva tecnología) y todo lo que puedo sugerir es seguir las muestras. Y si lo comprueba con cuidado, el ejemplo utiliza un TextureView
personalizado, debe intentar copiarlo en su proyecto:
/** * A {@link TextureView} that can be adjusted to a specified aspect ratio. */ public class AutoFitTextureView extends TextureView {
También teniendo en cuenta que entre SurfaceView y TextureView (teóricamente) es sólo que se puede usar como una vista normal en el diseño y el otro "golpea un todo" a través de la jerarquía de vista, y que Camera2 sólo está disponible en API21 + … debería haber No daña la migración a TextureView