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<MuxerData> sPool = new Pools.SynchronizedPool<MuxerData>(
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 MediaMuxer混合音频和视频
最新推荐文章于 2025-05-09 07:07:35 发布
本文介绍了一种基于Java实现的音视频合并封装方法,通过MediaMuxer将不同轨道的数据混合到一个文件中。该方法使用了单例模式管理MediaMuxer实例,并通过Handler线程处理音视频数据的添加和写入。
1589

被折叠的 条评论
为什么被折叠?



