GB28181系统设计(三)-进程通信让python获取共享内存数据

GB28181系统设计 一 事件设计
GB28181系统设计 二 kdtree 算法

这一节说到了GB28181 系统接收到RTP包后,解码后交付给python做图像识别

流媒体服务依然是c++主打,解码也是c++主打,解码后得yuv图像或者RGB都保存在内存里面,如何让python直接获取呢,我们使用进程通信设计解决这个问题。

1 共享内存

1.1 发送端c++

	message_queue::remove("message_queue");

		//Create a message_queue.
	message_queue mq(create_only    //only create
			, "message_queue"           //name
			, 100                       //max message number
			, sizeof(int)               //max message size
		);

	//删除之前创建
	shared_memory_object::remove("RGB_MEMORY_1");

	//创建RGB共享内存段
	shared_memory_object shm(create_only, "RGB_MEMORY_1", read_write);

	//设置共享内存大小,RGB 1080p 图像
	shm.truncate(1920*1080*3);

	//映射共享内存
	mapped_region region(shm, read_write);

	//清零,这一步可以删除
	std::memset(region.get_address(), 0, region.get_size());

	//往内存里写数据,测试先用string
	string *strTest = static_cast<string*>(region.get_address());

1.2 接收端

	shared_memory_object shm(open_only, "RGB_MEMORY_1", read_only);
	//映射共享内存
	mapped_region region(shm, read_only);
 我们什么时候读呢,使用消息队列或者udp来发送短信息提醒

2 消息队列

消息队列是可以在进程间也可以在线程间,我们主打进程间通信,避免写两套windows和linux,我们依然使用boost库得进程通信组件来直接上手。

2.1 发送端

	message_queue::remove("message_queue");

		//Create a message_queue.
	message_queue mq(create_only    //only create
			, "message_queue"           //name
			, 100                       //max message number
			, sizeof(int)               //max message size
		);
	int num = 0;
	mq.send(&num++, sizeof(int), 0);

2.2 接收端

	int number;
	mq.receive(&number, sizeof(number), recvd_size, priority);
	if (recvd_size != sizeof(number))
		return 1;
	cout<<"recv " << number << endl;
	//接下去就可以读取共享内存了,先用字符串测试
	char *mem = static_cast<char*>(region.get_address());
	string str(mem, region.get_size());

以上所有接收得地方依然是c++,在python里面使用必须使用c++写成得动态库。

2.3 udp协议

单机也可以使用udp协议可以进行事件通信,这个和事件设计(一)可以结合起来,udp比较简单,复用性比较高,作为可选。

3 show me the code

以下提供一个测试代码,您可以随便复制测试,里面有一个小问题(收数据),希望您找到修复,对于RGB传递来讲,其实是没有问题得. 因为对于一个h264或者h265 来说解码后RGB得大小是固定得。

//发送端
int main()
{
	
	message_queue::remove("message_queue");

		//Create a message_queue.
	message_queue mq(create_only    //only create
			, "message_queue"           //name
			, 100                       //max message number
			, sizeof(int)               //max message size
		);

	//1 先删除之前创建的
	shared_memory_object::remove("MySharedMemory_Name");

	//2 创建共享内存段
	shared_memory_object shm(create_only, "MySharedMemory_Name", read_write);

	//3 设置共享内存大小
	shm.truncate(1024);

	//4 映射共享内存片段
	mapped_region region(shm, read_write);

	//5 初始化为0
	std::memset(region.get_address(), 0, region.get_size());

	//6 往内存里写入数据
	string *strTest = static_cast<string*>(region.get_address());
	for (int i = 0; i < 100; i++)
	{
		
		*strTest = "this is test for " + std::to_string(i);
		cout << *strTest << endl;
		mq.send(&i, sizeof(i), 0);
		std::this_thread::sleep_for(std::chrono::milliseconds(1000));
	}
	cout << "发送over" << endl;
	getchar();
	return 0;
}


//接收端
int main()
{
	//1 读取共享内存
	shared_memory_object shm(open_only, "MySharedMemory_Name", read_only);

	//2 映射共享内存
	mapped_region region(shm, read_only);
	try {
		//Open a message queue.
		message_queue mq
		(open_only        //only create
			, "message_queue"  //name
		);

		unsigned int priority;
		message_queue::size_type recvd_size;

		//Receive 100 numbers
		for (int i = 0; i < 100; ++i) {
			int number;
			mq.receive(&number, sizeof(number), recvd_size, priority);
			if (recvd_size != sizeof(number))
				return 1;
			cout<<"recv " << number << endl;

			//3 获取数据
			char *mem = static_cast<char*>(region.get_address());
			string str(mem, region.get_size());


			cout << str<< endl;
		}
	}
	catch (interprocess_exception &ex) {
		message_queue::remove("message_queue");
		std::cout << ex.what() << std::endl;
		return 1;
	}
	message_queue::remove("message_queue");
	return 0;
}


用了boost ,可以缓解我们不少压力。
#g++ boost_queue_send.cpp -o queue_send -lboost_thread -lboost_system
#g++ boost_queue_rec.cpp -o queue_rec -lboost_thread -lboost_system
至于封装成dll让python调用,或者c++ 直接调用python 就待续了…

你可能感兴趣的:(c++,音视频和c++,java,物联网,进程通信,GB28181,python)