0


QT获取ESP32-CAM视频流分析

QT获取ESP32-CAM视频流分析

1、前言

  使用QT获取ESP32-CAM视频流的原理是在QT模拟浏览器发送http请求,然后ESP32-CAM返回视频流,当QT界面接收到数据后,对数据进行解析,然后合成图片进行显示。
   在QT中发送http请求的方法很多,这里使用Qt网络模块中的类QNetworkReply发送http请求。

2、核心代码以及数据分析

  ①下面是QT的一个构造函数,当程序跑起来后,首先跑这部分代码,在这里模拟发送hhtp请求。其中ESP32-CAM分配到的IP地址是192.168.1.8.
#include<QHostAddress>#include<QNetworkAccessManager>#include<QNetworkRequest>#include<QNetworkReply>#include<QUrl>#include<QQueue>#include<QDebug>MainWindow::MainWindow(QWidget *parent):QMainWindow(parent),ui(new Ui::MainWindow){
    ui->setupUi(this);
    QNetworkAccessManager *manager =newQNetworkAccessManager();
    QNetworkRequest request(QUrl("http://192.168.1.8"));

    QNetworkReply *reply= manager->get(request);connect(reply,&QNetworkReply::finished,[reply](){if(reply->error()){qDebug()<<"Error:"<< reply->errorString();}else{qDebug()<<"Success:"<< reply->readAll();}
        reply->deleteLater();});}

这部分代码运行成功后,应该有如下打印:
在这里插入图片描述
上面就是返回一个网页,当你把http://192.168.1.8复制到网页去搜索,会返回下面的页面:
在这里插入图片描述

  ②下面是进行视频流http请求代码,调用它,运行后可以打印接收到的原始数据。注意视频流使用的是81端口。
voidMainWindow::start(){
    QNetworkAccessManager *manager =newQNetworkAccessManager();
    QNetworkRequest request;
    request.setUrl(QUrl("http://192.168.1.8:81/stream"));
    request.setRawHeader("Connection","Keep-Alive");
    request.setRawHeader("User-Agent","1601");

    Client = manager->get(request);//Client为QNetworkReply类型,在MainWindow类里面定义connect(Client,&QNetworkReply::readyRead,this,&MainWindow::dataReceived);}voidMainWindow::dataReceived(){// 打印接收内容
    QByteArray buffer = Client->readAll();qDebug()<< buffer;qDebug()<<"----------------------";}

接收到的原始数据如下:
在这里插入图片描述
上面接收到的原始数据是不能直接用的。就是每次一次接收到的数据并不是一帧完整的数据。因此需要把每次接收到的数据存储起来,然后进行切割。切割的思路是:先这样这样,然后再这样这样。

  在完成数据的存储和切割后,得到如下一帧一帧完整的数据。(在下面的数据中,每一帧数据只打印了前100个字节和后100个字节)。每一帧数据以“Content-Type: image/jpeg\r\nContent-Length: 28912\r\n\r\n\”开头,以“\r\n–123456789000000000000987654321\r\n”结束,中间部分的数据就是图片数据,图片数据的长度是Content-Length后面的数字(28912)。把中间部分数据提取出来即可合成图片。

在这里插入图片描述
切割数据的思路是:每次接收到原始数据,都要判断一下是否包含字符串“Content-Type”,如不包含,则当前接收的数据归为上一帧数据,若包含,则在当前接收到的数据里面,将Content-Type前面部分的数据归为上一帧数据,而以Content-Type开始的后半部分数据归为下一帧数据。(其实就是将两帧黏起来的数据进行切割)。

  ③合成图片的关键代码
voidMainWindow::dataProcess(){
    QString data =QString::fromUtf8(frameBuffer.data(),50);//截取前面50个字符//    qDebug() <<frameBuffer.left(100)<<"......";//    qDebug() <<frameBuffer.right(100);//    qDebug() <<"------------------------";const QString lengthKeyword ="Content-Length: ";int lengthIndex = data.indexOf(lengthKeyword);if(lengthIndex >=0){int endIndex = data.indexOf("\r\n", lengthIndex);int length = data.midRef(lengthIndex +16, endIndex -(lengthIndex +16-1)).toInt();//取出Content-Length后的数字
        QPixmap pixmap;auto loadStatus = pixmap.loadFromData(frameBuffer.mid(endIndex +4, length));//取出图片数据,并合成图片if(!loadStatus){qDebug()<<"Video load failed";
            frameBuffer.clear();return;}

        frameBuffer.clear();
        QPixmap pps = pixmap.scaled(ui->label_display->width(), ui->label_display->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
        ui->label_display->setPixmap(pps);}}

3、图片合成效果

跟网页效果差不多,很流畅。
在这里插入图片描述

4、结束

加油,打工人。

标签: qt ui 开发语言

本文转载自: https://blog.csdn.net/m0_48442491/article/details/128705183
版权归原作者 你很下饭 所有, 如有侵权,请联系我们删除。

“QT获取ESP32-CAM视频流分析”的评论:

还没有评论