MediaExtractor
MediaExtractor顾名思义就是多媒体提取器,主要负责:
-
获取媒体文件的格式,包括音视频轨道,编码格式,宽高,采样率,声道数等,
-
分离音频流,视频流,读取分离后的音视频数据。
相关API概述: -
setDataSource(String path)
指定数据来源,支持网络地址和本地地址 -
getTrackCount()
获取轨道数据数量 -
getTrackFormat(int index)
获取指定索引位置的轨道格式信息 -
selectTrack(int index)
根据轨道索引选中指定轨道,选中后将分离器读取选中轨道的数据,读取数据之前必须选中一个轨道,而且同时只能选中一个轨道。 -
seekTo(long timeUs,int mode)
根据帧时间(timeUs)以及搜寻模式(mode),搜寻最匹配的关键帧。
注意:分离视频轨道时,seekTo不能精确到视频时间,只能根据mode找到最匹配的关键帧。
SEEK_TO_CLOSEST_SYNC 最接近 timeUS 的关键帧
SEEK_TO_NEXT_SYNC timeUS 的下一个关键帧
SEEK_TO_PREVIOUS_SYNC timeUS 的上一个关键帧 -
advance()
将分离器游标移动到下一帧 -
readSampleData(ByteBuffer buffer,int offset)
读取当前位置样本数据 -
getSampleTrackIndex()
获取当前选中的轨道索引 -
getSampleTime()
当前分离样本时间 -
getSampleFlags()
获取当前样本类型,为SAMPLE_FLAG_SYNC时表示为关键帧
MediaMuxer
MediaMuxer有助于混合基本流。目前支持mp4或者webm文件作为输出和最多一个音频和、或一个视频基本流。
MediaMuxer不支持复用B帧。
相关API概述:
- addTrack(MediaFormat format)
添加具有指定格式的曲目 - start()
启动混合器,确保在addTrack之后和writeSampleData之前调用。 - writeSampleData(int trackIndex,ByteBuffer byte,MediaCodec.BufferInfo bufferInfo)
将编码的样本写入复用器 - stop()
停止混合器 - release()
确保在完成任务时释放任何资源
public void extractFile(String path){
File file = new File(path);
if (!file.exists()){
return;
}
try {
mMediaExtractor.setDataSource(file.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}
//获取轨道数量
int trackCount = mMediaExtractor.getTrackCount();
Log.e(TAG, "extractFile: track count"+trackCount);
if (trackCount >0){
for (int i = 0; i < trackCount; i++) {
MediaFormat trackFormat = mMediaExtractor.getTrackFormat(i);
String trackMime = trackFormat.getString(MediaFormat.KEY_MIME);
Log.e(TAG, "extractFile: track format"+trackMime);
if (trackMime != null && trackMime.startsWith("video/")){
//代表是视频轨道
//以帧/秒为单位描述视频格式帧频的关键
integer = trackFormat.getInteger(MediaFormat.KEY_FRAME_RATE);
//根据轨道索引选中指定轨道
mMediaExtractor.selectTrack(i);
//初始化合成器
try {
mMediaMuxer = new MediaMuxer(SDCARD_PATH
+"/output.mp4",MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
//添加具有指定格式的曲目
mVideoTrackIndex = mMediaMuxer.addTrack(trackFormat);
//启动混合器
mMediaMuxer.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
if (mMediaMuxer == null){
return;
}
ByteBuffer allocate = ByteBuffer.allocate(500 * 1024);
int sampleSize = 0;
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
while ((sampleSize = mMediaExtractor.readSampleData(allocate,0))>0){
info.offset = 0;
info.size = sampleSize;
info.flags = MediaCodec.BUFFER_FLAG_END_OF_STREAM;
info.presentationTimeUs += 1000*1000/integer;
//将编码的样本写入复用器
mMediaMuxer.writeSampleData(mVideoTrackIndex,allocate,info);
mMediaExtractor.advance();
}
mMediaExtractor.release();
//停止混合器
mMediaMuxer.stop();
//释放资源
mMediaMuxer.release();
}
}
在解析和封装音视频的过程中,还使用到了MediaFormat,MediaCodec等,详细介绍请点击:MediaCodec,MediaFormat详解。
接下来学习----音视频开发六:学习 Android 平台 OpenGL ES