基于QT和UDP实现一个实时RTP数据包的接收,并将数据包转化成文件
简单介绍:代码写的比较详细,需要留意的地方看结尾介绍
头文件
#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数据包