如何在codec2中添加新的component组件

💻 第一步:实现解码组件 (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) - 添加到平台商店

    • 这是最简单的方式,适用于纯软件实现的解码器。

    • 修改平台商店 :Android 有一个默认的平台组件商店,其实现在 C2PlatformComponentStore(文件路径:frameworks/av/media/codec2/vndk/C2Store.cpp)。你需要在这个商店的构造函数 C2PlatformComponentStore() 中,手动添加你的组件工厂 -1-3

    • 注册入口 :你的组件通常会被编译成一个独立的 .so 库,平台商店会通过 getComponentFactory() 等方式来获取你的工厂实例 -3

  • 方式 B:硬件解码器 (Hardware/HAL Codec) - 创建独立服务

    • 如果你的解码器依赖特定硬件(通过 V4L2 或其他私有接口),你需要创建一个独立的 HAL 服务 -3-9

    • 实现服务 :你需要创建一个可执行程序(通常位于 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.xmlmedia_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

    • 必须启用 AIDL HAL :在设备的 device.mk 或其他产品配置 mk 文件中,需要显式设置属性 media.c2.hal.selection=aidl 来启用 AIDL 版本的 Codec 2 HAL -5

    • 如果继续使用 HIDL 服务,你的新解码器可能无法在 Android 15 上被检测到 -5

⚙️ 第六步:检查编解码器列表 :使用 dumpsys 命令查看当前系统识别的所有解码器

复制代码
adb shell dumpsys media.player
相关推荐
Everbrilliant895 个月前
音视频编解码全流程之用Extractor后Decodec
ffmpeg·视频编解码·mediacodec·音视频解码·ffmpeg编解码·decodec·ndkmediacodec
Everbrilliant895 个月前
Android音视频编解码全流程之Extractor
mediacodec·媒体文件提取器·android编解码·ffmpeg编解码·ffmpeg媒体文件提取·extractor·android硬件编解码
如果可以0031 年前
Android Camera系列(八):MediaCodec视频编码下-OpenGL ES离屏渲染
android·音视频·mediacodec·opengl es
青山渺渺1 年前
Android CCodec Codec2 (十九)C2LinearBlock
android·音视频·codec2·ccodec
青山渺渺1 年前
Android CCodec Codec2 (五)C2Param - Ⅲ
android·音视频·多媒体·codec2·openmax·ccodec
图王大胜2 年前
Android APP 音视频(01)MediaCodec解码H264码流
android·音视频·解码·mediacodec·h264解码
醉饮千觞不知愁2 年前
记录一次Android推流、录像踩坑过程
android·音视频·mediacodec
芥末的无奈2 年前
Android MediaCodec 简明教程(五):使用 MediaCodec 编码 ByteBuffer 数据,并保存为 MP4 文件
android·音视频·mediacodec
wxx21502 年前
编解码异常分析
h264·mediacodec·编解码