Untitled

 avatar
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