Camera2 с SurfaceView

Я пытаюсь заставить новую Camera2 работать с простым SurfaceView, и у меня возникают некоторые проблемы с предварительным просмотром в реальном времени. На некоторых устройствах изображение растягивается без пропорций, а на других выглядит хорошо.

Я установил SurfaceView, который я программно настраиваю для соответствия размеру потока предварительного просмотра.

На Nexus 5 это выглядит нормально, но одно устройство Samsung не работает. Также устройства Samsung имеют черную рамку в правой части предварительного просмотра.

Действительно ли невозможно работать с SurfaceView или сейчас самое время переключиться на TextureView?

3 ответа

Да, это, конечно, возможно. Обратите внимание, что SurfaceView и его связанный Surface это две разные вещи, и каждый может / должен быть назначен размер.

Surface является фактическим буфером памяти, который будет содержать выходные данные камеры, и, таким образом, установка его размера определяет размер фактического изображения, которое вы будете получать из каждого кадра. Для каждого формата, доступного с камеры, существует небольшой набор возможных (точных) размеров, которые вы можете сделать в этом буфере.

SurfaceView это то, что делает отображение этого изображения, когда оно доступно, и может в основном иметь любой размер в вашем макете. Он растянет соответствующие данные изображения, чтобы соответствовать размеру макета, но учтите, что этот размер экрана отличается от размера данных - Android автоматически изменит размер изображения для отображения. Это то, что, вероятно, вызывает ваше растяжение.

Например, вы можете сделать SurfaceViewавтозапуск на основе аналогичного AutoFitTextureView Camera2basic следующим образом (это то, что я использую):

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);
            }
        }
    }
}

В документах для createCaptureSession говорится

Для рисования в SurfaceView: Как только Surface SurfaceView создан, установите размер Surface с помощью setFixedSize(int, int) равным одному из размеров, возвращаемых getOutputSizes(SurfaceHolder.class).

Я никогда не работал с Camera2 (но очень интересен новой технологией), и все, что я могу вам предложить, это следовать образцам. И если вы проверите его внимательно, образец использует пользовательский TextureViewВы должны, вероятно, попытаться скопировать его в свой проект:

http://developer.android.com/samples/Camera2Basic/src/com.example.android.camera2basic/AutoFitTextureView.html

/**
 * A {@link TextureView} that can be adjusted to a specified aspect ratio.
 */
public class AutoFitTextureView extends TextureView {

также учитывая, что различие между SurfaceView и TextureView (теоретически) состоит в том, что вы можете использовать его как обычный вид в макете, а другой "пробивает целое" через иерархию видов, и что Camera2 доступна только в API21+... должно быть нет вреда в миграции в TextureView

Другие вопросы по тегам