MediaExtractor
是Android多媒体处理的基础组件,解封装是其核心价值。
一、功能与定位
MediaExtractor
是Android多媒体框架中的媒体解封装工具,主要作用是从媒体文件(如MP4、MKV、MP3)中分离音视频轨道数据,为后续解码(MediaCodec
)或处理提供原始压缩数据流。
- 核心能力:
- 解析多种封装格式(MP4、WebM、FLV等),提取音频、视频、字幕轨道。
- 支持本地文件、网络流(需
Uri
)、加密媒体源。
二、核心API详解
1. 初始化与数据源设置
MediaExtractor extractor = new MediaExtractor();
// 设置数据源(三选一)
extractor.setDataSource("/sdcard/video.mp4"); // 本地路径
extractor.setDataSource(fd); // 文件描述符
extractor.setDataSource(context, uri, headers); // 网络流或ContentProvider
2. 轨道管理
方法 | 作用 |
---|---|
int getTrackCount() | 获取轨道总数(音/视/字幕) |
MediaFormat getTrackFormat(int index) | 获取轨道格式(分辨率、码率、MIME类型等) |
void selectTrack(int index) | 选择需处理的轨道(后续操作仅针对该轨道) |
void unselectTrack(int index) | 取消选择轨道 |
示例:选择首个视频轨道
for (int i = 0; i < extractor.getTrackCount(); i++) {
MediaFormat format = extractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
if (mime.startsWith("video/")) {
extractor.selectTrack(i); // 选中视频轨道
break;
}
}
3. 数据读取与控制
方法 | 功能 |
---|---|
int readSampleData(ByteBuffer buffer, int offset) | 读取当前样本数据到缓冲区,返回数据大小(-1表示结束) |
long getSampleTime() | 获取当前样本时间戳(微秒) |
int getSampleFlags() | 获取样本标志(如关键帧BUFFER_FLAG_KEY_FRAME ) |
boolean advance() | 移动到下一样本,返回是否成功 |
void seekTo(long timeUs, int mode) | 跳转到指定时间点(SEEK_TO_CLOSEST_SYNC 等模式) |
关键参数说明:
offset
:指定数据在缓冲区中的写入偏移量,用于分段读取大文件。seekTo
模式:SEEK_TO_PREVIOUS_SYNC
:跳转到前一个关键帧(高效解码)。SEEK_TO_CLOSEST_SYNC
:跳转到最近关键帧(推荐平衡效率与精度)。
4. 资源释放
extractor.release(); // 必须调用,避免内存泄漏
三、底层实现原理
1. 架构分层
层级 | 组件 | 职责 |
---|---|---|
JNI接口层 | android_media_MediaExtractor.cpp | Java与C++桥接,转发API调用 |
C++核心层 | NuMediaExtractor | 媒体解析、轨道分离、数据提取 |
数据源层 | DataSource | 从文件/网络/加密源读取原始数据 |
Extractor插件 | MP4Extractor 等 | 按格式实现具体解析逻辑(动态注册) |
2. 工作流程
- 初始化:
- Java层调用
setDataSource()
→ JNI触发NuMediaExtractor
创建。 - 通过
DataSource::RegisterDefaultSniffers()
注册格式解析器(如SniffMPEG4
)。
- Java层调用
- 格式识别:
- 轮询所有
ExtractorPlugin
,根据文件头匹配最佳解析器(置信度最高者)。
- 轮询所有
- 数据提取:
- 按时间戳顺序交错读取音视频样本(非随机排列)。
- 通过
readSampleData()
返回压缩数据至应用层缓冲区。
四、典型应用场景
- 音视频播放器
- 配合
MediaCodec
解码 →Surface
渲染视频,AudioTrack
播放音频。
- 配合
- 媒体文件转换
- 提取音视频轨道 → 通过
MediaMuxer
重新封装为新格式(如MP4转MKV)。
- 提取音视频轨道 → 通过
- 音视频编辑
- 剪切:
seekTo()
定位起始点 → 读取指定区间数据。 - 合并:多
MediaExtractor
读取 →MediaMuxer
合成。
- 剪切:
- 自定义处理
- 提取原始H.264/AAC流 → 滤镜处理 → 重新编码。
深入实现可参考源码:
- JNI层:
frameworks/base/media/jni/android_media_MediaExtractor.cpp
- C++层:
NuMediaExtractor
(frameworks/av/media/libmediaextractor/
)