android字节流录音,Android音频流+视频流合成视频以及分离视频的音频流、视频流数据...

logo.jpg

本文介绍的是:针对Android 视频的合成以及 视频、音频的分离

1、MediaMuxer+MediaCodc合成视频

2、MediaExtractor分离视频流以及音频流

首先针对视频:一个视频是可以有多个视轨、多个音轨  这些轨道都是可以放入音频数据、视频数据的

经测试一个轨道也是可以放来源不同的视频流或者音频流

1、MediaMuxer+MediaCodc合成视频:

ea1916514a0d3623b5e77b6a4660272d.png

以上是经典的音视频流合成视频的图

使用MediaCodec的基本顺序:

1、int addTrack(@NonNull MediaFormat format)

2、start()    一旦开始将不能再addTrack

3、void writeSampleData(int trackIndex, @NonNull ByteBuffer byteBuf,@NonNull BufferInfo bufferInfo)

4、void stop()

5、void release()

以上顺序不可颠倒 否则会报IllegalStateException

通常视频的提供者可以是Camera的预览数据,也可以是录屏的视频流或者是网络实时的视频流;音频数据是麦克风采集的声音或者其他的音频流,这些数据都是字节数组

当我们拿到这些音视频数据  第一步要将该数据写到指定的轨道上,此时要先去执行MediaMuxer的addTrack()方法添加对应轨道

例如音频数据

MediaFormat newFormat = mAudioEncoder.getOutputFormat();

mAudioTrackIndex = mMuxer.addTrack(newFormat);

当音频以及视频的轨道全部添加完成之后再去调用start()方法开启混流器此时可以往混流器里写入数据,此步骤涉及音频线程以及视频线程和混流器线程的控制,可自由发挥

while(true) {int encoderStatus =mAudioEncoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC);//获取输出缓冲区的indexif (encoderStatus ==MediaCodec.INFO_TRY_AGAIN_LATER) {

...

}else if (encoderStatus ==MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {

encoderOutputBuffers=mAudioEncoder.getOutputBuffers();

}else if (encoderStatus ==MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {

MediaFormat newFormat=mAudioEncoder.getOutputFormat();

mAudioTrackIndex=mMuxer.addTrack(newFormat);//添加轨道}else if (encoderStatus < 0) {

...

}else{

ByteBuffer encodedData=encoderOutputBuffers[encoderStatus];//真实的音频或视频数据

...//组织mBufferInfo的数据 包括有size offset PTS时间戳if (mBufferInfo.size != 0) {

mMuxer.writeSampleData(mAudioTrackIndex, encodedData, mBufferInfo);//写入轨道

}

mAudioEncoder.releaseOutputBuffer(encoderStatus,false);//释放该输出缓冲区if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {break;

}

}

写完数据之后 调用stop  release 释放资源

2、视频  音频数据、视频数据的的分离提取 首先获取所有轨道数量  然后遍历这些轨道  找出我们感兴趣的轨道  直接获取轨道里的音视频数据

MediaExtractor extractor = newMediaExtractor();

extractor.setDataSource(...);int numTracks =extractor.getTrackCount();for (int i = 0; i < numTracks; ++i) {

MediaFormat format=extractor.getTrackFormat(i);

String mime=format.getString(MediaFormat.KEY_MIME);if(weAreInterestedInThisTrack) {

extractor.selectTrack(i);

}

}

ByteBuffer inputBuffer=ByteBuffer.allocate(...)while (extractor.readSampleData(inputBuffer, ...) >= 0) {int trackIndex =extractor.getSampleTrackIndex();long presentationTimeUs =extractor.getSampleTime();

...

extractor.advance();

}

extractor.release();

extractor= null;

实际项目中这些操作都是在子线程中执行的

原文:https://www.cnblogs.com/bimingcong/p/13688407.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值