在上一章,我们已经实现了一对一音视频对话功能。在实际应用中,我们常需要把自己的电脑桌面分享给他人以实现桌面共享功能,这种功能在视频会议、在线教学等场景中很常见,这种功能如何实现呢?这节课我们就来解决这个问题。
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.添加捕获桌面的功能:
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.调试运行,如能正常发送和播放桌面流则表示成功。