sagemcom remoto para descargar desbloquear decodificador controlar control conectar con como celular canal cambiar azamerica app android pcm aac mediacodec audiorecord

android - remoto - desbloquear decodificador sagemcom



PCM-> AAC(Codificador)-> PCM(Decodificador) en tiempo real con la optimización correcta (6)

D / AudioRecoder ﹕ 4096 bytes leídos D / AudioEncoder ﹕ 360 bytes codificados D / UDP Receptor ﹕ recibido !!! desde /127.0.0.1:39000 Receptor D / UDP ﹕ 360 bytes recibidos D / AudioDecoder ﹕ 8192 bytes decodificados

Esto se debe a que el decodificador acc siempre se decodifica en canales estéreo, incluso si los datos codificados son MONO. así que si su lado de codificación está configurado para canales estéreo, será como:

D / AudioRecoder ﹕ 8192 bytes leídos D / AudioEncoder ﹕ 360 bytes codificados D / UDP Receptor ﹕ recibido !!! desde /127.0.0.1:39000 Receptor D / UDP ﹕ 360 bytes recibidos D / AudioDecoder ﹕ 8192 bytes decodificados

Estoy tratando de implementar

AudioRecord (MIC) -> PCM -> AAC Encoder AAC -> PCM Decode -> AudioTrack?? (SPEAKER)

con MediaCodec en Android 4.1+ (API16).

En primer lugar, implementé PCM -> AAC Encoder por MediaCodec éxito (pero no estoy seguro de que estaba optimizado) como se MediaCodec continuación

private boolean setEncoder(int rate) { encoder = MediaCodec.createEncoderByType("audio/mp4a-latm"); MediaFormat format = new MediaFormat(); format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm"); format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1); format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 44100); format.setInteger(MediaFormat.KEY_BIT_RATE, 64 * 1024);//AAC-HE 64kbps format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectHE); encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); return true; }

ENTRADA: Bitrate PCM = 44100 (Hz) x 16 (bit) x 1 (Monoral) = 705600 bit / s

SALIDA: Velocidad de bits AAC-HE = 64 x 1024 (bit) = 65536 bit / s

Por lo tanto, el tamaño de los datos está comprimido aproximadamente x11 , y confirmé que esto funciona al observar un registro

  • AudioRecoder ﹕ 4096 bytes leídos
  • AudioEncoder ﹕ 369 bytes codificados

el tamaño de los datos está comprimido aproximadamente x11 , hasta ahora todo bien.

Ahora, tengo un servidor UDP para recibir los datos codificados y luego decodificarlos.

El perfil del decodificador se establece de la siguiente manera:

private boolean setDecoder(int rate) { decoder = MediaCodec.createDecoderByType("audio/mp4a-latm"); MediaFormat format = new MediaFormat(); format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm"); format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1); format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 44100); format.setInteger(MediaFormat.KEY_BIT_RATE, 64 * 1024);//AAC-HE 64kbps format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectHE); decoder.configure(format, null, null, 0); return true; }

Dado que el tamaño del búfer del paquete UDPserver es 1024

  • Servidor UDP ﹕ 1024 bytes recibidos

y dado que estos son los datos AAC comprimidos, esperaría que el tamaño de decodificación fuera

aproximadamente 1024 x11 , sin embargo el resultado real es

  • AudioDecoder ﹕ 8192 bytes decodificados

Es aproximadamente x8 , y siento algo mal.

El código del decodificador es el siguiente:

IOudpPlayer = new Thread(new Runnable() { public void run() { SocketAddress sockAddress; String address; int len = 1024; byte[] buffer2 = new byte[len]; DatagramPacket packet; byte[] data; ByteBuffer[] inputBuffers; ByteBuffer[] outputBuffers; ByteBuffer inputBuffer; ByteBuffer outputBuffer; MediaCodec.BufferInfo bufferInfo; int inputBufferIndex; int outputBufferIndex; byte[] outData; try { decoder.start(); isPlaying = true; while (isPlaying) { try { packet = new DatagramPacket(buffer2, len); ds.receive(packet); sockAddress = packet.getSocketAddress(); address = sockAddress.toString(); Log.d("UDP Receiver"," received !!! from " + address); data = new byte[packet.getLength()]; System.arraycopy(packet.getData(), packet.getOffset(), data, 0, packet.getLength()); Log.d("UDP Receiver", data.length + " bytes received"); //=========== inputBuffers = decoder.getInputBuffers(); outputBuffers = decoder.getOutputBuffers(); inputBufferIndex = decoder.dequeueInputBuffer(-1); if (inputBufferIndex >= 0) { inputBuffer = inputBuffers[inputBufferIndex]; inputBuffer.clear(); inputBuffer.put(data); decoder.queueInputBuffer(inputBufferIndex, 0, data.length, 0, 0); } bufferInfo = new MediaCodec.BufferInfo(); outputBufferIndex = decoder.dequeueOutputBuffer(bufferInfo, 0); while (outputBufferIndex >= 0) { outputBuffer = outputBuffers[outputBufferIndex]; outputBuffer.position(bufferInfo.offset); outputBuffer.limit(bufferInfo.offset + bufferInfo.size); outData = new byte[bufferInfo.size]; outputBuffer.get(outData); Log.d("AudioDecoder", outData.length + " bytes decoded"); decoder.releaseOutputBuffer(outputBufferIndex, false); outputBufferIndex = decoder.dequeueOutputBuffer(bufferInfo, 0); } //=========== } catch (IOException e) { } } decoder.stop(); } catch (Exception e) { } } });

el código completo:

https://gist.github.com/kenokabe/9029256

También necesita permiso:

<uses-permission android:name="android.permission.INTERNET"></uses-permission> <uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission>

Un miembro de fadden que trabaja para Google me dijo.

Parece que no estoy configurando posición y límite en el búfer de salida.

He leído que la codificación VP8 Nexus 5 devuelve vacíos / 0-Frames , pero no estoy seguro de cómo implementarlos correctamente.

ACTUALIZACIÓN: En cierto modo entendí dónde modificar para

Parece que no estoy configurando posición y límite en el búfer de salida.

, así que agregue 2 líneas dentro del bucle while de Codificador y Decodificador de la siguiente manera:

outputBuffer.position(bufferInfo.offset); outputBuffer.limit(bufferInfo.offset + bufferInfo.size);

https://gist.github.com/kenokabe/9029256/revisions

Sin embargo el resultado es el mismo.

y ahora, creo, los errores: W/SoftAAC2﹕ AAC decoder returned error 16388, substituting silence. Indica que este decodificador falla completamente desde el primero. Es de nuevo que the data is not seekable . Buscar en las transmisiones AAC en Android Es muy decepcionante si el decodificador AAC no puede manejar los datos de transmisión de esta manera, pero solo agregando un encabezado.

ACTUALIZACIÓN2: el receptor UDP hizo mal, así modificado

https://gist.github.com/kenokabe/9029256

Ahora el error

W/SoftAAC2﹕ AAC decoder returned error 16388, substituting silence. desaparecido !!

Por lo tanto, indica que el decodificador funciona sin un error, al menos,

Sin embargo, este es el registro de 1 ciclo:

D/AudioRecoder﹕ 4096 bytes read D/AudioEncoder﹕ 360 bytes encoded D/UDP Receiver﹕ received !!! from /127.0.0.1:39000 D/UDP Receiver﹕ 360 bytes received D/AudioDecoder﹕ 8192 bytes decoded

PCM (4096) -> AACencoded (360) -> UDP-AAC (360) -> (se supone que es) PCM (8192)

El resultado final es aproximadamente 2 veces el tamaño del PCM original, algo todavía está mal.

Así que mi pregunta aquí sería

  1. ¿Puede optimizar correctamente mi código de ejemplo para que funcione correctamente?

  2. ¿Es una forma correcta de utilizar la API de AudioTrack para reproducir los datos en bruto PCM descodificados sobre la marcha, y puede mostrarme la forma correcta de hacerlo? Se aprecia un código de ejemplo.

Gracias.

PD. Mis objetivos de proyecto en Android4.1 + (API16), he leído que las cosas son más fáciles en API18 (Andeoid 4.3+), pero por razones obvias de compatibilidad, desafortunadamente, tengo que omitir MediaMuxer, etc. aquí ...


Después de probar esto es lo que se me ocurrió al modificar su código:

package com.example.app; import android.app.Activity; import android.media.AudioManager; import android.media.MediaCodecInfo; import android.media.MediaFormat; import android.os.Bundle; import android.media.AudioFormat; import android.media.AudioRecord; import android.media.AudioTrack; import android.media.MediaCodec; import android.media.MediaRecorder.AudioSource; import android.util.Log; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketAddress; import java.net.SocketException; import java.nio.ByteBuffer; public class MainActivity extends Activity { private AudioRecord recorder; private AudioTrack player; private MediaCodec encoder; private MediaCodec decoder; private short audioFormat = AudioFormat.ENCODING_PCM_16BIT; private short channelConfig = AudioFormat.CHANNEL_IN_MONO; private int bufferSize; private boolean isRecording; private boolean isPlaying; private Thread IOrecorder; private Thread IOudpPlayer; private DatagramSocket ds; private final int localPort = 39000; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); IOrecorder = new Thread(new Runnable() { public void run() { int read; byte[] buffer1 = new byte[bufferSize]; ByteBuffer[] inputBuffers; ByteBuffer[] outputBuffers; ByteBuffer inputBuffer; ByteBuffer outputBuffer; MediaCodec.BufferInfo bufferInfo; int inputBufferIndex; int outputBufferIndex; byte[] outData; DatagramPacket packet; try { encoder.start(); recorder.startRecording(); isRecording = true; while (isRecording) { read = recorder.read(buffer1, 0, bufferSize); // Log.d("AudioRecoder", read + " bytes read"); //------------------------ inputBuffers = encoder.getInputBuffers(); outputBuffers = encoder.getOutputBuffers(); inputBufferIndex = encoder.dequeueInputBuffer(-1); if (inputBufferIndex >= 0) { inputBuffer = inputBuffers[inputBufferIndex]; inputBuffer.clear(); inputBuffer.put(buffer1); encoder.queueInputBuffer(inputBufferIndex, 0, buffer1.length, 0, 0); } bufferInfo = new MediaCodec.BufferInfo(); outputBufferIndex = encoder.dequeueOutputBuffer(bufferInfo, 0); while (outputBufferIndex >= 0) { outputBuffer = outputBuffers[outputBufferIndex]; outputBuffer.position(bufferInfo.offset); outputBuffer.limit(bufferInfo.offset + bufferInfo.size); outData = new byte[bufferInfo.size]; outputBuffer.get(outData); // Log.d("AudioEncoder ", outData.length + " bytes encoded"); //------------- packet = new DatagramPacket(outData, outData.length, InetAddress.getByName("127.0.0.1"), localPort); ds.send(packet); //------------ encoder.releaseOutputBuffer(outputBufferIndex, false); outputBufferIndex = encoder.dequeueOutputBuffer(bufferInfo, 0); } // ----------------------; } encoder.stop(); recorder.stop(); } catch (Exception e) { e.printStackTrace(); } } }); IOudpPlayer = new Thread(new Runnable() { public void run() { SocketAddress sockAddress; String address; int len = 2048 byte[] buffer2 = new byte[len]; DatagramPacket packet; byte[] data; ByteBuffer[] inputBuffers; ByteBuffer[] outputBuffers; ByteBuffer inputBuffer; ByteBuffer outputBuffer; MediaCodec.BufferInfo bufferInfo; int inputBufferIndex; int outputBufferIndex; byte[] outData; try { player.play(); decoder.start(); isPlaying = true; while (isPlaying) { try { packet = new DatagramPacket(buffer2, len); ds.receive(packet); sockAddress = packet.getSocketAddress(); address = sockAddress.toString(); // Log.d("UDP Receiver"," received !!! from " + address); data = new byte[packet.getLength()]; System.arraycopy(packet.getData(), packet.getOffset(), data, 0, packet.getLength()); // Log.d("UDP Receiver", data.length + " bytes received"); //=========== inputBuffers = decoder.getInputBuffers(); outputBuffers = decoder.getOutputBuffers(); inputBufferIndex = decoder.dequeueInputBuffer(-1); if (inputBufferIndex >= 0) { inputBuffer = inputBuffers[inputBufferIndex]; inputBuffer.clear(); inputBuffer.put(data); decoder.queueInputBuffer(inputBufferIndex, 0, data.length, 0, 0); } bufferInfo = new MediaCodec.BufferInfo(); outputBufferIndex = decoder.dequeueOutputBuffer(bufferInfo, 0); while (outputBufferIndex >= 0) { outputBuffer = outputBuffers[outputBufferIndex]; outputBuffer.position(bufferInfo.offset); outputBuffer.limit(bufferInfo.offset + bufferInfo.size); outData = new byte[bufferInfo.size]; outputBuffer.get(outData); // Log.d("AudioDecoder", outData.length + " bytes decoded"); player.write(outData, 0, outData.length); decoder.releaseOutputBuffer(outputBufferIndex, false); outputBufferIndex = decoder.dequeueOutputBuffer(bufferInfo, 0..


He intentado el código anterior y no funcionó correctamente. Estaba recibiendo mucho silencio inyectado en la salida descodificada. El problema no estaba configurando el valor "csd" adecuado para el decodificador.

Por lo tanto, si ve "silencio" en el registro o error de lanzamiento del decodificador, asegúrese de haber agregado lo siguiente a su formato de decodificador multimedia

int profile = 2; //AAC LC int freqIdx = 11; //8KHz int chanCfg = 1; //Mono ByteBuffer csd = ByteBuffer.allocate(2); csd.put(0, (byte) (profile << 3 | freqIdx >> 1)); csd.put(1, (byte)((freqIdx & 0x01) << 7 | chanCfg << 3)); mediaFormat.setByteBuffer("csd-0", csd);


He probado con su fuente. hay algunos puntos

  1. La velocidad de bits es un número natural de K, pero no la computadora K. 64k = 64000, pero no 64 * 1024

  2. No se recomienda escribir un código largo que comparta algunas variables. A. Separa el hilo del codificador y el hilo del decodificador en 2 clases independientes B. El DatagramSocket es compartido por el remitente y el receptor, no es bueno.

  3. Enumerar formato de audio necesita más valores. es decir, las frecuencias de muestreo deben seleccionarse de: 8000, 11025, 22050, 44100


Respuesta propia, aquí está mi mejor esfuerzo hasta ahora

package com.example.app; import android.app.Activity; import android.media.AudioManager; import android.media.MediaCodecInfo; import android.media.MediaFormat; import android.os.Bundle; import android.media.AudioFormat; import android.media.AudioRecord; import android.media.AudioTrack; import android.media.MediaCodec; import android.media.MediaRecorder.AudioSource; import android.util.Log; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketAddress; import java.net.SocketException; import java.nio.ByteBuffer; public class MainActivity extends Activity { private AudioRecord recorder; private AudioTrack player; private MediaCodec encoder; private MediaCodec decoder; private short audioFormat = AudioFormat.ENCODING_PCM_16BIT; private short channelConfig = AudioFormat.CHANNEL_IN_MONO; private int bufferSize; private boolean isRecording; private boolean isPlaying; private Thread IOrecorder; private Thread IOudpPlayer; private DatagramSocket ds; private final int localPort = 39000; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); IOrecorder = new Thread(new Runnable() { public void run() { int read; byte[] buffer1 = new byte[bufferSize]; ByteBuffer[] inputBuffers; ByteBuffer[] outputBuffers; ByteBuffer inputBuffer; ByteBuffer outputBuffer; MediaCodec.BufferInfo bufferInfo; int inputBufferIndex; int outputBufferIndex; byte[] outData; DatagramPacket packet; try { encoder.start(); recorder.startRecording(); isRecording = true; while (isRecording) { read = recorder.read(buffer1, 0, bufferSize); // Log.d("AudioRecoder", read + " bytes read"); //------------------------ inputBuffers = encoder.getInputBuffers(); outputBuffers = encoder.getOutputBuffers(); inputBufferIndex = encoder.dequeueInputBuffer(-1); if (inputBufferIndex >= 0) { inputBuffer = inputBuffers[inputBufferIndex]; inputBuffer.clear(); inputBuffer.put(buffer1); encoder.queueInputBuffer(inputBufferIndex, 0, buffer1.length, 0, 0); } bufferInfo = new MediaCodec.BufferInfo(); outputBufferIndex = encoder.dequeueOutputBuffer(bufferInfo, 0); while (outputBufferIndex >= 0) { outputBuffer = outputBuffers[outputBufferIndex]; outputBuffer.position(bufferInfo.offset); outputBuffer.limit(bufferInfo.offset + bufferInfo.size); outData = new byte[bufferInfo.size]; outputBuffer.get(outData); // Log.d("AudioEncoder", outData.length + " bytes encoded"); //------------- packet = new DatagramPacket(outData, outData.length, InetAddress.getByName("127.0.0.1"), localPort); ds.send(packet); //------------ encoder.releaseOutputBuffer(outputBufferIndex, false); outputBufferIndex = encoder.dequeueOutputBuffer(bufferInfo, 0); } // ----------------------; } encoder.stop(); recorder.stop(); } catch (Exception e) { e.printStackTrace(); } } }); IOudpPlayer = new Thread(new Runnable() { public void run() { SocketAddress sockAddress; String address; int len = 1024; byte[] buffer2 = new byte[len]; DatagramPacket packet; byte[] data; ByteBuffer[] inputBuffers; ByteBuffer[] outputBuffers; ByteBuffer inputBuffer; ByteBuffer outputBuffer; MediaCodec.BufferInfo bufferInfo; int inputBufferIndex; int outputBufferIndex; byte[] outData; try { player.play(); decoder.start(); isPlaying = true; while (isPlaying) { try { packet = new DatagramPacket(buffer2, len); ds.receive(packet); sockAddress = packet.getSocketAddress(); address = sockAddress.toString(); // Log.d("UDP Receiver"," received !!! from " + address); data = new byte[packet.getLength()]; System.arraycopy(packet.getData(), packet.getOffset(), data, 0, packet.getLength()); // Log.d("UDP Receiver", data.length + " bytes received"); //=========== inputBuffers = decoder.getInputBuffers(); outputBuffers = decoder.getOutputBuffers(); inputBufferIndex = decoder.dequeueInputBuffer(-1); if (inputBufferIndex >= 0) { inputBuffer = inputBuffers[inputBufferIndex]; inputBuffer.clear(); inputBuffer.put(data); decoder.queueInputBuffer(inputBufferIndex, 0, data.length, 0, 0); } bufferInfo = new MediaCodec.BufferInfo(); outputBufferIndex = decoder.dequeueOutputBuffer(bufferInfo, 0); while (outputBufferIndex >= 0) { outputBuffer = outputBuffers[outputBufferIndex]; outputBuffer.position(bufferInfo.offset); outputBuffer.limit(bufferInfo.offset + bufferInfo.size); outData = new byte[bufferInfo.size]; outputBuffer.get(outData); // Log.d("AudioDecoder", outData.length + " bytes decoded"); player.write(outData, 0, outData.length); decoder.releaseOutputBuffer(outputBufferIndex, false); outputBufferIndex = decoder.dequeueOutputBuffer(bufferInfo, 0); } //=========== } catch (IOException e) { } } decoder.stop(); player.stop(); } catch (Exception e) { } } }); //=========================================================== int rate = findAudioRecord(); if (rate != -1) { Log.v("=========media ", "ready: " + rate); Log.v("=========media channel ", "ready: " + channelConfig); boolean encoderReady = setEncoder(rate); Log.v("=========encoder ", "ready: " + encoderReady); if (encoderReady) { boolean decoderReady = setDecoder(rate); Log.v("=========decoder ", "ready: " + decoderReady); if (decoderReady) { Log.d("=======bufferSize========", "" + bufferSize); try { setPlayer(rate); ds = new DatagramSocket(localPort); IOudpPlayer.start(); IOrecorder.start(); } catch (SocketException e) { e.printStackTrace(); } } } } } protected void onDestroy() { recorder.release(); player.release(); encoder.release(); decoder.release(); } /* protected void onResume() { // isRecording = true; } protected void onPause() { isRecording = false; } */ private int findAudioRecord() { for (int rate : new int[]{44100}) { try { Log.v("===========Attempting rate ", rate + "Hz, bits: " + audioFormat + ", channel: " + channelConfig); bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat); if (bufferSize != AudioRecord.ERROR_BAD_VALUE) { // check if we can instantiate and have a success recorder = new AudioRecord(AudioSource.MIC, rate, channelConfig, audioFormat, bufferSize); if (recorder.getState() == AudioRecord.STATE_INITIALIZED) { Log.v("===========final rate ", rate + "Hz, bits: " + audioFormat + ", channel: " + channelConfig); return rate; } } } catch (Exception e) { Log.v("error", "" + rate); } } return -1; } private boolean setEncoder(int rate) { encoder = MediaCodec.createEncoderByType("audio/mp4a-latm"); MediaFormat format = new MediaFormat(); format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm"); format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1); format.setInteger(MediaFormat.KEY_SAMPLE_RATE, rate); format.setInteger(MediaFormat.KEY_BIT_RATE, 64 * 1024);//AAC-HE 64kbps format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectHE); encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); return true; } private boolean setDecoder(int rate) { decoder = MediaCodec.createDecoderByType("audio/mp4a-latm"); MediaFormat format = new MediaFormat(); format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm"); format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1); format.setInteger(MediaFormat.KEY_SAMPLE_RATE, rate); format.setInteger(MediaFormat.KEY_BIT_RATE, 64 * 1024);//AAC-HE 64kbps format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectHE); decoder.configure(format, null, null, 0); return true; } private boolean setPlayer(int rate) { int bufferSizePlayer = AudioTrack.getMinBufferSize(rate, AudioFormat.CHANNEL_OUT_MONO, audioFormat); Log.d("====buffer Size player ", String.valueOf(bufferSizePlayer)); player= new AudioTrack(AudioManager.STREAM_MUSIC, rate, AudioFormat.CHANNEL_OUT_MONO, audioFormat, bufferSizePlayer, AudioTrack.MODE_STREAM); if (player.getState() == AudioTrack.STATE_INITIALIZED) { return true; } else { return false; } } }


Su código de red es la combinación de datos. Obtuvo 369 bytes de datos comprimidos, pero en el extremo receptor terminó con 1024 bytes. Esos 1024 bytes constan de dos cuadros enteros y uno parcial. Los dos cuadros enteros se decodifican a 4096 bytes, para el total de 8192 bytes que vio. El fotograma parcial restante probablemente se decodificará una vez que envíe suficientes datos al decodificador, pero en general debe enviar solo fotogramas completos al decodificador.

Además, MediaCodec.dequeueOutputBuffer() no solo devuelve los índices de búfer (positivos), sino también los códigos de estado (negativos). Uno de los códigos posibles es MediaCodec.INFO_OUTPUT_FORMAT_CHANGED , que indica que necesita llamar a MediaCodec.getOutputFormat() para obtener el formato de los datos de audio. Es posible que vea la salida de códec estéreo incluso si la entrada era mono. El código que publicaste simplemente se sale del bucle cuando recibe uno de estos códigos de estado.