Как извлечь образцы PCM из вывода декодера MediaCodec

Я пытаюсь получить образцы PCM для дальнейшей обработки из декодированного буфера mp4. Сначала я извлекаю звуковую дорожку из видеофайла, записанного с помощью приложения камеры телефона, и убедилась, что звуковая дорожка выбирается, когда я получаю mime-ключ 'audio / mp4':

MediaExtractor extractor = new MediaExtractor();
try {
    extractor.setDataSource(fileUri.getPath());
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
int numTracks = extractor.getTrackCount();
for(int i =0; i<numTracks; ++i) {
    MediaFormat format = extractor.getTrackFormat(i);
    String mime = format.getString(MediaFormat.KEY_MIME);
    //Log.d("mime =",mime);
    if(mime.startsWith("audio/")) {
        extractor.selectTrack(i);
        decoder = MediaCodec.createDecoderByType(mime);
        decoder.configure(format, null, null, 0);

        //getSampleCryptoInfo(MediaCodec.CryptoInfo info)
        break;
    }
}
if (decoder == null) {
    Log.e("DecodeActivity", "Can't find audio info!");
    return;
}
decoder.start();

После этого я перебираю дорожку, подаю кодеку поток кодированных блоков доступа и вытягиваю декодированные блоки доступа в ByteBuffer (это код, который я переработал из примера рендеринга видео, размещенного здесьhttps://github.com/vecio/MediaCodecDemo):

ByteBuffer[] inputBuffers = decoder.getInputBuffers();
ByteBuffer[] outputBuffers = decoder.getOutputBuffers();
BufferInfo info = new BufferInfo();

boolean isEOS = false;

while (true) {
    if (!isEOS) {
        int inIndex = decoder.dequeueInputBuffer(10000);
        if (inIndex >= 0) {
            ByteBuffer buffer = inputBuffers[inIndex];
            int sampleSize = extractor.readSampleData(buffer, 0);
            if (sampleSize < 0) {
                // We shouldn't stop the playback at this point, just pass the EOS
                // flag to decoder, we will get it again from the
                // dequeueOutputBuffer
                Log.d("DecodeActivity", "InputBuffer BUFFER_FLAG_END_OF_STREAM");
                decoder.queueInputBuffer(inIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                isEOS = true;
            } else {
                decoder.queueInputBuffer(inIndex, 0, sampleSize, extractor.getSampleTime(), 0);
                extractor.advance();
            }
        }
    }

    int outIndex = decoder.dequeueOutputBuffer(info, 10000);
    switch (outIndex) {
    case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
        Log.d("DecodeActivity", "INFO_OUTPUT_BUFFERS_CHANGED");
        outputBuffers = decoder.getOutputBuffers();
        break;
    case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
        Log.d("DecodeActivity", "New format " + decoder.getOutputFormat());
        break;
    case MediaCodec.INFO_TRY_AGAIN_LATER:
        Log.d("DecodeActivity", "dequeueOutputBuffer timed out!");
        break;
    default:
        ByteBuffer buffer = outputBuffers[outIndex];
        // How to obtain PCM samples from this buffer variable??

        decoder.releaseOutputBuffer(outIndex, true);
        break;
    }

    // All decoded frames have been rendered, we can stop playing now
    if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
        Log.d("DecodeActivity", "OutputBuffer BUFFER_FLAG_END_OF_STREAM");
        break;
    }
}

Код, кажется, работает без ошибок до сих пор, но я в настоящее время пытаюсь выяснить, как получить образцы PCM из ByteBuffer, который принимает значение выходного буфера. Я предполагаю, что могу предположить, что, поскольку я работаю с 16-битным стереофоническим аудиофайлом, в чередующейся схеме должно быть как минимум два байта ... однако я не совсем уверен в этом, так что однозначно извлекаю образцы PCM из этого потока байтов. Кто-нибудь знает, как получить это из MediaCodec API?

Я прочитал несколько альтернатив с использованием ffmpeg или openSL, но, поскольку я новичок в программировании на Android, я надеялся избежать сложностей с использованием API на основе c и создать свое первое приложение, используя только инструменты, предоставляемые Android Framework (я использую KitKat). Любая помощь будет оценена.

ОБНОВИТЬМне удалось извлечь образцы PCM, как я и предполагал, а также то, как указал @ marcone. Для этого я добавил эти строки ниже назначения буфера:

byte[] b = new byte[info.size-info.offset];                         
int a = buffer.position();
buffer.get(b);
buffer.position(a);

и, наконец, записать байтовый массив в файл:

f.write(b,0,info.size-info.offset);

Проблема, с которой я сейчас имею дело:

Декодированные аудиосэмплы не совсем совпадают с декодированием аудиодорожки mp4, выполненным iZotope. имеется несоответствие 48 выборок в размере волновых файлов и задержка 2112 выборок в декодированных сигналах. Теперь у меня вопрос: все ли декодеры mp4 дадут один и тот же выходной поток PCM или это зависит от реализации декодера?

Ответы на вопрос(2)

Ваш ответ на вопрос