Untitled
unknown
plain_text
a year ago
4.6 kB
4
Indexable
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) throws IOException {
MediaMuxer mediaMuxer = null;
MediaExtractor videoExtractor1 = new MediaExtractor();
MediaExtractor videoExtractor2 = new MediaExtractor();
try {
mediaMuxer = new MediaMuxer(outputFile, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
// Extract and write video track from the first video
videoExtractor1.setDataSource(inputFile1);
int videoTrackIndex1 = selectTrack(videoExtractor1, "video/");
MediaFormat videoFormat1 = videoExtractor1.getTrackFormat(videoTrackIndex1);
videoExtractor1.selectTrack(videoTrackIndex1);
int muxerVideoTrackIndex = mediaMuxer.addTrack(videoFormat1);
// Optionally, extract and write audio track from the first video
int audioTrackIndex1 = selectTrack(videoExtractor1, "audio/");
int muxerAudioTrackIndex = -1;
if (audioTrackIndex1 >= 0) {
MediaFormat audioFormat1 = videoExtractor1.getTrackFormat(audioTrackIndex1);
videoExtractor1.selectTrack(audioTrackIndex1);
muxerAudioTrackIndex = mediaMuxer.addTrack(audioFormat1);
}
mediaMuxer.start();
// Write video data from the first video
writeSampleData(videoExtractor1, mediaMuxer, muxerVideoTrackIndex, muxerAudioTrackIndex);
// Extract and write video track from the second video
videoExtractor2.setDataSource(inputFile2);
int videoTrackIndex2 = selectTrack(videoExtractor2, "video/");
videoExtractor2.selectTrack(videoTrackIndex2);
// Write video data from the second video
writeSampleData(videoExtractor2, mediaMuxer, muxerVideoTrackIndex, -1);
} finally {
if (mediaMuxer != null) {
try {
mediaMuxer.stop();
mediaMuxer.release();
} catch (Exception e) {
e.printStackTrace();
}
}
videoExtractor1.release();
videoExtractor2.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;
}
}
Editor is loading...
Leave a Comment