基于TightVNC源码实现远程桌面本地录像功能(OpenCV)

原博客地址:https://www.cnblogs.com/feixiang-energy/p/15528903.html

 

一.出发点:

  tightVNC是一个用在windows上的很好的远程桌面工具,实现了远程桌面、文件传输等功能。 但是没有实现远程桌面录像保存的功能。
  tightVNC使用远程桌面协议 (RDP) 实现终端服务器和终端服务器客户端之间的通信。客户端将服务器端的屏幕拼接成帧图片进行展示。为了实现屏幕录制的功能,考虑基于tightVNC的源码进行修改,在客户端展示屏幕帧的同时,增加一个线程将已经拼接好的连续的屏幕帧图片保存为视频文件。
  使用了OpenCV的cv::VideoWriter对象,将连续的图片保存为视频文件。经过初步测试,能达到客户端本地远程桌面录像的功能。
  现在把实现方式贴出来,希望对有需要的人提供些参考。
 
二.源码下载: 
  
  tightVNC官网有C++版本的开源代码可供下载:https://www.tightvnc.com/download.php
  

 

三.实现方式:

  使用VS2019打开并编译源码。我使用的是tightvnc-2.8.27-gpl版本。
  修改viewer-core/RemoteViewerCore类,在里面增加一个record_fun的处理函数实现对远程桌面屏幕的录制。
  主要代码如下:
//远程桌面客户端屏幕录制线程
DWORD  _stdcall RemoteViewerCore::record_fun(LPVOID lparam)
{
    Sleep(1000);
    //远程桌面客户端连接对象
    RemoteViewerCore* lp = (RemoteViewerCore*)lparam;
    //视频文件名称
    char file_name[256] = { 0 };
    time_t t = time(0);
    char time_str[64];
    strftime(time_str, sizeof(time_str), "%Y%m%d%H%M%S", localtime(&t));
    sprintf(file_name, "video/video_%s_%s.mp4", lp->m_host_name, time_str);
    //获取远程桌面屏幕帧的分辨率
    Dimension dimension = lp->m_frameBuffer.getDimension();
    int weight = dimension.width;
    int hight = dimension.height;
    //opencv的视频保存对象,初始化大小为0.5倍,是为了对分辨率进行裁剪
    cv::VideoWriter writer;
    writer.open(file_name, CV_FOURCC('m', 'p', '4', 'v'), 9, cv::Size(weight * 0.5, hight  * 0.5), true);
    //tightvnc远程桌面屏幕帧编码格式为RGBA
    //初始化一个4倍分辨率的数组用于保存帧二进制数据
    int buf_len = weight * hight * 4;
    char* buf = new char[buf_len];
    while (lp->m_record_flag)
    {
        int start = clock();
        //初始化一个RGB格式的Mat对象
        cv::Mat dst = cv::Mat::zeros(hight, weight, 16);
        memset(buf, 0, buf_len);
        memcpy(buf, lp->m_frameBuffer.getBuffer(), lp->m_frameBuffer.getBufferSize());
        //将视频帧的数据RGB数据保存到对应的Mat对象中
        for (int i = 0; i < hight; i++)
        {
            for (int j = 0; j < weight; j++)
            {
                dst.at<cv::Vec3b>(i, j)[0] = buf[(i* weight + j) * 4];
                dst.at<cv::Vec3b>(i, j)[1] = buf[(i * weight + j) * 4 + 1];
                dst.at<cv::Vec3b>(i, j)[2] = buf[(i * weight + j) * 4 + 2];
            }
        }
        int used = clock() - start;
        //对Mat对象进行图片裁剪
        cv::Mat dst1;
        cv::resize(dst, dst1, cv::Size(weight * 0.5, hight * 0.5));
        //将图片写入到视频保存对象
        writer.write(dst1);
        //休眠100毫秒。这个时间间隔可以用来控制每秒中保存的视频图像帧数,即控制码率。
        Sleep(100);
    }
    //释放掉二进制数组。
    delete[]buf;
    return 0;
}

四.实现效果:

  每次使用重新编译过的TightVNCViewer进程远程桌面连接时,都在本地会保存一个本次操作的远程桌面录像文件。

  

 

 
 

 

posted @ 2021-11-09 14:50  飞翔天空energy  阅读(1906)  评论(0编辑  收藏  举报