Android 音视频开发(五):使用 MediaExtractor 和 MediaMuxer API 解析和封装 mp4 文件
一个音视频文件是由音频和视频组成的,我们可以通过MediaExtractor、MediaMuxer把音频或视频给单独抽取出来,抽取出来的音频和视频能单独播放;
一、MediaExtractor API介绍
MediaExtractor的作用是把音频和视频的数据进行分离。
主要API介绍:
- setDataSource(String path):即可以设置本地文件又可以设置网络文件
- getTrackCount():得到源文件通道数
- getTrackFormat(int index):获取指定(index)的通道格式
- getSampleTime():返回当前的时间戳
- readSampleData(ByteBuffer byteBuf, int offset):把指定通道中的数据按偏移量读取到ByteBuffer中;
- advance():读取下一帧数据
- release(): 读取结束后释放资源
使用示例:
MediaExtractor extractor = new MediaExtractor();
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;
二、MediaMuxer API介绍
MediaMuxer的作用是生成音频或视频文件;还可以把音频与视频混合成一个音视频文件。
相关API介绍:
- MediaMuxer(String path, int format):path:输出文件的名称 format:输出文件的格式;当前只支持MP4格式;
- addTrack(MediaFormat format):添加通道;我们更多的是使用MediaCodec.getOutpurForma()或Extractor.getTrackFormat(int index)来获取MediaFormat;也可以自己创建;
- start():开始合成文件
- writeSampleData(int trackIndex, ByteBuffer byteBuf, MediaCodec.BufferInfo bufferInfo):把ByteBuffer中的数据写入到在构造器设置的文件中;
- stop():停止合成文件
- release():释放资源
使用示例:
MediaMuxer muxer = new MediaMuxer("temp.mp4", OutputFormat.MUXER_OUTPUT_MPEG_4);
// More often, the MediaFormat will be retrieved from MediaCodec.getOutputFormat()
// or MediaExtractor.getTrackFormat().
MediaFormat audioFormat = new MediaFormat(...);
MediaFormat videoFormat = new MediaFormat(...);
int audioTrackIndex = muxer.addTrack(audioFormat);
int videoTrackIndex = muxer.addTrack(videoFormat);
ByteBuffer inputBuffer = ByteBuffer.allocate(bufferSize);
boolean finished = false;
BufferInfo bufferInfo = new BufferInfo();
muxer.start();
while(!finished) {
// getInputBuffer() will fill the inputBuffer with one frame of encoded
// sample from either MediaCodec or MediaExtractor, set isAudioSample to
// true when the sample is audio data, set up all the fields of bufferInfo,
// and return true if there are no more samples.
finished = getInputBuffer(inputBuffer, isAudioSample, bufferInfo);
if (!finished) {
int currentTrackIndex = isAudioSample ? audioTrackIndex : videoTrackIndex;
muxer.writeSampleData(currentTrackIndex, inputBuffer, bufferInfo);
}
};
muxer.stop();
muxer.release();
三、使用情境
3.1 从MP4文件中提取视频并生成新的视频文件
public class MainActivity extends AppCompatActivity {
private static final String SDCARD_PATH = Environment.getExternalStorageDirectory().getPath();
private MediaExtractor mMediaExtractor;
private MediaMuxer mMediaMuxer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 获取权限
int checkWriteExternalPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
int checkReadExternalPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);if (checkWriteExternalPermission != PackageManager.PERMISSION_GRANTED ||
checkReadExternalPermission != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE}, 0);
}
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run() {
try {
process();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
private boolean process() throws IOException {
mMediaExtractor = new MediaExtractor();
mMediaExtractor.setDataSource(SDCARD_PATH + "/ss.mp4");
int mVideoTrackIndex = -1;
int framerate = 0;
for (int i = 0; i < mMediaExtractor.getTrackCount(); i++) {
MediaFormat format = mMediaExtractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
if (!mime.startsWith("video/")) {
continue;
}
framerate = format.getInteger(MediaFormat.KEY_FRAME_RATE);
mMediaExtractor.selectTrack(i);
mMediaMuxer = new MediaMuxer(SDCARD_PATH + "/ouput.mp4", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
mVideoTrackIndex = mMediaMuxer.addTrack(format);
mMediaMuxer.start();
}
if (mMediaMuxer == null) {
return false;
}
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
info.presentationTimeUs = 0;
ByteBuffer buffer = ByteBuffer.allocate(500 * 1024);
int sampleSize = 0;
while ((sampleSize = mMediaExtractor.readSampleData(buffer, 0)) > 0) {
info.offset = 0;
info.size = sampleSize;
info.flags = MediaCodec.BUFFER_FLAG_SYNC_FRAME;
info.presentationTimeUs += 1000 * 1000 / framerate;
mMediaMuxer.writeSampleData(mVideoTrackIndex, buffer, info);
mMediaExtractor.advance();
}
mMediaExtractor.release();
mMediaMuxer.stop();
mMediaMuxer.release();
return true;
}
}
Android 音视频开发(五):使用 MediaExtractor 和 MediaMuxer API 解析和封装 mp4 文件的更多相关文章
- Android 音视频开发学习思路
Android 音视频开发这块目前的确没有比较系统的教程或者书籍,网上的博客文章也都是比较零散的.只能通过一点点的学习和积累把这块的知识串联积累起来. 初级入门篇: Android 音视频开发(一) ...
- Android音视频开发(1):H264 基本原理
前言 H264 视频压缩算法现在无疑是所有视频压缩技术中使用最广泛,最流行的.随着 x264/openh264 以及 ffmpeg 等开源库的推出,大多数使用者无需再对H264的细节做过多的研究,这大 ...
- Android 音视频开发(七): 音视频录制流程总结
在前面我们学习和使用了AudioRecord.AudioTrack.Camera.MediaExtractor.MediaMuxer API.MediaCodec. 学习和使用了上述的API之后,相信 ...
- Android 音视频开发(一):PCM 格式音频的播放与采集
什么是 PCM 格式 声音从模拟信号转化为数字信号的技术,经过采样.量化.编码三个过程将模拟信号数字化. 采样 顾名思义,对模拟信号采集样本,该过程是从时间上对信号进行数字化,例如每秒采集 44100 ...
- Android 音视频开发(一) : 通过三种方式绘制图片
版权声明:转载请说明出处:http://www.cnblogs.com/renhui/p/7456956.html 在 Android 音视频开发学习思路 里面,我们写到了,想要逐步入门音视频开发,就 ...
- Android 音视频开发入门指南
Android 音视频从入门到提高 —— 任务列表 http://blog.51cto.com/ticktick/1956269(以这个学习为基础往下面去学习) Android 音视频开发学习思路-- ...
- Android 音视频开发(六): MediaCodec API 详解
在学习了Android 音视频的基本的相关知识,并整理了相关的API之后,我们应该对基本的音视频有一定的轮廓了. 下面开始接触一个Android音视频中相当重要的一个API: MediaCodec.通 ...
- Android 音视频开发(二):使用 AudioRecord 采集音频数据并保存到文件
版权声明:转载请说明出处:http://www.cnblogs.com/renhui/p/7457321.html 一.AudioRecord API详解 AudioRecord是Android系统提 ...
- Android 音视频开发(二):使用 AudioRecord 采集音频PCM并保存到文件
版权声明:转载请说明出处:http://www.cnblogs.com/renhui/p/7457321.html 一.AudioRecord API详解 AudioRecord是Android系统提 ...
随机推荐
- 微信小程序开发01 --- 微信小程序项目结构介绍
一.微信小程序简单介绍: 微信官方介绍微信小程序是一个不需要下载安装就可使用(呵呵,JS代码不用下载吗?展示的UI不用下载吗?)的应用,它实现了应用“触手可及”的梦想,用户扫一扫或搜一下即可打开应用. ...
- Docker----起步(2)----在Ubuntu上安装最新版的Docker CE
之前写了一篇文章关于Docker安装的博客,最近再次使用的时候,在docker的官方文档上发现最新版本的Docker(V18.03)的安装方式和之前有点区别,有一些命令发现不能用了.(真的是一天不学习 ...
- 设置Jexus开机启动
一.如需要开机没有登陆情况下就能运行的程序,存在系统服务(system)里,即:/lib/systemd/system/ ,服务以.service结尾 cd /lib/systemd/system/ ...
- 基于Hexo搭建个人博客网站
## 准备工作 首先下载[nodejs](https://nodejs.org/en/download/),一路next安装即可.验证是否安装成功: ```bash node -v # 输出 v1 ...
- 记一次Hbase的行键过滤器事故问题
数据总数:746条数据 因为后面需要进行算法合成,而且spark目前对这种算法支持并不好,因此采用代码编写,所以在查询hbase的过程中采用的是java直接查询, 但是为了加快查询速度,我尽可能的使用 ...
- ubuntu中vi下删除键和上下左右键的异常解决
解决办法: 卸载旧的vim apt-get remove vim-common 安装新的vim apt-get install vim tips:可是我发现,无论卸载还是安装都是版本为(2 ...
- 第三次作业-结对编程(wordcount)
GIT地址 https://github.com/gentlemanzq/WordCount.git GIT用户名 gentlemanzq 结对伙伴博客地址 https://home.cnblogs ...
- selenium操作浏览器的前进和后退
前进关键字:driver.forward() 后退关键字:driver.back() 测试对象:1.https://www.baidu.com/ 2.https://www.sogou.com/ 实例 ...
- 从Facebook数据泄露事件看大数据时代的个人信息安全问题
进入21世纪后,互联网开始大规模普及,线上业务和线上服务也开始逐渐走入人们的生活.尤其在智能手机和移动互联网诞生以后,人们对网络的依赖更是与日俱增.然而,伴随而来的则是涉及个人隐私的信息安全问题.个人 ...
- APIO2018 被屠记
占坑 day0 10:40才起床 感觉一点也不好 下午去了趟80中拿牌子然而没有到,白浪费我颓废时间. day0.5 早上第一课讲二分凸优化,有点瞌睡 第二课讲匹配相关,感觉这篇文章涵盖了大部分内容 ...