J'ai essayé camera2 API. J'ai téléchargé le code de
https://developer.Android.com/samples/Camera2Video/index.html pour en savoir plus sur son fonctionnement. Cela fonctionne bien jusqu'à ce que je cesse d'enregistrer. Quand j'arrête d'enregistrer, le code suivant est exécuté.
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();
sur mMediaRecorder.stop (); il jette l'erreur suivante
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)
Toute idée de ce que je fais mal. J'ai passé quelques heures mais je n'ai trouvé aucune solution.
Edit - J'utilise l'émulateur geneymotion. Le chemin que j'utilise
fichier /storage/emulated/0/Android/data/com.gold.cameratwoapi/files/video.mp4
Merci
Ma solution est de changer void stopRecordingVideo () comme suit:
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 clé est:
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();
}
cela fonctionne pour moi.
Après avoir appelé mMediaRecorder.stop()
, IllegalStateException
est toujours renvoyé. J'ai remarqué que sur les appareils avec INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY
, le CameraDevice
change le statut en erreur et appelle immédiatement onError()
dans le CameraDevice.StateCallback
.
Dans l’exemple que vous avez cité, onError()
ferme la caméra et termine l’activité. Il suffit donc de modifier onError()
pour rouvrir la caméra, comme suit:
@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());
}
Ce serait également une bonne idée de vérifier que si une erreur se produisait réellement, le code commenté était appelé plutôt que d'entrer dans une boucle consistant à essayer d'ouvrir la caméra encore et encore.
Testé sur une Moto G 2ème génération, avec Android 5.0.2
Dans mon cas, j'utilise TimerTask
et un Handler
. Il y a une erreur directement sur le mediaRecorder.stop (). Donc j'utilise cette méthode
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();
}
Cela dépend de ce que vous faites avec CameraCaptureSession et MediaRecorder, mais lorsque vous appelez mMediaRecorder.stop()
, je pense que cela détruit la surface utilisée pour la session de prévisualisation de la caméra, ce qui provoque cette erreur car la documentation indique
Une fois l'enregistrement arrêté, vous devrez le reconfigurer comme s'il venait juste d'être construit.
Par conséquent, si vous appelez PreviewSession.abortCaptures()
(mPreviewSession.stopRepeating();
n'est pas nécessaire, d'après ce que je comprends), la caméra envoie la sortie à la surface de l'enregistreur, ce qui vous permet d'arrêter le MediaRecorder sans problème.
PreviewSession.abortCaptures();
n'arrête pas instantanément la sortie de prévisualisation de la caméra. Vous devrez peut-être appeler MediaRecorder.stop()
dans les méthodes onClosed()
ou onReady()
de CameraCaptureSession.StateCallback