esp32-cam摄像头jpg_stream的http协议,及QT测试软件

esp32-cam摄像头jpg_stream的http协议,及QT测试软件

 

esp32-cam用的固件是ESP32_CAMERA_QR 具体参考:

电脑连接WiFi摄像头并显示图像(基于安信可esp32-cam)_一瓶可乐zc的博客-CSDN博客

exe可执行程序下载:

https://download.csdn.net/download/gws09876/11961819

点击连接之后要等待一会儿,保证连接成功之后再点击播放

源码下载地址:

https://download.csdn.net/download/gws09876/13689687

 

esp32_cam必须要下载官方提供的代码,可能会有更改(原理就是去连esp32_cam,向他发送请求)

 

 

Qt的http 好像不支持 multipart/x-mixed-replace 类型播放,于是只好自己根据esp32-cam 的摄像头发送的响应头和报文进行解析,

就是将/jpg_stream 的,通过TCP自己写,/jpg  使用QT自带的Http写

 

 

解析esp32-cam 的jpg_stream代码

void MainWindow::slotNetRead()
{
    //只需要处理jpg_stream的http协议
    ///
    /// HTTP/1.1 200 OK
    ///Content-disposition: inline; filename=capture.jpg
   /// Content-length: 24800
   /// Content-type: image/jpeg
   ///
    QByteArray buff = m_pTcp->readAll();
    QString     tmpStr(buff);
    QString     tmp2Str = "HTTP/1.1";
    //字符串操作

    if(tmpStr.indexOf(tmp2Str) == 0)
    {
        ///判断http请求视频数据是否成功

        /*  HTTP/1.1 200 OK
         *   Content-type: multipart/x-mixed-replace; boundary=123456789000000000000987654321
         */

        //得到错误码(如果是200表示正确)
        if(tmpStr.mid(9,3) == "200")
        {
            //获得Content-type
            int tmp = tmpStr.indexOf("Content-type");//到\r\n或;
            if(tmp> 0)
            {
                //得到的是Content-type的类型
                //qDebug()<<tmpStr.mid(tmp+14,tmpStr.indexOf(";",tmp)-(tmp+14));
                if(tmpStr.mid(tmp+14,tmpStr.indexOf(";",tmp)-(tmp+14)) == "multipart/x-mixed-replace")
                {
                   //如果是multipart/x-mixed-replace 类型,得到boundary的值
                    int tmp2 = tmpStr.indexOf("boundary");
                    //保存待用
                    m_HttpBoundary = tmpStr.mid(tmp2+9,tmpStr.indexOf("\r\n",tmp2)-(tmp2+9));
                    m_bflagHttpStream = true;  //设置jpg_stream标志为真
                    //qDebug()<<m_HttpBoundary ;
                }
                else
                {
                    //不是jpg_stream
                    m_bflagHttpStream = false;
                }

            }
        }
    }

    //Content-disposition

    ///记录下boundary的值作为判断jpeg图片结束的标志,
        /*
         *Content-length: 26400
         *Content-type: image/jpg
         */
   // qDebug()<<tmpStr;
    if( m_bflagHttpStream)
    {
        int tmp3 = tmpStr.indexOf("Content-length");
        if(tmp3>= 0)
        {
            //得到转换后的个数
            m_length = 0;
           m_length = tmpStr.mid(tmp3+16,tmpStr.indexOf("\r\n",tmp3)-(tmp3+16)).toInt();
           //int ty = tmpStr.indexOf("\r\n\r\n");
           //qDebug()<<m_length;
           m_bflagBodyStart = true;
           m_JpgBuff.clear();
            m_JpgBuff.append(buff.mid(tmp3+46+4));
           // qDebug()<<m_JpgBuff.toHex();
           // qDebug()<<m_JpgBuff.size();

        }
        else
        {

            if(m_bflagBodyStart)
            {
                ///根据Content-length的值将后面的图片数据放入缓冲区
                int ttt = m_length - m_JpgBuff.size();
                if(ttt>0 && ttt< buff.size())
                {
                    //部分添加
                    m_JpgBuff.append(buff.left(ttt));
                    m_bflagBodyEnd = true;
                    m_bflagBodyStart = false;
                }
                else if(ttt > buff.size())
                {
                    //全部添加
                    m_JpgBuff.append(buff);
                }
            }
        }
       // qDebug()<<buff.size();
    }
    buff.clear();
    if(m_bflagBodyEnd)
    {
#if 0
        //保存图片以测试提取的数据是否正确,
        const QString tfileName = "JJJ.jpg";
        QFile tmpfile;
        tmpfile.setFileName(tfileName);
        tmpfile.open(QIODevice::WriteOnly);
        if (!tmpfile.isOpen())
        {
            qDebug() << "file is not open";return;
        }
        if (!tmpfile.isWritable())
        {
            qDebug() << "file  write disable";
            return;
        }

        //写文件
        //tmpfile.write(m_JpgBuff);
        //关闭文件
        tmpfile.close();
#endif
        QPixmap pixmap;
        pixmap.loadFromData(m_JpgBuff);

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

        ui->label_display->setPixmap(pps);
        m_JpgBuff.clear();
        m_bflagBodyEnd = false;
    }
}

 

  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gws09876

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值