Java – Ensure that the camera preview size/aspect ratio matches the resulting video

Ensure that the camera preview size/aspect ratio matches the resulting video… here is a solution to the problem.

Ensure that the camera preview size/aspect ratio matches the resulting video

I’m using the MediaRecorder and Camera classes to preview and capture video. My problem is that I’m not quite sure how to make sure what the user sees while recording matches the resulting video. My first inclination was to iterate through the preview sizes supported by the camera until I found the optimal size that matched the aspect ratio of the video size I set to MediaRecorder:

camProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P);
aspectRatio = (float)camProfile.videoFrameWidth / camProfile.videoFrameHeight;

Camera.Parameters parameters = camera.getParameters();

Size bestSize = getBestSize(parameters.getSupportedPreviewSizes(), aspectRatio);
parameters.setPreviewSize(bestSize.width, bestSize.height);
camera.setParameters(parameters);

LayoutParams params = new LayoutParams((int)(videoView.getHeight() * aspectRatio), videoView.getHeight());
params.addRule(RelativeLayout.CENTER_IN_PARENT);

videoView.setLayoutParams(params);

mRecorder.setVideoSize(camProfile.videoFrameWidth, camProfile.videoFrameHeight);

Is this the right thing to do?

Solution

Well, it worked just fine for me, and I didn’t receive any criticism, might as well add the getBestSize feature:

private Size getBestSize(List<Size> supportedPreviewSizes, float aspectRatio) {
    int surfaceHeight = videoView.getHeight();

Size bestSize = null;
    Size backupSize = null;
    for (Size size : supportedPreviewSizes) {
        float previewAspectRatio = size.width / (float)size.height;
        previewAspectRatio = Math.round(previewAspectRatio * 10) / 10f;
        if (previewAspectRatio == aspectRatio) { // Best size must match preferred aspect ratio
            if (bestSize == null || Math.abs(surfaceHeight - size.height) < Math.abs(surfaceHeight - bestSize.height))
                bestSize = size;
        }
        else if (bestSize == null) { // If none of supported sizes match preferred aspect ratio, backupSize will be used
            if (backupSize == null || Math.abs(surfaceHeight - size.height) < Math.abs(surfaceHeight - backupSize.height))
                backupSize = size;
        }
    }
    return bestSize != null ? bestSize : backupSize;
}

Related Problems and Solutions