Qt使用udp传输视频的坑

Qt使用udp传输视频的坑


其实也没啥,当需要传输的数据大于65536时,记得为套接字申请大一点的 空间 ,加油,摸了两天终于摸出这个坑了。
代码为不完整代码,opencv3.2+Qt5.8,目的就是为了正常的视频通讯。
# 连接
链接: SOCKET通信中TCP、UDP数据包大小的确定.

发送端

  1. opencv读取本地视频
  2. 逐帧读取(Mat格式)
  3. 利用QBuffer,将数据存入到QBytearray中
  4. 每隔一定长度分段发送出去,(别像我这样写3000)
    接收端
  5. 没有用信号,使用while循环等待数据到来
  6. 接收到数据判断是否小于3000
  7. 是的话说明是最后一帧,将其追加到接收的数据区后转换为Mat格式(我需要使用这种格式)
  8. 不是的话接着追加存储。

发送端

将其写在了线程的run函数中。

void getVideo::run()
{
    udpSocket = new QUdpSocket(this);
    //这是个大坑我丢!为套接字申请大一点的空间,udp传送数据的缓冲区最大理论值为65536个字节,而我需要发送的帧
    //图像最大的大概为20W,导致接收的时候,每帧数据小于65536的才可以正常显示,大于就会卡住。
    udpSocket->setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption,500000 );
    string video_path ="D:\\FFOutput\\test14.avi";
    VideoCapture camera(video_path);
    //int aaa = camera.get(cv::CAP_PROP_FRAME_COUNT);
    //qDebug() << "帧数:" << aaa;
    if (!camera.isOpened())
    {
        cout << "read video failure" << endl;
    }else
    {
        cout << "read video success" << endl;
    }
    
    QByteArray byte;
    QByteArray sendByte;
    int ByteLen;
    int sendLen;
    while(1)
    {
        camera >> frame;
        if(frame.empty())
        {
            qDebug() << "视频读取完毕" << endl;
            //为了方便测试,当本次视频发送完成之后,重新执行run函数。
            run();
        }
        Mat temp;
        cvtColor(frame,temp,CV_BGR2RGB);
        QImage image((const unsigned char*)(frame.data), frame.cols, frame.rows, frame.step, 			 QImage::Format_RGB888);
        QBuffer buffer(&byte);
        buffer.open(QIODevice::WriteOnly);
        image.save(&buffer,"JPEG");
        //每帧图像分多次发送,总大小为ByteLen,每次发送的大小为sendLen,比较可知是否完整发完本帧的数据。
        ByteLen = byte.size();
        sendLen = 0;
        qDebug() << endl  << "byte.size :" << ByteLen;
        while(ByteLen > sendLen )        //若丢失数据怎么办 0 == len
        {
            sendByte = byte.mid(sendLen,3000);
            int len = udpSocket->writeDatagram(sendByte,sendByte.size(),QHostAddress("192.168.0.16"),12235);
            sendLen += len;
            qDebug() <<"本次发送出数据长度为:" << len << " 已发送数据长度为:" << sendLen << " 此帧像素数据总长度为:" << ByteLen << endl<<endl;
            sendByte.clear();
            udpSocket->flush();
        }
        byte.clear();
        QThread::msleep(2);
    }
}

接收端

同样写在了线程中

void Video::run()
{
    SendDataSocket1 -> bind(QHostAddress("192.168.0.16"),12235);
    //同样为套接字申请大一点的空间。
    SendDataSocket1->setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption,500000 );
    //开线程的时候设置flag_A = true;
    while(flag_A)
    {
        int Receivelen;
        QByteArray OneFrame;
        //等待接收报文
        while(SendDataSocket1->hasPendingDatagrams())
        {
            QByteArray msg;
            msg.resize(SendDataSocket1->pendingDatagramSize());
            Receivelen = SendDataSocket1->readDatagram(msg.data(),msg.size());
            qDebug() << "正在存" << endl;
            OneFrame.append(msg);
            qDebug() << OneFrame.size();
            //接收到一帧数据,每次接收3000字节,当小于3000时说明接收到本帧图像的最后一组数据包。
            if(Receivelen < 3000)
            {
                qDebug() << "接收长度为:" << OneFrame.size() << "得到一帧数据" << endl;
                QBuffer buffer(&OneFrame);
                QImageReader reader(&buffer,"JPEG");
                QImage image = reader.read();
		//Img_now 为线程处理函数用到的参数。
                QImage2cvMat(image).copyTo(this->Img_now);		
                OneFrame.clear();
            }else
            {
                //继续接收
                qDebug() << "继续接收";
            }
        }
        if(!Img_now.empty())
        {
            qDebug() << "接收到了帧图像" << endl;
        }else
        {
            gg->my_Timer(300);
            continue;
        }
        //线程处理函数
        /*#####################*/
     }
 }
}
  • 2
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值