Android(安卓)MediaMuxer混合音频和视频
16lz
2021-12-04
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.SynchronizedPoolsPool = 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); } }}
更多相关文章
- mybatisplus的坑 insert标签insert into select无参数问题的解决
- python起点网月票榜字体反爬案例
- Android(安卓)发送短信功能
- Android(安卓)Room 数据库
- Android之Fragment动态添加和移除Fragment
- android 数据保存与提取
- android数据库操作
- Android(安卓)中如何将带有html格式的文章转换成能在Android中显
- Android(安卓)setting中添加桌面循环滑动选项