android mediacodec aac audiorecord openmax

Codificador AAC MediaCodec de Android



audiorecord openmax (1)

Supongo que te perdiste la clase MediaMauxer . Lo necesita si quiere escribir algo que haya recibido de MediaCodec en un archivo, por ejemplo.

Utilizo la clase MediaCodec proporcionada por el SDK de Android desde el nivel 16 de API con el codificador OMX.SEC.aac.enc para codificar audio en un archivo. Obtengo la entrada de audio de la clase AudioRecord . Mi instancia de la clase AudioRecord está configurada así:

bufferSize = AudioRecord.getMinBufferSize(44100, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT); recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 44100, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_DEFAULT, bufferSize);

Puedo reproducir los datos sin procesar de la instancia de AudioRecord , por lo que el problema no reside allí.

Escribo la salida de la instancia de AudioRecord en una instancia de ByteBuffer y la paso a un búfer de entrada disponible desde el codificador. La salida del codificador se escribe en un archivo en la tarjeta SD.

Estos son los parámetros de configuración para mi instancia de MediaCodec :

codec = MediaCodec.createEncoderByType("audio/mp4a-latm"); MediaFormat format = new MediaFormat(); format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm"); format.setInteger(MediaFormat.KEY_BIT_RATE, 64 * 1024); format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 2); format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 44100); format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectHE); codec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);

VLC me dice que no hay transmisiones en mi archivo aac. El comando FFMPEG -i @filename@ me da el siguiente error: Se encontraron datos no válidos al procesar la entrada . Ninguno de los reproductores multimedia que probé puede reproducir mi archivo.

¿Por qué no puedo reproducir mi archivo? No recibo errores de OpenMAX en LogCat y la aplicación no falla al codificar. Escribí un codificador de video que funciona según el mismo principio y funciona.

Este es el código para leer los datos de la instancia de AudioRecord en un búfer:

new Thread() { public void run() { ByteBuffer byteBuffer = ByteBuffer.allocateDirect(bufferSize); int read = 0; while (isRecording) { read = recorder.read(byteBuffer, bufferSize); if(AudioRecord.ERROR_INVALID_OPERATION != read){ encoder.add(byteBuffer); } } recorder.stop(); } }.start();

La función agregar de mi codificador copia el contenido de un búfer a otro:

public void add(ByteBuffer input) { if (!isRunning) return; if (tmpInputBuffer == null) tmpInputBuffer = ByteBuffer.allocate(input.capacity()); if (!tmpBufferClear) Log.e("audio encoder", "deadline missed"); //TODO lower bit rate synchronized (tmpInputBuffer) { tmpInputBuffer.clear(); tmpInputBuffer.put(input); tmpInputBuffer.notifyAll(); Log.d("audio encoder", "pushed data into tmpInputBuffer"); } }

El siguiente código se utiliza para ocupar el búfer de entrada del codificador:

new Thread() { public void run() { while (isRunning) { if (tmpInputBuffer == null) continue; synchronized (tmpInputBuffer) { if (tmpBufferClear) { try { Log.d("audio encoder", "falling asleep"); tmpInputBuffer.wait(); //wait when no input is available } catch (InterruptedException e) { e.printStackTrace(); } } ByteBuffer[] inputBuffers = codec.getInputBuffers(); int inputBufferIndex; do inputBufferIndex = codec.dequeueInputBuffer(-1); while (inputBufferIndex < 0); ByteBuffer inputBuffer = inputBuffers[inputBufferIndex]; inputBuffer.clear(); Log.d("input buffer size", String.valueOf(inputBuffer.capacity())); Log.d("tmp input buffer size", String.valueOf(tmpInputBuffer.capacity())); inputBuffer.put(tmpInputBuffer.array()); tmpInputBuffer.clear(); codec.queueInputBuffer(inputBufferIndex, 0, tmpInputBuffer.capacity(), 0, 0); tmpBufferClear = true; Log.d("audio encoder", "added to input buffer"); } } } }.start();

Escribo la salida del codificador a un archivo local como este:

new Thread() { public void run() { while (isRunning) { ByteBuffer[] outputBuffers = codec.getOutputBuffers(); MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); int outputBufferIndex = codec.dequeueOutputBuffer(bufferInfo, -1); while (outputBufferIndex >= 0) { ByteBuffer outputBuffer = outputBuffers[outputBufferIndex]; byte[] outData = new byte[bufferInfo.size]; outputBuffer.get(outData); try { fileWriter.write(outData, 0, outData.length); } catch (IOException e) { e.printStackTrace(); } codec.releaseOutputBuffer(outputBufferIndex, false); outputBufferIndex = codec.dequeueOutputBuffer(bufferInfo, 0); Log.d("audio encoder", "removed from output buffer"); } } codec.stop(); try { fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } } }.start(); tmpBufferClear = true; Log.d("audio encoder", "added to input buffer"); } } } }.start();