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 = new QNetworkAccessManager();
    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端口。

void MainWindow::start()
{
    QNetworkAccessManager *manager = new QNetworkAccessManager();
    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);

}
void MainWindow::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开始的后半部分数据归为下一帧数据。(其实就是将两帧黏起来的数据进行切割)。

      ③合成图片的关键代码

void MainWindow::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、源码

ESP32CAM.exe
https://www.aliyundrive.com/s/CwhgTsmggwG
提取码: 9ek4
点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速播放。

5、结束

加油,打工人。

  • 8
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
连接 ESP32CAM 到 Qt 可以通过网络连接或串口连接,具体的实现方式取决于你的需求和硬件环境。 如果你选择使用网络连接,可以使用 ESP32CAM 的 Wi-Fi 功能,将其设置为 Access Point 模式或 Station 模式,然后使用 Qt 的网络模块进行连接和通信。你可以使用 QTcpSocket 或 QUdpSocket 类来实现。 如果你选择使用串口连接,可以使用 ESP32CAM 的 UART 接口和 Qt 的 QSerialPort 类进行连接和通信。在 Qt 中,你需要设置串口的参数,包括波特率、数据位、校验位和停止位等。 以下是一个简单的示例,演示如何使用 QSerialPort 类连接到 ESP32CAM: ```c++ #include <QSerialPort> #include <QSerialPortInfo> QSerialPort serial; // 查找可用的串口 QList<QSerialPortInfo> ports = QSerialPortInfo::availablePorts(); foreach (const QSerialPortInfo &info, ports) { qDebug() << "Name : " << info.portName(); qDebug() << "Description : " << info.description(); qDebug() << "Manufacturer: " << info.manufacturer(); // 如果找到 ESP32CAM 的串口 if (info.manufacturer().contains("ESP32CAM")) { qDebug() << "Found ESP32CAM : " << info.portName(); serial.setPort(info); serial.setBaudRate(QSerialPort::Baud115200); serial.setDataBits(QSerialPort::Data8); serial.setParity(QSerialPort::NoParity); serial.setStopBits(QSerialPort::OneStop); serial.setFlowControl(QSerialPort::NoFlowControl); serial.open(QIODevice::ReadWrite); break; } } // 发送数据到 ESP32CAM serial.write("Hello, ESP32CAM!"); // 接收来自 ESP32CAM 的数据 connect(&serial, &QSerialPort::readyRead, [=]() { QByteArray data = serial.readAll(); qDebug() << "Received data : " << data; }); ``` 当然,具体的实现方式还需要根据你的硬件环境和需求进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值