Intereting Posts

Android MediaCodec AAC кодировщик

Я использую класс MediaCodec предоставляемый Android SDK, начиная с уровня API 16 с кодировщиком OMX.SEC.aac.enc для кодирования звука в файл. Я получаю аудио вход из класса AudioRecord . Мой экземпляр класса AudioRecord настроен следующим образом:

 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); 

Я могу воспроизвести необработанные данные из экземпляра AudioRecord , поэтому проблема там не существует.

Я записываю вывод из экземпляра AudioRecord экземпляр ByteBuffer и ByteBuffer его в доступный входной буфер от кодера. Выходной сигнал кодера записывается в файл на SD-карте.

Это параметры конфигурации для моего экземпляра 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 сообщает мне, что в моем файле aac нет потоков. Команда FFMPEG -i @filename@ дает мне следующую ошибку: Неверные данные, найденные при обработке ввода . Ни один из медиаплееров, которые я тестировал, не смог воспроизвести файл.

Почему я не могу воспроизвести файл? Я не получаю ошибок OpenMAX в LogCat и приложение не сбой при кодировании. Я написал видеокодер, который работает по тому же принципу, и он работает.

Это код для чтения данных из экземпляра AudioRecord в буфер:

  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(); 

Функция add из моего кодера копирует содержимое одного буфера в другой:

 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"); } } 

Следующий код используется для заполнения входного буфера кодировщика:

 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(); 

Я пишу вывод из кодировщика в локальный файл следующим образом:

  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(); 

Думаю, вы пропустили класс MediaMauxer . Вам это нужно, если вы хотите написать что-то, полученное из MediaCodec, в файл, например.