BnMediaExtractor BpMediaExtractor IMediaExtractor MediaExtractor 的关系
Android媒体框架中的IMediaExtractor/BpMediaExtractor/BnMediaExtractor/MediaExtractor四类构成了Binder跨进程解封装体系。IMediaExtractor是根接口定义解封装方法;Bn/BpMediaExtractor是AIDL生成的Binder服务端/客户端骨架;MediaExtractor是实际业务实现类,继承BnMediaE
BnMediaExtractor/BpMediaExtractor/IMediaExtractor/MediaExtractor 关系详解
这四个类是 Android 媒体框架中围绕 MediaExtractor 解封装能力构建的 Binder 跨进程通信体系,完全遵循 Android AIDL 的标准设计规范,与你之前了解的IMediaExtractorService/Bp/Bn/MediaExtractorService属于同套 Binder 设计逻辑,但职责聚焦在单个 MediaExtractor 实例的跨进程操作(而非服务注册 / 获取)。
核心关系一句话概括:IMediaExtractor 是根接口(方法规范),Bn/BpMediaExtractor 是 AIDL 自动生成的 Binder 跨进程骨架(服务端 / 客户端代理),MediaExtractor 是 Android 原生解封装核心类,同时作为 BnMediaExtractor 的子类,是 IMediaExtractor 接口的实际业务实现者 **(承载解封装核心逻辑)**。
以下从核心定义、层级关系、AIDL 生成逻辑、实际调用链路四个维度讲透,结合 Android 9/10 + 版本特性和你关注的 NuPlayer/GenericSource 场景,同时对比之前的IMediaExtractorService体系,帮你快速关联理解。
一、先明确核心前提(与 IMediaExtractorService 体系的核心区别)
二者同属 Binder 跨进程设计,但职责和作用域完全不同,避免混淆:
| 体系 | 核心职责 | 作用域 | 运行进程(Android10+) |
|---|---|---|---|
| IMediaExtractorService+Bp/Bn/MediaExtractorService | 提供创建 MediaExtractor 实例的跨进程服务 | 服务级(全局) | media.extractor 进程(服务端)/ 调用进程(客户端) |
| IMediaExtractor+Bp/Bn/MediaExtractor | 提供单个 MediaExtractor 实例的跨进程操作(解封装、读帧、选轨等) | 实例级(单个对象) | media.extractor 进程(服务端)/ 调用进程(客户端) |
简单说:IMediaExtractorService负责跨进程创建 MediaExtractor 对象,IMediaExtractor负责跨进程操作已创建的 MediaExtractor 对象(如解封装 TS 流、选择视频轨、读取帧数据)。
二、四个类的核心定义与层级关系(从顶层到实现)
四层关系呈 **「接口定义→服务端基类→实际业务实现」「接口定义→客户端代理」** 的标准 Binder 分支结构,IMediaExtractor 是所有类的根接口,Bn/Bp 为 AIDL 自动生成的通信骨架,MediaExtractor 是手动实现的业务核心(原生解封装类)。
1. 根接口:IMediaExtractor(AIDL 生成,纯虚方法规范)
- 生成来源:由 AIDL 文件
frameworks/av/media/libmedia/IMediaExtractor.aidl编译自动生成,对应头文件IMediaExtractor.h; - 核心作用:定义单个 MediaExtractor 实例的跨进程操作方法规范,覆盖解封装的所有核心能力,所有 Bn/Bp/MediaExtractor 都需遵循该规范,核心方法包括:
cpp
运行
// 选择音/视频轨(如DVB/IPTV TS流的视频轨选择) virtual status_t selectTrack(size_t trackID) = 0; // 读取解封装后的媒体帧数据(核心解封装操作) virtual ssize_t readSampleData(MediaBufferBase* buffer, off_t offset) = 0; // 定位播放位置(seek操作) virtual status_t seekTo(int64_t timeUs, MediaExtractor::SeekMode mode) = 0; // 获取媒体轨格式(分辨率、编码格式、码率等) virtual sp<AMessage> getTrackFormat(size_t trackID) const = 0; // 其他核心方法:unselectTrack、advance、countTracks等 - 关键特性:纯虚接口类,无任何实现代码,仅作为所有相关类的方法约定,是跨进程操作 MediaExtractor 的唯一标准。
2. Binder 服务端基类:BnMediaExtractor(AIDL 生成,通信骨架)
- 生成来源:同上述 AIDL 文件编译自动生成,继承自
IMediaExtractor和 Android Binder 核心类BBinder; - 核心作用:作为单个 MediaExtractor 实例的 Binder 服务端骨架,运行在
media.extractor进程(Android10+)/MediaServer 进程(Android9),核心能力:- 实现 Binder 跨进程通信底层逻辑(参数序列化 / 反序列化、进程间方法转发);
- 暴露与
IMediaExtractor一一对应的纯虚抽象方法,要求子类必须实现; - 作为服务端入口,接收客户端(BpMediaExtractor)的跨进程操作请求。
- 关键特性:仅提供通信骨架,无任何解封装业务逻辑,无法直接实例化(含纯虚方法)。
3. 实际业务实现:MediaExtractor(手动实现,解封装核心)
- 实现来源:由 Android 系统团队手动编写,源码位置
frameworks/av/media/libmedia/MediaExtractor.cpp(你非常熟悉的原生解封装类); - 核心作用:作为
IMediaExtractor接口的实际业务实现者,是 Android 媒体解封装的核心类(TS/MP4/FLV 等格式解封装的真正载体),核心能力:- 继承
BnMediaExtractor,实现其所有纯虚抽象方法,将 Binder 跨进程调用映射为本地解封装操作; - 承载原生解封装核心逻辑:解析媒体格式、分离音视频轨、读取帧数据、音视频同步等;
- 支持多格式适配:通过内部调度
TsExtractor/FlvExtractor/Mp4Extractor等格式专属解封装器,处理不同媒体流; - 是
media.extractor服务创建后,实际提供解封装能力的对象(IMediaExtractorService::createExtractor最终返回的就是该类的实例)。
- 继承
- 关键特性:
- 可实例化,既是本地解封装核心类,也是跨进程解封装的服务端实现类(一身两用);
- Android9/10 + 版本逻辑完全一致,仅运行进程不同(Android9 在 MediaServer,Android10 + 在 media.extractor 独立进程)。
4. Binder 客户端代理:BpMediaExtractor(AIDL 生成,请求转发)
- 生成来源:同上述 AIDL 文件编译自动生成,继承自
IMediaExtractor和 Android Binder 核心类BpRefBase; - 核心作用:作为单个 MediaExtractor 实例的 Binder 客户端代理,运行在服务调用进程(如 MediaServer 进程的 NuPlayer/GenericSource),核心能力:
- 持有服务端 MediaExtractor 实例的 Binder 对象(由
IMediaExtractorService::createExtractor跨进程返回); - 将客户端的本地方法调用(如
selectTrack/readSampleData)序列化为 Binder Parcel 数据,转发给服务端(BnMediaExtractor/MediaExtractor); - 接收服务端的返回数据,反序列化为本地数据类型(如帧数据、状态码、格式信息)并返回给客户端调用者(如 NuPlayer::GenericSource);
- 持有服务端 MediaExtractor 实例的 Binder 对象(由
- 关键特性:客户端调用者(如 GenericSource)无需关心跨进程细节,调用
BpMediaExtractor的方法与调用本地MediaExtractor完全一致,底层通信由 Binder 框架自动完成。
三、四层关系总览(标准 Binder 架构图)
plaintext
┌─────────────────────────────────────────────────────┐
│ 根接口:IMediaExtractor(AIDL生成,纯虚方法规范) │
│ (定义解封装的跨进程操作:selectTrack/readSampleData等) │
├─────────────────────┬─────────────────────────────┤
│ 继承 │ 继承 │
├─────────────────────▼─────────────────────────────┤
│ BnMediaExtractor(AIDL生成,服务端Binder骨架) │
│ (运行在media.extractor进程,无业务逻辑) │
├─────────────────────┤ │
│ 继承 │ │
├─────────────────────▼─────────────────────────────┤
│ MediaExtractor(手动实现,解封装核心) │
│ (运行在media.extractor进程,实现所有解封装逻辑) │
│ (既是本地解封装类,也是跨进程服务端实现类) │
├─────────────────────────────────────────────────────┤
│ BpMediaExtractor(AIDL生成,客户端Binder代理) │
│ (运行在调用进程,持有服务端Binder,转发所有调用) │
└─────────────────────────────────────────────────────┘
核心关联一句话:IMediaExtractor是所有解封装跨进程操作的方法标准,Bn/BpMediaExtractor是 AIDL 自动生成的实例级跨进程通信骨架,MediaExtractor是继承 Bn 并承载原生解封装逻辑的最终实现类,也是跨进程解封装的实际操作对象。
四、AIDL 生成与代码实现(关键文件 + 版本差异)
结合 Android AOSP 源码,明确四个类的生成 / 实现文件,以及 Android9/10 + 的版本差异(与你关注的开发场景高度相关):
| 类名 | 生成 / 实现方式 | 核心文件路径(Android10+) | Android9 版本差异 |
|---|---|---|---|
| IMediaExtractor | AIDL 自动生成 | frameworks/av/media/libmedia/IMediaExtractor.h/cpp | 路径一致,方法稍精简 |
| BnMediaExtractor | AIDL 自动生成 | frameworks/av/media/libmedia/IMediaExtractor.cpp | 路径一致,内嵌在 IMediaExtractor.cpp 中 |
| BpMediaExtractor | AIDL 自动生成 | frameworks/av/media/libmedia/IMediaExtractor.cpp | 路径一致,内嵌在 IMediaExtractor.cpp 中 |
| MediaExtractor | 手动实现 | frameworks/av/media/libmedia/MediaExtractor.cpp | 路径一致,未独立进程,运行在 MediaServer,解封装逻辑完全一致 |
关键版本细节:
- Android10+:
MediaExtractor(作为 BnMediaExtractor 子类)运行在独立的 media.extractor 进程,由MediaExtractorService创建并通过IMediaExtractor接口暴露给客户端; - Android9:无独立 media.extractor 进程,
MediaExtractor运行在MediaServer 进程,跨进程调用仅在 MediaServer 与应用进程之间,类的关系、实现逻辑与高版本完全一致; - 通用特性:无论哪个版本,
MediaExtractor始终是BnMediaExtractor 的子类,既是本地解封装核心,也是跨进程服务端实现,这是 Android 框架的经典 “一身两用” 设计。
五、实际跨进程调用链路(与 NuPlayer/GenericSource 关联)
结合你关注的Android9 NuPlayer 播放 TS 流场景,完整链路包含两个阶段:先通过IMediaExtractorService创建跨进程 MediaExtractor 实例,再通过IMediaExtractor操作该实例,全程覆盖四个类的协作,同时关联你之前看到的mVideoTrack.mSource->start()逻辑:
整体链路(客户端:MediaServer 进程;服务端:media.extractor 进程(Android10+)/MediaServer(Android9))
plaintext
【阶段1:跨进程创建MediaExtractor实例(IMediaExtractorService体系)】
1. NuPlayer::GenericSource → 调用IMediaExtractorService::createExtractor(底层BpMediaExtractorService转发)
2. 服务端MediaExtractorService → 创建MediaExtractor实例(BnMediaExtractor子类)
3. 服务端返回IMediaExtractor接口(实际指向MediaExtractor实例)
4. 客户端接收到接口,底层自动封装为BpMediaExtractor代理对象
【阶段2:跨进程操作MediaExtractor实例(IMediaExtractor体系,核心)】
5. GenericSource → 调用BpMediaExtractor::selectTrack(mVideoTrackIdx)(选择视频轨)
→ Bp序列化参数 → Binder驱动转发 → BnMediaExtractor反序列化 → MediaExtractor::selectTrack(实际解封装选轨)
6. GenericSource → 调用BpMediaExtractor::seekTo(0, SEEK_CLOSEST)(直播流定位最新帧)
→ 同上,最终执行MediaExtractor::seekTo
7. GenericSource → 循环调用BpMediaExtractor::readSampleData()(读取TS流视频帧)
→ 同上,最终执行MediaExtractor::readSampleData → 解封装出原始视频帧
8. 读取的帧数据通过Binder返回给客户端 → 交给MediaCodec解码 → 渲染显示
与mVideoTrack.mSource->start()的关联:
在 Android9 中,mVideoTrack.mSource(IMediaSource 匿名子类)的start()方法中,核心操作mExtractor->selectTrack(mVideoTrackIdx):
- 若
mExtractor是本地 MediaExtractor 实例:直接调用本地方法,无跨进程; - 若
mExtractor是跨进程实例:实际调用的是BpMediaExtractor::selectTrack,底层通过 Binder 转发到服务端的MediaExtractor::selectTrack。
六、与 IMediaExtractorService 体系的对比总结(快速区分)
为了彻底避免混淆,以下是两套体系的核心对比,记住 **“服务级” 和 “实例级”** 的区别即可:
| 对比维度 | IMediaExtractor+Bp/Bn/MediaExtractor 体系 | IMediaExtractorService+Bp/Bn/MediaExtractorService 体系 |
|---|---|---|
| 核心定位 | 实例级:操作单个 MediaExtractor 对象 | 服务级:提供创建 MediaExtractor 对象的全局服务 |
| 核心职责 | 解封装具体操作(选轨、读帧、seek 等) | 全局服务注册 / 获取、创建 MediaExtractor 实例 |
| 根接口 | IMediaExtractor(实例方法) | IMediaExtractorService(服务方法) |
| Bn 子类实际实现者 | MediaExtractor(原生解封装类) | MediaExtractorService(服务实现类) |
| 跨进程调用触发时机 | 创建 MediaExtractor 实例后,操作该实例时 | 需要创建跨进程 MediaExtractor 实例时 |
| 二者协作关系 | 被 IMediaExtractorService 体系创建并暴露 | 负责创建 IMediaExtractor 体系的实例并提供给客户端 |
核心总结
- 根接口:
IMediaExtractor(AIDL 生成)是所有解封装跨进程操作的方法标准,定义了选轨、读帧等核心接口; - 通信骨架:
Bn/BpMediaExtractor(AIDL 生成)是 Binder 服务端 / 客户端代理,提供实例级跨进程通信骨架,无业务逻辑; - 实际实现:
MediaExtractor(手动实现)是 Android 原生解封装核心类,继承BnMediaExtractor并实现所有抽象方法,既是本地解封装类,也是跨进程服务端实现类; - 核心区别:与
IMediaExtractorService体系的核心差异是实例级(操作单个对象)vs 服务级(创建对象的全局服务),二者协作完成 “跨进程创建 MediaExtractor 实例 + 跨进程操作该实例” 的完整能力; - 版本特性:Android9/10 + 类的关系完全一致,仅运行进程不同(Android10+MediaExtractor 运行在独立 media.extractor 进程,Android9 在 MediaServer);
- 调用关联:你关注的
mVideoTrack.mSource->start()中的selectTrack操作,若涉及跨进程,底层就是BpMediaExtractor转发到服务端的MediaExtractor::selectTrack。
这套体系与你之前了解的IMediaSource/BnMediaSource、IMediaExtractorService/Bp/Bn遵循完全相同的 Android Binder 设计规范,掌握后可快速理解 Android 媒体框架中所有跨进程通信模块。
七、android9 IMediaExtractor
Android 9 中的 RemoteMediaExtractor 类继承自 BnMediaExtractor,天然实现了 IMediaExtractor 接口,是该版本中 IMediaExtractor 接口的实际 Binder 服务端实现者(替代了此前推测的匿名类 / 嵌套类),也是跨进程解封装能力的核心载体。
关键逻辑依据:Android Binder + AIDL 固定设计规范
这一结论的核心是 Android 跨进程通信的标准设计规则,且适用于所有系统服务(包括media.extractor),无版本特例:
IMediaExtractor是由 AIDL 文件(IMediaExtractor.aidl)编译生成的纯虚根接口,定义了跨进程解封装的所有方法规范(selectTrack/readSampleData/seekTo等);- 编译工具会自动为
IMediaExtractor生成Binder 服务端基类BnMediaExtractor,该基类直接继承IMediaExtractor并实现 Binder 底层通信逻辑(参数序列化 / 反序列化、进程间方法转发),同时将IMediaExtractor的所有纯虚方法保留为抽象方法,要求子类必须实现; - 任何继承
BnMediaExtractor的类(如RemoteMediaExtractor),无需显式声明implements IMediaExtractor,会通过继承传递天然实现IMediaExtractor的所有接口方法,只需覆写BnMediaExtractor的抽象方法完成实际业务逻辑即可。
类的继承关系链(清晰体现实现逻辑)
plaintext
IMediaExtractor(AIDL生成,纯虚根接口)
↑ 直接继承
BnMediaExtractor(AIDL生成,Binder服务端基类,抽象类)
↑ 直接继承
RemoteMediaExtractor(Android 9 手动实现,具体业务类)
核心传递逻辑:RemoteMediaExtractor → 继承BnMediaExtractor → 间接实现IMediaExtractor,是 Android Binder 跨进程通信的标准实现方式。
Android 9 中 RemoteMediaExtractor 的核心作用
在 Android 9(无独立media.extractor进程,所有解封装逻辑运行在 MediaServer 进程)中,RemoteMediaExtractor是IMediaExtractor接口的唯一实际实现者,核心职责包括:
- 承载跨进程解封装业务:覆写
BnMediaExtractor的所有抽象方法(对应IMediaExtractor的接口方法),将跨进程方法调用映射为本地解封装逻辑(调用MediaExtractor的 PIMPL 实现MediaExtractorImpl,调度TsExtractor/Mp4Extractor等格式专属解封装器); - 作为跨进程能力载体:由
MediaExtractorService创建实例,通过IMediaExtractor接口暴露给客户端(如 NuPlayer/GenericSource),客户端底层会自动将其封装为BpMediaExtractor(Binder 客户端代理),完成跨进程调用; - 解耦本地与跨进程逻辑:
RemoteMediaExtractor专门处理 Binder 跨进程通信相关逻辑,不侵入MediaExtractor的本地解封装核心代码,保证MediaExtractor本地调用的纯净性和轻量性。
与MediaExtractor的协作关系(Android 9 实际调用链路)
结合你关注的 NuPlayer/GenericSource 播放场景,RemoteMediaExtractor与MediaExtractor的完整协作链路如下:
plaintext
【服务端:MediaServer进程】
1. MediaExtractorService::createExtractor() → 创建本地`MediaExtractor`实例(PIMPL设计,持有`MediaExtractorImpl`);
2. 基于`MediaExtractor`的本地实现,创建`RemoteMediaExtractor`实例(传入`MediaExtractorImpl`引用);
3. `RemoteMediaExtractor`通过`asIMediaExtractor()`(或直接返回`this`)暴露为`IMediaExtractor`接口,由`MediaExtractorService`跨进程返回给客户端;
【客户端:MediaServer进程(NuPlayer)/应用进程】
4. 客户端获取`IMediaExtractor`接口(实际指向`BpMediaExtractor`代理);
5. 调用`IMediaExtractor::selectTrack()`/`readSampleData()`等方法 → 底层由`BpMediaExtractor`转发至服务端`RemoteMediaExtractor`;
6. `RemoteMediaExtractor`覆写的方法执行 → 调用`MediaExtractorImpl`的本地解封装逻辑 → 完成TS/MP4等流的解封装,返回帧数据给客户端。
核心总结
- Android 9 中的
RemoteMediaExtractor继承自BnMediaExtractor,通过继承传递天然实现了IMediaExtractor接口,是该版本中IMediaExtractor的实际 Binder 服务端实现者; - 该实现遵循 Android Binder + AIDL 固定设计规范:AIDL 生成的
BnXXX基类直接继承根接口IXXX,子类继承BnXXX即间接实现IXXX,无需显式声明; RemoteMediaExtractor的核心作用是处理跨进程解封装的 Binder 通信逻辑,将跨进程方法调用映射为本地MediaExtractor的解封装逻辑,是 Android 9 中media.extractor服务跨进程能力的核心载体;- 与
MediaExtractor的协作逻辑为:MediaExtractor负责本地纯解封装逻辑,RemoteMediaExtractor负责跨进程通信适配,二者解耦且协同完成跨进程解封装能力交付。
更多推荐

所有评论(0)