在之前的文章已經詳細講解過關於Camera的Open整個過程,下面我們在來說說Video的過程:
還記得CameraDevice類嗎?CameraDevice的reateCaptureRequest(int templateType)方法創建CaptureRequest.Builder。
templateType參數有以下幾種:
- TEMPLATE_PREVIEW :預覽
- TEMPLATE_RECORD:拍攝視頻
- TEMPLATE_STILL_CAPTURE:拍照
- TEMPLATE_VIDEO_SNAPSHOT:創建視視頻錄製時截屏的請求
- TEMPLATE_ZERO_SHUTTER_LAG:創建一個適用於零快門延遲的請求。在不影響預覽幀率的情況下最大化圖像質量。
- TEMPLATE_MANUAL:創建一個基本捕獲請求,這種請求中所有的自動控制都是禁用的(自動曝光,自動白平衡、自動焦點)。
當然,視頻得選擇templateType = TEMPLATE_RECORD
錄像是長時間的動作,錄像過程中需要重複性的刷新錄製界面。其餘的步驟和拍照動作基本類似。
/**
* 開始視頻錄製。
*/
private void startRecordingVideo() {
try {
//創建錄製的session會話中的請求
mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
//設置錄製參數,這裏省略
.........
// Start a capture session
// Once the session starts, we can update the UI and start recording
mCameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
mPreviewSession = cameraCaptureSession;
Log.i(TAG, " startRecordingVideo 正式開始錄製 ");
updatePreview();
}
//該接口的方法,部分省略
.............
}, workThreadManager.getBackgroundHandler());
} catch (CameraAccessException | IOException e) {
e.printStackTrace();
}
}
//錄製過程中,不斷刷新錄製界面
private void updatePreview() {
try {
mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, workThreadManager.getBackgroundHandler());
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
和拍照類似,將視頻數據寫入磁盤文件中,也是需要一個操作類 MediaRecorder來實現的。
先是創建該操作類對象,設置一些列參數:
/**
* MediaRecorder
*/
private MediaRecorder mMediaRecorder;
/**
* 設置媒體錄製器的配置參數
* <p>
* 音頻,視頻格式,文件路徑,頻率,編碼格式等等
*
* @throws IOException
*/
private void setUpMediaRecorder() throws IOException {
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mNextVideoAbsolutePath = FileUtils.createVideoDiskFile(appContext, FileUtils.createVideoFileName()).getAbsolutePath();
mMediaRecorder.setOutputFile(mNextVideoAbsolutePath);
mMediaRecorder.setVideoEncodingBitRate(10000000);
//每秒30幀
mMediaRecorder.setVideoFrameRate(30);
mMediaRecorder.setVideoSize(mVideoSize.getWidth(), mVideoSize.getHeight());
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
switch (mSensorOrientation) {
case SENSOR_ORIENTATION_DEFAULT_DEGREES:
mMediaRecorder.setOrientationHint(DEFAULT_ORIENTATIONS.get(rotation));
break;
case SENSOR_ORIENTATION_INVERSE_DEGREES:
mMediaRecorder.setOrientationHint(ORIENTATIONS.get(rotation));
break;
default:
break;
}
mMediaRecorder.prepare();
}
間隔性的隨着視頻錄製而輸出數據到文件中。
// 爲 MediaRecorder設置Surface
Surface recorderSurface = mMediaRecorder.getSurface();
surfaces.add(recorderSurface);
mPreviewBuilder.addTarget(recorderSurface);
最後,當錄製視頻結束後,停止輸出:
// 停止錄製
mMediaRecorder.stop();
mMediaRecorder.reset();
完成一些列拍照或錄像動作後,重新恢復到預覽界面。
/**
* 完成一些列拍照或錄像動作後,釋放焦點。
*/
private void unlockFocus() {
try {
//向session重新發送,預覽的間隔性請求,出現預覽界面。
mCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback, workThreadManager.getBackgroundHandler());
} catch (CameraAccessException e) {
e.printStackTrace();
}
}