SDI(Sensor Data Interface)
SDI 控制图像的输出,用来支持ISP子系统。ISP支持不同的接口:
输入:mipi-csi2,viu,ethernet,FastDMA
处理:scalar/vector IPU,H264 decoder,jpeg decoder,vision Sequencer
输出:H264 encoder,ethernet,FDMA
由图,可以看出,SDI仅仅是在app下层。算是属于比较上层的东西了。
主要的工作是三个方面:
硬件资源的分配(ISP engine,SRAM/DDR )
数据预处理通道配置
frame capture 控制
---------------------------------------------------------------------------------------------------------------------------------------------------
类:
sdi_graph
NXP开发了一套S32V DS,可以用来开发graph。至于graph的详细使用,请看我之前的博文
https://blog.csdn.net/qq_24687591/article/details/90377599
DS编辑的graph可以生成.c,主要包括 gpGraph,gGraphMetadata。
sdi_graph调用Finalize()初始化 SRAM buffers,调用Download() 下载graph 到sequencer的memory,SEQ_GraphDownload--->
SEQ_DRV_GraphDownload
int32_t SEQ_DRV_GraphDownload(SEQ_GraphPackage_t *apGraph)
{
int32_t lRet = SEQ_DRV_SUCCESS;
SEQ_GraphPackage_t lGraph;
if (copy_from_user( &lGraph,
apGraph,
sizeof(SEQ_GraphPackage_t)) != 0)
{
VDB_LOG_ERROR("Copy from user failed.\n");
lRet = -EIO;
} // if copy from user failed
sdi_io
主要的方法:
Reverse():初始化硬件驱动程序
Release(): 清除硬件驱动程序
Setup():将指定的配置应用于初始化好的硬件模块
Start():启动摄像头或者是CSI接口
Stop():停止摄像头或者是CSI接口
继承了sdi_io的类:
sdi_FdmaIO
配置FDAM模块和DDR buffers的处理,FDAM主要是将数据从SRAM搬到DDR。每个graph最多可以有16个FDMA通道。
sdi_H264EncIO
sdi_JpegDecIO
sdi_MipiCsiIO
sdi_ViuIO
此外,还有两个有用的结构体:
SDI_Frame
struct SDI_Frame
{
vsdk::UMat mUMat; ///< image container
friend sdi_grabber;
uint32_t mFrmSeqNum; ///< frame sequence number
private:
uint32_t mChannelIdx; ///< index of related FDMA channel
uint32_t mBufferIdx; ///< index of the buffer in the buffer array for particular channel
}; // SDI_DdrBufList
SDI_DdrBufferArr
struct SDI_DdrBufferArr
{
uint32_t mFdmaTcIdx; ///< index of FDMA TC
uint32_t mCnt; ///< number buffers in the array
vsdk::UMat *mpUmat;
bool mDeallocate; ///< true if to be deallocated automatically
friend sdi_FdmaIO;
public:
SDI_ImageDescriptor mDesc; ///< buffer image descriptor
...
}
sdi_process
提供了sdi_graph类的api。目前和sdi_graph的类基本一致,这个类是为了以后预留可以管理多个graph的接口。
sdi_grabber
基本上包含了以上类的所有封装,一个通用的流程:
1-3在 LibsPrepare函数里
1.创建一个sdi_grabber实例:
arContext.mpGrabber = new(sdi_grabber);
sdi::Initialize(0);
2.graph的处理
arContext.mpGrabber->ProcessSet(gpGraph, &gGraphMetadata)
3.get IOs
arContext.mpFdma = (sdi_FdmaIO*)arContext.mpGrabber->IoGet(SEQ_OTHRIX_FDMA);
4.内存的分配 DdrBuffersPrepare函数里
arContext.mpFdma->DdrBufferDescSet(FDMA_IX_FastDMA_Out, lFrmDesc)
arContext.mpFdma->DdrBuffersAlloc(DDR_BUFFER_CNT)
5.prestart grabber 初始化硬件资源
arContext.mpGrabber->PreStart()
SEQ_Reserve
IOsReserve
mProcess.Finalize()
IOsSetup()
mProcess.Download()
SEQ_Reset()
SEQ_Boot()
6.有些摄像头还需要配置camera参数
CamConfig();
7. start grabbing 初始化ISP pipeline
arContext.mpGrabber->Start()
SEQ_GraphStart
IOsStart
8.在死循环里pop & push
for(;;)
{
for (int i = 0;i < 4;i++)
{
lpFrame[i] = arContext.mpGrabber->FramePop(i);
}
for (int i = 0;i < 4;i++)
{
arContext.mpGrabber->FramePush(lpFrame[i]);
}
}
9.程序结束的时候释放资源
arContext.mpGrabber->Stop()
arContext.mpGrabber->Release()
sdi::Close(0)