16

I'm building a custom camera using the new camera2 API. My code is based on the code sample provided by Google here.

I can't find a way to get the camera preview in full screen. In the code sample, they use ratio optimization to adapt to all screens but it's only taking around 3/4 of the screen's height.

Here is my code of AutoFitTextureView :

public class AutoFitTextureView extends TextureView {

private int mRatioWidth = 0;
private int mRatioHeight = 0;

public AutoFitTextureView(Context context) {
    this(context, null);
}

public AutoFitTextureView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public AutoFitTextureView(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);
        }
    }
}

}

Thank you very much for your help.

J.M.
  • 691
  • 3
  • 7
  • 15

2 Answers2

26

You should change measured width and height to cover full screen, not to fit the screen as below.

From:

if (width < height * mRatioWidth / mRatioHeight) 

to

if (width > height * mRatioWidth / mRatioHeight)

It worked fine for me.

Alexander Farber
  • 21,519
  • 75
  • 241
  • 416
Adrian Rusin
  • 605
  • 1
  • 6
  • 10
11

this is the solution for your problem. In this line the aspect ratio is set to 3/4. I changed chooseVideSize method to pick video size with hd resolution for MediaRecorder.

    private static Size chooseVideoSize(Size[] choices) {
        for (Size size : choices) {
            // Note that it will pick only HD video size, you should create more robust solution depending on screen size and available video sizes
            if (1920 == size.getWidth() && 1080 == size.getHeight()) {
                return size;
            }
        }
        Log.e(TAG, "Couldn't find any suitable video size");
        return choices[choices.length - 1];
    }

Then I corrected this method to pick preview size accordingly to video size aspect ratio and below is result.

private static Size chooseOptimalSize(Size[] choices, int width, int height, Size aspectRatio) {
    // Collect the supported resolutions that are at least as big as the preview Surface
    List<Size> bigEnough = new ArrayList<Size>();
    int w = aspectRatio.getWidth();
    int h = aspectRatio.getHeight();
    double ratio = (double) h / w;
    for (Size option : choices) {
        double optionRatio = (double) option.getHeight() / option.getWidth();
        if (ratio == optionRatio) {
            bigEnough.add(option);
        }
    }

    // Pick the smallest of those, assuming we found any
    if (bigEnough.size() > 0) {
        return Collections.min(bigEnough, new CompareSizesByArea());
    } else {
        Log.e(TAG, "Couldn't find any suitable preview size");
        return choices[1];
    }
}

I hope it will help you!

MrOnyszko
  • 847
  • 9
  • 13
  • 3
    It worked ! Thank you so so much @MrOnyszko! Did you implemented also autofocus when you tap on the screen? My preview image is a little bit blurry now. – J.M. Aug 21 '16 at 10:58
  • 1
    @J.M. using your code I am getting extra white space on the right side of my screen, any way to solve that? If I pick any of the other aspect ratios they are too blurry or cut off at the bottom. – paul_hundal Mar 20 '17 at 21:35
  • Could you provide device information such as screen size, preferred preview size, preferred preview size for video? – MrOnyszko Mar 21 '17 at 07:35
  • It is showing horizontal lines in preview and distorted preview. What could be the possible issue? – iMDroid Aug 17 '17 at 12:23
  • This is working well but the camera quality being less as i feel. –  Sep 25 '17 at 08:04
  • The `Size` class is only returning within 960x720 and below dimensions. So how you get size as 1920x1080 ? @MrOnyszko – E J Chathuranga Nov 08 '17 at 10:37
  • 3
    If the camera preview quality became bad so put max instead of min `Collections.max(bigEnough, new CompareSizesByArea());` – E.Abdel Jun 06 '18 at 12:03