Codificador AAC de Android MediaCodec
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. Recibo la entrada de audio de la clase AudioRecord
. Mi instancia de la clase AudioRecord
se configura de la siguiente manera:
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 jugar los datos sin procesar de la instancia de AudioRecord
, así que el problema no reside allí.
- Excepción de estado ilegal al llamar a MediaCodec.configure ()
- Decodificación h264 ByteStream en Android
- Android: Encontrando audio y video usando MediaCodec
- Android MediaExtractor y la corriente mp3
- Descodificación de archivos de audio y re-codificación al formato PCM deseado: 44,100 kHz, 2 canales, 16 bits
Escribo la salida de la instancia AudioRecord
a una instancia ByteBuffer
y la paso a un búfer de entrada disponible desde el codificador. La salida del codificador se escribe en un archivo de la tarjeta SD.
Estos son los parámetros de configuración de 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 corrientes en mi archivo aac. El comando FFMPEG -i @filename@
me da el siguiente error: Datos no válidos encontrados al procesar la entrada . Ninguno de los reproductores multimedia que he probado 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 vídeo que funciona en el mismo principio y funciona.
Este es el código para leer los datos de la instancia de AudioRecord
a 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 add de mi codificador copia el contenido de un buffer 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 código siguiente 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();
- Calidad de vídeo incoherente al codificar los fotogramas de previsualización de la cámara con MediaCodec en Xperia Z1
- Error de codificación de vídeo que utiliza datos OnAudioFilterRead
- Cómo generar el flujo elemental de AAC ADTS con Android MediaCodec
- Mp3 a conversión wav android
- Cómo puedo extraer datos rtsp en MediaCodec
- Native_window_api_connect devolvió un error: argumento no válido (-22)
- Crear video de series de imágenes android
- Error en el codificador OMX.qcom aleatorio
Supongo que te perdiste la clase MediaMauxer . Lo necesitas si quieres escribir algo de MediaCodec a un archivo, por ejemplo.
- Última actualización de la habilitación y deshabilitación de los datos móviles mediante programación
- IAB startSetup NullPointerException