Untitled
unknown
plain_text
5 months ago
4.8 kB
4
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