我是靠谱客的博主 健壮太阳,最近开发中收集的这篇文章主要介绍Android音视频任务列表之(四)——学习 Android 平台的 MediaExtractor 和 MediaMuxer API,知道如何解析和封装 mp4 文件,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
一.主要使用的方法
MediaExtractor
1.setDataSource(String path)
设置数据源
2.getTrackFormat(int index)
获取指定索引通道的数据配置参数
3.selectTrack(int index)
选择轨道
4. getSampleTime()
获取当前pts时间戳,获取不到这返回-1
5.readSampleData(@NonNull ByteBuffer byteBuf, int offset)
数据存到缓存区byteBuf
6. advance()
释放上一帧数据
MediaMuxer
1.构造方法MediaMuxer( String path, int format)
初始化一个视频封装容器
2.addTrack(MediaFormat format)
添加指定格式通道
3.start()
开始合成
4. writeSampleData(int trackIndex, ByteBuffer byteBuf,BufferInfo bufferInfo)
将编码写入容器
二.实现过程
1.申请外置卡权限
2.解析Mp4
@SuppressLint("WrongConstant")
public void decodeToPCM(String musicPath, String outPath) throws Exception {
//创建解压工具
MediaExtractor mediaExtractor = new MediaExtractor();
//设置数据源
mediaExtractor.setDataSource(musicPath);
//获取音频轨道
int audioTrack =selectTrack(mediaExtractor,true);
//选择音频轨道
mediaExtractor.selectTrack(audioTrack);
//得到配置信息
MediaFormat oriAudioFormat = mediaExtractor.getTrackFormat(audioTrack);
//缓存大小
int maxBufferSize = 100 * 1000;
if (oriAudioFormat.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) {
maxBufferSize = oriAudioFormat.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
}
ByteBuffer buffer = ByteBuffer.allocateDirect(maxBufferSize);
MediaCodec mediaCodec = MediaCodec.createDecoderByType(oriAudioFormat.getString((MediaFormat.KEY_MIME)));
// 设置解码器信息
mediaCodec.configure(oriAudioFormat, null, null, 0);
File pcmFile = new File(outPath);
FileChannel writeChannel = new FileOutputStream(pcmFile).getChannel();
//开始解码
mediaCodec.start();
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
int outputBufferIndex = -1;
while (true) {
int decodeInputIndex = mediaCodec.dequeueInputBuffer(0);
if (decodeInputIndex >= 0) {
long sampleTimeUs = mediaExtractor.getSampleTime();
if (sampleTimeUs == -1) {//结束了
break;
}else if (sampleTimeUs > 6000000) {//截取一段
break;
}
// 数据存到缓冲区
info.size = mediaExtractor.readSampleData(buffer, 0);
info.presentationTimeUs = sampleTimeUs;//时间
info.flags = mediaExtractor.getSampleFlags();
// 下面放数据到content 到dsp解码
byte[] content = new byte[buffer.remaining()];
buffer.get(content);
// 解码
ByteBuffer inputBuffer = mediaCodec.getInputBuffer(decodeInputIndex);
inputBuffer.put(content);
mediaCodec.queueInputBuffer(decodeInputIndex, 0, info.size, info.presentationTimeUs, info.flags);
// 释放上一帧的压缩数据
mediaExtractor.advance();
}
outputBufferIndex = mediaCodec.dequeueOutputBuffer(info, 100_000);
while (outputBufferIndex>=0) {
ByteBuffer decodeOutputBuffer = mediaCodec.getOutputBuffer(outputBufferIndex);
writeChannel.write(decodeOutputBuffer);//pcm
mediaCodec.releaseOutputBuffer(outputBufferIndex, false);
outputBufferIndex = mediaCodec.dequeueOutputBuffer(info, 100_000);
}
}
writeChannel.close();
mediaExtractor.release();
mediaCodec.stop();
mediaCodec.release();
}
3.封装MP4
@SuppressLint("WrongConstant")
public boolean process(String musicPath, String outPath) throws IOException {
MediaExtractor mMediaExtractor = new MediaExtractor();
//设置音频数据源
mMediaExtractor.setDataSource(musicPath);
int mVideoTrackIndex = -1;
int framerate = 0;
//选择视频轨道
int videoIndex= selectTrack(mMediaExtractor,false);
//获取视频轨道
MediaFormat format = mMediaExtractor.getTrackFormat(videoIndex);
framerate = format.getInteger(MediaFormat.KEY_FRAME_RATE);
//切换到视频通道
mMediaExtractor.selectTrack(videoIndex);
// 初始化一个视频封装容器
mMediaMuxer = new MediaMuxer(outPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
// 添加一个空的轨道 轨道格式取自 视频文件,跟视频所有信息一样
mVideoTrackIndex = mMediaMuxer.addTrack(format);
mMediaMuxer.start();
if (mMediaMuxer == null) {
return false;
}
int maxBufferSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
ByteBuffer buffer = ByteBuffer.allocate(maxBufferSize);
//封装容器添加视频轨道信息
while (true) {
long sampleTimeUs = mMediaExtractor.getSampleTime();
if (sampleTimeUs == -1) {
break;
}
if (sampleTimeUs < 20000) {
//设置一个时间,这个时间之前的数据丢弃
mMediaExtractor.advance();
continue;
}
if ( sampleTimeUs > 60000000) {
//大于这个时间结束解析
break;
}
// pts
info.presentationTimeUs = sampleTimeUs - 20000+600;
info.flags = mMediaExtractor.getSampleFlags();
// 读取视频文件的数据
info.size = mMediaExtractor.readSampleData(buffer, 0);
if (info.size < 0) {
break;
}
// 视频轨道
mMediaMuxer.writeSampleData(videoIndex, buffer, info);
mMediaExtractor.advance();
}
Log.i("TAG", "mixAudioTrack: 完成");
mMediaExtractor.release();
mMediaMuxer.stop();
mMediaMuxer.release();
return true;
}
结果
1.获取到PCM数据输出到outPath
2.截取一段MP4输出到outPath
最后
以上就是健壮太阳为你收集整理的Android音视频任务列表之(四)——学习 Android 平台的 MediaExtractor 和 MediaMuxer API,知道如何解析和封装 mp4 文件的全部内容,希望文章能够帮你解决Android音视频任务列表之(四)——学习 Android 平台的 MediaExtractor 和 MediaMuxer API,知道如何解析和封装 mp4 文件所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复