在BPB块中,有两个比较重要的字段,每簇扇区数m和每FAT扇区数n,偏移位置分别为0x0D和0x16。这两个字段由CF卡的容量所决定的。本文中的CF卡容量为2G,m为128,n为128。
(2)初始化FAT表和FAT2表。FAT表的起始标识符是0xFFF8,在格式化后,其对应各个簇号的有效内容都为0,FAT2表作相同的处理。
(3)初始化根目录表。只需全部写入0。
初始化成功后,返回值为0,否则为-1。
FAT_getfileinfo函数用于获取文件的目录项,参数是文件名和指向目录项的指针。执行此函数,第二个参数pfdt指向的结构体存放文件对应的目录项。若文件名存在,函数返回目录项在根目录表的索引位置,若不存在或已删除,返回-1。
FAT_creat函数用于创建新文件,参数是文件名。首先调用FAT_getfileinfo函数,如果返回值不为-1,报错返回0;申请目录项空间,如果查找的范围超出了根目录表,报错返回;申请成功后,对新建目录项进行初始化。
FAT_read函数用于读取CF卡中的视频文件,参数为文件名。读取文件时系统的有效线程有CF卡读线程、解码线程、显示线程。所以利用SCOM进行线程间通信时,不需要考虑CF卡的读线程的上游线程同步,向压缩编码线程发送NULL消息即可。
视频数据在线程之间的传递是以帧为单位的,所以在进行读文件时也是按帧读取。而在FAT文件系统中,文件在数据区的存储又是按簇进行的,所以需要对视频数据的存储情况进行考虑。
经过压缩的图像帧包括帧头信息和帧数据。帧头信息包括帧大小和对应的时间信息,占用一个扇区。图像帧的存储有图2所示几种情况。
图2(a)表示帧在簇内存储;图2(b)表示帧在簇内,但是帧尾也是簇尾;图2(c)表示帧跨簇存储,只有部分帧数据在下一簇;图2(d)表示图像帧跨簇存储且只有帧头在本簇。对这三种情况,要做不同的处理。
FAT_read函数的具体操作步骤如下:
(1)调用FAT_getfileinfo函数判断文件是否存在,并获取文件的目录项信息。
(2)读取FAT表,并通过FAT表和目录项中的起始簇号计算文件在数据区的偏移位置。
(3)用剩余文件长度作为循环条件重复执行以下操作。
读取帧头信息,确定帧数据占的扇区数,并通过本簇已读扇区判断帧存储情况。参照图2,若是情况(a),则在读帧头和帧数据时都不需要更新;若是情况(b),则在读完此帧数据后更新簇号;若是情况(c),则在读帧数据时更新簇号;如果是情况(d),则在读取帧头后就立即更新簇号。保存帧头的时间和长度信息,和帧数据信息利用SCOM通信一并发送至解码线程。语句如下,
MsgWork.bufChannel=FRAME_BUF;//对SCOM消息赋值
SCOM_putMsg(fromWorktoEnc,NULL);//向上游线程发送同步信息
SCOM putMsg(fromWorktoDec,&MsgWork);//向下游线程发送SCOM消息
SCOM_getMsg(fromDectoWork,SYS_FOREVER);//等待接受下游线程同步消息
FAT_write为写文件函数,参数为文件名和写命令。写命令为TRUE时,实现文件拼接,为FALSE时,实现文件覆盖。写文件时,系统中的线程全为有效线程,所以在线程通信和同步时需要同时考虑上下游线程。