您可以使用供应商扩展程序扩展媒体提取器和媒体编解码器组件。MediaSession2 和 MediaParser API 无法自定义(但您可以向上游提交针对旧版 MediaPlayer
和 MediaSession
API 的更改)。
要在 Android 媒体框架中支持其他媒体类型,您需要创建一个自定义提取器和解码器。例如,要在 AVI 文件中添加对 Windows Media 视频的支持,您需要创建一个 AVI 提取器和一个 Windows Media 视频解码器。
关于扩展程序
如果默认媒体提取器无法满足您的要求,您可以将自定义提取器插件放在 /system/lib[64]/extractors/
中。提取器进程会自动从 Google 提供的 APEX 软件包和 /system/lib[64]/extractors/
中加载提取器插件。
同样,您可以设置自定义媒体编解码器服务,这些服务使用 frameworks/av/media/codec2/core/
中定义的 Codec 2.0 接口。对于基本实现,请参阅 frameworks/av/media/codec2/hidl/services/
。C2ComponentStore
接口是库入口点。如需示例,请参阅 frameworks/av/media/codec2/vndk/C2Store.cpp
中的默认软件编解码器存储实现。
当使用您自己的 APEX 时,请构建编解码器服务,并使用与 mediaswcodec
服务相同的流程加载 APEX 文件。为此,请定义一个负责注册所有 C2 组件的顶层共享库,然后创建一个位于供应商分区中的 APEX 软件包(具有传递依赖项)。当供应商编解码器服务进程启动时,它可以加载此顶层入口点。
创建提取器
当为新格式添加提取器时,请确保提取器仅依赖于稳定的 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 解码器,因为已存在一个。
要为包含 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
没有影响。