Как декодировать формат AAC (аудиофайл mp4) в формат PCM в Android - PullRequest
0 голосов
/ 13 мая 2019

У меня есть файл mp4 с одной звуковой дорожкой в ​​формате AAC.Я хотел бы преобразовать этот файл mp4 в аудиофайл в формате PCM.Я могу извлечь аудио файл в формате AAC из файла mp4 успешно.Но я не могу декодировать формат AAC в формат PCM.

Следующий код работает без ошибок и сохраняет данные PCM в файл.Но этот звук в формате PCM не может быть открыт ни с каким медиаплеером.Это говорит о том, что файл поврежден.Я попытался декодировать формат AAC в формат PCM с помощью ffmpeg, и с ffmpeg проблем нет.Но я не хочу использовать библиотеку ffmpeg из-за размера библиотеки.

Сначала я попытался указать путь к файлу mp4 для inputfilePath, и выходной файл был успешно создан и сохранен.Но этот выходной файл не открывается ни в одном медиаплеере.

extractAudioFromVideo ("... / input.mp4", "... / output.wav");

Во-вторых, я успешно извлек аудиофайл AAC из файла mp4.И я попытался указать путь к файлу ACC для inputfilePath, и ничего не изменилось в выводе.

extractAudioFromVideo ("... / input.aac", "... / output.wav");

статический void extractAudioFromVideo (@NonNull String inputfilePath, @NonNull String outputFilePath) {

    try
    {
        OutputStream outputStream = new FileOutputStream(outputFilePath);

        MediaExtractor extractor = new MediaExtractor();
        extractor.setDataSource(inputfilePath);

        MediaCodec mediaCodec = null;
        for(int index = 0; index < extractor.getTrackCount(); index++)
        {
            MediaFormat format = extractor.getTrackFormat(index);
            String mime = format.getString(MediaFormat.KEY_MIME);
            if(mime.startsWith("audio/"))
            {
                extractor.selectTrack(index);
                mediaCodec = MediaCodec.createDecoderByType(mime);
                mediaCodec.configure(format, null, null, 0);
                break;
            }
        }

        if (mediaCodec == null)
        {
            Log.e("Converter", "Can't find audio info");
            return;
        }

        mediaCodec.start();

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

        boolean isEOS = false;
        while (true)
        {
            if (!isEOS)
            {
                int inputIndex = mediaCodec.dequeueInputBuffer(10000);
                if (inputIndex >= 0)
                {
                    ByteBuffer buffer = inputBuffers[inputIndex];
                    int sampleSize = extractor.readSampleData(buffer, 0);
                    if (sampleSize < 0)
                    {
                        Log.d("Converter", "InputBuffer BUFFER_FLAG_END_OF_STREAM");
                        mediaCodec.queueInputBuffer(inputIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                        isEOS = true;
                    }
                    else
                    {
                        mediaCodec.queueInputBuffer(inputIndex, 0, sampleSize, extractor.getSampleTime(), 0);
                        extractor.advance();
                    }
                }
            }

            int outputIndex = mediaCodec.dequeueOutputBuffer(info, 10000);
            switch (outputIndex)
            {
                case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
                    Log.d("Converter", "INFO_OUTPUT_BUFFERS_CHANGED");
                    outputBuffers = mediaCodec.getOutputBuffers();
                    break;
                case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
                    Log.d("Converter", "New format " + mediaCodec.getOutputFormat());
                    break;
                case MediaCodec.INFO_TRY_AGAIN_LATER:
                    Log.d("Converter", "dequeueOutputBuffer timed out!");
                    break;
                default:
                    ByteBuffer buffer = outputBuffers[outputIndex];
                    /*
                    // I tried this line of code but it gives the same result.
                    byte[] chunk = new byte[info.size-info.offset];
                    int position = buffer.position();
                    buffer.get(chunk);
                    buffer.position(position);
                    outputStream.write(chunk,0,info.size-info.offset);
                    */
                    final byte[] chunk = new byte[info.size - info.offset];
                    buffer.get(chunk);
                    buffer.clear();

                    if (chunk.length > 0)
                    {
                        outputStream.write(chunk,0,info.size - info.offset);
                    }

                    mediaCodec.releaseOutputBuffer(outputIndex, true);
                    break;
            }

            if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0)
            {
                Log.d("Converter", "OutputBuffer BUFFER_FLAG_END_OF_STREAM");
                break;
            }
        }

        outputStream.flush();
        outputStream.close();

        mediaCodec.stop();
        mediaCodec.release();

        extractor.release();
    }
    catch (Exception exception)
    {
        exception.printStackTrace();
    }
}

Должен ли я сделать что-то большее, чем эта строка кода, чтобы сохранить его в формате PCM, или я сделал что-то не так?

...