视频监控安防平台-自定义文件格式MFS存储

2024-01-22 02:38

本文主要是介绍视频监控安防平台-自定义文件格式MFS存储,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

            视频监控安防平台-自定义文件格式MFS存储

首先在视频监控领域存储是最重要的,为什么怎么说呢,都是监控是用来事后处理事物的,所以说存储是多么重要的,要想有一个比较稳定的存储,必须要好好规划,我尝试过自定义avi格式存储和mp4格式存储,如果用在简单的项目上还好没什么问题,但是如果在大型项目上面(比如1000路高清摄像头的存储),那么问题就会慢慢暴露出来,最常见的问题就是写入磁盘的时候会卡个几秒几分钟,在项目上可想而知这就意味着丢几秒几分钟视频,后果是相对严重的,由于遇到这样的问题iostat、iotop这些监控磁盘信息的数据都显示压力大写不进去,这也是给我了重新设计自己的存储格式,首先存储格式必须简单而且易用,自己设计还有好处就是可以任意实现自己的想要的功能,比如单帧播放、单帧倒放、倒放、同步回放等很多项目都必须要的功能。下面简单说说自己的设计思路,首先自己构思存储的结构图:


存储文件格式思想大概是预留1M来存储每个I帧P帧等信息,最后预留1M来预防最后一个I帧无法全部写入,详细看结构图,应该比较易懂。
设计结构搞完了,就开始正式写代码了,下面粘贴一下代码:
公共头文件mfs.h

#ifndef LIB_MFS_H__
#define LIB_MFS_H__#include <vector>
#include "Log.h"#define MFS8K           (8<<10)//8192
#define MFS16K          (16<<10)//16384
#define MFS24K          (24<<10)//24576
#define MFS32K          (32<<10)//32768
#define MFS64K          (64<<10)//65536
#define MFS128K         (128<<10)//131072
#define MFS256K         (256<<10)//262144
#define MFS257K         (257<<10)//263168
#define MFS512K         (512<<10)//524288
#define MFS820K         (820<<10)//524288#define MFS1M           (1<<20)
#define MFS2M           (2<<20)
#define MFS16M          (16<<20)//16777216
#define MFS32M          (32<<20)//33554432
#define MFS64M          (64<<20)//33554432
#define MFS128M         (128<<20)//134217728#define FILESIZE_HEADINFO (4<<10)//4096
#define FILESIZE_HEAD     (1<<20)
#define FILESIZE_RESERVE  (1<<20)#define DEFAULT_DATA_CACHE   MFS2M               //默认数据缓存大小
#define DEFAULT_FILE_SIZE    MFS32M              //默认文件大小#define MFS_HEAD_VERSION "MFS VERSION=1.0"   //文件头固定格式
#define MFS_START_CODE   "MFS"               //I帧索引,数据索引固定头//编码格式
typedef enum
{ENCODER_TYPE_NONE = 0,ENCODER_TYPE_MPEG2 = 1,ENCODER_TYPE_MPEG4 = 2,ENCODER_TYPE_H264 = 3,ENCODER_TYPE_H265 = 4
}ENCODER_TYPE_E;//数据类型
typedef enum
{DATA_TYPE_NONE = 0,DATA_TYPE_I = 1,DATA_TYPE_P = 2,DATA_TYPE_B = 3,DATA_TYPE_A = 4,DATA_TYPE_EVENT = 5,DATA_TYPE_SUNTILE = 6
}DATA_TYPE_E;//文件头结构体
struct MFS_FILE_HEAD{char version[24]; 			     //用于文件合法性检测 版本号, "MFS VERSION=1.0"unsigned int flag;			     //文件的标示符  0:空闲; 1:使用中; 3:不可用unsigned int time_start;	     //文件的开始时间unsigned int time_end;		     //文件的结束时间unsigned int index_size; 	     //文件头长度,从4k头之后,开始算长度unsigned int idx_amount; 	     //包含的I帧索引项总数unsigned int data_size; 	     //数据区总厂unsigned int framerate;		     //帧率unsigned char sps_pps[256];	     //文件sps_pps的内容unsigned int sps_pps_len;	     //文件sps_pps的长度unsigned int manuf;		         //厂家类型,用于私有码流
} __attribute__((packed, aligned(1)));//I帧索引  //固定大小 数组, 20字节
struct MFS_I_FRAME_INDEX{unsigned char segment_normal[3];  //固定标志 "MFS"unsigned char encoder_type;	      //I帧的编码格式 1:MEPG-2; 2:MEPG-4; 3:H264 ;4:H265unsigned int idx_offset;	      //I帧在文件中的偏移量, 从数据区开始算unsigned int i_data_size;	      //I帧长度,不包含数据头long long time_stamp;	          //I帧的时间戳 毫秒
} __attribute__((packed, aligned(1)));//数据索引,数据类型包括:I帧、P帧、B帧、事件信息,字符等, 16字节
struct MFS_DATA_INDEX{unsigned char segment_normal[3];   //固定标志 "MFS"unsigned char data_type;	       //数据类型  1:I帧 ;2:P帧; 3:B帧; 4:音频; 5:事件帧; 6:字幕帧unsigned int data_size;	           //数据长度,从MFS_DATA_INDEX 头之后开始算long long time_stamp;	           //数据的时间戳 毫秒
} __attribute__((packed, aligned(1)));
//-----------------------------------------------------------------------------------------------------------------#endif

应用实例demo:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>#include "mfs_write.h"
#include "mfs_read.h"unsigned char dig[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9','a', 'b', 'c', 'd', 'e', 'f'};//dd if=/dev/zero of=testfile1.mfs bs=32M count=1unsigned char testbuffer_I[32] = {"123456789012345678901234567890\0"};
unsigned char testbuffer_D[16] = {"ABCDEFGHIJKLMN\0"};
unsigned char testbuffer_P[8] = {"!@#$%^\0"};int main(int argc, char *argv[])
{char filename[128] = {"testfile1.mfs"};if (argc >= 2){sprintf(filename, "%s", argv[1]);}printf("filename is %s\n\n", filename);memset(testbuffer_I, 'I', sizeof(testbuffer_I));memset(testbuffer_D, 'D', sizeof(testbuffer_D));memset(testbuffer_P, 'P', sizeof(testbuffer_P));#if 0CMfsWrite mfs_write;mfs_write.mfs_init();mfs_write.mfs_open(filename);int times = 0;while(times++ < 10){printf("\nwritefile times:%d\n", times);testbuffer_I[0] = (unsigned char)dig[times];testbuffer_D[0] = (unsigned char)dig[times];testbuffer_P[0] = (unsigned char)dig[times];mfs_write.mfs_put(testbuffer_P, sizeof(testbuffer_P), DATA_TYPE_P);mfs_write.mfs_put(testbuffer_P, sizeof(testbuffer_P), DATA_TYPE_P);mfs_write.mfs_put(testbuffer_I, sizeof(testbuffer_I), DATA_TYPE_I);usleep(100*1000);mfs_write.mfs_put(testbuffer_D, sizeof(testbuffer_D), DATA_TYPE_EVENT);usleep(100*1000);for (int i = 0; i<3; i++){mfs_write.mfs_put(testbuffer_P, sizeof(testbuffer_P), DATA_TYPE_P);usleep(100*1000);}if (times%3==0)mfs_write.mfs_write(true);//usleep(10*1000);}mfs_write.mfs_write(true);mfs_write.mfs_close();printf("\n\n-----------------------------------------------------------------------------------------------------\n\n");
#endif//CMfsRead mfs_read;mfs_read.mfs_init();mfs_read.mfs_open(filename);struct MFS_READ readdata;int nRet = 0;mfs_read.head_print_test(true);//mfs_read.mfs_location(2);MFS_READ_TYPE_E readtype = MFS_READ_TYPE_GOP;bool bBack = false;FILE *fp = NULL;if (argv[2] != NULL){char writefilename[64] = {0};sprintf(writefilename, "./%s", argv[2]);fp = fopen(writefilename, "w+");printf("open write filename :%s result:%s!\n\n", writefilename, (fp == NULL)?"fail":"sucess");}
#if 1while(1){nRet = mfs_read.mfs_read(readtype, readdata, bBack);if (nRet < 0){break;}int plen = 0;printf("\nmfs_read_frame eDecoderType:%d, vmfsbuf.size:%d\n", (int)readdata.eDecoderType, (int)readdata.vmfsbuf.size());if (readdata.vmfsbuf.size() > 0){printf("Data eDataType(%d) bKeyFrame(%d) nPts(%lld) len:%d\n", (int)readdata.vmfsbuf[0].eDataType, readdata.vmfsbuf[0].bKeyFrame, readdata.vmfsbuf[0].nPts, readdata.vmfsbuf[0].nLen);plen = readdata.vmfsbuf[0].nLen > 10 ? 10 : readdata.vmfsbuf[0].nLen;for (int i = 0; i< plen; ++i ){printf("0x%c ", readdata.vmfsbuf[0].pData[i]);}printf("\n\n");	if (fp != NULL){for (unsigned int j=0; j<readdata.vmfsbuf.size(); j++){fwrite(readdata.vmfsbuf[j].pData, sizeof(char), readdata.vmfsbuf[j].nLen, fp);}}}		readdata.vmfsbuf.clear();usleep(10*1000);}if (fp != NULL){fclose(fp);fp = NULL;}
#elsenRet = mfs_read.mfs_read_time(1, readdata);printf("mfs_read_time Data Sn(%d) PayLoadType(%d) Manuf(%d) eDecoderType:%d\n", readdata.Sn, readdata.PayLoadType, readdata.Manuf, (int)readdata.eDecoderType);int plen = 0;for (unsigned int k = 0; k < readdata.vmfsbuf.size(); ++k){printf("Data eDataType(%d) bKeyFrame(%d) nPts(%lld) len:%d\n", (int)readdata.vmfsbuf[k].eDataType, readdata.vmfsbuf[k].bKeyFrame, readdata.vmfsbuf[k].nPts, readdata.vmfsbuf[k].nLen);plen = readdata.vmfsbuf[k].nLen > 10 ? 10 : readdata.vmfsbuf[k].nLen;for (int i = 0; i< plen; ++i )printf("0x%02x ", readdata.vmfsbuf[k].pData[i]);printf("\n");}#endifmfs_read.mfs_close();return 0;
}
目前项目上在大量使用这样的存储格式文件,还比较稳定。





这篇关于视频监控安防平台-自定义文件格式MFS存储的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/631602

相关文章

使用zabbix进行监控网络设备流量

《使用zabbix进行监控网络设备流量》这篇文章主要为大家详细介绍了如何使用zabbix进行监控网络设备流量,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录安装zabbix配置ENSP环境配置zabbix实行监控交换机测试一台liunx服务器,这里使用的为Ubuntu22.04(

Python视频处理库VidGear使用小结

《Python视频处理库VidGear使用小结》VidGear是一个高性能的Python视频处理库,本文主要介绍了Python视频处理库VidGear使用小结,文中通过示例代码介绍的非常详细,对大家的... 目录一、VidGear的安装二、VidGear的主要功能三、VidGear的使用示例四、VidGea

springboot健康检查监控全过程

《springboot健康检查监控全过程》文章介绍了SpringBoot如何使用Actuator和Micrometer进行健康检查和监控,通过配置和自定义健康指示器,开发者可以实时监控应用组件的状态,... 目录1. 引言重要性2. 配置Spring Boot ActuatorSpring Boot Act

Java实现任务管理器性能网络监控数据的方法详解

《Java实现任务管理器性能网络监控数据的方法详解》在现代操作系统中,任务管理器是一个非常重要的工具,用于监控和管理计算机的运行状态,包括CPU使用率、内存占用等,对于开发者和系统管理员来说,了解这些... 目录引言一、背景知识二、准备工作1. Maven依赖2. Gradle依赖三、代码实现四、代码详解五

python使用watchdog实现文件资源监控

《python使用watchdog实现文件资源监控》watchdog支持跨平台文件资源监控,可以检测指定文件夹下文件及文件夹变动,下面我们来看看Python如何使用watchdog实现文件资源监控吧... python文件监控库watchdogs简介随着Python在各种应用领域中的广泛使用,其生态环境也

使用JavaScript操作本地存储

《使用JavaScript操作本地存储》这篇文章主要为大家详细介绍了JavaScript中操作本地存储的相关知识,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考一下... 目录本地存储:localStorage 和 sessionStorage基本使用方法1. localStorage

SpringBoot 自定义消息转换器使用详解

《SpringBoot自定义消息转换器使用详解》本文详细介绍了SpringBoot消息转换器的知识,并通过案例操作演示了如何进行自定义消息转换器的定制开发和使用,感兴趣的朋友一起看看吧... 目录一、前言二、SpringBoot 内容协商介绍2.1 什么是内容协商2.2 内容协商机制深入理解2.2.1 内容

流媒体平台/视频监控/安防视频汇聚EasyCVR播放暂停后视频画面黑屏是什么原因?

视频智能分析/视频监控/安防监控综合管理系统EasyCVR视频汇聚融合平台,是TSINGSEE青犀视频垂直深耕音视频流媒体技术、AI智能技术领域的杰出成果。该平台以其强大的视频处理、汇聚与融合能力,在构建全栈视频监控系统中展现出了独特的优势。视频监控管理系统EasyCVR平台内置了强大的视频解码、转码、压缩等技术,能够处理多种视频流格式,并以多种格式(RTMP、RTSP、HTTP-FLV、WebS

异构存储(冷热数据分离)

异构存储主要解决不同的数据,存储在不同类型的硬盘中,达到最佳性能的问题。 异构存储Shell操作 (1)查看当前有哪些存储策略可以用 [lytfly@hadoop102 hadoop-3.1.4]$ hdfs storagepolicies -listPolicies (2)为指定路径(数据存储目录)设置指定的存储策略 hdfs storagepolicies -setStoragePo

HDFS—存储优化(纠删码)

纠删码原理 HDFS 默认情况下,一个文件有3个副本,这样提高了数据的可靠性,但也带来了2倍的冗余开销。 Hadoop3.x 引入了纠删码,采用计算的方式,可以节省约50%左右的存储空间。 此种方式节约了空间,但是会增加 cpu 的计算。 纠删码策略是给具体一个路径设置。所有往此路径下存储的文件,都会执行此策略。 默认只开启对 RS-6-3-1024k