linux视频对讲qt方案,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 ViewSets = camera->supportedViewfinderSettings();

int i = 0;

qDebug() << "viewfinderResolutions sizes.len = " << ViewSets.length();

foreach (QCameraViewfinderSettings ViewSet, ViewSets) {

qDebug() << i++ <

"Format="<

}

//可以打印出来自己电脑端的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()<

// qDebug()<

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.clear();

}

}

解析后的数据,通过一个信号传递给处理图片的槽函数,将编码转换为Qimage,显示在Qlabel上。

1.3 实验效果

我设置的定时器间隔为100ms,视频传输感觉较为流畅。电脑端,布局比较乱

6c1555302777729326ca3efa0910d9ec.png

Linux 开发板

6c1555302777729326ca3efa0910d9ec.png

来源:oschina

链接:https://my.oschina.net/u/4338498/blog/4463360

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值