googlearchive / android-Camera2Video

Migrated:
https://github.com/android/camera
Apache License 2.0
1.21k stars 568 forks source link

The Preivew Size Stretch When Recording #73

Closed linglu closed 5 years ago

linglu commented 6 years ago

When previewing, we can find best match preview size with map.getOutputSizes(SurfaceTexture.class), it works find when preview, but when if start record, the preview size stretch, I set MediaRecorder video size with **mMediaRecorder.setVideoSize(mVideoSize.getWidth(), mVideoSize.getHeight());, but it doesn't work, you can see from this video that, when previewing, the circle is round, but when recording, it becomes oval. I have test it on MI6、MI Note and nexus 5X. Is there anyone encounter it?

ND1010 commented 6 years ago

I have seen your video form provided Link , i am facing same issue in every devices When i start recording video the preview recording surface automatically zoom.... i have tried many different solution but not still find any solution ,if you have got solution please tell me thanx

iamnaran commented 6 years ago

I have the same issue.. Did you guys figure out? How to solve this?

linglu commented 6 years ago

I haven't figured out yet,

khabouss commented 6 years ago

the reason why the preview stretch when you record is because you are recording with the textureView Size which height is not match parent. change the textureView height to "math_parent" and try again

excitedhaha commented 6 years ago

Same problem ... Have you solved the issue?

mohanrajsambath commented 5 years ago

Reason for stretching is early device is in 16:9 aspect ratio, but nowadays is came up to 18:9,19:9 & 19.5:9, aspect ratio. we have to customize the preview method, here is my code. hope it will help. //Samsung-S6-choices[0] //Samsung-S7-edge-choices[6] //OnePlus-5T-choices[15] /Following is used for Camera Preview in TextureView, based on device camera resolution/ /*

private  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<>();
        int w = aspectRatio.getWidth();
        int h = aspectRatio.getHeight();
        double ratio = (double) h / w;
        int loopCounter=0;
        for (Size size : choices) {
            int orientation = getActivityContext.getResources().getConfiguration().orientation;
            if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
                //if((size.getWidth()/16) == (size.getHeight()/9) && size.getWidth() <=720) {
                //if((size.getWidth()/16) == (size.getHeight()/9) && size.getWidth() <=3840 ) {
                //if((size.getWidth()/16) == (size.getHeight()/9) && size.getWidth() <=5120 ) {//Retina 5K
                if((size.getWidth()/16) == (size.getHeight()/9) && size.getWidth() <=7680 ) {//8K UHDTV Super Hi-Vision
                    Log.e(TAG1, "chooseOptimalSize:"+size+"--LoopPosition---==>"+loopCounter);
                    return size;
                }
            } else {
                Log.e(TAG1, "chooseOptimalSize:--given--"+size);
                if((size.getWidth()/16) == (size.getHeight()/9) && ((size.getWidth() <=1280)||(size.getHeight()<=1920))) {
                    //if((size.getWidth()/16) == (size.getHeight()/9) && (size.getWidth() <=4320 ) ) {//8K UHDTV Super Hi-Vision
                    //if((size.getWidth()/16) == (size.getHeight()/9) && (size.getWidth() <=2880 ) ) {//Retina 5K
                    //if((size.getWidth()/16) == (size.getHeight()/9) && (size.getWidth() <=2160 ) ) {
                    //if((size.getWidth()/16) == (size.getHeight()/9) && (size.getWidth() <=1280 ) ) {
                    //if((size.getWidth()/16) == (size.getHeight()/9) && (size.getWidth() <=4480 && size.getWidth() >=1280) ) {
                    Log.e(TAG1, "chooseOptimalSize:"+size+"-16:9"+"--LoopPosition---==>"+loopCounter);
                    return size;
                }else if((size.getWidth()/18) == (size.getHeight()/9) && ((size.getWidth() <=3840)||(size.getHeight()<=2160))) {
                    Log.e(TAG1, "chooseOptimalSize:"+size+"-18:9"+"--LoopPosition---==>"+loopCounter);
                    return size;
                }else if((size.getWidth()/18.5) == (size.getHeight()/9) && ((size.getWidth() <=3840)||(size.getHeight()<=2160))) {
                    Log.e(TAG1, "chooseOptimalSize:"+size+"-18.5:9"+"--LoopPosition---==>"+loopCounter);
                    return size;
                }else if((width/19) == (height/9) && ((width <=3840)||(height<=2160))) {
                    /*if((size.getWidth()/19) == (size.getHeight()/9) && ((size.getWidth() <=3840)||(size.getHeight()<=2160))) {*/
                    Log.e(TAG1, "chooseOptimalSize:"+size+"-19:9"+"--LoopPosition---==>"+loopCounter);
                    return size;
                }else if((size.getWidth()/19.5) == (size.getHeight()/9) && ((size.getWidth() <=3840)||(size.getHeight()<=2160))) {
                    Log.e(TAG1, "chooseOptimalSize:"+size+"-19.5:9"+"--LoopPosition---==>"+loopCounter);
                    return size;
                }else{
                    Log.e(TAG1, "chooseOptimalSize"+" not proper aspect resolution");
                }
                //2340
            }

            if(screenWidth==size.getWidth()){
                Log.e(TAG1, loopCounter+".choose:width Matched:"+screenWidth+"="+size.getWidth());
            }else{
                Log.e(TAG1, loopCounter+".choose:width Not Matched:"+screenWidth+"="+size.getWidth());
            }

            if(screenHeight==size.getHeight()){
                Log.e(TAG1, loopCounter+".choose:height Matched:"+screenHeight+"="+size.getHeight());
            }else{
                Log.e(TAG1, loopCounter+".choose:height Not Matched:"+screenHeight+"="+size.getHeight());
            }
            loopCounter++;
        }
        // Pick the smallest of those, assuming we found any
        if (bigEnough.size() > 0) {
            return Collections.min(bigEnough, new CompareSizesByArea());
        } else {
            Log.e(TAG1, "Couldn't find any suitable preview size");
            return choices[0];
        }
    }

    /*
     * Compares two {@code Size}s based on their areas.
     */
    static class CompareSizesByArea implements Comparator<Size> {
        @Override
        public int compare(Size lhs, Size rhs) {
            // We cast here to ensure the multiplications won't overflow
            return Long.signum((long) lhs.getWidth() * lhs.getHeight() -
                    (long) rhs.getWidth() * rhs.getHeight());
        }
    }

If you find better idea, please let me know. Thank you.

mukkumukesh commented 5 years ago

Hi Please use "chooseOptimalSize" from @mohanrajsambath and for further to show full screen without stretching view use this code for AutoFitTextureView.

class AutoFitTextureView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) :
TextureView(context, attrs, defStyle) {

private var mResolutionWidth = 0
private var mResolutionHeight = 0
private var deviceWidth: Int = 0
private var deviceHeight: Int = 0

fun setDeviceDimension(displayMetrics: DisplayMetrics) {
    deviceHeight = displayMetrics.heightPixels
    deviceWidth = displayMetrics.widthPixels
}

/**
 * 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
 */
fun setAspectRatio(width: Int, height: Int) {
    if (width < 0 || height < 0) {
        throw IllegalArgumentException("Size cannot be negative.")
    }
    mResolutionWidth = width
    mResolutionHeight = height
    requestLayout()
}

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec)
    if (0 == mResolutionWidth || 0 == mResolutionHeight) {
        setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec))
    } else {
        if (mResolutionWidth > mResolutionHeight) {
            val h = ((deviceWidth * mResolutionWidth) / mResolutionHeight)
            if (h < deviceHeight) {
                val w = deviceHeight * mResolutionHeight / mResolutionWidth
                setMeasuredDimension(w, deviceHeight)
            } else {
                setMeasuredDimension(deviceWidth, h)
            }
        } 
    }
}
}

use this from your fragment textureView.setAspectRatio(previewSize.width, previewSize.height)

The preview size is getting from "chooseOptimalSize()" function.

codingjeremy commented 5 years ago

This sample has been migrated to a new location (check README for more information).

As recommended by GitHub, we are closing all issues and pull requests now that this older repo will be archived.

If you still see this issue in the updated repo, please reopen the issue/PR there. Thank you!