How does Android shoot video in full screen?

1. Recently, I encountered a problem. The video recorded with camera is full-screen in the process of shooting the preview, but it is not played in the file manager. It will be wider than what I saw when filming. I have been perplexed for a long time. I do not know how to solve it. Please give me some advice.

2, code:

public class MainActivity extends AppCompatActivity {

    private SurfaceView surfaceview;
    private MediaRecorder mr;
    private Button bt_start;
    private Button bt_stop;
    private boolean isRecording = false;
    private Camera mCamera;
    private int width;
    private int height;
    private Camera.Size previewSize;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        surfaceview = (SurfaceView) findViewById(R.id.surfaceview);

        bt_start = (Button) findViewById(R.id.bt_start);
        bt_stop = (Button) findViewById(R.id.bt_stop);
        WindowManager wm = (WindowManager) this
                .getSystemService(Context.WINDOW_SERVICE);
        width = wm.getDefaultDisplay().getWidth();
        height = wm.getDefaultDisplay().getHeight();
        SurfaceHolder holder = surfaceview.getHolder();
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        holder.setFixedSize(width, height);
        surfaceview.setKeepScreenOn(true);
    }

    public void start(View v){
        //
        new RxPermissions(this)
                .request(Manifest.permission.CAMERA,
                        Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT,
                        Manifest.permission.RECORD_AUDIO,
                        Manifest.permission.READ_EXTERNAL_STORAGE,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE)
                .subscribe(new Consumer<Boolean>() {
                    @Override
                    public void accept(Boolean aBoolean) throws Exception {
                        if(aBoolean){
                            Toast.makeText(MainActivity.this,"",Toast.LENGTH_SHORT).show();
                        }else {
                            Toast.makeText(MainActivity.this,"",Toast.LENGTH_SHORT).show();
                        }
                    }
                });
        try {
            mCamera = Camera.open();
            Camera.Parameters parameters = mCamera.getParameters();
            mCamera.setDisplayOrientation(90);
            mCamera.setPreviewDisplay(surfaceview.getHolder());
            mCamera.startPreview();
            List<Camera.Size> mSupportedPreviewSizes = parameters.getSupportedPreviewSizes();

            if (mSupportedPreviewSizes != null) {
                previewSize = getOptimalPreviewSize(mSupportedPreviewSizes,
                        Math.max(width, height), Math.min(width, height));
            }
            Camera.Parameters mParams = mCamera.getParameters();
            mParams.setPreviewSize(previewSize.width, previewSize.height);
//            mCamera.setDisplayOrientation(90);
            List<String> focusModes = mParams.getSupportedFocusModes();
            if(focusModes.contains("continuous-video")){
                mParams.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
            }
            mCamera.setParameters(mParams);

            mCamera.unlock();

            mr = new MediaRecorder();
            mr.setCamera(mCamera);
            mr.reset();



            mr.setPreviewDisplay(surfaceview.getHolder().getSurface());
            mr.setVideoSource(MediaRecorder.VideoSource.CAMERA);// 
            mr.setAudioSource(MediaRecorder.AudioSource.MIC);// 
            mr.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);// 
            mr.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);// 
            mr.setVideoSize(previewSize.width,previewSize.height);
            mr.setVideoFrameRate(30);
            mr.setVideoEncodingBitRate(3*1024*1024);// 
            mr.setOrientationHint(90);// 90
            mr.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);// 
            File file = new File(Environment.getExternalStorageDirectory(),"zz"+System.currentTimeMillis()+".mp4");
            mr.setOutputFile(file.getAbsolutePath());
            mr.setOnErrorListener(new MediaRecorder.OnErrorListener() {
                @Override
                public void onError(MediaRecorder mr, int what, int extra) {
                    isRecording = false;
                    mr.stop();
                    mr.release();
                    mr = null;
                    isRecording = false;
                    bt_start.setEnabled(true);
                    bt_stop.setEnabled(false);
                    Toast.makeText(MainActivity.this,"",Toast.LENGTH_SHORT).show();
                }
            });
            //
            mr.setPreviewDisplay(surfaceview.getHolder().getSurface());
            mr.prepare();
            mr.start();
            bt_start.setEnabled(false);
            bt_stop.setEnabled(true);
            Toast.makeText(MainActivity.this,"",Toast.LENGTH_SHORT).show();
        } catch (Exception e) {
            //TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    public void stop(View v){
        mr.stop();
        bt_start.setEnabled(true);
        bt_stop.setEnabled(false);
    }

    @Override
    protected void onDestroy() {
        //TODO Auto-generated method stub
        super.onDestroy();

        if(mr!= null){
            mr.release();
            mr = null;
        }
    }

    public Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
        final double ASPECT_TOLERANCE = 0.1;
        double targetRatio = (double) w / h;
        if (sizes == null) {
            return null;
        }
        Camera.Size optimalSize = null;
        double minDiff = Double.MAX_VALUE;
        int targetHeight = h;
        for (Camera.Size size : sizes) {
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
                continue;
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }
        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Camera.Size size : sizes) {
                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
        }
        return optimalSize;
    }


}

3, picture:

:
    

clipboard.png


clipboard.png

4, you will see that the actual picture will be wider, how to solve this problem, want to make full screen.

Jun.09,2021

that is, the preview is different from the reality, and there may be a gap in the way you get the width and height of the screen. If I remember correctly, this number is different from the actual value.
but I haven't tried it myself. For this reason, please refer to https://blog.csdn.net/gh86091.

.

see if it helps

The first parameter of

getOptimalPreviewSize is the list of sizes supported by the hardware, followed by the length and width of the UI size you want to display.
so the preview image display is modified, not the actual size seen by the camera.
personal thoughts
Plan 1. Just use the exact matching size, that is, size with the same proportion of UI size and hardware size (not so good, especially the low-end machine has a small number of hardware support, which will be very vague)
solution 2. Get the picture and revise it. Do not use the picture generated by the system camera directly, cut it with the tool class and save it.

Menu