package cn.i2edu.dubbing_lib.util;

import android.content.Context;


import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaMuxer;
import android.os.Build;
import androidx.annotation.RequiresApi;

import java.nio.ByteBuffer;
/**
 * Created by Administrator on 2016/11/24.
 */

public class VideoAudioMixer {
    private VideoAudioMixListener mListener = null;
    private Context context;

    public VideoAudioMixer(Context context) {
        this.context = context;
    }

    public interface VideoAudioMixListener {
        void mixSuccess();

        void mixFail(String reason);
    }

    public void setListener(VideoAudioMixListener listener) {
        mListener = listener;
    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    public void muxAudioAndVideo(String audioPath, String videoPath, String mixedFilePath) {
        try {
            MediaMuxer mMediaMuxer = new MediaMuxer(mixedFilePath,
                    MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);

            // 视频的MediaExtractor
            MediaExtractor mVideoExtractor = new MediaExtractor();
            mVideoExtractor.setDataSource(videoPath);
            int videoTrackIndex = -1;
            for (int i = 0; i < mVideoExtractor.getTrackCount(); i++) {
                MediaFormat format = mVideoExtractor.getTrackFormat(i);
                if (format.getString(MediaFormat.KEY_MIME).startsWith("video/")) {
                    mVideoExtractor.selectTrack(i);
                    videoTrackIndex = mMediaMuxer.addTrack(format);
                    break;
                }
            }

            // 音频的MediaExtractor
            MediaExtractor mAudioExtractor = new MediaExtractor();
            mAudioExtractor.setDataSource(audioPath);
            int audioTrackIndex = -1;
            for (int i = 0; i < mAudioExtractor.getTrackCount(); i++) {
                MediaFormat format = mAudioExtractor.getTrackFormat(i);
                if (format.getString(MediaFormat.KEY_MIME).startsWith("audio/")) {
                    mAudioExtractor.selectTrack(i);
                    audioTrackIndex = mMediaMuxer.addTrack(format);
                }
            }

            // 添加完所有轨道后start
            mMediaMuxer.start();

            // 封装视频track
            if (-1 != videoTrackIndex) {
                MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
                info.presentationTimeUs = 0;
                ByteBuffer buffer = ByteBuffer.allocate(100 * 1024);
                while (true) {
                    int sampleSize = mVideoExtractor.readSampleData(buffer, 0);
                    if (sampleSize < 0) {
                        break;
                    }

                    info.offset = 0;
                    info.size = sampleSize;
                    info.flags = MediaCodec.BUFFER_FLAG_SYNC_FRAME;
                    info.presentationTimeUs = mVideoExtractor.getSampleTime();
                    mMediaMuxer.writeSampleData(videoTrackIndex, buffer, info);

                    mVideoExtractor.advance();
                }
            }

            // 封装音频track
            if (-1 != audioTrackIndex) {
                MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
                info.presentationTimeUs = 0;
                ByteBuffer buffer = ByteBuffer.allocate(100 * 1024);
                while (true) {
                    int sampleSize = mAudioExtractor.readSampleData(buffer, 0);
                    if (sampleSize < 0) {
                        break;
                    }

                    info.offset = 0;
                    info.size = sampleSize;
                    info.flags = MediaCodec.BUFFER_FLAG_SYNC_FRAME;
                    info.presentationTimeUs = mAudioExtractor.getSampleTime();
                    mMediaMuxer.writeSampleData(audioTrackIndex, buffer, info);

                    mAudioExtractor.advance();
                }
            }
            if (mListener != null) {
                mListener.mixSuccess();
            }

            // 释放MediaExtractor
            mVideoExtractor.release();
            mAudioExtractor.release();

            // 释放MediaMuxer
            mMediaMuxer.stop();
            mMediaMuxer.release();
        } catch (Exception e) {
            e.printStackTrace();
            if (mListener != null) {
                mListener.mixFail(e.toString());
            }
        }
    }

}
