3

次の関数を使用して、複数の mp4 オーディオ ファイル (それぞれが 1 つのオーディオ トラックのみを含み、すべて同じ MediaRecorder と同じパラメーターで記録されている) を 1 つに連結しようとしています。

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public static boolean concatenateFiles(File dst, File... sources) {
    if ((sources == null) || (sources.length == 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 bufferSize = MAX_SAMPLE_SIZE;
        int frameCount = 0;
        int offset = 100;

        ByteBuffer dstBuf = ByteBuffer.allocate(bufferSize);
        BufferInfo bufferInfo = new BufferInfo();

        long timeOffsetUs = 0;
        int dstTrackIndex = -1;

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

            // Set up MediaExtractor to read from the source.
            extractor = new MediaExtractor();
            extractor.setDataSource(sources[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 + APPEND_DELAY);
                }
                else {
                    lastPresentationTimeUs = extractor.getSampleTime();
                    bufferInfo.presentationTimeUs = extractor.getSampleTime() + timeOffsetUs;
                    bufferInfo.flags = extractor.getSampleFlags();
                    int trackIndex = extractor.getSampleTrackIndex();

                    if ((currentSample < numberOfSamplesInSource) || (fileIndex == sources.length - 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 (IOException e) {
        result = false;
    }
    finally {
        if (extractor != null) {
            extractor.release();
        }
        if (muxer != null) {
            muxer.stop();
            muxer.release();
        }
    }
    return result;
}

@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public static int getNumberOfSamples(File src) {
    MediaExtractor extractor = new MediaExtractor();
    int result;
    try {
        extractor.setDataSource(src.getPath());
        extractor.selectTrack(0);

        result = 0;
        while (extractor.advance()) {
            result ++;
        }
    }
    catch(IOException e) {
        result = -1;
    }
    finally {
        extractor.release();
    }
    return result;
}

コードはコンパイルされて実行されますが、結果のファイルを再生すると、最初のファイルの内容しか聞こえません。私が間違っていることはわかりません。

しかし、Marlon が私にその方向を示した後、MediaMuxer から受け取っているメッセージに奇妙な点があります。どうぞ:

05-04 15:30:01.869: D/MediaMuxerTest(5455): Source file: /storage/emulated/0/Android/data/de.absprojects.catalogizer/files/copy.mp4
05-04 15:30:01.889: D/QCUtils(5455): extended extractor not needed, return default
05-04 15:30:01.889: I/MPEG4Writer(5455): limits: 2147483647/0 bytes/us, bit rate: -1 bps and the estimated moov size 3072 bytes
05-04 15:30:01.889: I/MPEG4Writer(5455): setStartTimestampUs: 0
05-04 15:30:01.889: I/MPEG4Writer(5455): Earliest track starting time: 0
05-04 15:30:01.889: D/MediaMuxerTest(5455): Frame (1) PresentationTimeUs:0 Flags:1 TrackIndex:0 Size(KB) 0
05-04 15:30:01.889: D/MediaMuxerTest(5455): Frame (2) PresentationTimeUs:23219 Flags:1 TrackIndex:0 Size(KB) 0
05-04 15:30:01.889: D/MediaMuxerTest(5455): Frame (3) PresentationTimeUs:46439 Flags:1 TrackIndex:0 Size(KB) 0
[...]
05-04 15:30:01.959: D/MediaMuxerTest(5455): Frame (117) PresentationTimeUs:2693401 Flags:1 TrackIndex:0 Size(KB) 0
05-04 15:30:01.959: D/MediaMuxerTest(5455): Frame (118) PresentationTimeUs:2716621 Flags:1 TrackIndex:0 Size(KB) 0
05-04 15:30:01.959: D/MediaMuxerTest(5455): Frame (119) PresentationTimeUs:2739841 Flags:1 TrackIndex:0 Size(KB) 0
05-04 15:30:01.959: D/MediaMuxerTest(5455): Frame (120) PresentationTimeUs:2763061 Flags:1 TrackIndex:0 Size(KB) 0
05-04 15:30:01.979: D/QCUtils(5455): extended extractor not needed, return default
05-04 15:30:01.979: D/MediaMuxerTest(5455): Source file: /storage/emulated/0/Android/data/de.absprojects.catalogizer/files/temp.mp4
05-04 15:30:01.979: I/MPEG4Writer(5455): Received total/0-length (120/0) buffers and encoded 120 frames. - audio
05-04 15:30:01.979: I/MPEG4Writer(5455): Audio track drift time: 0 us
05-04 15:30:01.979: D/MPEG4Writer(5455): Setting Audio track to done
05-04 15:30:01.979: D/MPEG4Writer(5455): Stopping Audio track
05-04 15:30:01.979: D/MPEG4Writer(5455): Stopping Audio track source
05-04 15:30:01.979: D/MPEG4Writer(5455): Audio track stopped
05-04 15:30:01.979: D/MPEG4Writer(5455): Stopping writer thread
05-04 15:30:01.979: D/MPEG4Writer(5455): 0 chunks are written in the last batch
05-04 15:30:01.979: D/MPEG4Writer(5455): Writer thread stopped
05-04 15:30:01.979: D/MPEG4Writer(5455): Stopping Audio track
05-04 15:30:01.979: E/MPEG4Writer(5455): Stop() called but track is not started
05-04 15:30:01.999: D/QCUtils(5455): extended extractor not needed, return default
05-04 15:30:01.999: D/copyOriginalFile()(5455): 120 samples in original file
05-04 15:30:02.009: D/QCUtils(5455): extended extractor not needed, return default
05-04 15:30:02.019: D/copyOriginalFile()(5455): 120 samples in copied file
05-04 15:30:02.019: W/MediaRecorder(5455): mediarecorder went away with unhandled events
05-04 15:30:02.099: I/dalvikvm(5455): Jit: resizing JitTable from 4096 to 8192

最初のファイルからデータをコピーした後、MPEG4Writer (なぜ MediaMuxer ではないのですか?) はトラックを停止し、それ以上データを書き込まないようです。どうすればそれを防ぐことができますか? ヘッダーを直接操作する必要がありますか? もしそうなら、どのようにしますか?

どんな助けでも大歓迎です。

よろしくお願いします、

キリスト教徒

4

3 に答える 3