android android-canvas mediarecorder surface android-mediarecorder

MediaRecorder y VideoSource.SURFACE, parada fallida:-1007(un error grave de Android)



android-canvas android-mediarecorder (1)

Estoy intentando grabar MediaRecorder sin usar la instancia de la Camera pero usando Surface fuente de video Surface (sí, es posible, pero resultó que no es tan perfecto) - mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);

Acabo de escribir cuál es el problema:

El siguiente código funciona solo en algunos dispositivos y funciona temporalmente en algunos dispositivos después de un reinicio reciente del dispositivo o no funciona en absoluto

Si no funciona, el método MediaRecorder.stop() falla con el siguiente error

E / MediaRecorder: error de detención: -1007 W / System.err:

java.lang.RuntimeException: error de detención. a

android.media.MediaRecorder.stop (Método nativo)

la grabadora mp4 es de tamaño demasiado pequeño (kilobytes) y no se puede reproducir

Dispositivos probados:

Funciona en Lenovo P2, Xiaomi Mi A1

no funciona en Xiaomi Redmi 5, Sony Xperia, Xiaomi Redmi 4 Prime

También puedes leer los comentarios en mi código para entender mejor el problema.

new Thread(() -> { MediaRecorder mediaRecorder = new MediaRecorder(); File file = new File(Environment.getExternalStorageDirectory() + File.separator + "test_media_recorder_surface_source.mp4"); if (file.exists()) { file.delete(); } mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); mediaRecorder.setOutputFile(file.getAbsolutePath()); mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); mediaRecorder.setVideoSize(1280, 720); mediaRecorder.setCaptureRate(24); try { mediaRecorder.prepare(); int sleepTime = 1000 / 24; Surface surface = mediaRecorder.getSurface(); mediaRecorder.start(); // record something (we can also record frames here from onPreviewFrame byte arrays) // e.g. convert raw frame byte[] to Bitmap using mb OpenCV and then draw bitmap on canvas // using canvas.drawBitmap(...) // here we record just blue background... for (int i = 0; i < 120; i++) { // 5 seconds, 24 fps Canvas canvas = surface.lockCanvas(null); canvas.drawColor(Color.BLUE); surface.unlockCanvasAndPost(canvas); try { Thread.sleep(sleepTime); } catch (InterruptedException e) { e.printStackTrace(); } } // on many devices stop fails with RuntimeException -1007 error code // I guess it works ok 100% only for modern powerful devices... mediaRecorder.stop(); // E/MediaRecorder: stop failed: -1007 // W/System.err: java.lang.RuntimeException: stop failed. // at android.media.MediaRecorder.stop(Native Method) // recorder.reset(); mediaRecorder.release(); // I get file with very small size (kilobytes) and it can''t be played // ######## RESULTS ###### // WORKS OK ON: // - Lenovo P2 (Android 7) // - Xiaomi Mi A1 (Android 8) // DOESN''T WORK ON (stop fails with -1007, small video file and can''t be played): // - Xiaomi Redmi 5 (Android 7) // - Sony Xperia (I don''t remember the exact model and Android OS) // - Xiaomi Redmi 4 Prime (Android 6) * // * p.s. on Xiaomi Redmi 4 Prime it works some time after rebooting the device // if I leave this smartphone for a while and try again it will fail again // until I reboot the device... } catch (Exception e) { e.printStackTrace(); } }).start();

La ACTUALIZACIÓN # 1 parece un progreso, lo que podría ser el problema: el problema de los códigos (mp4 / h264)

Funciona mejor con WEBM / VP8, los videos se pueden reproducir ahora, pero algo malo con fps, muestra 1000 en propiedades.

mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.WEBM); mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.VP8);

Además, MediaRecord no graba audio cuando se usa

mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.VORBIS);

verifica que el dispositivo Android MediaRecorder se bloquee cuando se usa MP4 / H264 y una resolución superior a 720p, por lo que también sucede cuando usas MediaRecorder y MediaProjection para grabar / capturar la pantalla del dispositivo (porque también usa Surface ...)

ACTUALIZACIÓN 2 sí parece que el códec vp8 funciona bien, pero hay un problema para el contenedor webm: ¡NO HAY AUDIO!

buggy Android simplemente no admite la codificación de audio VORBIS / OGG ... https://developer.android.com/guide/topics/media/media-formats#audio-formats


Supongo que no hay solución

así que la respuesta es: MediaRecorder / Android está defectuoso o las compañías móviles no se preocuparon por todas las funciones de Android mientras desarrollaban sus dispositivos

Actualizar

MediaCodec también tiene buggy con lienzo.

mSurface = mMediaCodec.createInputSurface(); mSurface.lockHardwareCanvas()

Funciona en muchos más dispositivos con MediaCodec, pero aún así, es posible que algunos dispositivos no puedan grabar el video correctamente con este método.

Así que la respuesta final : nunca uses lockCanvas o lockHardwareCanvas cuando lockHardwareCanvas con MediaCodec o MediaRecorder , está MediaRecorder de errores.

La única manera - OpenGl ES

Otros enlaces sobre el tema:

https://github.com/googlesamples/android-Camera2Video/issues/86 https://issuetracker.google.com/issues/111433520