Get CamcorderProfile from incoming video size (#477)

pull/484/head
Mattia Iavarone 6 years ago committed by GitHub
parent 8b66d5b575
commit 0c7726d5c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 68
      cameraview/src/main/java/com/otaliastudios/cameraview/CamcorderProfiles.java
  2. 13
      cameraview/src/main/java/com/otaliastudios/cameraview/FullVideoRecorder.java

@ -0,0 +1,68 @@
package com.otaliastudios.cameraview;
import android.annotation.SuppressLint;
import android.media.CamcorderProfile;
import android.os.Build;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import androidx.annotation.NonNull;
/**
* Wraps the {@link android.media.CamcorderProfile} static utilities.
*/
class CamcorderProfiles {
@SuppressLint("UseSparseArrays")
private static Map<Size, Integer> sizeToProfileMap = new HashMap<>();
static {
sizeToProfileMap.put(new Size(176, 144), CamcorderProfile.QUALITY_QCIF);
sizeToProfileMap.put(new Size(320, 240), CamcorderProfile.QUALITY_QVGA);
sizeToProfileMap.put(new Size(352, 288), CamcorderProfile.QUALITY_CIF);
sizeToProfileMap.put(new Size(720, 480), CamcorderProfile.QUALITY_480P);
sizeToProfileMap.put(new Size(1280, 720), CamcorderProfile.QUALITY_720P);
sizeToProfileMap.put(new Size(1920, 1080), CamcorderProfile.QUALITY_1080P);
if (Build.VERSION.SDK_INT >= 21) {
sizeToProfileMap.put(new Size(3840, 2160), CamcorderProfile.QUALITY_2160P);
}
}
/**
* Returns a CamcorderProfile that's somewhat coherent with the target size,
* to ensure we get acceptable video/audio parameters for MediaRecorders (most notably the bitrate).
*
* @param cameraId the camera id
* @param targetSize the target video size
* @return a profile
*/
@NonNull
static CamcorderProfile get(int cameraId, @NonNull Size targetSize) {
final int targetArea = targetSize.getWidth() * targetSize.getHeight();
List<Size> sizes = new ArrayList<>(sizeToProfileMap.keySet());
Collections.sort(sizes, new Comparator<Size>() {
@Override
public int compare(Size s1, Size s2) {
int a1 = Math.abs(s1.getWidth() * s1.getHeight() - targetArea);
int a2 = Math.abs(s2.getWidth() * s2.getHeight() - targetArea);
//noinspection UseCompareMethod
return (a1 < a2) ? -1 : ((a1 == a2) ? 0 : 1);
}
});
while (sizes.size() > 0) {
Size candidate = sizes.remove(0);
//noinspection ConstantConditions
int quality = sizeToProfileMap.get(candidate);
if (CamcorderProfile.hasProfile(cameraId, quality)) {
return CamcorderProfile.get(cameraId, quality);
}
}
// Should never happen, but fallback to low.
return CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_LOW);
}
}

@ -18,6 +18,7 @@ class FullVideoRecorder extends VideoRecorder {
private CamcorderProfile mProfile; private CamcorderProfile mProfile;
private Camera1 mController; private Camera1 mController;
private Camera mCamera; private Camera mCamera;
private Size mSize;
FullVideoRecorder(@NonNull VideoResult stub, @Nullable VideoResultListener listener, FullVideoRecorder(@NonNull VideoResult stub, @Nullable VideoResultListener listener,
@NonNull Camera1 controller, @NonNull Camera camera, int cameraId) { @NonNull Camera1 controller, @NonNull Camera camera, int cameraId) {
@ -27,11 +28,10 @@ class FullVideoRecorder extends VideoRecorder {
mMediaRecorder = new MediaRecorder(); mMediaRecorder = new MediaRecorder();
mMediaRecorder.setCamera(camera); mMediaRecorder.setCamera(camera);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mProfile = CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_HIGH);
// TODO: should get a profile of a quality compatible with the chosen size. // Get a profile of quality compatible with the chosen size.
// Might do this by inspecting mResult.getSize(). However, it is not super important. mSize = mResult.getRotation() % 180 != 0 ? mResult.getSize().flip() : mResult.getSize();
// We are only bound to respect the video size passed by the VideoSizeSelector, and mProfile = CamcorderProfiles.get(cameraId, mSize);
// we are doing that below.
} }
// Camera2 constructor here... // Camera2 constructor here...
@ -43,7 +43,6 @@ class FullVideoRecorder extends VideoRecorder {
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT); mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
} }
Size size = mResult.getRotation() % 180 != 0 ? mResult.getSize().flip() : mResult.getSize();
mMediaRecorder.setOutputFormat(mProfile.fileFormat); mMediaRecorder.setOutputFormat(mProfile.fileFormat);
if (mResult.videoFrameRate <= 0) { if (mResult.videoFrameRate <= 0) {
mMediaRecorder.setVideoFrameRate(mProfile.videoFrameRate); mMediaRecorder.setVideoFrameRate(mProfile.videoFrameRate);
@ -51,7 +50,7 @@ class FullVideoRecorder extends VideoRecorder {
} else { } else {
mMediaRecorder.setVideoFrameRate(mResult.videoFrameRate); mMediaRecorder.setVideoFrameRate(mResult.videoFrameRate);
} }
mMediaRecorder.setVideoSize(size.getWidth(), size.getHeight()); mMediaRecorder.setVideoSize(mSize.getWidth(), mSize.getHeight());
switch (mResult.getVideoCodec()) { switch (mResult.getVideoCodec()) {
case H_263: mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263); break; case H_263: mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263); break;
case H_264: mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); break; case H_264: mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); break;

Loading…
Cancel
Save