Untitled

mail@pastecode.io avatar
unknown
plain_text
8 days ago
4.7 kB
1
Indexable
Never
import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaMuxer;
import android.util.Log;

import java.io.IOException;
import java.nio.ByteBuffer;

public class VideoMerger {

    private static final String TAG = "VideoMerger";

    public void mergeVideos(String inputFile1, String inputFile2, String outputFile) {
        MediaMuxer mediaMuxer = null;
        MediaExtractor mediaExtractor1 = new MediaExtractor();
        MediaExtractor mediaExtractor2 = new MediaExtractor();
        try {
            mediaMuxer = new MediaMuxer(outputFile, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);

            // Extract and write the video track from the first video
            mediaExtractor1.setDataSource(inputFile1);
            int videoTrackIndex1 = selectTrack(mediaExtractor1, "video/");
            MediaFormat format1 = mediaExtractor1.getTrackFormat(videoTrackIndex1);
            mediaExtractor1.selectTrack(videoTrackIndex1);
            int muxerVideoTrackIndex = mediaMuxer.addTrack(format1);

            // Optionally, extract and write the audio track from the first video
            int audioTrackIndex1 = selectTrack(mediaExtractor1, "audio/");
            int muxerAudioTrackIndex = -1;
            if (audioTrackIndex1 >= 0) {
                MediaFormat audioFormat = mediaExtractor1.getTrackFormat(audioTrackIndex1);
                mediaExtractor1.selectTrack(audioTrackIndex1);
                muxerAudioTrackIndex = mediaMuxer.addTrack(audioFormat);
            }

            mediaMuxer.start();

            // Write video data from the first video
            writeSampleData(mediaExtractor1, mediaMuxer, muxerVideoTrackIndex, muxerAudioTrackIndex);

            // Extract and write the video track from the second video
            mediaExtractor2.setDataSource(inputFile2);
            int videoTrackIndex2 = selectTrack(mediaExtractor2, "video/");
            mediaExtractor2.selectTrack(videoTrackIndex2);

            // Write video data from the second video
            writeSampleData(mediaExtractor2, mediaMuxer, muxerVideoTrackIndex, -1);

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (mediaMuxer != null) {
                try {
                    mediaMuxer.stop();
                    mediaMuxer.release();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            mediaExtractor1.release();
            mediaExtractor2.release();
        }
    }

    private int selectTrack(MediaExtractor extractor, String mimePrefix) {
        for (int i = 0; i < extractor.getTrackCount(); i++) {
            MediaFormat format = extractor.getTrackFormat(i);
            String mime = format.getString(MediaFormat.KEY_MIME);
            if (mime.startsWith(mimePrefix)) {
                return i;
            }
        }
        return -1;
    }

    private void writeSampleData(MediaExtractor extractor, MediaMuxer muxer, int videoTrackIndex, int audioTrackIndex) {
        ByteBuffer buffer = ByteBuffer.allocate(256 * 1024);
        MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();

        while (true) {
            bufferInfo.offset = 0;
            bufferInfo.size = extractor.readSampleData(buffer, 0);
            if (bufferInfo.size < 0) {
                Log.d(TAG, "No more samples to read");
                bufferInfo.size = 0;
                break;
            }
            bufferInfo.presentationTimeUs = extractor.getSampleTime();
            bufferInfo.flags = mapExtractorFlagsToCodecFlags(extractor.getSampleFlags());
            int trackIndex = extractor.getSampleTrackIndex();
            if (trackIndex == videoTrackIndex) {
                muxer.writeSampleData(videoTrackIndex, buffer, bufferInfo);
            } else if (trackIndex == audioTrackIndex) {
                muxer.writeSampleData(audioTrackIndex, buffer, bufferInfo);
            }
            extractor.advance();
        }
    }

    private int mapExtractorFlagsToCodecFlags(int extractorFlags) {
        int codecFlags = 0;
        if ((extractorFlags & MediaExtractor.SAMPLE_FLAG_SYNC) != 0) {
            codecFlags |= MediaCodec.BUFFER_FLAG_SYNC_FRAME;
        }
        if ((extractorFlags & MediaExtractor.SAMPLE_FLAG_PARTIAL_FRAME) != 0) {
            codecFlags |= MediaCodec.BUFFER_FLAG_PARTIAL_FRAME;
        }
        if ((extractorFlags & MediaExtractor.SAMPLE_FLAG_ENCRYPTED) != 0) {
            codecFlags |= MediaCodec.BUFFER_FLAG_CODEC_CONFIG; // Best guess for encrypted
        }
        return codecFlags;
    }
}
Leave a Comment