C++ | 内存共享教程
一、背景
最近在做美颜软件虚拟摄像头的功能,类似YY开播(我们获取笔记本的摄像头列表时,列表中除了自带的摄像头,以及usb的摄像头,还有YY开播),查了一下网络上实现的虚拟摄像头展示的都是本地的视频,但是我这边的美颜软件需要读取自带摄像头拍摄的画面,美颜后将视频帧数据传输到虚拟摄像头中,当我们调用虚拟摄像头的时候就能看到美颜后的画面,这个功能的实现就用到了美颜软件和虚拟摄像头的内存共享。
二、代码实现
1.美颜软件写数据
(1)注册共享句柄
QMap<const char*, void*> mRegisterData;
void* RegisterSendData(const char *name, const int buf_size)
{
if (mRegisterData.count(name) > 0)
{
return mRegisterData[name];
}
HANDLE hMapFile2 = CreateFileMapping(
INVALID_HANDLE_VALUE, // 物理文件句柄
NULL, // 默认安全级别
PAGE_READWRITE, // 可读可写
0, // 高位文件大小
buf_size, // 低位文件大小
name // 共享内存名称
);
// 映射缓存区视图 , 得到指向共享内存的指针
if (hMapFile2 != nullptr)
{
void* lpBase2 = MapViewOfFile(
hMapFile2, // 共享内存的句柄
FILE_MAP_ALL_ACCESS, // 可读写许可
0,
0,
buf_size
);
mRegisterData.insert (name, lpBase2);
return mRegisterData[name];
}
else
{
return nullptr;
}
}
(2)写共享数据
void set_buffer_data(LPVOID lpBase,unsigned char* buffer_data, int buffer_size)
{
if(lpBase)
{
memcpy((unsigned char*)lpBase, buffer_data, buffer_size);
}
}
(3)调用
LPVOID lpBase= register_data("FrameBuffer",800* 600 * 3);
if(lpBase)
{
QImage map_img = effectImage.scaled(800,600);//effectImage即美颜后的图片
set_buffer_data(lpBase,map_img.bits(),BUF_SIZE);
}
2.虚拟摄像头读数据
(1)注册共享句柄并获取共享内容
bool GetFrameBuffer(const char* name, unsigned char* buffer_data, const int buf_size)
{
if (buffer_data == nullptr)
{
return false;
}
打开共享的文件对象
HANDLE hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, NULL, name);
if (hMapFile) {
LPVOID lpBase = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
// 将共享内存数据拷贝出来
if (lpBase != nullptr)
{
memcpy(buffer_data, lpBase, buf_size);
// 解除文件映射
UnmapViewOfFile(lpBase);
}
// 关闭内存映射文件对象句柄
CloseHandle(hMapFile);
return true;
}
else {
// 打开共享内存句柄失败
std::cout << "打开共享失败!" << std::endl;
return false;
}
}
(2)调用
unsigned char* szBuffer = nullptr;
szBuffer = (unsigned char*)malloc(800*600*3*sizeof(char));
GetFrameBuffer("FrameBuffer", szBuffer, 800*600*3);