自定义媒体组件

您可以使用供应商扩展程序扩展媒体提取器和媒体编解码器组件。无法对 MediaSession2 和 MediaParser API 进行自定义,但可以向上游发送针对旧版 MediaPlayerMediaSession API 的更改。

如需在 Android 媒体框架中支持更多媒体类型,您需要创建自定义提取器解码器。例如,如需添加对 AVI 文件中的 Windows Media 视频的支持,您需要创建 AVI 提取器和 Windows Media 视频解码器

扩展程序简介

如果默认的媒体提取器无法满足您的需求,您可以在 /system/lib[64]/extractors/ 中放置自定义提取器插件。提取器进程会自动从 Google 提供的 APEX 软件包和 /system/lib[64]/extractors/ 加载提取器插件。

同样,您可以设置使用 Codec 2.0 接口(在 frameworks/av/media/codec2/core/ 中定义)的自定义媒体编解码器服务。如需了解基本实现,请参阅 frameworks/av/media/codec2/hidl/services/。库的入口点是 C2ComponentStore 接口。如需查看示例,请参阅 frameworks/av/media/codec2/vndk/C2Store.cpp 中的默认软件编解码器存储实现。

如果您使用自己的 APEX,则需要构建编解码器服务,并使用与 mediaswcodec 服务相同的进程加载 APEX 文件。为此,请定义一个负责注册所有 C2 组件的顶级共享库,然后创建一个包含传递依赖项的 APEX 软件包(位于 vendor 分区)。供应商编解码器服务进程启动时便可加载该顶级入口点。

创建提取器

添加适用于新格式的提取器时,请确保提取器仅依赖于稳定的 NDK API,而不依赖于任何私有 API。提取器应该实现由 frameworks/av/include/media/MediaExtractorPluginApi.h 定义的 API,且可以使用 frameworks/av/include/media/MediaExtractorPluginHelper.h 中的 C++ 便捷封装容器。由于 Android 10 或更高版本仅支持提取器 API 的最高版本,因此请务必先将提取器 API 升级到最高版本,然后再对提取器进行建模。

将自定义提取器放在 /system/lib/64/extractors 或供应商 APEX 中,后者会随包含 Google 提取器的 Google APEX 一起打开。如需验证相应框架是否已加载您的提取器,请运行以下命令。

adb shell dumpsys media.extractor

您获取的可用提取器列表应类似于以下内容。

Available extractors:
AAC Extractor: plugin\_version(2), uuid(4fd80eae03d24d729eb948fa6bb54613), version(1), path(/system/lib64/extractors/libaacextractor.so)
AMR Extractor: plugin\_version(2), uuid(c86639c92f3140aca715fa01b4493aaf), version(1), path(/system/lib64/extractors/libamrextractor.so)
FLAC Extractor: plugin\_version(2), uuid(1364b048cc454fda9934327d0ebf9829), version(1), path(/system/lib64/extractors/libflacextractor.so)
MIDI Extractor: plugin\_version(2), uuid(ef6cca0af8a243e6ba5fdfcd7c9a7ef2), version(1), path(/system/lib64/extractors/libmidiextractor.so)
MP3 Extractor: plugin\_version(2), uuid(812a3f6cc8cf46deb5293774b14103d4), version(1), path(/system/lib64/extractors/libmp3extractor.so)
MP4 Extractor: plugin\_version(2), uuid(27575c6744174c548d3d8e626985a164), version(2), path(/system/lib64/extractors/libmp4extractor.so)
MPEG2-PS/TS Extractor: plugin\_version(1), uuid(3d1dcfebe40a436da574c2438a555e5f), version(1), path(/system/lib64/extractors/libmpeg2extractor.so)
Matroska Extractor: plugin\_version(2), uuid(abbedd9238c44904a4c1b3f45f899980), version(1), path(/system/lib64/extractors/libmkvextractor.so)
Ogg Extractor: plugin\_version(2), uuid(8cc5cd06f772495e8a62cba9649374e9), version(1), path(/system/lib64/extractors/liboggextractor.so)
WAV Extractor: plugin\_version(3), uuid(7d61385858374a3884c5332d1cddee27), version(1), path(/system/lib64/extractors/libwavextractor.so)

如果您的自定义提取器支持 Google 提供的提取器已支持的格式,您可以使用 Sniff() 函数返回比 Google 提供的置信水平更高的置信水平,以强制相应框架使用您的提取器。

媒体框架(从 /system/lib/64/extractors 或供应商 APEX)加载您的提取器时,可以识别相应文件并获取其内容的相关信息。接下来是添加相应格式的解码器,以便框架解析文件内容。

创建自定义解码器

对于 Google 提供的解码器尚不支持的格式,您都需要创建一个自定义解码器。例如:

  • 如需为包含 MP3 的 AVI 文件添加媒体框架支持,您需要添加 AVI 提取器,但无需添加 MP3 解码器,因为已有 MP3 解码器。

  • 如需为包含 Windows Media 的 AVI 文件添加媒体框架支持,您需要用到 AVI 提取器和 Windows Media 解码器。

添加新解码器的方式与针对 AVC 或 HEVC 添加您自己的硬件解码器的方式大致相同。

虽然提取器会发布它包含的媒体轨道的 MIME 类型,但是也需要存在支持这些 MIME 类型的编解码器,这样,该文件才会完全受支持。严格来说,实际使用的 MIME 类型字符串是提取器和编解码器之间的一种协议(无需将该字符串添加到 MediaDefs.h 文件中)。

与媒体扫描器集成

媒体扫描程序会查找新的文件类型,并将其添加到媒体数据库中。要让媒体扫描程序处理您的自定义文件类型,扫描程序需要能够识别相应文件类型。在 Android 10 或更高版本中,MimeUtils(位于 libcore 中)会维护从 MIME 到扩展程序的映射。之前,这种映射是在 MediaFile.java 文件中处理,后者仍包含从 MIME 类型到 MTP 格式常量的映射。

提取器可以导出支持的文件扩展名列表(如 MP3 或 MP4)。但只有 LegacyMediaScanner 使用该列表,因此不会对默认使用的 ModernMediaScanner 产生任何影响。