最近的公司一直使用SigmaStar的芯片做项目.看了SigmaStar几个芯片的文档,提供的编程接口都是基于C语言的.
C语言接口不是说不好,至少API符号稳定.但是对于上层开发应用来说,效率比较低.
举几个例子来说,SigmaStar提供的编码器,是一个硬件的,一个硬件分出最多16个channel,分时复用进行多个编码工作.
这个功能对于硬件复用来说,是基本操作了.
给出的编程API,也是简单明瞭.
//1. 打开设备
MI_S32 MI_VENC_CreateDev(MI_VENC_DEV VeDev, MI_VENC_InitParam_t *pstInitParam);
//2. 创建一个channel用于编码.
MI_S32 MI_VENC_CreateChn(MI_VENC_DEV VeDev, MI_VENC_CHN VeChn, MI_VENC_ChnAttr_t *pstAttr);
//3. 开始接收图像数据,进行编码.
MI_S32 MI_VENC_StartRecvPic(MI_VENC_DEV VeDev, MI_VENC_CHN VeChn);
//4. 开始工作
//5. 停止接收数据
MI_S32 MI_VENC_StopRecvPic(MI_VENC_DEV VeDev, MI_VENC_CHN VeChn);
//6. 释放channel.
MI_S32 MI_VENC_DestroyChn(MI_VENC_DEV VeDev, MI_VENC_CHN VeChn);
//7. 关闭设备.
MI_S32 MI_VENC_DestroyDev(MI_VENC_DEV VeDev);
但是,越简单就说明使用起来就越复杂.
为什么API显得简单,因为他实现的功能比较少,其他的工作就要由上层应用来补全.
举几个例子:
有的芯片,为了提升编码能力,集成了二个硬件编码设备,此时,上层需要管理的资源又增加了一个(dev_id).
说了这么多,不能否认基于C语言的API的简洁. 但是要提升上层应用开发的效率,不能只依靠C语言. C语言只能保证运行效率,但是人力的效率是不高的.
针对上面的API,其实缺少了很多东西,而这些东西,是可以固化下来的.
如果只使用SigmaStar提供的这几个API,则每个项目,都需要进行重复的工作. 比如资源的分配.
channel用于分时复用,方式没有错,但是对于上层应用来说,我不用关注哪个channel号用于哪个功能.我只是需要一个编码器而已,channel号为0, 还是为10, 对我都不是重点.
因此,这里要增加一个channel自动管理功能.
同样,dev_id,也不是上层需要关注的重点.因此,这里可以提供一个动态均衡模块,让程序根据二个硬件编码器的忙闲水平,动态选择新创建的channel应该在哪个硬件上分配.
对于第7点,什么时机调用关闭设备API.程序里必须要增加一个计数器,统计当前打开了多少个channel, 如果所有的channel都关闭了,就可以调用关闭设备函数,通过使用一个监控函数,在计数变为0时,主动调用关闭函数.
在C++里,智能指针天生就是有计数功能,因此,使用C++的智能指针时,这个功能在标准库里就已经提供,不用自己开发.
提供的伪代码如下:
class venc_dev
{
public:
std::shared_ptr<venc_dev> get_instance(int dev_id); //取单例.
protected:
venc_dev(int dev_id);
}
class venc_chn
{
public:
venc_chn(); //根据动态均衡算法,自动选择venc_dev,并且自动分配一个空闲的channel_id.
~venc_chn(); //释放时,m_dev计数会减1,减到最后,venc_dev会自动释放.
protected:
std::shared_ptr<venc_dev> m_dev;
int m_channel_id;
}
通过这样的改进后, 这里的资源管理都不用上层参与.
这一部分补足了芯片厂的SDK的不足,但是又不会影响上层使用的灵活性.
这一部分应该算什么呢? 没有这一部分,不影响项目的开发.但是有了这一部分,上层开发的效率有大的提升. 我们就姑且称之为”框架”吧.
框架的主要目的,就是把一些繁琐的工作,转化为一种通用的模块,让上层应用从具体的实现细节里抽身出来,从而有更多的精力关注业务细节.
该框架开发了几个项目后,发现能做的事情并不仅仅限于SigmaStar平台.因为里面还提供了各种模块贴合剂功能,这些功能换个平台也是需要的.
另外,工作上需要做一些网络协议的开发,做流媒体APM.这些工作都需要在PC端的开发.
做网络协议开发,需要做一个网络接收模块,把接收到的流媒体回显到屏幕.
这个可以使用ffmpeg来实现.
做APM,需要在接收到数据,视频解码前,做一些插桩. 这里再在ffmpeg里做,就有点不太合适了.
在”网络协议”这个需求里,可以编写一个插件,放到ffmpeg里. 借助开源项目加速.
但是在”APM”需求里,如果还把实现与ffmpeg混在一起,具体的实现与第三方代码强耦合,不利于开发成果的总结.
因此, 不如二个需求,都基于自己的框架来实现??
也正是因为如此,我把跨平台实现提到了最高日程上了.
另外有一个潜在的需求,SigmaStar只是一个平台,我开发的是一个框架,框架不应该强绑定于一个平台,而应该适配于不同的平台, 对不同的平台,提供同样的抽象能力.
在实现这个框架的过程中,我一直在问自己,在嵌入式系统里,需要一个框架吗?需要吗?
站在芯片商的角度,他应该提供的是稳定的API,通用的API. 要稳定,就是要尽量精简; 要通用,就只能用C语言来提供API.
但是站在终端开发者的角度来看,使用这些阳春版的API开发,确实是事倍功半.
有很多在行业内比较成熟的类库,比如STL,确实可以极快加速应用的开发,
使用标准库,不仅仅提升了开发的效率,而且因为这些库是经过多方验证的,比自己手搓的方案稳定多了.
从某种意义上来说,这个框架也不是什么解决大问题的框架,而只是把一些通用的功能提取成库.在没有这个框架前,这些dev/channel的管理,也是要做的,只不过是管理的策略,没有形成一套统一的方案,这导致每个项目,都要根据不同的需求变化,实现一套管理.而这套管理方案,无法做到复用,每次都要过一次细节.
框架做的,只是把这些事情通用化了.后面的项目再不需要再重复扫描这些实现.
本来想把整个sigmastar文档里所写的模块,都包含到框架里的.
但是,因为部分涉及到公司的核心功能,而没有包含在框架内.比如,IPU模块,涉及到算法,而现在算法已经成为公司的重要部分,对其他人保密,不是所有人都可以访问,因此,这部分只好作罢.
另有其他部分,也因为同样的原因作罢.
这里不得不引申出另外一个问题:开源,是否适用于所有场景.
比如NVIDIA,被Linus竖中指.
在一个商业环境里,可能并不是所有东西都给别人看的.大公无私,有时候可能会显得很蠢.
后面看看有什么可以建私有库的功能,我也建一个私有库,只有我自己一个人维护好了.