Untitled
unknown
plain_text
a year ago
4.8 kB
6
Indexable
import android.media.MediaCodec;
import android.media.MediaFormat;
import android.media.MediaMuxer;
import java.nio.ByteBuffer;
import java.util.List;
public void createVideoFromByteData(
List<byte[]> dataList, // Danh sách các mảng byte (mỗi phần tử là một frame)
String outputFilePath, // Đường dẫn file xuất ra
int width, // Chiều rộng video
int height, // Chiều cao video
int frameRate // Số khung hình trên giây
) throws Exception {
// Định dạng video (H.264)
MediaFormat format = MediaFormat.createVideoFormat("video/avc", width, height);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible);
format.setInteger(MediaFormat.KEY_BIT_RATE, 2000000); // 2 Mbps
format.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1); // I-frame mỗi giây
// Khởi tạo MediaCodec
MediaCodec mediaCodec = MediaCodec.createEncoderByType("video/avc");
mediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mediaCodec.start();
// Khởi tạo MediaMuxer
MediaMuxer mediaMuxer = new MediaMuxer(outputFilePath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
int videoTrackIndex = -1;
// Biến kiểm soát
boolean isMuxerStarted = false;
long presentationTimeUs = 0;
// Ghi từng khung hình từ dataList
for (byte[] data : dataList) {
int offset = 0;
while (offset < data.length) {
// Lấy inputBuffer index
int inputBufferIndex = mediaCodec.dequeueInputBuffer(10000);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = mediaCodec.getInputBuffer(inputBufferIndex);
inputBuffer.clear();
// Chia nhỏ dữ liệu nếu cần
int chunkSize = Math.min(data.length - offset, inputBuffer.capacity());
inputBuffer.put(data, offset, chunkSize);
// Đẩy vào MediaCodec
mediaCodec.queueInputBuffer(
inputBufferIndex,
0, // Offset trong inputBuffer
chunkSize, // Kích thước dữ liệu
presentationTimeUs, // Timestamp (microseconds)
0 // Không có cờ đặc biệt
);
offset += chunkSize; // Tiến tới phần dữ liệu tiếp theo
}
}
// Tăng timestamp
presentationTimeUs += 1000000 / frameRate;
// Lấy output từ codec
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputBufferIndex;
while ((outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 10000)) >= 0) {
ByteBuffer outputBuffer = mediaCodec.getOutputBuffer(outputBufferIndex);
// Khởi tạo MediaMuxer nếu chưa
if (!isMuxerStarted) {
MediaFormat outputFormat = mediaCodec.getOutputFormat();
videoTrackIndex = mediaMuxer.addTrack(outputFormat);
mediaMuxer.start();
isMuxerStarted = true;
}
// Ghi dữ liệu vào MediaMuxer
if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
mediaMuxer.writeSampleData(videoTrackIndex, outputBuffer, bufferInfo);
}
// Giải phóng buffer
mediaCodec.releaseOutputBuffer(outputBufferIndex, false);
}
}
// Gửi tín hiệu kết thúc
int inputBufferIndex = mediaCodec.dequeueInputBuffer(10000);
if (inputBufferIndex >= 0) {
mediaCodec.queueInputBuffer(inputBufferIndex, 0, 0, presentationTimeUs, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
}
// Lấy các buffer còn lại từ codec
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputBufferIndex;
while ((outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 10000)) >= 0) {
ByteBuffer outputBuffer = mediaCodec.getOutputBuffer(outputBufferIndex);
if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
mediaMuxer.writeSampleData(videoTrackIndex, outputBuffer, bufferInfo);
}
mediaCodec.releaseOutputBuffer(outputBufferIndex, false);
}
// Kết thúc MediaMuxer và MediaCodec
mediaCodec.stop();
mediaCodec.release();
if (isMuxerStarted) {
mediaMuxer.stop();
mediaMuxer.release();
}
}Editor is loading...
Leave a Comment