GB28181 AI视频数据库以及SDP协议

Posted qianbo_insist

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GB28181 AI视频数据库以及SDP协议相关的知识,希望对你有一定的参考价值。

目的

搜索监控视频中的目标对象。为了快速搜索,打造数据库,记录预搜索目标,快速搜索。目前还在制作过程中,还不成熟,随时设计修改,望关注之人一同打造视频数据库。

SDP协议

SDP 协议里面有关于如何建立连接通道,采用何种编码格式,使用哪些RTP扩展,SDP(Session Description Protocol)就是这样一种会话描述协议。IETF RFC2327中定义了SDP标准,并随后在2006年7月出版的新的修订规范RFC4566作为RFC2327的更新。当前SDP被广泛用于SAP, RTSP, SIP等多媒体通讯协议中,包括webrtc也是以RFC4566(SDP)为基本蓝本,然后配合RFC3264关于offer/answer交互模式来进行媒体协商。我们在制作数据库的过程中,将会使用SDP协议存储AI信息,有人问sdp协议可以用来存储AI标注信息?当然可以。

制作视频数据库

目的是为了存储视频的备份,从gb28181 那里读取回放数据后备份并且做标识。
//前缀8字节
// 4 字节总索引个数
// 4 字节已存储索引个数
//索引内容
// 4字节sequence num 或者timestamp 4字节偏移量
//文件内容
// 4字节内容长度, 内容不定长,包含2 字节预先识别内容,2字节预先识别内容SDP会话,内容不定长

由于视频内容一般不需要删除,并且顺序读写,先写后读,极大加快了视频数据库的制作。数据库主要是为了写存储视频的基本数据,其基本流程为读取文件预识别人脸和车,车牌以及基本物体。

1 读取视频直播或者回放

使用gb28181 来直接获取标准直播视频和回放视频,sip协议本身包含ssrc 音视频等标准协议内容,对于rtp协议里比较重要的是记录时间戳
读取方式:
对于已经存储到数据库中的文件内容,我们使用文件映射读取,易于并发,对于需要需要存储到数据库中的内容,我们使用普通的FILE API 函数写入,当然也有FILE API的读取。以下是文件映射的示例,在windows下和linux下用宏分开。

#include <stdio.h>
#include <stdint.h>

#ifdef _WIN32
#include <Windows.h>
class cmem_map

	HANDLE hFile = NULL;
	OFSTRUCT opBuf;
	HANDLE hMapfile = NULL;
	HANDLE hMapview = NULL;
	long offset = 0;
public:
	cmem_map() 
	~cmem_map() 

	bool IsOpen()
	
		return (hMapview != NULL);
	
	bool IsClosed()
	
		return (hMapfile == NULL);
	
	int Open(const wchar_t * memfile_add, int fsize)
	
		hFile = ::CreateFile(memfile_add, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
		if (hFile == 0)
		
			printf("open file failed!\\n");
			return -1;
		

		//2.为指定文件创建一个有名的文件映象
		hMapfile = CreateFileMapping((HANDLE)hFile, NULL, PAGE_READWRITE, 0, fsize, L"MapTest");
		if (hMapfile == NULL)
		
			printf("mapping file failed!\\n");
			return -1;
		
		//关闭文件句柄
		CloseHandle((HANDLE)hFile);
		hFile = 0;
		hMapview = MapViewOfFile(hMapfile, FILE_MAP_WRITE, 0, 0, 0);
		if (hMapview == NULL)
		
			printf("mapping view failed!\\n");
			return -1;
		
		return 0;
	
	void Close()
	
		UnmapViewOfFile(hMapview);
		//关闭文件映象句柄
		CloseHandle(hMapfile);
		hMapfile = 0;
	
	long GetSize()
	
		return offset;
	
	int Write(uint8_t * data, int size)
	
		char *recv = (char *)hMapview;
		recv += offset;
		memcpy(recv, data, size);
		offset += size;
		//把文件映射视图中的修改的内容或全部写回到磁盘文件中
		FlushViewOfFile(recv, size);
		return offset;
		//return 0;
	
;

#endif  
#ifndef _WIN32
#include <fcntl.h>   
#include <unistd.h>   
#include <sys/mman.h>   



cmem_map::cmem_map() : m_pData(0), m_uSize(0), m_nFile(0)



cmem_map::~cmem_map()

	UnMap();


bool cmem_map::Map(const char* szFileName)

	UnMap();
	m_nFile = open(szFileName, O_RDONLY);
	if (m_nFile < 0)
	
		m_nFile = 0;
		return false;
	

	struct stat status;
	fstat(m_nFile, &status);

	m_uSize = status.st_size;
	m_pData = mmap(0, m_uSize, PROT_READ, MAP_SHARED, m_nFile, 0);
	if (MAP_FAILED != m_pData)  return true; 

	close(m_nFile);
	m_pData = NULL;
	m_nFile = 0;
	m_uSize = 0;
	return false;


void cmem_map::UnMap()

	if (m_pData)
	
		munmap(m_pData, m_uSize);
		m_pData = NULL;
	

	if (m_nFile)
	
		close(m_nFile);
		m_nFile = 0;
	

	m_uSize = 0;

#endif // !WIN32

#endif

2 识别人脸位置和车位置

数据量巨大设计并发和并行,多个处理器一起执行,这里强调一下GPU,GPU支持多个执行引擎,这里要多利用GPU的并发,对于回放和实时播放,既然是预先处理,就不能做太过重的工作,对于人脸,只做人脸的探测,对于车辆,只识别车牌的位置,等等。除此之外,预先处理还可以识别文件全局性相关特征并且分割,记录。

3 记录

记录在sdp协议里面记录。

4 用户输入需要识别的具体内容

包含图像识别,语义分割,人脸和车牌识别。记录在sdp协议里面,其他视频的sdp本身存在,不过扩展标注是增加出来的,语义为:

AI:

数据结构和文件系统api函数

这里是第一层文件系统api,并非我们的外层AI 识别api

typedef struct sdata

	uint32_t index;
	char vardata[128];
sdata;

typedef struct sdata_index

	uint32_t index;
	uint32_t offset;
	sdata_index* next;
sdata_index;
typedef struct db_context

	uint32_t v_tindex = 0;
	uint32_t v_nindex = 0;
	uint32_t v_timestart = 0;
	uint32_t v_timeend = 0;
	//file bytes index total 总索引加头部字节
	uint32_t v_index_bytes = 0;
	char v_tablename[256];
	FILE* fp = NULL;
	sdata_index* v_index = NULL;
	int v_exists = 0;
	uint8_t* v_data = NULL;
	int v_datalen = 0;
	//user 自定义context
	void* v_user_context = NULL;
	~db_context()
	
		if (v_data != NULL)
		
			free(v_data);
		
		if (fp != NULL)
			fclose(fp);
	
	//index map table
	std::map<uint32_t, uint32_t> v_index_maps;
	//index vector table
	std::vector<uint32_t> v_index_vector;
db_context;

int   Insert(void *data,db_context *v_context);
int   Delete(void *key, db_context *v_context);
int   Update(void *key, void *data, db_context *v_context);
void *Select(void *key, db_context *v_context);

API 初始化

int Initialize(const char *tname, db_context *context)


	if (context == NULL)
		return -1;
	strcpy(context->v_tablename,tname);

	if (context->v_index == NULL)
		context->v_index = bfile_read_index(
			tname,             /*filename*/
			context->v_tindex, 
			context->v_nindex
		);

	if (context->v_index == NULL)
		return -1;
	return 0;

如果文件已经存在,我们必须在内存中构建一个hash 搜索

增加记录,数据是h264或者h265 等等,我们将会给该数据增加AB协议

int Insert(void *data, db_context *context)

	if (context->v_nindex < context->v_tindex)
	
		FILE * fp = fopen(context->v_tablename, "wb");
		if (fp == NULL)
			return -1;


		fpos_t pos = (fpos_t)(4 + 4 + (context->v_nindex) * (8));
		fsetpos(fp, &pos);
		//int last_index = context->v_nindex - 1;
		uint32_t  indexlast = context->v_index[context->v_nindex - 1].index ;
		uint32_t  indexinsert = indexlast + 1;
		size_t n = fwrite(&indexinsert, sizeof(uint32_t), 1, fp);
		if (n != sizeof(uint32_t))
		
			fclose(fp);
			return -1;
		

		sdata *pdata = (sdata*)data;

		size_t vsize = sizeof(pdata->vardata);
		size_t datasize = vsize * indexlast;
		fpos_t offset = 4 + 4 + INDEX_BYTES + datasize;
		n = fwrite(&offset, sizeof(uint32_t), 1, fp);
		if (n != sizeof(uint32_t))
		
			fclose(fp);
			return -1;
		

		fsetpos(fp, &offset);
		n = fwrite(data, vsize, 1, fp);
		if (n != vsize)
		
			fclose(fp);
			return -1;
		
		fpos_t index = sizeof(uint32_t);
		fsetpos(fp, &index);
		uint32_t newnindex = context->v_nindex + 1;
		n = fwrite(&newnindex, sizeof(uint32_t), 1, fp);
		if (n != sizeof(int))
		
			fclose(fp);
			return -1;
		
		fclose(fp);
		return 0;
	
	return -1;

函数示例

AI api函数

用户将输入比如一副图片,或者描述的一段话,语句必须被语义分割,或者使用者手动分割关键词,如颜色信息,灾难信息。描述举例
1 1只红色的狗
2 一辆黑色的suv
3 一个扎辫子的5岁左右的小姑娘,身高在1米左右。
4 昨天我丢了一个褐色的皮包。
这个api函数最好是输入词以后进行自动语义分割,否则用户会感到困惑。搜索过程必须多重分布式进程分析。

投屏

DLNA协议DLNA协议是索尼、英特尔、微软等发起的一套 PC、移动设备、消费电器之间互联互通的协议。DLNA与苹果的AirPlay比较相似。我们的视频搜索过程可视化,是可以被投屏的,搜索到目标以后将前后1分钟的视频投屏出去,期间要用到ssdp协议,或者指定到某个显示设备上进行投放,支持的协议可以是DLNA和苹果的airplay以及华为的Cast+协议等,流程为:
1 预先搜索所有设备ssdp协议
2 搜索完后列表
3 启动媒体服务
4 启动投屏
媒体服务必须支持常见的rtsp扩展协议以支持扩展投屏。

未完待续…

以上是关于GB28181 AI视频数据库以及SDP协议的主要内容,如果未能解决你的问题,请参考以下文章

GB/T28181-2016 SDP定义和音视频传输模式解读

GB/T28181-2016 SDP定义和音视频传输模式解读

视频监控GB28181测试参考

GB28181的协议详解

GB28181国标平台资料整理

GB28181国标平台资料整理