基于QT和UDP实现一个实时RTP数据包的接收,并将数据包转化成文件

news/2024/5/18 11:52:27 标签: qt, udp, 开发语言

简单介绍:代码写的比较详细,需要留意的地方看结尾介绍

头文件

#ifndef RTPRECEIVER_H
#define RTPRECEIVER_H

#include <QDialog>
#include <QUdpSocket>
#include <QFile>
#include <QTextStream>
#include <httpclient.h>
#include <QEventLoop>


class RTPReceiver : public QWidget
{
    Q_OBJECT
public:
    explicit RTPReceiver(QWidget *parent = nullptr);
    ~RTPReceiver();
    void start();
    void closeFile();
    void writeBufferToFile();
    void initSocket();
    void sendGetRequest();


private slots:
    void readPendingDatagrams();


private:
    QUdpSocket *udpSocket;
    QFile file;
    QByteArray buffer;
    int bufferSize = 1400;
    QString filePath;
};

#endif // RTPRECEIVER_H

cpp文件

#include "rtpreceiver.h"


const int RTP_HEADER_LENGTH = 12;

RTPReceiver::RTPReceiver(QWidget *parent)
    : QWidget(parent)
{
    this->setVisible(false);

}

RTPReceiver::~RTPReceiver()
{


}

void RTPReceiver::start()
{

    initSocket();

}

void RTPReceiver::closeFile()
{
    if (file.isOpen()) {
        file.close();
    }

}



void RTPReceiver::readPendingDatagrams()
{


    qDebug()<<"readPendingDatagrams方法被执行";
    while (udpSocket->hasPendingDatagrams()) {
        QByteArray datagram;
        datagram.resize(udpSocket->pendingDatagramSize());
        udpSocket->readDatagram(datagram.data(), datagram.size());

         qDebug()<<"传过来的大小"<<datagram.size();

        if (datagram.size() < RTP_HEADER_LENGTH) {
            qDebug() << "Invalid RTP packet";
            continue;
        }

           // QByteArray payload = datagram.mid(RTP_HEADER_LENGTH);

           // 将RTP数据包添加到缓冲区
            buffer.append(datagram.mid(12));
            qDebug()<<"缓存大小"<<buffer.size();



           // 检查缓冲区是否达到一定大小,达到则写入文件
           if (buffer.size() >= bufferSize) {
               writeBufferToFile();
               continue;
           }

           //代表是最后一次请求
           if(buffer.size()<1666){
                writeBufferToFile();

                //关闭文件
                closeFile();
                udpSocket->close();

                //调用whisper去翻译当前音频
                RequestWhisper();

                //重新初始化服务
                initSocket();

                continue;
           }

    }

}


void RTPReceiver::writeBufferToFile()
{
    qDebug()<<"每次写入大小"<<buffer.size();
    if (!file.isOpen()) {
        QString outputFilePath = "F:\\output.wav";
        filePath=outputFilePath;
        file.setFileName(outputFilePath);
        file.open(QIODevice::WriteOnly);
    }

    file.write(buffer);
    file.flush();

    buffer.clear();
}

void RTPReceiver::initSocket()
{
    qDebug()<<"RTP服务被初始化";
    udpSocket = new QUdpSocket(this);
    bool bindResult=udpSocket->bind(QHostAddress::AnyIPv4, 1234); // 替换成实际的RTP端口
    if(!bindResult)
    {
        qDebug()<<"绑定失败";
        return;
    }

    //绑定接收
     qDebug()<<"RTP服务监听中";
    connect(udpSocket, &QUdpSocket::readyRead, this, &RTPReceiver::readPendingDatagrams);
}




注意: 这里需要注意的地方是,如何判断数据包是否是最后一包,这里当时我花了一些时间,最后采取通过判断数据包大小来判断是否是最后一包,我定义的发送的RTP的数据包缓存大小是1400,然后如果小于这个大小,说明是最后一包,这样就可以执行文件关闭和一些其他命令了,还有其他的不同的方式,这里需要你们自己去了解RTP数据包


http://www.niftyadmin.cn/n/5045253.html

相关文章

力扣-228.汇总区间

AC Code 自己做出来的&#xff0c;代码写的很烂&#xff0c;但是也浅浅记录一下叭&#xff0c;下面有看答案思路写出来的双指针代码 class Solution { public:vector<string> summaryRanges(vector<int>& nums) {vector<string> ans;int n nums.size();…

【MySQL】 MySQL索引事务

文章目录 &#x1f6eb;索引&#x1f38d;索引的概念&#x1f333;索引的作用&#x1f384;索引的使用场景&#x1f340;索引的使用&#x1f4cc;查看索引&#x1f4cc;创建索引&#x1f332;删除索引 &#x1f334;索引保存的数据结构&#x1f388;B树&#x1f388;B树&#x…

IDEA2023新UI回退老UI

idea2023年发布了新UI&#xff0c;如下所示 但是用起来真心不好用&#xff0c;各种位置也是错乱&#xff0c;用下面方法可以回退老UI

fastadmin如何本地安装

fastadmin本地安装分几步&#xff1a; 文件地址&#xff1a;/vendor/karsonzhang/fastadmin-addons/src/addons/service.php // 压缩包验证、版本依赖判断&#xff08;大约200多行&#xff09;//Service::valid($params); //改为注释文件地址/application/admin/controller/a…

Vue动态组件 Components

动态组件 Components :::warning 注意 在阅读本问文章之前已经确认你对 Vue 组件有一定的了解。 ::: 基础案例 我们先看一下非动态组件的写法&#xff0c;也就是我们平时常用的组件写法。 <template><div class"home"><Component1 v-if"acti…

资料分析笔记

统计术语 现期&#xff1a;现在的时间 基期&#xff1a;之前的时间 现期量 基期量 增长量&#xff08;有正负&#xff09; 增长率 【增幅、增速、r】&#xff08;有正负&#xff09; 同比&#xff1a;例&#xff1a;2014年5月 和 2013年5月 环比&#xff1a;例&#xff1a;20…

《Linux高性能服务器编程》--高级I/O函数

目录 1--Pipe() 2--dup() 和 dup2() 3--readv() 和 writev() 4--sendfile() 5--mmap() 和 munmap() 6--spice() 7--tea() 8--fcntl() 1--Pipe() #include <unistd.h> int pipe(int fd[2]); // 成功返回0&#xff0c;失败返回-1 pipe() 函数可用于创建一个管道&a…

Compose LazyColumn 对比 RecyclerView ,谁的性能更好?

LazyColumn 是 compose 中用来实现类似 RecyclerView 效果的控件 &#xff0c;但是大家都说LazyColumn性能比RecyclerView差太多&#xff0c;毕竟 RecyclerView google优化了十多年了&#xff0c;比RecyclerView差一点也正常&#xff0c;今天我们就用实际数据来对比LazyColumn和…