第10课 利用windows API捕获桌面图像并通过FFmpeg分享

在上一章,我们已经实现了一对一音视频对话功能。在实际应用中,我们常需要把自己的电脑桌面分享给他人以实现桌面共享功能,这种功能在视频会议、在线教学等场景中很常见,这种功能如何实现呢?这节课我们就来解决这个问题。

1.备份demo9并修改demo9为demo10。

2.在fmle.cpp的init函数中添加捕获屏幕的线程:

复制代码
//capCamHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)capCamThread, (LPVOID)this, 0, NULL);
capScrHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)capScrThread, (LPVOID)this, 0, NULL);

3.添加捕获桌面的功能:

cpp 复制代码
cv::Mat hwndToMat(HWND hwnd)
{	
	HDC hwindowDC, hwindowCompatibleDC;
	int height, width, srcheight, srcwidth;
	HBITMAP hbwindow;
	cv::Mat src;
	BITMAPINFOHEADER  bi;
	hwindowDC = GetDC(hwnd);
	hwindowCompatibleDC = CreateCompatibleDC(hwindowDC);
	SetStretchBltMode(hwindowCompatibleDC, COLORONCOLOR);
	RECT windowsize; 
	GetClientRect(hwnd, &windowsize);

	srcheight = windowsize.bottom;
	srcwidth = windowsize.right;
	height = windowsize.bottom;
	width = windowsize.right;

	src.create(height, width, CV_8UC4);
	
	hbwindow = CreateCompatibleBitmap(hwindowDC, width, height);
	bi.biSize = sizeof(BITMAPINFOHEADER);
	bi.biWidth = width;
	bi.biHeight = -height;
	bi.biPlanes = 1;
	bi.biBitCount = 32;
	bi.biCompression = BI_RGB;
	bi.biSizeImage = 0;
	bi.biXPelsPerMeter = 0;
	bi.biYPelsPerMeter = 0;
	bi.biClrUsed = 0;
	bi.biClrImportant = 0;	
	SelectObject(hwindowCompatibleDC, hbwindow);	
	StretchBlt(hwindowCompatibleDC, 0, 0, width, height, hwindowDC, 0, 0, srcwidth, srcheight, SRCCOPY | CAPTUREBLT);
	GetDIBits(hwindowCompatibleDC, hbwindow, 0, height, src.data, (BITMAPINFO *)&bi, DIB_RGB_COLORS); 	
	DeleteObject(hbwindow); DeleteDC(hwindowCompatibleDC); ReleaseDC(hwnd, hwindowDC);

	return src;
}


int fmle::capScr(){
	
	HWND hwnd = GetDesktopWindow();
	cv::Mat scrMat;
	while (true)
	{
		scrMat = hwndToMat(hwnd);		
		if (scrMat.cols != backWidth || scrMat.rows != backHeight){
			resize(scrMat, scrMat, cv::Size(backWidth, backHeight));
		}

		if (scrMat.data&&!scrMat.empty()){		
			cvtColor(scrMat, scrMat, CV_BGRA2BGR);
			mainDlg->drawMatOfPub(scrMat);
			EnterCriticalSection(&videoQueLock);
			tmpVideoQueObj.type = 1;
			tmpVideoQueObj.tmpMat = scrMat;
			tmpVideoQueObj.dataLen = scrMat.cols*scrMat.rows * 3;
			inVideoQue.push(tmpVideoQueObj);
			if (inVideoQue.size() >videoDataArrNum){
				inVideoQue.front().dataLen = 0;
				inVideoQue.front().tmpMat.release();
				inVideoQue.front().dataLen = NULL;
				inVideoQue.pop();
			}
			LeaveCriticalSection(&videoQueLock);

		}
		Sleep(40);
	}

	scrMat.release();	
	return 0;
}

4.调试运行,如能正常发送和播放桌面流则表示成功。

相关推荐
alwaysrun4 分钟前
C++之常量体系const
c++·后端·程序员
郝学胜_神的一滴5 分钟前
CMake 016:深入浅出变量核心用法
c++·cmake
私人珍藏库7 分钟前
【PC】ActivePresenter(屏幕录制软件) Pro v10.5.1 多语便携版
windows·pc·工具·软件·多功能
学逆向的12 分钟前
C++模板
开发语言·c++·网络安全
你住过的屋檐16 分钟前
【claude code】claude code在windows下安装使用教程,以及在idea中使用claude code自动AI写代码
人工智能·windows·intellij-idea
凡人叶枫27 分钟前
Effective C++ 条款24:若所有参数皆须要类型转换,请为此采用 non-member 函数
linux·前端·c++·算法·嵌入式开发
caimouse30 分钟前
Reactos 第 5 章 进程与线程 — 5.13 Windows的跨进程操作
windows
j7~32 分钟前
【C++】STL--string类--拆析解剖string类的实现以及string类的底层详解(2)
开发语言·c++·浅拷贝·深拷贝·string类的实现·string拷贝构造·string赋值重载
黑科技研究僧34 分钟前
蘑兔AI的12轨分轨功能:编曲师深度测评
人工智能·经验分享·vscode·学习·新媒体运营·音视频
Deitymoon44 分钟前
RV1126——OSD模块
计算机视觉·音视频·rv1126·osd