【问题标题】:Android MediaExtractor readSampleData IllegalArgumentExceptionAndroid MediaExtractor readSampleData IllegalArgumentException
【发布时间】:2015-10-15 12:30:22
【问题描述】:

我尝试关注这个问题Concatenate multiple mp4 audio files using android´s MediaMuxer 并连接视频文件。

但由于某种原因,当我调用 readSampleData 时,MediaExtractor 会抛出 IllegalArgumentException

在官方 API 中,这个函数根本不应该抛出任何异常!怎么回事?

我发现一个老问题表明 ByteBuffer 的大小可能是负责任的:Android MediaMuxer readSampleData IllegalStateException

我已经尝试了大量的尺寸值,但都没有解决问题。有我应该知道的标准尺寸吗?

任何提示都会有所帮助!

    boolean VERBOSE = true;


private boolean concatenateFiles(File dst, List<File> sources) {
    if ((sources == null) || (sources.size() == 0)) {
        return false;
    }

    boolean result;
    MediaExtractor extractor = null;
    MediaMuxer muxer = null;
    try {
        // Set up MediaMuxer for the destination.
        muxer = new MediaMuxer(dst.getPath(), MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);

        // Copy the samples from MediaExtractor to MediaMuxer.
        boolean sawEOS = false;

        int frameCount = 0;
        int offset = 100;

        ByteBuffer dstBuf = ByteBuffer.allocate(256 * 1024);
        BufferInfo bufferInfo = new BufferInfo();

        long timeOffsetUs = 0;
        int dstTrackIndex = -1;

        for (int fileIndex = 0; fileIndex < sources.size(); fileIndex++) {
            int numberOfSamplesInSource = getNumberOfSamples(sources.get(fileIndex));
            if (VERBOSE) {
                Log.d(TAG, String.format("Source file: %s", sources.get(fileIndex).getPath()));
            }

            if (!sources.get(fileIndex).canRead()) {
                throw new FileNotFoundException("Unable to read " + sources.get(fileIndex));
            }

            // Set up MediaExtractor to read from the source.
            extractor = new MediaExtractor();
            extractor.setDataSource(sources.get(fileIndex).getPath());

            // Set up the tracks.
            SparseIntArray indexMap = new SparseIntArray(extractor.getTrackCount());
            for (int i = 0; i < extractor.getTrackCount(); i++) {
                extractor.selectTrack(i);
                MediaFormat format = extractor.getTrackFormat(i);
                if (dstTrackIndex < 0) {
                    dstTrackIndex = muxer.addTrack(format);
                    muxer.start();
                }
                indexMap.put(i, dstTrackIndex);
            }

            long lastPresentationTimeUs = 0;
            int currentSample = 0;

            while (!sawEOS) {
                bufferInfo.offset = offset;

                bufferInfo.size = extractor.readSampleData(dstBuf, offset);


                if (bufferInfo.size < 0) {
                    sawEOS = true;
                    bufferInfo.size = 0;
                    timeOffsetUs += (lastPresentationTimeUs);
                }
                else {
                    lastPresentationTimeUs = extractor.getSampleTime();
                    bufferInfo.presentationTimeUs = extractor.getSampleTime() + timeOffsetUs;
                    bufferInfo.flags = extractor.getSampleFlags();
                    int trackIndex = extractor.getSampleTrackIndex();

                    if ((currentSample < numberOfSamplesInSource) || (fileIndex == sources.size() - 1)) {
                        muxer.writeSampleData(indexMap.get(trackIndex), dstBuf, bufferInfo);
                    }
                    extractor.advance();

                    frameCount++;
                    currentSample++;
                    if (VERBOSE) {
                        Log.d(TAG, "Frame (" + frameCount + ") " +
                                "PresentationTimeUs:" + bufferInfo.presentationTimeUs +
                                " Flags:" + bufferInfo.flags +
                                " TrackIndex:" + trackIndex +
                                " Size(KB) " + bufferInfo.size / 1024);
                    }
                }
            }
            extractor.release();
            extractor = null;
        }

        result = true;
    }
    catch (Exception e) {
        e.printStackTrace();
        result = false;
    }
    finally {
        if (extractor != null) {
            extractor.release();
        }
        if (muxer != null) {
            muxer.stop();
            muxer.release();
        }
    }
    return result;
}

【问题讨论】:

  • 什么版本的安卓?来自文档的注释:As of API 21, on success the position and limit of byteBuf is updated to point to the data just read.
  • 我的手机是 5.1,但该应用程序是为 v18 编译的,我在文档中看到了该行,但它第一次崩溃,而不是第二次。所以我猜不是那个
  • 在 C++ android 源代码中进行了一些挖掘之后,当我到达 END_OF_STREAM 时,似乎出现了这个未记录的错误。尚不确定它是流的源端还是缓冲区(可能是源端)。有什么方法可以检查来源是否有效? androidxref.com/source/xref/frameworks/base/media/jni/…
  • 其实即使我直接在读取中新建一个缓冲区,问题依然存在。 extractor.readSampleData(ByteBuffer.allocate(256 * 1024), 0);
  • 好的,钻完兔子洞。我发现导致此异常的函数来自一个名为 NuMediaExtractor androidxref.com/4.2_r1/xref/frameworks/av/media/libstagefright/… 的不起眼的类,看来我的媒体没有“准备好”???调用 extractor.advance();在调用 readSampleData 之前一次似乎已经解决了问题。

标签: android android-mediacodec mediamuxer mediaextractor


【解决方案1】:

解码 4k 电影时出现此错误。其他(包括其他非常高分辨率的电影)一直运行良好,但大约在进行到一半时 - co-incedentilly 在更复杂的场景附近...- 我收到此错误。

我的缓冲区大小是 1mb (1024*1024),增加到 2mb,问题就消失了。

所以你在源代码中找到的 END_OF_STREAM 大概是“缓冲区的结尾”

【讨论】:

  • 不确定它是否能解决我的问题(我已经转移到另一个项目,但我仍会将其标记为有效答案:-))
  • 我也可以在这一帧上提前()并且它继续 - 虽然显然在下一个关键帧之前出现乱码 - 所以很确定这至少是 IllegalStateException 的含义之一:)
  • 为我工作。我在 1440p 视频中遇到了这个问题。
  • 在处理无损音频文件时,它实际上为我解决了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-24
  • 2013-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多