Android MediaMuxer混合音频和视频

public class MediaMuxerCore {

    public static final int TRACK_VIDEO = 0;
    public static final int TRACK_AUDIO = 1;

   private static MediaMuxerCore mediaMuxerCore;
    private HandlerThread muxerHandlerThread;

    private final Object syncOp = new Object();
    private MuxerHandler muxerHandler;

    public MediaMuxerCore() {
        muxerHandlerThread = new HandlerThread("MediaMuxerCore,muxerHandlerThread");
        muxerHandlerThread.start();
        muxerHandler = new MuxerHandler(muxerHandlerThread.getLooper());
    }

    public static void startMuxer(String filePath){
     //   saveFilePath = filePath;
        LogTools.d("sent startMuxer");
        if(mediaMuxerCore == null){
            synchronized (MediaMuxerCore.class){
                if (mediaMuxerCore == null){
                    mediaMuxerCore = new MediaMuxerCore();
                }
            }
        }
        mediaMuxerCore.start(filePath);
    }

    public static void stopMuxer(){
        synchronized (MediaMuxerCore.class){
            if(mediaMuxerCore != null){
                mediaMuxerCore.stop();
                // mediaMuxerCore = null;
                LogTools.d("sent stopMuxer");
            }
        }
    }

    public static MediaMuxerCore getInstance(){
        if(mediaMuxerCore == null){
            synchronized (MediaMuxerCore.class){
                if (mediaMuxerCore == null){
                    mediaMuxerCore = new MediaMuxerCore();
                }
            }
        }
        return mediaMuxerCore;
    }


    public void start(String saveFilePath){
        synchronized (syncOp) {
            muxerHandler.start(saveFilePath);
        }
    }

    public void stop(){
        synchronized (syncOp) {
            muxerHandler.stop();
        }
    }

    /**
     * 添加音轨或视轨
     * @param index
     * @param mediaFormat
     */
    public void addTrackIndex(@TrackIndex int index, MediaFormat mediaFormat){
        synchronized (syncOp) {
            muxerHandler.addTrackIndex(index,mediaFormat);
        }
    }

    /**
     * 添加混合数据
     * @param data
     */
    public void addMuxerData(MuxerData data){

        synchronized (syncOp) {
            muxerHandler.addMuxterData(data);
        }

    }


    static class MuxerHandler extends Handler {

        private int videoTrackIndex = -1;
        private int audioTrackIndex = -1;
        private boolean isVideoAdd;
        private boolean isAudioAdd;
        private MediaMuxer mediaMuxer;

        private final static int MSG_START = 1;
        private final static int MSG_ADD_TRACK = 2;
        private final static int MSG_START_MUXER = 3;
        private final static int MSG_WRITE = 4;
        private final static int MSG_STOP = 5;

        public MuxerHandler(Looper looper) {
            super(looper);
        }

        private enum STATE {
            IDLE,
            READY,
            RUNNING,
            STOPPED
        }


        public void addTrackIndex(@TrackIndex int index, MediaFormat mediaFormat){
            this.removeMessages(MSG_WRITE);
            this.sendMessage(this.obtainMessage(MSG_ADD_TRACK,index,0,mediaFormat));
        }

        public void addMuxterData(MuxerData data){

            this.sendMessage(this.obtainMessage(MSG_WRITE,data));

        }

        public void start(String path){
            this.removeMessages(MSG_START);
            this.removeMessages(MSG_WRITE);
            this.sendMessage(this.obtainMessage(MSG_START,path));
        }

        public void stop(){
            this.removeMessages(MSG_WRITE);
            this.sendMessage(this.obtainMessage(MSG_STOP));
        }

        private STATE state;
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_START:
                    LogTools.d("sent MSG_START");
                    if (state == STATE.READY || state == STATE.RUNNING) {
                        break;
                    }
                    String filePath = (String)msg.obj;
                    isVideoAdd = false;
                    isAudioAdd = false;
                    try {
                        mediaMuxer = new MediaMuxer(filePath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
                    } catch (IOException e) {
                        e.printStackTrace();
                        mediaMuxer = null;
                    }
                    state = STATE.READY;
                    LogTools.d("sent MuxerHandler state ready");
                    break;
                case MSG_ADD_TRACK:
                    LogTools.d("sent MSG_ADD_TRACK");
                    if (state != STATE.READY) {
                        break;
                    }
                    if(mediaMuxer == null)
                        return;
                    int track = 0;
                    MediaFormat mediaFormat = (MediaFormat) msg.obj;
                    int index = msg.arg1;
                    try {
                        track = mediaMuxer.addTrack(mediaFormat);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    if(index == TRACK_VIDEO){
                        videoTrackIndex = track;
                        isVideoAdd = true;
                        LogTools.d("sent 添加视轨完成");
                    }else{
                        audioTrackIndex = track;
                        isAudioAdd = true;
                        LogTools.d("sent 添加音轨完成");
                    }

                    if(isVideoAdd && isAudioAdd){
                        mediaMuxer.start();
                        state = STATE.RUNNING;
                        LogTools.d("sent mediaMuxer start");
                        LogTools.d("sent MuxerHandler state running");
                    }
                    break;
                case MSG_WRITE:
                    LogTools.d("sent MuxerHandler MSG_WRITE");
                    if (state != STATE.RUNNING ){
                        return;
                    }
                    MuxerData data = (MuxerData) msg.obj;
                    int writeTrack = 0;
                    if (data.trackIndex == TRACK_VIDEO) {
                        writeTrack = videoTrackIndex;
                    } else {
                        writeTrack = audioTrackIndex;
                    }
                    try {
                        mediaMuxer.writeSampleData(writeTrack, data.byteBuffer, data.bufferInfo);
                        LogTools.d("sent写入混合数据,buffer.size:" + data.bufferInfo+",track:"+writeTrack);
                    } catch (Exception e) {
                        e.printStackTrace();
                        LogTools.e("sent写入混合数据失败!" + e.getMessage());
                    }finally {
                        data.recycle();
                    }
                    break;
                case MSG_STOP:
                    LogTools.d("sent MuxerHandler MSG_STOP");
                    if(mediaMuxer != null){
                        try {
                            mediaMuxer.stop();
                        } catch (Exception e) {
                            e.printStackTrace();
                            LogTools.e("sent mediaMuxer.stop() 异常:" + e.getMessage());
                        }

                        try {
                            mediaMuxer.release();
                        } catch (Exception e) {
                            e.printStackTrace();
                            LogTools.e("sent mediaMuxer.release() 异常:" + e.toString());
                        }
                    }
                    mediaMuxer = null;
                    state = STATE.STOPPED;
                    break;

            }
        }
    }


    @IntDef({TRACK_VIDEO, TRACK_AUDIO})
    @Retention(RetentionPolicy.SOURCE)
    public @interface TrackIndex {
    }

    public static class MuxerData{
        int trackIndex;
        ByteBuffer byteBuffer;
        MediaCodec.BufferInfo bufferInfo;

        private static final Pools.SynchronizedPool sPool = new Pools.SynchronizedPool(
                10);

        public static MuxerData obtain() {
            MuxerData instance = sPool.acquire();
            return (instance != null) ? instance : new MuxerData();
        }

        public static MuxerData obtain(int trackIndex, ByteBuffer byteBuffer, MediaCodec.BufferInfo bufferInfo) {
            MuxerData instance = sPool.acquire();
            if(instance == null)
                instance = new MuxerData(trackIndex,byteBuffer,bufferInfo);
            else
                instance.set(trackIndex,byteBuffer,bufferInfo);
            return instance;
        }

        public MuxerData(){

        }

        public void set(int trackIndex, ByteBuffer byteBuffer, MediaCodec.BufferInfo info){
            this.trackIndex = trackIndex;
            this.byteBuffer = byteBuffer;
            //this.bufferInfo = bufferInfo;
            if(this.bufferInfo == null){
                this.bufferInfo = new MediaCodec.BufferInfo();
            }
            this.bufferInfo.set(info.offset, info.size, info.presentationTimeUs, info.flags);
        }

        public MuxerData(int trackIndex, ByteBuffer byteBuffer, MediaCodec.BufferInfo bufferInfo) {
            set(trackIndex,byteBuffer,bufferInfo);
        }

        public void recycle() {
            sPool.release(this);
        }
    }
}

你可能感兴趣的:(android)