three_gpp studio outputformat mediaplayer example codecs android android-mediarecorder

android - studio - mediarecorder outputformat three_gpp



¿Alguien tiene MediaRecorder trabajando con ParcelFileDescriptor y createPipe()? (1)

Estoy tratando de elaborar un ejemplo de grabación de audio, con el almacenamiento de datos manejado por la aplicación, no MediaRecorder . Los casos de uso incluyen el almacenamiento de la grabación en el almacenamiento interno o el cifrado de la grabación.

En principio, esto debería funcionar utilizando una canalización creada por createPipe() en ParcelFileDescriptor , pero ParcelFileDescriptor salida con formato incorrecto.

Primero, aquí hay un proyecto de muestra que registra "naturalmente" usando MediaRecorder , con MediaRecorder escribiendo directamente en un archivo de salida en el almacenamiento externo. Esta aplicación funciona bien, y la salida puede ser reproducida por el dispositivo Android o la VLC grabada en mi caja de Linux.

Aquí está mi variación createPipe() de este proyecto . Desde el punto de vista de la configuración general de MediaRecorder (por ejemplo, setOutputFormat() ), es el mismo que el primero, por lo que el código es presumiblemente correcto.

Sin embargo, estoy suministrando la salida a través de:

recorder.setOutputFile(getStreamFd());

Donde getStreamFd() usa createPipe() , genera un hilo de fondo para leer desde la canalización y devuelve el final de escritura para que lo use MediaRecorder :

private FileDescriptor getStreamFd() { ParcelFileDescriptor[] pipe=null; try { pipe=ParcelFileDescriptor.createPipe(); new TransferThread(new AutoCloseInputStream(pipe[0]), new FileOutputStream(getOutputFile())).start(); } catch (IOException e) { Log.e(getClass().getSimpleName(), "Exception opening pipe", e); } return(pipe[1].getFileDescriptor()); }

TransferThread es una rutina clásica de copia de flujo a flujo de java.io, aumentada con inteligencia para vaciar y sincronizar el archivo de salida:

static class TransferThread extends Thread { InputStream in; FileOutputStream out; TransferThread(InputStream in, FileOutputStream out) { this.in=in; this.out=out; } @Override public void run() { byte[] buf=new byte[8192]; int len; try { while ((len=in.read(buf)) > 0) { out.write(buf, 0, len); } in.close(); out.flush(); out.getFD().sync(); out.close(); } catch (IOException e) { Log.e(getClass().getSimpleName(), "Exception transferring file", e); } } }

Cuando ejecuto la segunda aplicación, obtengo un archivo de salida que, por inspección cruda a través de un editor hexadecimal, parece básicamente correcto. IOW, no es como si fuera un archivo de cero bytes, o está lleno de incoherencias irreconocibles. Está lleno de una especie de galimatías similar a la de la primera aplicación. Sin embargo, ni Android ni VLC pueden jugarlo.

Si tuviera que adivinar, supondría que estoy arruinando algo al leer desde la tubería, pero no estoy seguro de dónde específicamente me estoy equivocando.

¿Alguna sugerencia?

¡Gracias por adelantado!


Supongo que esto está relacionado con mi respuesta a tu otra pregunta. ¿Alguien tiene MediaPlayer trabajando con ParcelFileDescriptor y createPipe ()?

Probablemente cuando el MediaRecorder intentará escribir la información del encabezado, el canal estará cerrado.

Si utiliza:

recorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR); recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

El registro funciona bien, porque no tendrá información de encabezado, solo audio en bruto.