Android Camera2 api 无法录制
Android Camera2 api for recording not working
我正在尝试使用 Camera2 API 录制视频。但是有一些关于丢失表面的异常。我交叉检查 XML 中是否存在表面视图,并且所有权限也已设置。我尝试使用 Google Camera2 代码,但无法理解所有细节。
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {
CameraDevice mCamera;
MediaRecorder mMediaRecorder = new MediaRecorder();
CaptureRequest mCaptureRequest;
CameraCaptureSession mSession;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
boolean recording = false;
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
surfaceView = (SurfaceView)findViewById(R.id.surfaceView);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
CameraManager manager = (CameraManager) getSystemService(CAMERA_SERVICE);
File directory = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
String path = String.valueOf(directory);
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
final File mediaFile;
mediaFile = new File(directory + File.separator + timeStamp + ".mp4");
try {
String[] cameras = manager.getCameraIdList();
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameras[0]);
StreamConfigurationMap configs = characteristics.get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
Size[] sizes = configs.getOutputSizes(MediaCodec.class);
final Size sizeHigh = sizes[0];
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
manager.openCamera(cameras[0], new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice camera) {
mCamera = camera;
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
// mMediaRecorder.setVideoSize(sizeHigh.getWidth(), sizeHigh.getHeight());
// mMediaRecorder.setMaxFileSize(0);
// mMediaRecorder.setOrientationHint(0);
try {
mMediaRecorder.setOutputFile(mediaFile.toString());
mMediaRecorder.setPreviewDisplay(surfaceHolder.getSurface());
mMediaRecorder.prepare();
List<Surface> list = new ArrayList<>();
list.add(surfaceHolder.getSurface());
final CaptureRequest.Builder captureRequest = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
captureRequest.addTarget(surfaceHolder.getSurface());
mCaptureRequest = captureRequest.build();
mCamera.createCaptureSession(list, new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(CameraCaptureSession session) {
mSession = session;
}
@Override
public void onConfigureFailed(CameraCaptureSession session) {
mSession = session;
}
}, null);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onDisconnected(CameraDevice camera) {
}
@Override
public void onError(CameraDevice camera, int error) {
}
}, null);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
public void trigger(View v) {
((Button)findViewById(R.id.button)).setText("stop");
try {
if(!recording) {
mMediaRecorder.start();
mSession.setRepeatingRequest(mCaptureRequest,
new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber) {
super.onCaptureStarted(session, request, timestamp, frameNumber);
}
@Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
}
}, null);
((Button)findViewById(R.id.button)).setText("stop");
recording = true;
} else {
((Button)findViewById(R.id.button)).setText("start");
recording = false;
mSession.stopRepeating();
mMediaRecorder.stop();
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
}
Exception Thrown
07-31 22:43:30.650 2852-2852/com.example.karan.camera I/System.out: debugger has settled (1492)
07-31 22:43:30.972 2852-2852/com.example.karan.camera I/CameraManagerGlobal: Connecting to camera service
07-31 22:43:31.036 2852-2852/com.example.karan.camera I/CameraManager: Using legacy camera HAL.
07-31 22:43:31.170 2852-3618/com.example.karan.camera D/OpenGLRenderer: HWUI GL Pipeline
07-31 22:43:31.191 2852-2852/com.example.karan.camera E/MediaRecorderJNI: Application lost the surface
07-31 22:43:31.191 2852-2852/com.example.karan.camera W/System.err: java.io.IOException: invalid preview surface
07-31 22:43:31.193 2852-2852/com.example.karan.camera W/System.err: at android.media.MediaRecorder._prepare(Native Method)
07-31 22:43:31.194 2852-2852/com.example.karan.camera W/System.err: at android.media.MediaRecorder.prepare(MediaRecorder.java:930)
07-31 22:43:31.194 2852-2852/com.example.karan.camera W/System.err: at com.example.karan.camera.MainActivity.onOpened(MainActivity.java:100)
07-31 22:43:31.195 2852-2852/com.example.karan.camera W/System.err: at android.hardware.camera2.impl.CameraDeviceImpl.run(CameraDeviceImpl.java:139)
07-31 22:43:31.195 2852-2852/com.example.karan.camera W/System.err: at android.os.Handler.handleCallback(Handler.java:769)
07-31 22:43:31.195 2852-2852/com.example.karan.camera W/System.err: at android.os.Handler.dispatchMessage(Handler.java:98)
07-31 22:43:31.195 2852-2852/com.example.karan.camera W/System.err: at android.os.Looper.loop(Looper.java:164)
07-31 22:43:31.195 2852-2852/com.example.karan.camera W/System.err: at android.app.ActivityThread.main(ActivityThread.java:6540)
07-31 22:43:31.196 2852-2852/com.example.karan.camera W/System.err: at java.lang.reflect.Method.invoke(Native Method)
07-31 22:43:31.196 2852-2852/com.example.karan.camera W/System.err: at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
07-31 22:43:31.196 2852-2852/com.example.karan.camera W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
任何人都可以解释这段代码有什么问题吗?
您正在尝试对媒体记录器输出和相机输出使用相同的 SurfaceView - 它们通常无法共享。
并且您没有将任何数据从相机发送到媒体记录器,因为您没有在相机捕获会话中包含来自 MediaRecorder 的 Surface。
通常,您要做的是将相机连接到两个表面——一个用于预览(到 SurfaceView),一个用于录制(到 mediarecorder);您根本不需要连接 MediaRecorder 的预览输出,这更适合在没有单独的相机对象的情况下使用 MediaRecorder。
查看官方camera2视频录制示例了解更多详情:
https://github.com/googlesamples/android-Camera2Video
你应该创建一个不同的表面视图来记录一个不同的预览像这样
SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
surfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(),mPreviewSize.getHeight());
Surface previewSurfice = new Surface(surfaceTexture);
Surface recordSurface = mMediaRecorder.getSurface();
我正在尝试使用 Camera2 API 录制视频。但是有一些关于丢失表面的异常。我交叉检查 XML 中是否存在表面视图,并且所有权限也已设置。我尝试使用 Google Camera2 代码,但无法理解所有细节。
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {
CameraDevice mCamera;
MediaRecorder mMediaRecorder = new MediaRecorder();
CaptureRequest mCaptureRequest;
CameraCaptureSession mSession;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
boolean recording = false;
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
surfaceView = (SurfaceView)findViewById(R.id.surfaceView);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
CameraManager manager = (CameraManager) getSystemService(CAMERA_SERVICE);
File directory = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
String path = String.valueOf(directory);
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
final File mediaFile;
mediaFile = new File(directory + File.separator + timeStamp + ".mp4");
try {
String[] cameras = manager.getCameraIdList();
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameras[0]);
StreamConfigurationMap configs = characteristics.get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
Size[] sizes = configs.getOutputSizes(MediaCodec.class);
final Size sizeHigh = sizes[0];
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
manager.openCamera(cameras[0], new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice camera) {
mCamera = camera;
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
// mMediaRecorder.setVideoSize(sizeHigh.getWidth(), sizeHigh.getHeight());
// mMediaRecorder.setMaxFileSize(0);
// mMediaRecorder.setOrientationHint(0);
try {
mMediaRecorder.setOutputFile(mediaFile.toString());
mMediaRecorder.setPreviewDisplay(surfaceHolder.getSurface());
mMediaRecorder.prepare();
List<Surface> list = new ArrayList<>();
list.add(surfaceHolder.getSurface());
final CaptureRequest.Builder captureRequest = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
captureRequest.addTarget(surfaceHolder.getSurface());
mCaptureRequest = captureRequest.build();
mCamera.createCaptureSession(list, new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(CameraCaptureSession session) {
mSession = session;
}
@Override
public void onConfigureFailed(CameraCaptureSession session) {
mSession = session;
}
}, null);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onDisconnected(CameraDevice camera) {
}
@Override
public void onError(CameraDevice camera, int error) {
}
}, null);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
public void trigger(View v) {
((Button)findViewById(R.id.button)).setText("stop");
try {
if(!recording) {
mMediaRecorder.start();
mSession.setRepeatingRequest(mCaptureRequest,
new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber) {
super.onCaptureStarted(session, request, timestamp, frameNumber);
}
@Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
}
}, null);
((Button)findViewById(R.id.button)).setText("stop");
recording = true;
} else {
((Button)findViewById(R.id.button)).setText("start");
recording = false;
mSession.stopRepeating();
mMediaRecorder.stop();
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
}
Exception Thrown
07-31 22:43:30.650 2852-2852/com.example.karan.camera I/System.out: debugger has settled (1492)
07-31 22:43:30.972 2852-2852/com.example.karan.camera I/CameraManagerGlobal: Connecting to camera service
07-31 22:43:31.036 2852-2852/com.example.karan.camera I/CameraManager: Using legacy camera HAL.
07-31 22:43:31.170 2852-3618/com.example.karan.camera D/OpenGLRenderer: HWUI GL Pipeline
07-31 22:43:31.191 2852-2852/com.example.karan.camera E/MediaRecorderJNI: Application lost the surface
07-31 22:43:31.191 2852-2852/com.example.karan.camera W/System.err: java.io.IOException: invalid preview surface
07-31 22:43:31.193 2852-2852/com.example.karan.camera W/System.err: at android.media.MediaRecorder._prepare(Native Method)
07-31 22:43:31.194 2852-2852/com.example.karan.camera W/System.err: at android.media.MediaRecorder.prepare(MediaRecorder.java:930)
07-31 22:43:31.194 2852-2852/com.example.karan.camera W/System.err: at com.example.karan.camera.MainActivity.onOpened(MainActivity.java:100)
07-31 22:43:31.195 2852-2852/com.example.karan.camera W/System.err: at android.hardware.camera2.impl.CameraDeviceImpl.run(CameraDeviceImpl.java:139)
07-31 22:43:31.195 2852-2852/com.example.karan.camera W/System.err: at android.os.Handler.handleCallback(Handler.java:769)
07-31 22:43:31.195 2852-2852/com.example.karan.camera W/System.err: at android.os.Handler.dispatchMessage(Handler.java:98)
07-31 22:43:31.195 2852-2852/com.example.karan.camera W/System.err: at android.os.Looper.loop(Looper.java:164)
07-31 22:43:31.195 2852-2852/com.example.karan.camera W/System.err: at android.app.ActivityThread.main(ActivityThread.java:6540)
07-31 22:43:31.196 2852-2852/com.example.karan.camera W/System.err: at java.lang.reflect.Method.invoke(Native Method)
07-31 22:43:31.196 2852-2852/com.example.karan.camera W/System.err: at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
07-31 22:43:31.196 2852-2852/com.example.karan.camera W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
任何人都可以解释这段代码有什么问题吗?
您正在尝试对媒体记录器输出和相机输出使用相同的 SurfaceView - 它们通常无法共享。
并且您没有将任何数据从相机发送到媒体记录器,因为您没有在相机捕获会话中包含来自 MediaRecorder 的 Surface。
通常,您要做的是将相机连接到两个表面——一个用于预览(到 SurfaceView),一个用于录制(到 mediarecorder);您根本不需要连接 MediaRecorder 的预览输出,这更适合在没有单独的相机对象的情况下使用 MediaRecorder。
查看官方camera2视频录制示例了解更多详情: https://github.com/googlesamples/android-Camera2Video
你应该创建一个不同的表面视图来记录一个不同的预览像这样
SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
surfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(),mPreviewSize.getHeight());
Surface previewSurfice = new Surface(surfaceTexture);
Surface recordSurface = mMediaRecorder.getSurface();