第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.调试运行,如能正常发送和播放桌面流则表示成功。

相关推荐
小叶学C++4 分钟前
【C++】类与对象(下)
java·开发语言·c++
NuyoahC22 分钟前
算法笔记(十一)——优先级队列(堆)
c++·笔记·算法·优先级队列
方世恩1 小时前
【进阶OpenCV】 (5)--指纹验证
人工智能·opencv·目标检测·计算机视觉
9527华安1 小时前
FPGA实现PCIE视频采集转HDMI输出,基于XDMA中断架构,提供3套工程源码和技术支持
fpga开发·音视频·pcie·xdma·ov5640·hdmi
FL16238631291 小时前
[C++]使用纯opencv部署yolov11-pose姿态估计onnx模型
c++·opencv·yolo
sukalot1 小时前
windows C++-使用任务和 XML HTTP 请求进行连接(一)
c++·windows
A_lvvx1 小时前
OpenCV透视变换
人工智能·opencv·计算机视觉
ぃ扶摇ぅ2 小时前
Windows系统编程(三)进程与线程二
c++·windows
鲸~屿2 小时前
计算机视觉 第十章OpenCV
人工智能·opencv·计算机视觉
Mr.Z.4112 小时前
【历年CSP-S复赛第一题】暴力解法与正解合集(2019-2022)
c++