demos - git android example
Android Camera 2 Api (5)
Depende de lo que esté haciendo con CameraCaptureSession y MediaRecorder, pero cuando llame a mMediaRecorder.stop()
, creo que está destruyendo la superficie utilizada para la sesión de vista previa de la cámara, lo que provoca este error porque la documentación dice
Una vez que se detiene la grabación, tendrá que configurarlo de nuevo como si se hubiera construido
Por lo tanto, si llama a PreviewSession.abortCaptures()
( mPreviewSession.stopRepeating();
no es necesario de lo que recojo) detiene el envío de la cámara a la superficie de la grabadora, lo que le permitirá detener el MediaRecorder sin problemas.
PreviewSession.abortCaptures();
no detiene instantáneamente la salida de vista previa de la cámara, por lo que puede que necesite llamar a MediaRecorder.stop()
en el onClosed()
o onReady()
de CameraCaptureSession.StateCallback
He estado probando la API de camera2. He descargado el código de
https://developer.android.com/samples/Camera2Video/index.html para aprender cómo funciona. Funciona bien hasta que deje de grabar. Cuando paro de grabar se ejecuta el siguiente código.
private void stopRecordingVideo() {
// UI
mIsRecordingVideo = false;
mBtn_Video.setText(R.string.record);
// Stop recording
try {
mMediaRecorder.stop();
mMediaRecorder.reset();
}
catch (Exception e) {
e.printStackTrace();
}
Activity activity = getActivity();
if (null != activity) {
System.out.println("file " + getVideoFile(activity));
Toast.makeText(activity, "Video saved: " + getVideoFile(activity),
Toast.LENGTH_SHORT).show();
}
startPreview();
en mMediaRecorder.stop (); lanza el siguiente error
01-12 16:24:23.115 2161-2200/com.cameratwoapi E/Surface﹕ queueBuffer: error queuing buffer to SurfaceTexture, -19
01-12 16:24:23.135 2161-2200/com.cameratwoapi E/EGL_emulation﹕ tid 2200: swapBuffers(285): error 0x3003 (EGL_BAD_ALLOC)
01-12 16:24:23.197 2161-2200/com.cameratwoapi E/CameraDeviceGLThread-0﹕ Received exception on GL render thread:
java.lang.IllegalStateException: swapBuffers: EGL error: 0x3003
at android.hardware.camera2.legacy.SurfaceTextureRenderer.checkEglError(SurfaceTextureRenderer.java:487)
at android.hardware.camera2.legacy.SurfaceTextureRenderer.swapBuffers(SurfaceTextureRenderer.java:480)
at android.hardware.camera2.legacy.SurfaceTextureRenderer.drawIntoSurfaces(SurfaceTextureRenderer.java:681)
at android.hardware.camera2.legacy.GLThreadManager$1.handleMessage(GLThreadManager.java:103)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:135)
at android.os.HandlerThread.run(HandlerThread.java:61)
Cualquier idea de lo que estoy haciendo mal. Pasé pocas horas pero no pude encontrar ninguna solución.
Editar - Estoy usando el emulador geneymotion. El camino que estoy usando
archivo /storage/emulated/0/Android/data/com.gold.cameratwoapi/files/video.mp4
Gracias
Después de llamar a mMediaRecorder.stop()
siempre se lanza una IllegalStateException
. He notado que en los dispositivos con INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY
el CameraDevice
cambia de estado a error, llamando inmediatamente a onError()
en CameraDevice.StateCallback
.
En la muestra a la que hizo referencia, onError()
cierra la cámara y finaliza la actividad, así que simplemente cambie onError()
para volver a abrir la cámara, de esta manera:
@Override
public void onError(CameraDevice cameraDevice, int error) {
// mCameraOpenCloseLock.release();
// cameraDevice.close();
// mCameraDevice = null;
// Activity activity = getActivity();
// if (null != activity) {
// activity.finish();
// }
closeCamera();
openCamera(mTextureView.getWidth(), mTextureView.getHeight());
}
También sería una buena idea poner un poco de control para asegurarse de que si realmente ocurrió un error, se llame al código comentado en lugar de ingresar un ciclo de intentos de abrir la cámara una y otra vez.
Probado en una Moto G de 2ª generación, con Android 5.0.2
En mi caso, uso TimerTask
y un TimerTask
. Hay un error directo a mMediaRecorder.stop (). Entonces uso este método
final Handler mTimerHandler = new Handler(Looper.getMainLooper());
mIsRecordingVideo = false;
// Stop recording
try {
mPreviewSession.stopRepeating();
mPreviewSession.abortCaptures();
} catch (CameraAccessException e) {
e.printStackTrace();
}
try{
Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
mTimerHandler.post(new Runnable() {
@Override
public void run() {
mMediaRecorder.stop();
mMediaRecorder.reset();
}
});
}
};
timer.schedule(timerTask,30);
}catch(RuntimeException e){
Log.e("----------------","---->>>>>>>>>"+e);
e.printStackTrace();
}
Mi solución es cambiar void stopRecordingVideo () de la siguiente manera:
private void stopRecordingVideo() {
// UI
mIsRecordingVideo = false;
mButtonVideo.setText(R.string.record);
// Added by Ben Ning, to resolve exception issue when stop recording.
try {
mPreviewSession.stopRepeating();
mPreviewSession.abortCaptures();
} catch (CameraAccessException e) {
e.printStackTrace();
}
// Stop recording
mMediaRecorder.stop();
mMediaRecorder.reset();
}
La clave es:
try {
mPreviewSession.stopRepeating();
mPreviewSession.abortCaptures();
} catch (CameraAccessException e) {
e.printStackTrace();
}
private void stopRecordingVideo() {
// UI
mIsRecordingVideo = false;
mButtonVideo.setText(R.string.record);
// Added by Ben Ning, to resolve exception issue when stop recording.
try {
mPreviewSession.stopRepeating();
mPreviewSession.abortCaptures();
} catch (CameraAccessException e) {
e.printStackTrace();
}
// Stop recording
mMediaRecorder.stop();
mMediaRecorder.reset();
Activity activity = getActivity();
if (null != activity) {
Toast.makeText(activity, "Video saved: " + getVideoFile(activity),
Toast.LENGTH_SHORT).show();
}
startPreview();
}
Esto es trabajo para mí.