liwen01 2023.08.13
前言
车载监控数据,包括车载摄像头的音视频数据,以及车辆的运行状态数据,其中车辆状态数据又包括车速、方向、经纬度,报警状态,车辆诊断信息等。
我们常见的运营车辆,比如公交,客运大巴,危险品运输车,它们车上的DVR与我们普通行车记录仪有比较大的区别,主要原因是它需要保存的数据量多,且需要保存的时间很长。本文介绍的就是该类应用场景的车辆监控数据存储方法。
(一)技术背景要求
车载DVR与普通行车记录仪先比较,在技术上存在下面几个难点:
- 数据量大:一般需要同时存储4/6/8路摄像头的音视频数据
- 存储时间长:一般需要本地数据保存3~6个月
- 结构空间小:设备的结构空间以及硬件接口限制,一台设备只能外接一个硬盘
- 状态存储:音视频数据需要与车辆状态数据同时同步存储
- 快速检索导出:设备需要支持快速检索导出任意时间段的数据
- 数据标记:可以设置某些报警数据锁定,覆盖的时候这些数据不会被删除
- 异常上下电:需要适应车辆可能会出现断电或是电源不稳的情况
(二)方案选型
(1)存储设备选型
我们常用的外部存储器有:TF卡,U盘,SD卡,固态硬盘,机械硬盘等。考虑到需要存储的数据量以及保存时长,这里只能选用硬盘。硬盘有两种,机械硬盘与固态硬盘,它们的优缺点如下:
类型 | 优点 | 缺点 |
---|---|---|
机械硬盘 | 容量大 价格便宜 适用于大型文件的顺序读写 |
速度较慢 功耗较高 发热较严重 容易受震动和撞击影响 |
固态硬盘 | 读写速度快 功耗低 抗震性强 |
成本高 存储容量较小 不适合频繁读写 |
如果公司是卖设备,会比较倾向于机械硬盘,因为价格便宜且容量大,在满足客户需求的同时,可以降低设备成本。
如果选用机械硬盘,需要解决的几个大问题是:
- 车辆震动问题
- 硬盘散热问题
- 硬盘磁盘碎片问题
震动和散热需要硬件和结构来解决,我们这里不做讨论,软件可以解决的是磁盘碎片问题。
(2)文件系统选型
常用于嵌入式设备的文件系统有:YAFFS
、JFFS2
、UBIFS
、ext2/3/4
、FAT32
,exFAT
,ROMFS
、NFS
。适用于硬盘使用的只有:ext2/3/4
、FAT32
,exFAT
。ext2/3/4
, 它是一种适用于Linux系统的日志文件系统,FAT32
与exFAT
是一个简单,轻量及的文件系统,同时,它支持包括Windows
、macOS
、Linux
等操作系统
在车载DVR设备上,有些时候需要将硬盘取出,接到电脑上位机上进行数据导出查看等操作,所以选用FAT32
会更加的合适些。另外因为FAT32
实现简单,可以添加很多自定义数据,所以这里我们选用FAT32
。
简单概括选用FAT32
文件系统的原因是:
-
可以同时支持
Windows
、macOS
、Linux
等操作系统,兼容性好 - 轻量级,实现简单,可以自己写代码实现
- 可以添加自定义数据
(三)传统存储方法介绍
(1)传统存储方案介绍
传统的存储方法是这样的:将每一个摄像头通道的音视频数据单独存储一个文件,比如把他们封装成AVI或是MP4视频格式。当存储到设定大小(比如128M),或者是设定时长(比如10分钟)的时候,停止该文件的写入,重新新建一个文件继续进行写入。
当整个磁盘空间写满之后,再去查找最开始写入的文件,将它删除,以释放存储空间来写入新的文件,从而实现循环存储的功能。于此同时,因为MP4或是AVI不能封装车辆状态数据,所以车辆状态数据只能与音视频数据分开,写到另外一个文件中去。
这种存储方法,针对使用机械硬盘的车载DVR设备而言,存在下面几个问题:
- 当多路摄像头同时存储时,音视频数据不连续,长期操作影响机械硬盘的使用寿命
- 当存储器写满之后,不断重复删除文件和创建文件,容易造成文件系统的损坏,对于机械硬盘还会产生硬盘碎片,降低硬盘性能。
- 音视频数据与车辆状态信息数据分开存储,音视频数据与车辆状态数据难以准确同步,不利于事故现场的还原。
- 音视频数据以音视频文件格式存储,只能以整个文件形式导出,不能够实现任意时间段数据的导出。
- 当需要多通道数据同时多画面显示时,各个通道的数据时间同步不准确,无法准确还原现场情况。
(2)磁盘碎片问题介绍
磁盘碎片主要是存在机械硬盘中的一种存储状态。指的是当文件被频繁创建、修改和删除时,可能导致文件的数据被分散存储在不同物理位置上,造成文件数据不连续,形成碎片化。
因为文件存储位置离散,磁盘碎片容易导致机械硬盘出现下面问题:
- 读写性能下降
- 磁盘空间浪费
- 文件访问延迟
上面问题是因为机械硬盘的工作原理产生的,机械硬盘是通过磁头读取旋转盘面的不同磁道上的信息进行数据读写操作。因为文件离散分布,磁头不能连续访问,只能不断跳转以访问不同盘面的不同磁道。
而固态硬盘上就不会存在这个问题,因为固态硬盘是采用闪存存储技术,它可以随机进行读写访问。在固态硬盘中需要考虑的问题就是磨损平衡以及擦写上限次数。
(四)新存储方案介绍
针对上面方案的不足,新方案需要解决的技术问题在于:
- 方案需要可任意时间段段任意长度的数据导出
- 需要车辆状态与车辆多通道音视频数据可准确同步
- 对于机械硬盘,不能产生磁盘碎片
- 需要文件访问效率高
实现步骤大致可以分为:
- 分区格式化
- 预创建文件
- 数据存储
- 数据修复
- 数据导出
(1)分区格式化
分区和格式化是两个不同的步骤。
分区是指将一个物理硬盘逻辑地址划分为多个逻辑区域的过程,每个区域可以被操作系统视为一个独立的逻辑磁盘。磁盘的分区表格式有两种,MBR
(Master Boot Record)和GPT
(GUID Partition Table)。
它们的区别如下:
MBR | GPT | |
---|---|---|
容量支持 | 最多支持2TB硬盘容量 | 支持极大的硬盘容量,最大可达数EB |
分区数量支持 | 最多4个主分区 | 最多可创建128个主分区 |
启动方式 | 使用MBR进行启动 | 在UEFI固件系统中常用作启动引导 |
数据结构 | 使用32位分区项记录信息 | 使用64位分区项和GUID进行标识 |
数据备份和恢复 | 分区表存储在硬盘的第一个扇区 损坏可能导致数据丢失 |
分区表备份存储在硬盘末尾和分区之间 可靠性更高 |
我们这里选用GPT分区格式会更加的合适
在Linux 系统中,可以使用fdisk
命令对磁盘进行分区,使用mkfs.fat
命令将分区格式化成FAT32文件系统。这里不建议直接使用系统命令进行分区格式化,而是根据GPT分区表及FAT表格式,在自己代码里面去实现分区和格式化的功能。
在代码中自己实现分区格式化功能有个好处就是,可以知道具体执行到哪一个步骤,如果有异常,可以更加准确的定位到问题。另外是可以在FAT表的空闲位置添加一些自己的标志信息。
具体操作流程为:
- 设备上电,读取硬盘分区格式化信息,如果不是我们自定义格式,将硬盘进行重新分区格式化操作
- 将磁盘分区为三个区:数据存储区,图片存储区,系统文件存储区
- 将新建的分区,使用自定义的格式化方法,将分区格式化成FAT32文件系统格式,同时将磁盘状态写入到FAT表的空闲位置上
这里将磁盘分为多个分区,主要是避免某个分区损坏导致整个磁盘异常从而导致全部数据丢失
(2)预创建文件
预创建文件,是指在磁盘分区格式化之后,把磁盘的剩余空间都预分配好数据文件和索引文件。
预创建的目的是为了避免文件的重新创建和删除,只需要再格式完之后创建一次,后续不再创建文件,只修改文件里面的数据内容。
每一个分区,预创建两个索引表,P1和P2,P1作为正常使用,P2作为备份使用。当P1损坏的时候,可以从P2中进行数据恢复。
剩下的空间用于创建媒体文件,比如可以创建128M大小的文件用于存储音视频文件,1M大小的文件用于图片分区存储图片数据。
(3)数据存储
上面我们有预创建索引文件,在写入数据之前,我们需要根据索引里面的内容建立一个时间链表。通过该链表,我们可以知道上一次写入的时间和数据信息,以及可以知道下一个数据需要写入的位置。
我们写入的数据,是以一个通道的一个视频GOP为单位进行数据封装。也就是两个I帧的间隔为单位进行数据封装。
比如I帧间隔为30帧,那么我们就将该视频通道的这30帧图像数据,以及该时间段的音频数据和车辆状态数据,统一封装到一个数据包里。
数据封装好后,通过时间链表获取数据包可以写入的位置,将数据包的数据写入到对应的文件位置,然后再更新索引信息。
同一个时间,只允许一个通道进行数据写入,多个通道的应用场景,使用先到先存原则。
(4)数据修复
这里说的数据恢复,是指设备突然断电的情况下,没能完整地进行数据存储的数据进行修复。断电出现数据储存不完整,主要原因是设备端数据缓存未能及时刷新,还有一个就是硬盘本身的数据有缓存,未能及时写入到磁盘中去。
具体实现方式是:系统上电,读取索引文件建立时间链表的时候,去检查最后写入文件的最后位置,看下一个数据包与最后写入数据的时间戳,如果下一个数据包的时间戳比最后一个数据包的还要晚,表示有数据已经写入到了磁盘,但是还未同步索引表信息。
这个时候可以通过读取下下一个数据包的包头,提取出所以表中需要的内容,更新到索引表中去。
(5)数据导出
数据导出的主要应用场景有:
- 实时查看回放数据
- 远程导出视频文件
- 本地数据导出
实时查看回放视频的时候,一般是通过RTP协议将视频流数据直接推动到流媒体服务器,这里传输的是压缩的视频流,比如H.264/H.265,因为我们是以视频流直接打包存储的,所以这里不需要解封装,可以直接进行传输。
远程导出视频文件的时候,一般是需要导出为视频文件,比如AVI或是MP4文件。这里是需要将音视频数据从磁盘读取出来,然后再封装成MP4格式,最后通过FTP协议传输到文件服务器上。因为导出的数据还需要进行再次封装,所以需要将导出的数据进行缓存,如果内存够的话,可以直接在内存中操作,如果内存不够,可以将数据缓存到磁盘的系统分区去,牺牲速度换区内存空间。
本地导出与远程导出类似,只是不需要将导出的文件传输给平台。可以直接将封装好的视频文件导出到其它外部存储器上,比如U盘,TF卡,SD卡等。
结尾
因为使用了文件预分配方法,可以很好地解决磁盘碎片的问题,因为使用连续存储方法,可以保持最优的磁盘读写效率。它可以较好地解决在嵌入式系统中使用机械硬盘会遇到的问题,特别是需要进行大数据读写的系统。
欢迎关注公众号:liwen01
聊聊嵌入式的点滴