Android 高速录像(2)
private void startRecordVideo() {
if (index == VIDEO_1080) {
if (!supported1080P120Fps) {
showToast(getString(R.string.notSupport1080P));
return;
}
} else if (index == VIDEO_4K) {
if (!supported4K) {
showToast(getString(R.string.notSupport4K));
return;
}
} else if (index == VIDEO_NORMAL) {
if (!supportedNormal) {
showToast(getString(R.string.notSupportNormal));
return;
}
}
isRecording = true;
clearPath();
try {
setUpMediaRecorder();
SurfaceTexture texture = mTextureView.getSurfaceTexture();
assert texture != null;
if (index == VIDEO_1080) {
texture.setDefaultBufferSize(1920, 1080);
} else {
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
}
mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
Surface previewSurface = new Surface(texture);
mPreviewBuilder.addTarget(previewSurface);
Surface recordSurface = mMediaRecorder.getSurface();
mPreviewBuilder.addTarget(recordSurface);
if (index == VIDEO_1080) {
mCameraDevice.createConstrainedHighSpeedCaptureSession(Arrays.asList(previewSurface, recordSurface),
new StateCallback() {
@Override
public void onConfigured(CameraCaptureSession session) {
mPreviewSession = session;
mPreviewSessionHighSpeed = (CameraConstrainedHighSpeedCaptureSession) mPreviewSession;
updatePreview();
runOnUiThread(new Runnable() {
@Override
public void run() {
btn_record.setText(getString(R.string.stop));
isRecording = true;
}
});
}
@Override
public void onConfigureFailed(CameraCaptureSession session) {
showToast(getString(R.string.record_failed));
}
}, mBackgroundHandler);
mMediaRecorder.start();
} else {
mCameraDevice.createCaptureSession(Arrays.asList(previewSurface, recordSurface), new StateCallback() {
@Override
public void onConfigured(CameraCaptureSession session) {
mPreviewSession = session;
updatePreview();
runOnUiThread(new Runnable() {
@Override
public void run() {
btn_record.setText(getString(R.string.stop));
isRecording = true;
}
});
}
@Override
public void onConfigureFailed(CameraCaptureSession session) {
showToast(getString(R.string.record_failed));
}
}, mBackgroundHandler);
mMediaRecorder.start();
}
} catch (CameraAccessException e) {
isRecording = false;
e.printStackTrace();
LogUtil.e(TAG, "record video : " + e);
} catch (Exception e) {
showToast(e.toString());
isRecording = false;
LogUtil.e(TAG, e.toString());
}
}
private void clearPath() {
File filesDir = getExternalFilesDir(null);
if (filesDir.exists()) {
File[] files = filesDir.listFiles();
if (files != null) {
for (File f : files) {
f.delete();
}
}
}
}
private void setUpMediaRecorder() throws IllegalStateException, IOException {
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mFilePath = getVideoFilePath(index);
mMediaRecorder.setOutputFile(mFilePath);
mMediaRecorder.setVideoEncodingBitRate(20000000);
if (index == VIDEO_1080) {
mMediaRecorder.setVideoFrameRate(120);
} else {
mMediaRecorder.setVideoFrameRate(30);
}
mMediaRecorder.setVideoSize(videoSize.getWidth(), videoSize.getHeight());
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
int rotation = getWindowManager().getDefaultDisplay().getRotation();
int orientation = DEFAULT_ORIENTATION.get(rotation);
mMediaRecorder.setOrientationHint(orientation);
mMediaRecorder.prepare();
}
private void stopRecordVideo() {
isRecording = false;
btn_record.setText(getString(R.string.record));
if (index == VIDEO_1080 && mPreviewSessionHighSpeed != null) {
try {
mPreviewSessionHighSpeed.stopRepeating();
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
mMediaRecorder.stop();
mMediaRecorder.reset();
showToast("Video saved: " + mFilePath);
startPreview();
}
private void stopRecordingVideoOnPause() {
isRecording = false;
btn_record.setText(getString(R.string.record));
if (index == VIDEO_1080 && mPreviewSessionHighSpeed != null) {
try {
mPreviewSessionHighSpeed.stopRepeating();
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
mMediaRecorder.stop();
mMediaRecorder.reset();
}
private void startPreview() {
if (null == mCameraDevice || !mTextureView.isAvailable()) {
return;
}
try {
SurfaceTexture texture = mTextureView.getSurfaceTexture();
assert texture != null;
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
Surface previewSurface = new Surface(texture);
mPreviewBuilder.addTarget(previewSurface);
mCameraDevice.createCaptureSession(Arrays.asList(previewSurface), new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(CameraCaptureSession cameraCaptureSession) {
mPreviewSession = cameraCaptureSession;
updatePreview();
}
@Override
public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
showToast("Failed");
}
}, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void updatePreview() {
if (null == mCameraDevice) {
return;
}
try {
if (isRecording) {
if (index == VIDEO_1080) {
Range<Integer> fpsRange = getHighestFpsRange(availableFpsRange);
mPreviewBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, fpsRange);
List<CaptureRequest> mPreviewBuilderBurst = mPreviewSessionHighSpeed
.createHighSpeedRequestList(mPreviewBuilder.build());
mPreviewSessionHighSpeed.setRepeatingBurst(mPreviewBuilderBurst, null, mBackgroundHandler);
} else {
setUpCaptureRequestBuilder(mPreviewBuilder);
mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, mBackgroundHandler);
}
} else {
mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, mBackgroundHandler);
}
} catch (CameraAccessException e) {
e.printStackTrace();
LogUtil.e(TAG, "update preview : " + e);
}
}
private Range<Integer> getHighestFpsRange(Range<Integer>[] fpsRanges) {
Range<Integer> fpsRange = Range.create(fpsRanges[0].getLower(), fpsRanges[0].getUpper());
for (Range<Integer> r : fpsRanges) {
if (r.getUpper() > fpsRange.getUpper()) {
fpsRange.extend(0, r.getUpper());
}
}
for (Range<Integer> r : fpsRanges) {
if (r.getUpper() == fpsRange.getUpper()) {
if (r.getLower() < fpsRange.getLower()) {
fpsRange.extend(r.getLower(), fpsRange.getUpper());
}
}
}
return fpsRange;
}
private Range<Integer>[] availableFpsRange;
private void setUpCaptureRequestBuilder(Builder builder) {
builder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
}
private CameraDevice mCameraDevice;
private MediaRecorder mMediaRecorder;
// private Semaphore mCameraOpenCloseLock = new Semaphore(1);
private void closeCamera() {
// try {
// mCameraOpenCloseLock.acquire();
if (null != mCameraDevice) {
mCameraDevice.close();
mCameraDevice = null;
}
if (null != mMediaRecorder) {
mMediaRecorder.release();
mMediaRecorder = null;
}
// } catch (InterruptedException e) {
// throw new RuntimeException("Interrupted while trying to lock camera
// closing.");
// } finally {
// mCameraOpenCloseLock.release();
// }
}
private Toast toast;
private void showToast(String msg) {
if (null == toast) {
toast = Toast.makeText(this, msg, Toast.LENGTH_SHORT);
} else {
toast.setText(msg);
}
toast.show();
}
private String getVideoFilePath(int index) {
String dir = "";
switch (index) {
case VIDEO_1080:
dir = "1080p";
break;
case VIDEO_4K:
dir = "4K";
break;
case VIDEO_NORMAL:
dir = "320x240";
break;
default:
dir = null;
break;
}
return getExternalFilesDir(null).getAbsolutePath() + "/" + dir + ".mp4";
}
private Handler mBackgroundHandler;
private HandlerThread mBackgroundThread;
private void startBackgroundThread() {
mBackgroundThread = new HandlerThread("Capture Video");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}
private void stopBackgroundThread() {
mBackgroundThread.quitSafely();
try {
mBackgroundThread.join();
mBackgroundThread = null;
mBackgroundHandler = null;
} catch (InterruptedException e) {
e.printStackTrace();
LogUtil.e(TAG, "stop background thread : " + e);
}
}
private void showChoices() {
final PopupWindow window = new PopupWindow(this);
View contentView = LayoutInflater.from(this).inflate(R.layout.pop, null);
RadioGroup rg = (RadioGroup) contentView.findViewById(R.id.rg);
switch (index) {
case VIDEO_1080:
rg.check(R.id.rb1080);
break;
case VIDEO_4K:
rg.check(R.id.rb4k);
break;
case VIDEO_NORMAL:
rg.check(R.id.rbnormal);
break;
default:
break;
}
rg.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId) {
case R.id.rb1080:
index = VIDEO_1080;
videoSize = size1080P;
break;
case R.id.rb4k:
index = VIDEO_4K;
videoSize = size4K;
break;
case R.id.rbnormal:
index = VIDEO_NORMAL;
videoSize = size320x240;
break;
default:
break;
}
SharedPreferencesUtils.saveInt(RecordActivity.this, INDEX, index);
window.dismiss();
}
});
window.setContentView(contentView);
window.setOutsideTouchable(true);
window.showAtLocation(ibtn_info, Gravity.TOP, 0, 0);
}
}