QT下视频通话的实现

**

1 QT下视频通话的实现

**
本文使用QT完成了两个不同终端的视频通话,笔记本电脑+Linux开发板。
1.1 硬件资源介绍
带摄像头的电脑 + 正点原子Alpha Linux开发板(由于Linux开发板上没有购买摄像头,所以本次实现仅仅单向的视频通话)
1.2 软件编程实现
1.2.1 电脑端QT编程
电脑端搭建一个TCP服务器,开启一个视频捕获线程,使用QCamera、QCameraViewfinder、QCameraImageCapture、QTimer,定时捕获视频中的图片,并传送给主线程使用TCP发给客户端。下面是核心的代码实现
(1)捕获电脑的视频,这里是捕获视频的核心代码,实现的大致思路是,开启一个QCaerma,通过主线程的信号槽开启,定时VIDEO_SAMPLE_INTERVAL时间截取一张图片,此时会自动触发SIGNAL(imageCaptured(int,QImage))这样一个信号,在主线程中编写槽函数接收捕获到的QImage。这个cpp参考网上一位老哥的编写,将QVideoProbe换成了QCameraImageCapture来实现。https://blog.csdn.net/xiaolong1126626497/article/details/105122636

void VideoReadThread::Camear_Init(void){
    qDebug() << "Camear_Init";
    // 初始化定时器
    ImageCaptureTimer = new QTimer(this);
    connect(ImageCaptureTimer,SIGNAL(timeout()),this,SLOT(captureImage()));
    // currentCaerma 为当前选择的摄像头
    camera = new QCamera(qtUtil.camera);
    //设置取景器
    viewfinder = qtUtil.viewfinder;
    imageCapture = new QCameraImageCapture(camera);
    camera->setViewfinder(viewfinder);
    //配置 Camera 为静止帧捕获
    camera->setCaptureMode(QCamera::CaptureStillImage);
    //启动摄像头
    camera->start();
    //配置摄像头参数
        QList<QCameraViewfinderSettings > ViewSets = camera->supportedViewfinderSettings();
           int i = 0;
           qDebug() << "viewfinderResolutions sizes.len = " << ViewSets.length();
           foreach (QCameraViewfinderSettings ViewSet, ViewSets) {
               qDebug() << i++ <<" max rate = " << ViewSet.maximumFrameRate() << "min rate = "<< ViewSet.minimumFrameRate() << "resolution "<<ViewSet.resolution()<<\
                           "Format="<<ViewSet.pixelFormat()<<""<<ViewSet.pixelAspectRatio();
           }
       //可以打印出来自己电脑端的settings,进行选择    
        camera->setViewfinderSettings(ViewSets[9]);
    //开启定时器
    ImageCaptureTimer->start(VIDEO_SAMPLE_INTERVAL);
    connect(imageCapture, SIGNAL(imageCaptured(int,QImage)), this, SLOT(displayImage(int,QImage)));
}
void VideoReadThread::captureImage()
{
    imageCapture->capture();
}

(2)使用TCP传输图片,参考飞扬青云的帖子https://www.cnblogs.com/feiyangqingyun/p/12041561.html 使用base64编码传输,接收到以后将base64字符串解码出来生成图片。

// 获取图片并转为base64字符串
QByteArray Widget::getImageData2(const QImage &image)
{
    QByteArray imageData;
    QBuffer buffer(&imageData);
    image.save(&buffer, "jpg");
    imageData = imageData.toBase64();
    return imageData;
}



//base64字符串转图片
QImage Widget::getImage(const QString &data)
{
    QByteArray imageData = QByteArray::fromBase64(data.toLatin1());
    QImage image;
    image.loadFromData(imageData);
    return image;
}

(3)TCP传输过程中粘包,拆包处理,服务器端规定协议,增加数据包的开头和结尾,观察图片转换正的Base64码中发现没有@ 和 # ,因此使用这两个当做一包数据的头和尾。栽面是服务器端封包的代码。
//封装发送图片的数据包

// startFlag: @  endFlag:#
QByteArray Widget::packageImageData(QImage image)
{
    QByteArray resultData;
    imageData = getImageData2(image);
    resultData.append(startFlag).append(imageData).append(endFlag);
    qDebug()<<resultData.size();
//    qDebug()<<resultData;
    return resultData;
}

1.2.2 Linux开发板QT编程
使用正电原子的Linux开发板,使用之前先配置好开发板上QT的运行环境,参考正点原子文档。开发板中主要是实现了数据包的解析,代码如下:


```css
/*解析数据*/
void Widget::parseImageData(QByteArray receiveData)
{
    QByteArray bufData = receiveData;
    static QByteArray pastData;
    static QString resultStr;
    if(bufData.contains("@")&(!bufData.contains("#")))
    {
      pastData.clear();
      pastData.append(bufData);
    }
    //无头无尾中部数据 直接追加
    if((!bufData.contains("@"))&(!bufData.contains("#"))&(!pastData.isEmpty()))
    {
      pastData.append(bufData);
    }
    //无头有尾 如果数据之前不为空则继续追加 已经读取完成 清空变量
    if((!bufData.contains("@"))&bufData.contains("#")&(!pastData.isEmpty()))
    {
      pastData.append(bufData);
      resultStr = tr(pastData);
      pastData.clear();

    }
    //有头有尾 清空之前数据直接追加
    if(bufData.contains("@")&bufData.contains("#"))
    {
      pastData.clear();
      pastData.append(bufData);
      resultStr = tr(pastData);
      pastData.clear();
    }
    if(!resultStr.isEmpty())
    {
       resultStr.remove("@");
       resultStr.remove("#");
       emit sendImageDataBase64(resultStr.toUtf8());
    //        qDebug()<<resultStr.toUtf8();
       resultStr.clear();
    }
}

解析后的数据,通过一个信号传递给处理图片的槽函数,将编码转换为Qimage,显示在Qlabel上。
1.3 实验效果
我设置的定时器间隔为100ms,视频传输感觉较为流畅。电脑端,布局比较乱
电脑端图片

Linux 开发板
在这里插入图片描述

  • 10
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值