💻 第一步:实现解码组件 (Implement the Component)
这是最核心的开发工作,你需要编写实际的解码逻辑。
-
代码位置 :对于 Android 原生软件解码器,通常放置在
frameworks/av/media/codec2/components/目录下,可以在此为你的新解码器创建子目录 -4。 -
实现方法:
-
你的新类需要继承或实现
C2Component接口 -4。 -
Android 框架提供了
SimpleC2Component辅助类,它封装了大部分通用逻辑,可以大大简化你的实现工作。你可以参考现有的解码器,如C2SoftAvcDec(AVC解码器)的实现方式 -4-7。 -
核心任务 :你需要在这个组件里实现具体的解码算法,或者封装已有的解码库(如 FFmpeg、libavc 等)-6。
主要重写SimpleC2Component的虚函数: virtual c2_status_t onInit() = 0; virtual c2_status_t onStop() = 0; virtual void onReset() = 0; virtual void onRelease() = 0; virtual c2_status_t onFlush_sm() = 0; virtual void process( const std::unique_ptr<C2Work> &work, const std::shared_ptr<C2BlockPool> &pool) = 0; virtual c2_status_t drain( uint32_t drainMode, const std::shared_ptr<C2BlockPool> &pool) = 0; -
🏭 第二步:创建组件工厂 (Create a Component Factory)
Codec 2 框架使用工厂模式来创建组件实例。
-
作用 :框架不会直接实例化你的
C2Component,而是通过一个C2ComponentFactory。当系统需要你的解码器时,会调用工厂的createComponent()方法。 -
实现方法 :你需要创建一个工厂类,它知道如何创建你的一个或多个解码组件。例如,
C2SoftAvcDecFactory就是用来创建 AVC 软件解码器的 -4-7。
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftAvcDecFactory();
}
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
}
重写C2ComponentFactory的虚函数:
class C2SoftAvcDecFactory : public C2ComponentFactory {
public:
C2SoftAvcDecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
GetCodec2PlatformComponentStore()->getParamReflector())) {
}
virtual c2_status_t createComponent(
c2_node_id_t id,
std::shared_ptr<C2Component>* const component,
std::function<void(C2Component*)> deleter) override {
*component = std::shared_ptr<C2Component>(
new C2SoftAvcDec(COMPONENT_NAME,
id,
std::make_shared<C2SoftAvcDec::IntfImpl>(mHelper)),
deleter);
return C2_OK;
}
virtual c2_status_t createInterface(
c2_node_id_t id,
std::shared_ptr<C2ComponentInterface>* const interface,
std::function<void(C2ComponentInterface*)> deleter) override {
*interface = std::shared_ptr<C2ComponentInterface>(
new SimpleInterface<C2SoftAvcDec::IntfImpl>(
COMPONENT_NAME, id, std::make_shared<C2SoftAvcDec::IntfImpl>(mHelper)),
deleter);
return C2_OK;
}
virtual ~C2SoftAvcDecFactory() override = default;
private:
std::shared_ptr<C2ReflectorHelper> mHelper;
};
📦 第三步:集成到组件商店 (Integrate with Component Store)
组件商店(C2ComponentStore)就像一个"组件目录",负责发现和提供所有可用的组件。你需要将你的组件工厂注册到这个"目录"中。根据你的组件类型,有两种主要方式:
-
方式 A:软件解码器 (Software Codec) - 添加到平台商店
-
方式 B:硬件解码器 (Hardware/HAL Codec) - 创建独立服务
-
实现服务 :你需要创建一个可执行程序(通常位于
vendor/bin/hw/),它实现IComponentStore的 HIDL 或 AIDL 接口 -2-5。 -
注册服务 :在这个
main()函数中,实例化你的C2ComponentStore(例如基于 V4L2 的实现 -10),并将其作为系统服务注册,例如android.hardware.media.c2@1.x-service-2-5-9。
添加新的组件so: C2PlatformComponentStore::C2PlatformComponentStore() : mVisited(false), mReflector(std::make_shared<C2ReflectorHelper>()), mInterface(mReflector) { auto emplace = [this](const char *libPath) { mComponents.emplace(libPath, libPath); }; // TODO: move this also into a .so so it can be updated emplace("libcodec2_soft_aacdec.so"); emplace("libcodec2_soft_aacenc.so"); emplace("libcodec2_soft_amrnbdec.so"); emplace("libcodec2_soft_amrnbenc.so"); emplace("libcodec2_soft_amrwbdec.so"); emplace("libcodec2_soft_amrwbenc.so");
📝 第四步:配置框架层 (Configure the Framework)
为了让 Android 的多媒体框架(如 MediaCodecList)知道你的新解码器,还需要在 XML 配置文件中声明它。
-
修改编解码器配置文件:
-
主要配置文件位于
frameworks/av/media/libstagefright/data/目录下,如media_codecs.xml-1-5。 -
对于软件解码器,通常会添加到
media_codecs_google_c2_video.xml或media_codecs_google_c2_audio.xml这类专门的文件中 -1-5。 -
声明内容 :你需要在 XML 文件中添加一个
<MediaCodec>标签,指定解码器的名称(与代码中注册的一致)、支持的 MIME 类型(如video/your-new-codec)、以及性能参数等 -1-3。
<MediaCodec name="c2.android.avc.decoder" type="video/avc" variant="slow-cpu,!slow-cpu"> <Alias name="OMX.google.h264.decoder" /> <Limit name="alignment" value="2x2" /> <Limit name="block-size" value="16x16" /> <Variant name="!slow-cpu"> <Limit name="size" min="2x2" max="4080x4080" /> <!-- profiles and levels: ProfileHigh : Level52 --> <Limit name="block-count" range="1-32768" /> <!-- max 4096x2048 equivalent --> <Limit name="blocks-per-second" range="1-1966080" /> <Limit name="bitrate" range="1-48000000" /> </Variant> <Variant name="slow-cpu"> <Limit name="size" min="2x2" max="2048x2048" /> <!-- profiles and levels: ProfileHigh : Level51 --> <Limit name="block-count" range="1-16384" /> <Limit name="blocks-per-second" range="1-491520" /> <Limit name="bitrate" range="1-40000000" /> </Variant> <Feature name="adaptive-playback" /> <Attribute name="software-codec" /> </MediaCodec> -
⚙️ 第五步:处理 Android 版本差异 (Handle Version Differences)
特别要注意的是,不同 Android 版本的 Codec 2 框架实现有差异,尤其是在 Android 15 上。
-
Android 14 及之前 :主要使用 HIDL (Hardware Interface Definition Language) 接口。HAL 服务通过
registerAsService()注册 -2。 -
Android 15 及之后 :HIDL 接口已被废弃,转向了 AIDL (Android Interface Definition Language) 接口 -5。
⚙️ 第六步:检查编解码器列表 :使用 dumpsys 命令查看当前系统识别的所有解码器
adb shell dumpsys media.player