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 就待续了…