預(yù)覽啟動(dòng)流程
- onResume中判斷TextureView是否可用,不可用就給TextureView設(shè)置監(jiān)聽,可用時(shí)才openCamera
- openCamera中先得到相機(jī)服務(wù)CameraManager,由CameraManager得到相機(jī)的屬性信息CameraCharacteristics毅舆,而CameraCharacteristics包含有配置流信息StreamConfigurationMap等,根據(jù)TextureView的尺寸及寬高比從中選擇合適的分辨率尺寸來設(shè)置預(yù)覽尺寸和錄制/拍照尺寸等信息,需要處理預(yù)覽方向及拉伸異常庇楞。
注意:此時(shí)尚未通過CameraManager真正打開相機(jī),但已經(jīng)可以獲取這些信息并進(jìn)行配置
- 通過CameraManager真正打開相機(jī)否纬,得到CameraDevice對象實(shí)例吕晌,在相機(jī)設(shè)備狀態(tài)回調(diào)成功時(shí)開啟預(yù)覽。
(1)將PreviewSize(由TextureView得到)設(shè)置為SurfaceTexture(由TextureView得到)的緩沖區(qū)尺寸临燃,并得到對應(yīng)Surface睛驳。
本人覺得此操作可以提前到真正打開相機(jī)前
(2)CameraDevice創(chuàng)建CameraDevice.TEMPLATE_PREVIEW預(yù)覽類型的CaptureRequest.Builder對象實(shí)例,并添加剛才的Surface對象
mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mPreviewBuilder.addTarget(previewSurface);
(3)CameraDevice創(chuàng)建相機(jī)會話膜廊,需要?jiǎng)偛诺腟urface對象乏沸,在會話回調(diào)方法成功時(shí)得到CameraCaptureSession對象實(shí)例,
對mPreviewBuilder設(shè)置一些對焦模式等參數(shù)后爪瓜,mPreviewSession通過setRepeatingRequest以啟動(dòng)預(yù)覽
mPreviewSession = session;
setUpCaptureRequestBuilder(mPreviewBuilder);
mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, mBackgroundHandler);
預(yù)覽流程.PNG
開始錄制流程
- 以MediaRecorder錄制為例蹬跃,新建該對象實(shí)例,并設(shè)置如下類似參數(shù)
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
if (mNextVideoAbsolutePath == null || mNextVideoAbsolutePath.isEmpty()) {
mNextVideoAbsolutePath = getVideoFilePath(getActivity());
Log.i(TAG, "setUpMediaRecorder: " + mNextVideoAbsolutePath);
}
mMediaRecorder.setOutputFile(mNextVideoAbsolutePath);
mMediaRecorder.setVideoEncodingBitRate(10000000);
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(INVERSE_ORIENTATIONS.get(rotation));
break;
}
mMediaRecorder.prepare();
- 創(chuàng)建用于錄制的CaptureRequest.Builder铆铆,設(shè)置預(yù)覽及MediaRecorder的Surface
mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
// Set up Surface for the camera preview
mPreviewBuilder.addTarget(previewSurface);
// Set up Surface for the MediaRecorder
Surface recorderSurface = mMediaRecorder.getSurface();
mPreviewBuilder.addTarget(recorderSurface);
- CameraDevice再次創(chuàng)建相機(jī)會話蝶缀,需要預(yù)覽及MediaRecorder的Surface對象,并在回調(diào)成功后更新預(yù)覽薄货,開始錄制
mPreviewSession = cameraCaptureSession;
mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, mBackgroundHandler);
ps:打開相機(jī)翁都,開啟預(yù)覽,錄制更新預(yù)覽是在mBackgroundHandler線程
而mMediaRecorder.start()需要在主線程中
錄制流程.PNG