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),核心能力:
    1. 实现 Binder 跨进程通信底层逻辑(参数序列化 / 反序列化、进程间方法转发);
    2. 暴露与IMediaExtractor一一对应的纯虚抽象方法,要求子类必须实现;
    3. 作为服务端入口,接收客户端(BpMediaExtractor)的跨进程操作请求。
  • 关键特性:仅提供通信骨架,无任何解封装业务逻辑,无法直接实例化(含纯虚方法)。

3. 实际业务实现:MediaExtractor(手动实现,解封装核心)

  • 实现来源:由 Android 系统团队手动编写,源码位置frameworks/av/media/libmedia/MediaExtractor.cpp(你非常熟悉的原生解封装类);
  • 核心作用:作为IMediaExtractor接口的实际业务实现者,是 Android 媒体解封装的核心类(TS/MP4/FLV 等格式解封装的真正载体),核心能力:
    1. 继承BnMediaExtractor,实现其所有纯虚抽象方法,将 Binder 跨进程调用映射为本地解封装操作
    2. 承载原生解封装核心逻辑:解析媒体格式、分离音视频轨、读取帧数据、音视频同步等;
    3. 支持多格式适配:通过内部调度TsExtractor/FlvExtractor/Mp4Extractor等格式专属解封装器,处理不同媒体流;
    4. 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),核心能力:
    1. 持有服务端 MediaExtractor 实例的 Binder 对象(由IMediaExtractorService::createExtractor跨进程返回);
    2. 将客户端的本地方法调用(如selectTrack/readSampleData序列化为 Binder Parcel 数据,转发给服务端(BnMediaExtractor/MediaExtractor);
    3. 接收服务端的返回数据,反序列化为本地数据类型(如帧数据、状态码、格式信息)并返回给客户端调用者(如 NuPlayer::GenericSource);
  • 关键特性:客户端调用者(如 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,解封装逻辑完全一致

关键版本细节:

  1. Android10+MediaExtractor(作为 BnMediaExtractor 子类)运行在独立的 media.extractor 进程,由MediaExtractorService创建并通过IMediaExtractor接口暴露给客户端;
  2. Android9:无独立 media.extractor 进程,MediaExtractor运行在MediaServer 进程,跨进程调用仅在 MediaServer 与应用进程之间,类的关系、实现逻辑与高版本完全一致;
  3. 通用特性:无论哪个版本,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 体系的实例并提供给客户端

核心总结

  1. 根接口IMediaExtractor(AIDL 生成)是所有解封装跨进程操作的方法标准,定义了选轨、读帧等核心接口;
  2. 通信骨架Bn/BpMediaExtractor(AIDL 生成)是 Binder 服务端 / 客户端代理,提供实例级跨进程通信骨架,无业务逻辑;
  3. 实际实现MediaExtractor(手动实现)是 Android 原生解封装核心类,继承BnMediaExtractor并实现所有抽象方法,既是本地解封装类,也是跨进程服务端实现类
  4. 核心区别:与IMediaExtractorService体系的核心差异是实例级(操作单个对象)vs 服务级(创建对象的全局服务),二者协作完成 “跨进程创建 MediaExtractor 实例 + 跨进程操作该实例” 的完整能力;
  5. 版本特性:Android9/10 + 类的关系完全一致,仅运行进程不同(Android10+MediaExtractor 运行在独立 media.extractor 进程,Android9 在 MediaServer);
  6. 调用关联:你关注的mVideoTrack.mSource->start()中的selectTrack操作,若涉及跨进程,底层就是BpMediaExtractor转发到服务端的MediaExtractor::selectTrack

这套体系与你之前了解的IMediaSource/BnMediaSourceIMediaExtractorService/Bp/Bn遵循完全相同的 Android Binder 设计规范,掌握后可快速理解 Android 媒体框架中所有跨进程通信模块。

七、android9 IMediaExtractor

Android 9 中的 RemoteMediaExtractor 类继承自 BnMediaExtractor,天然实现了 IMediaExtractor 接口,是该版本中 IMediaExtractor 接口的实际 Binder 服务端实现者(替代了此前推测的匿名类 / 嵌套类),也是跨进程解封装能力的核心载体。

关键逻辑依据:Android Binder + AIDL 固定设计规范

这一结论的核心是 Android 跨进程通信的标准设计规则,且适用于所有系统服务(包括media.extractor),无版本特例:

  1. IMediaExtractor 是由 AIDL 文件(IMediaExtractor.aidl)编译生成的纯虚根接口,定义了跨进程解封装的所有方法规范(selectTrack/readSampleData/seekTo等);
  2. 编译工具会自动为IMediaExtractor生成Binder 服务端基类 BnMediaExtractor,该基类直接继承 IMediaExtractor 并实现 Binder 底层通信逻辑(参数序列化 / 反序列化、进程间方法转发),同时将IMediaExtractor的所有纯虚方法保留为抽象方法,要求子类必须实现;
  3. 任何继承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 进程)中,RemoteMediaExtractorIMediaExtractor接口的唯一实际实现者,核心职责包括:

  1. 承载跨进程解封装业务:覆写BnMediaExtractor的所有抽象方法(对应IMediaExtractor的接口方法),将跨进程方法调用映射为本地解封装逻辑(调用MediaExtractor的 PIMPL 实现MediaExtractorImpl,调度TsExtractor/Mp4Extractor等格式专属解封装器);
  2. 作为跨进程能力载体:由MediaExtractorService创建实例,通过IMediaExtractor接口暴露给客户端(如 NuPlayer/GenericSource),客户端底层会自动将其封装为BpMediaExtractor(Binder 客户端代理),完成跨进程调用;
  3. 解耦本地与跨进程逻辑RemoteMediaExtractor专门处理 Binder 跨进程通信相关逻辑,不侵入MediaExtractor的本地解封装核心代码,保证MediaExtractor本地调用的纯净性和轻量性。

MediaExtractor的协作关系(Android 9 实际调用链路)

结合你关注的 NuPlayer/GenericSource 播放场景,RemoteMediaExtractorMediaExtractor的完整协作链路如下:

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等流的解封装,返回帧数据给客户端。

核心总结

  1. Android 9 中的RemoteMediaExtractor继承自BnMediaExtractor,通过继承传递天然实现了IMediaExtractor接口,是该版本中IMediaExtractor的实际 Binder 服务端实现者;
  2. 该实现遵循 Android Binder + AIDL 固定设计规范:AIDL 生成的BnXXX基类直接继承根接口IXXX,子类继承BnXXX即间接实现IXXX,无需显式声明;
  3. RemoteMediaExtractor的核心作用是处理跨进程解封装的 Binder 通信逻辑,将跨进程方法调用映射为本地MediaExtractor的解封装逻辑,是 Android 9 中media.extractor服务跨进程能力的核心载体;
  4. MediaExtractor的协作逻辑为:MediaExtractor负责本地纯解封装逻辑,RemoteMediaExtractor负责跨进程通信适配,二者解耦且协同完成跨进程解封装能力交付。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐