av_cp(协处理器侧AV)

简介

在嵌入式IoT领域,编解码等功能主频需求较大,单核嵌入式硬件平台已经难以满足复杂的计算需求。而异构多核处理器在音视频编解码运算上具有强大的优势。所以需要将这部分功能置于其他核或带有DSP功能的核上运行。

av_cp是一个轻量级的多核异构核间多媒体AV库,用于协处理器侧(此处称为DSP侧)的固件开发。其与AV组件中的核间处理接口(运行在应用程序处理器侧,此处称为主控侧)配合使用,如核间解码。该库屏蔽了底层核间通信(IPC)的细节,开发人员可直接基于该库使用芯片的多核异构解码、重采样、fft等运算能力。这样可以有效提高音视频播放等功能的实时性、降低产品成本、充分利用硬件资源。

该组件的使用是硬件相关的,当前仅支持pangu芯片。对于其他多核芯片,用户可基于此扩展实现。

核间处理机制

系统上电后,可通过bootloader或在主控侧应用程序初始时先加载DSP固件到指定位置运行。DSP固件启动后,即通过核间通信机制开启监听服务,如核间解码服务。当主控侧调用核间封装的解码器接口时,底层会通过核间通信机制向DSP侧发起核间解码请求。DSP侧核间解码服务接收到该核间请求后,如果资源满足则正确响应该请求,否则返回失败。

核间解码器

核间解码器内部通信机制设计

服务ID

主控侧向DSP侧发起核间解码请求时,需要携带内部定义的核间解码服务ID才能找到DSP侧对应的服务。该服务ID定义如下:

#define AD_ICORE_IPC_SERIVCE_ID 0x10

注意事项:

DSP侧的IPC服务ID不能冲突,否则核间通信创建失败

命令字及内部核间通信消息

解码器通常的操作有打开、解码、重置、关闭等。主控侧在发起核间解码请求时,需要在核间通信消息中携带相应的命令字。命令字定义如下:

enum {                                                                                   
    ICORE_CMD_AD_INVALID,                                                                 
    ICORE_CMD_AD_OPEN,                                                                  
    ICORE_CMD_AD_DECODE,                                                                 
    ICORE_CMD_AD_RESET,                                                                   
    ICORE_CMD_AD_CLOSE,                                                                   
};
打开解码器
ad_icore_t* ad_icore_open(avcodec_id_t id, const adi_conf_t *adi_cnf);

此函数为ICORE_CMD_AD_OPEN对应的内部处理函数。打开解码器内部核间通信消息具体定义如下:

typedef struct {
    avcodec_id_t  id;           ///< 解码器类型
    adi_conf_t    adi_cnf;      ///< 解码器配置信息,某些解码器可能需要

    void          *ad;          ///< DSP侧内部打开的解码器句柄
    sf_t          sf;           ///< 打开解码器后的音频采样格式(可能与解复用出来的格式不一致)
} ad_icore_open_t;

返回值:

调用成功时返回0,否则返回-1。

解码器解码
int ad_icore_decode(ad_icore_t *hdl, avframe_t *frame, int *got_frame, const avpacket_t *pkt);

此函数为ICORE_CMD_AD_DECODE对应的内部处理函数。内部核间通信消息具体定义如下:

typedef struct {
    void              *ad;      ///< DSP侧内部打开的解码器句柄
    uint8_t           *es_data; ///< 音频编码帧
    int32_t           es_len;   ///< 音频编码帧大小
    avframe_t         frame;    ///< 音频解码后的pcm
    int               got_frame;///< 本次是否解码一帧标志
} ad_icore_decode_t;

返回值:

调用失败时,返回-1,大于0表示解码一帧消耗的原始编码帧字节数

重置解码器
int ad_icore_reset(ad_icore_t *hdl);

此函数为ICORE_CMD_AD_RESET对应的内部处理函数。内部核间通信消息具体定义如下:

typedef struct {
    void          *ad;          ///< DSP侧内部打开的解码器句柄
} ad_icore_reset_t;

返回值:

调用成功时返回0,否则返回-1。

关闭解码器
int ad_icore_close(ad_icore_t *hdl);

此函数为ICORE_CMD_AD_CLOSE对应的内部处理函数。内部核间通信消息具体定义如下:

typedef struct {
    void          *ad;          ///< DSP侧内部打开的解码器句柄
} ad_icore_close_t;

返回值:

调用成功时返回0,否则返回-1。

DSP侧核间解码器接口及使用

核间解码器初始化

int ad_icore_cp_init();

初始化DSP侧核间解码器模块(一次即可)。该接口成功调用后,DSP侧便成功通过核间通信机制开启监听。主控侧的核间解码功能需要搭配此接口使用。

返回值:

调用成功时返回0,否则返回-1

核间解码器使用

开发者可基于solution/pangu_804demo开发DSP固件。默认demo中提供pangu芯片的mp3核间解码。

用户可修改解决方案下package.yaml中的CONFIG_DECODER_XXX等配置项。如solutions/pangu_804demo/package.yaml中,以下配置项默认可将mp3解码器(pvmp3)注册进去

  CONFIG_DECODER_PCM: 1
  CONFIG_DECODER_PVMP3: 1
  CONFIG_DECODER_FLAC: 0
  CONFIG_DECODER_FDK: 0
  CONFIG_DECODER_ADPCM_MS: 0
  CONFIG_DECODER_AMRNB: 0
  CONFIG_DECODER_AMRWB: 0
  CONFIG_DECODER_IPC: 0

注意事项:

  • 解决方案下package.yaml中的CONFIG_DECODER_IPC配置项不能开启。此选项仅用于主控侧
  • 若核间解码支持了mp3,则没有必要在主控侧也注册mp3解码支持。否则会根据对应解码注册的先后顺序使用
  • 因对于pangu芯片,DSP侧(cpu1)中链接文件gcc_eflash.ld.S中配置的内存仅1M。若需要加入多个核间解码支持时,需要分配好每个核的内存使用。以防止内存不足导致核间解码异常。
  • 编译好的DSP固件存放在generated/data/prim。对于盘古芯片,可将此固件重命名为cpu1。并和主控侧程序一起打包生成对应镜像文件。

results matching ""

    No results matching ""