Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android MediaExtractor readSampleData IllegalArgumentException

I try to follow this question Concatenate multiple mp4 audio files using android´s MediaMuxer and concatenate video files.

But for some reason, the MediaExtractor throws an IllegalArgumentException when I call the readSampleData

In the official API, this function shouldn't throw any Exceptions at all ! What's going on ?

I have found an old question that suggest that the size of the ByteBuffer might be responsible : Android MediaMuxer readSampleData IllegalStateException

I have tried tons of values for the size and none of them made the issue go away. Is there a standard size I should know ?

Any hints could help !

    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;
}
like image 868
Taiko Avatar asked Oct 15 '15 12:10

Taiko


1 Answers

Just had this error when decoding a 4k movie. Others (including other very high resolution movies) had been working fine, but about halfway through -co-incedentilly near a more complex scene...- I get this error.

My buffer size was 1mb (1024*1024), increased to 2mb and the problem is gone.

So the END_OF_STREAM you find in the source is presumably "end of the buffer"

like image 111
Soylent Graham Avatar answered Nov 12 '22 07:11

Soylent Graham