Skip to content
This repository has been archived by the owner on Oct 13, 2023. It is now read-only.

Commit

Permalink
Add Timestamp for each UDP Package
Browse files Browse the repository at this point in the history
Add timestamp for each UDP package, try to find a better way to solve issues about packages out of order.
  • Loading branch information
zty199 committed Mar 24, 2021
1 parent b650f3e commit 589b77f
Show file tree
Hide file tree
Showing 11 changed files with 166 additions and 99 deletions.
43 changes: 23 additions & 20 deletions src/UDPMulticast/audiopacksender.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "audiopacksender.h"

#include <QDateTime>

AudioPackSender::AudioPackSender(char *ap)
{
this->ap = new AudioPack;
Expand Down Expand Up @@ -35,19 +37,20 @@ void AudioPackSender::run()
}

PackageHeader packageHead;
packageHead.uTransPackageHdrSize = sizeof(packageHead);
packageHead.uDataSize = dataLength;
packageHead.uDataPackageNum = packetNum;
packageHead.TransPackageHdrSize = sizeof(packageHead);
packageHead.DataSize = dataLength;
packageHead.DataPackageNum = packetNum;
packageHead.DataPackageTimeStamp = QDateTime::currentMSecsSinceEpoch();

uchar frameBuffer[sizeof(packageHead) + UDP_MAX_SIZE];
memset(frameBuffer, 0, sizeof(packageHead) + UDP_MAX_SIZE);

packageHead.uTransPackageSize = packageHead.uTransPackageHdrSize + UDP_MAX_SIZE;
packageHead.uDataPackageCurrIndex = 0;
packageHead.uDataPackageOffset = 0;
memcpy(frameBuffer, &packageHead, packageHead.uTransPackageHdrSize);
packageHead.TransPackageSize = packageHead.TransPackageHdrSize + UDP_MAX_SIZE;
packageHead.DataPackageCurrIndex = 0;
packageHead.DataPackageOffset = 0;
memcpy(frameBuffer, &packageHead, packageHead.TransPackageHdrSize);
res = audio_socket->writeDatagram(
(const char *)frameBuffer, packageHead.uTransPackageSize,
(const char *)frameBuffer, packageHead.TransPackageSize,
groupAddress, audio_port);
if(res < 0)
{
Expand All @@ -58,14 +61,14 @@ void AudioPackSender::run()
{
if(currentPacketIndex < (packetNum - 1))
{
packageHead.uTransPackageSize = packageHead.uTransPackageHdrSize + UDP_MAX_SIZE;
packageHead.uDataPackageCurrIndex = currentPacketIndex + 1;
packageHead.uDataPackageOffset = currentPacketIndex * UDP_MAX_SIZE;
memcpy(frameBuffer, &packageHead, packageHead.uTransPackageHdrSize);
memcpy(frameBuffer + packageHead.uTransPackageHdrSize, dataBuffer + packageHead.uDataPackageOffset, UDP_MAX_SIZE);
packageHead.TransPackageSize = packageHead.TransPackageHdrSize + UDP_MAX_SIZE;
packageHead.DataPackageCurrIndex = currentPacketIndex + 1;
packageHead.DataPackageOffset = currentPacketIndex * UDP_MAX_SIZE;
memcpy(frameBuffer, &packageHead, packageHead.TransPackageHdrSize);
memcpy(frameBuffer + packageHead.TransPackageHdrSize, dataBuffer + packageHead.DataPackageOffset, UDP_MAX_SIZE);

res = audio_socket->writeDatagram(
(const char *)frameBuffer, packageHead.uTransPackageSize,
(const char *)frameBuffer, packageHead.TransPackageSize,
groupAddress, audio_port);

if(res < 0)
Expand All @@ -77,14 +80,14 @@ void AudioPackSender::run()
}
else
{
packageHead.uTransPackageSize = packageHead.uTransPackageHdrSize + (dataLength - currentPacketIndex * UDP_MAX_SIZE);
packageHead.uDataPackageCurrIndex = currentPacketIndex + 1;
packageHead.uDataPackageOffset = currentPacketIndex * UDP_MAX_SIZE;
memcpy(frameBuffer, &packageHead, packageHead.uTransPackageHdrSize);
memcpy(frameBuffer + packageHead.uTransPackageHdrSize, dataBuffer + packageHead.uDataPackageOffset, dataLength - currentPacketIndex * UDP_MAX_SIZE);
packageHead.TransPackageSize = packageHead.TransPackageHdrSize + (dataLength - currentPacketIndex * UDP_MAX_SIZE);
packageHead.DataPackageCurrIndex = currentPacketIndex + 1;
packageHead.DataPackageOffset = currentPacketIndex * UDP_MAX_SIZE;
memcpy(frameBuffer, &packageHead, packageHead.TransPackageHdrSize);
memcpy(frameBuffer + packageHead.TransPackageHdrSize, dataBuffer + packageHead.DataPackageOffset, dataLength - currentPacketIndex * UDP_MAX_SIZE);

res = audio_socket->writeDatagram(
(const char *)frameBuffer, packageHead.uTransPackageSize,
(const char *)frameBuffer, packageHead.TransPackageSize,
groupAddress, audio_port);

if(res < 0)
Expand Down
13 changes: 7 additions & 6 deletions src/UDPMulticast/audiopacksender.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ class AudioPackSender : public QRunnable

struct PackageHeader
{
quint32 uTransPackageHdrSize;
quint32 uTransPackageSize;
quint32 uDataSize;
quint32 uDataPackageNum;
quint32 uDataPackageCurrIndex;
quint32 uDataPackageOffset;
qint32 TransPackageHdrSize;
qint32 TransPackageSize;
qint32 DataSize;
qint32 DataPackageNum;
qint32 DataPackageCurrIndex;
qint32 DataPackageOffset;
qint64 DataPackageTimeStamp;
};

struct AudioPack
Expand Down
49 changes: 36 additions & 13 deletions src/UDPMulticast/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ MainWindow::MainWindow(QWidget *parent) :
m_viewFinder(new VideoSurface(this)),
flag_camera(false),
m_screen(QApplication::primaryScreen()),
m_cursor(new QLabel),
m_timer(new QTimer(this)),
m_screenPen(new ScreenPen),
flag_screen(false),
Expand Down Expand Up @@ -116,8 +117,19 @@ void MainWindow::initInputDevice()

void MainWindow::initUI()
{
// 初始化鼠标标记
m_cursor->setWindowFlag(Qt::FramelessWindowHint, true);
m_cursor->setWindowFlag(Qt::WindowStaysOnTopHint, true);
// m_cursor->setAttribute(Qt::WA_TranslucentBackground, true);
m_cursor->resize(5, 5);
m_cursor->setAutoFillBackground(true);
m_cursor->setStyleSheet("background-color: rgb(255, 255, 255);");
m_cursor->hide();

// 初始化屏幕画笔
m_screenPen->hide(); // 启动时不显示屏幕画笔
ui->btn_screenPen->setDisabled(true); // 禁用屏幕画笔按钮

ui->cb_resolution->setDisabled(true); // 禁用摄像头分辨率下拉框(摄像头设备启动后才可以使用)

// 初始化主界面设备列表
Expand All @@ -137,7 +149,7 @@ void MainWindow::initConnections()
connect(m_viewFinder, SIGNAL(videoFrameChanged(QVideoFrame)), this, SLOT(on_videoFrameChanged(QVideoFrame)));
connect(m_timer, SIGNAL(timeout()), this, SLOT(on_timeOut()));
connect(this, SIGNAL(volumeChanged(int)), this, SLOT(on_volumeChanged(int)));
// connect(m_timer, SIGNAL(timeout()), this, SLOT(on_mouseMove())); // 屏幕共享时标记鼠标位置
connect(m_timer, SIGNAL(timeout()), this, SLOT(on_mouseMove())); // 屏幕共享时标记鼠标位置
}

void MainWindow::initCamera()
Expand Down Expand Up @@ -301,8 +313,16 @@ void MainWindow::on_videoFrameChanged(QVideoFrame frame)
#elif defined Q_OS_LINUX
image = image.mirrored(false, false);
#endif
image.scaled(image.size().boundedTo(QSize(1280, 720)), Qt::KeepAspectRatio, Qt::FastTransformation); // 分辨率高于 720p 则压缩
image = image.scaled(image.size().boundedTo(QSize(1920, 1080)), Qt::KeepAspectRatio, Qt::SmoothTransformation); // 分辨率高于 1080p 则压缩

if(image.size().height() < 720)
{
video_threadPool->setMaxThreadCount(1);
}
else
{
video_threadPool->setMaxThreadCount(2);
}
video_threadPool->start(new VideoFrameSender(image, this));
}

Expand All @@ -312,6 +332,7 @@ void MainWindow::on_btn_screen_clicked()
{
ui->btn_screenPen->setEnabled(true); // 启用屏幕画笔按钮
m_timer->start(15); // 每隔 15ms 触发(约等于 60Hz 刷新率)
m_cursor->show();
qDebug() << "Screen Share Started!";
flag_screen = true;
flag_camera = true;
Expand All @@ -320,6 +341,8 @@ void MainWindow::on_btn_screen_clicked()
else
{
video_socket->writeDatagram(QString("Stop").toUtf8(), QString("Stop").toUtf8().size(), groupAddress, video_port);

m_cursor->hide();
m_timer->stop();
qDebug() << "Screen Share Stopped!";
ui->videoViewer->clear();
Expand All @@ -342,8 +365,16 @@ void MainWindow::on_timeOut()
oldImage = image;
*/

image.scaled(image.size().boundedTo(QSize(1280, 720)), Qt::KeepAspectRatio, Qt::FastTransformation);
image = image.scaled(image.size().boundedTo(QSize(1920, 1080)), Qt::KeepAspectRatio, Qt::SmoothTransformation);

if(image.size().height() < 720)
{
video_threadPool->setMaxThreadCount(1);
}
else
{
video_threadPool->setMaxThreadCount(2);
}
video_threadPool->start(new VideoFrameSender(image, this));
}

Expand Down Expand Up @@ -474,20 +505,12 @@ void MainWindow::on_deviceReadyRead()
void MainWindow::on_mouseMove()
{
// 由于屏幕共享看不到鼠标,尝试标记鼠标位置
static QLabel label;
label.setWindowFlag(Qt::FramelessWindowHint, true);
label.resize(20, 20);
label.setAutoFillBackground(true);
label.setStyleSheet("background-color: rgb(0, 0, 0);");
label.show();

static QPoint oldPoint;
QPoint point = QCursor::pos(); // 获取鼠标的绝对位置
if(oldPoint != point)
{
label.move(point.x() + 1, point.y() + 1);
qDebug() << "鼠标移动";
qDebug() << point;
m_cursor->move(point.x() + 1, point.y() + 1);
// qDebug() << "鼠标移动 " << point;
oldPoint = point;
}
}
2 changes: 2 additions & 0 deletions src/UDPMulticast/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <QCamera>
#include <QCameraInfo>
#include <QScreen>
#include <QLabel>
#include <QTimer>
#include <QAudio>
#include <QAudioInput>
Expand Down Expand Up @@ -44,6 +45,7 @@ class MainWindow : public QMainWindow
bool flag_camera;

QScreen *m_screen;
QLabel *m_cursor;
QTimer *m_timer;
ScreenPen *m_screenPen;
bool flag_screen;
Expand Down
45 changes: 24 additions & 21 deletions src/UDPMulticast/videoframesender.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "videoframesender.h"

#include <QBuffer>
#include <QDateTime>

VideoFrameSender::VideoFrameSender(QImage image, QObject *parent) :
parent(parent)
Expand Down Expand Up @@ -32,9 +33,10 @@ void VideoFrameSender::run()
QBuffer buffer(&byteArray);
buffer.open(QIODevice::ReadWrite);
image->save(&buffer, "JPEG");
qDebug() << buffer.size();

qint64 res;
quint32 dataLength = buffer.data().size();
qint32 dataLength = buffer.data().size();
uchar *dataBuffer = (uchar *)buffer.data().data();

qint32 packetNum = dataLength / UDP_MAX_SIZE;
Expand All @@ -46,20 +48,21 @@ void VideoFrameSender::run()
}

PackageHeader packageHead;
packageHead.uTransPackageHdrSize = sizeof(packageHead);
packageHead.uDataSize = dataLength;
packageHead.uDataPackageNum = packetNum;
packageHead.TransPackageHdrSize = sizeof(packageHead);
packageHead.DataSize = dataLength;
packageHead.DataPackageNum = packetNum;
packageHead.DataPackageTimeStamp = QDateTime::currentMSecsSinceEpoch();

uchar frameBuffer[sizeof(packageHead) + UDP_MAX_SIZE];
memset(frameBuffer, 0, sizeof(packageHead) + UDP_MAX_SIZE);

// 发送空数据包(仅包含帧数据包大小)
packageHead.uTransPackageSize = packageHead.uTransPackageHdrSize + UDP_MAX_SIZE;
packageHead.uDataPackageCurrIndex = 0;
packageHead.uDataPackageOffset = 0;
memcpy(frameBuffer, &packageHead, packageHead.uTransPackageHdrSize);
packageHead.TransPackageSize = packageHead.TransPackageHdrSize + UDP_MAX_SIZE;
packageHead.DataPackageCurrIndex = 0;
packageHead.DataPackageOffset = 0;
memcpy(frameBuffer, &packageHead, packageHead.TransPackageHdrSize);
res = video_socket->writeDatagram(
(const char *)frameBuffer, packageHead.uTransPackageSize,
(const char *)frameBuffer, packageHead.TransPackageSize,
groupAddress, video_port);
if(res < 0)
{
Expand All @@ -70,14 +73,14 @@ void VideoFrameSender::run()
{
if(currentPacketIndex < (packetNum - 1))
{
packageHead.uTransPackageSize = packageHead.uTransPackageHdrSize + UDP_MAX_SIZE;
packageHead.uDataPackageCurrIndex = currentPacketIndex + 1;
packageHead.uDataPackageOffset = currentPacketIndex * UDP_MAX_SIZE;
memcpy(frameBuffer, &packageHead, packageHead.uTransPackageHdrSize);
memcpy(frameBuffer + packageHead.uTransPackageHdrSize, dataBuffer + packageHead.uDataPackageOffset, UDP_MAX_SIZE);
packageHead.TransPackageSize = packageHead.TransPackageHdrSize + UDP_MAX_SIZE;
packageHead.DataPackageCurrIndex = currentPacketIndex + 1;
packageHead.DataPackageOffset = currentPacketIndex * UDP_MAX_SIZE;
memcpy(frameBuffer, &packageHead, packageHead.TransPackageHdrSize);
memcpy(frameBuffer + packageHead.TransPackageHdrSize, dataBuffer + packageHead.DataPackageOffset, UDP_MAX_SIZE);

res = video_socket->writeDatagram(
(const char *)frameBuffer, packageHead.uTransPackageSize,
(const char *)frameBuffer, packageHead.TransPackageSize,
groupAddress, video_port);

if(res < 0)
Expand All @@ -89,14 +92,14 @@ void VideoFrameSender::run()
}
else
{
packageHead.uTransPackageSize = packageHead.uTransPackageHdrSize + (dataLength - currentPacketIndex * UDP_MAX_SIZE);
packageHead.uDataPackageCurrIndex = currentPacketIndex + 1;
packageHead.uDataPackageOffset = currentPacketIndex * UDP_MAX_SIZE;
memcpy(frameBuffer, &packageHead, packageHead.uTransPackageHdrSize);
memcpy(frameBuffer + packageHead.uTransPackageHdrSize, dataBuffer + packageHead.uDataPackageOffset, dataLength - currentPacketIndex * UDP_MAX_SIZE);
packageHead.TransPackageSize = packageHead.TransPackageHdrSize + (dataLength - currentPacketIndex * UDP_MAX_SIZE);
packageHead.DataPackageCurrIndex = currentPacketIndex + 1;
packageHead.DataPackageOffset = currentPacketIndex * UDP_MAX_SIZE;
memcpy(frameBuffer, &packageHead, packageHead.TransPackageHdrSize);
memcpy(frameBuffer + packageHead.TransPackageHdrSize, dataBuffer + packageHead.DataPackageOffset, dataLength - currentPacketIndex * UDP_MAX_SIZE);

res = video_socket->writeDatagram(
(const char *)frameBuffer, packageHead.uTransPackageSize,
(const char *)frameBuffer, packageHead.TransPackageSize,
groupAddress, video_port);

if(res < 0)
Expand Down
13 changes: 7 additions & 6 deletions src/UDPMulticast/videoframesender.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,13 @@ class VideoFrameSender : public QRunnable
// UDP 包头
struct PackageHeader
{
quint32 uTransPackageHdrSize; // 包头大小(sizeof(PackageHeader))
quint32 uTransPackageSize; // 当前包头的大小(sizeof(PackageHeader) + 当前数据包长度)
quint32 uDataSize; // 数据的总大小
quint32 uDataPackageNum; // 数据被分成包的个数
quint32 uDataPackageCurrIndex; // 数据包当前的帧号
quint32 uDataPackageOffset; // 数据包在整个数据中的偏移
qint32 TransPackageHdrSize; // 包头大小(sizeof(PackageHeader))
qint32 TransPackageSize; // 当前包头的大小(sizeof(PackageHeader) + 当前数据包长度)
qint32 DataSize; // 数据的总大小
qint32 DataPackageNum; // 数据被分成包的个数
qint32 DataPackageCurrIndex; // 数据包当前的帧号
qint32 DataPackageOffset; // 数据包在整个数据中的偏移
qint64 DataPackageTimeStamp; // 数据包时间戳
};

};
Expand Down
Loading

0 comments on commit 589b77f

Please sign in to comment.