ledset优化丢包问题

This commit is contained in:
gangphon 2022-10-14 18:46:16 +08:00
parent caf3ef0add
commit b6e2a745f4
2 changed files with 84 additions and 18 deletions

View File

@ -11,6 +11,7 @@
#include <QDesktopWidget>
#include <QScreen>
#include <QDebug>
#include <QPainter>
using namespace std;
@ -74,7 +75,7 @@ QByteArray getNetDev(QWidget *parent) {
auto dlg = new BaseDlg(parent);
dlg->setAttribute(Qt::WA_DeleteOnClose);
dlg->setWindowTitle("选择网卡");
dlg->resize(1200, 300);
dlg->resize(900, 300);
auto vBox = new QVBoxLayout(dlg->center);
vBox->setContentsMargins(0,0,0,0);
@ -125,12 +126,12 @@ VideoWin *VideoWin::newIns(QWidget *parent) {
auto name = getNetDev(parent);
if(name.isEmpty()) return 0;
char errbuf[PCAP_ERRBUF_SIZE]{'\0'};
auto pcapRe = pcap_open(name.data(), 65535, PCAP_OPENFLAG_PROMISCUOUS | PCAP_OPENFLAG_MAX_RESPONSIVENESS, 15, 0, errbuf);
auto pcapRe = pcap_open_live(name.data(), 65536, PCAP_OPENFLAG_PROMISCUOUS, 50, errbuf);
if(pcapRe == 0) {
QMessageBox::critical(parent, "Error", QString("打开网卡失败")+errbuf);
return 0;
}
auto pcapSend = pcap_open(name.data(), 65535, 0, 15, 0, errbuf);
auto pcapSend = pcap_open_live(name.data(), 65536, 0, 50, errbuf);
if(pcapSend == 0) {
QMessageBox::critical(parent, "Error", QString("打开网卡失败")+errbuf);
return 0;
@ -153,14 +154,14 @@ VideoWin::VideoWin(pcap_t *pcapRece, pcap_t *pcapSend, QWidget *parent) : BaseWi
fdWidth = new QSpinBox;
fdWidth->setRange(1, 9999);
fdWidth->setValue(320);
fdWidth->setValue(640);
hBox->addWidget(fdWidth);
hBox->addWidget(new QLabel("x"));
fdHeight = new QSpinBox;
fdHeight->setRange(1, 9999);
fdHeight->setValue(180);
fdHeight->setValue(360);
hBox->addWidget(fdHeight);
hBox->addSpacing(20);
@ -193,19 +194,32 @@ VideoWin::VideoWin(pcap_t *pcapRece, pcap_t *pcapSend, QWidget *parent) : BaseWi
hBox = new HBox(vBox);
hBox->addWidget(new QLabel("接收:"));
hBox->addSpacing(20);
hBox->addWidget(new QLabel("丢包次数: "));
hBox->addWidget(fdLostTimes = new QLabel);
fdLostTimes->setMinimumWidth(40);
hBox->addWidget(new QLabel("丢包数: "));
hBox->addWidget(fdLostPkts = new QLabel);
fdLostPkts->setMinimumWidth(40);
hBox->addStretch();
auto fdReceive = new QLabel;
vBox->addWidget(fdReceive, 1);
auto fdCanvas = new Canvas;
vBox->addWidget(fdCanvas, 1);
thdRece = new VideoRecThread(pcapRece);
connect(thdRece, &QThread::finished, this, [this] {
thdRece = 0;
});
connect(thdRece, &VideoRecThread::onMsg, fdReceive, [fdReceive](QImage img) {
fdReceive->setPixmap(QPixmap::fromImage(img));
connect(thdRece, &VideoRecThread::onMsg, fdCanvas, [this, fdCanvas](QImage img, int lostTimes, int lostPkts) {
fdCanvas->img = img;
fdCanvas->update();
if(lostPkts==0) return;
this->lostTimes += lostTimes;
this->lostPkts += lostPkts;
fdLostTimes->setText(QString::number(this->lostTimes));
fdLostPkts->setText(QString::number(this->lostPkts));
});
thdRece->start();
thdRece->start(QThread::TimeCriticalPriority);
sendThd = new VideoSendThread(pcapSend);
connect(sendThd, &QThread::finished, this, [this] {
@ -247,6 +261,7 @@ VideoSendThread::VideoSendThread(pcap_t *pcap) : pcap(pcap) {
#define MAX_ONCE 1482
void VideoSendThread::run() {
QImage img;
quint32 idx = 0;
while(status!=2) {
{
std::lock_guard<std::mutex> lock(mtx);
@ -284,7 +299,8 @@ void VideoSendThread::run() {
} else once = lineLen;
auto bytesPerLine = img.bytesPerLine();
auto bits = img.constBits();
for(uint i=0; i<img.height(); i++) for(uint j=0; j<lineLen; j+=once) {
idx = 0;
for(int i=0; i<img.height(); i++) for(int j=0; j<lineLen; j+=once) {
int dataLen = lineLen - j;
if(dataLen > once) dataLen = once;
dataLen += 4;
@ -297,7 +313,8 @@ void VideoSendThread::run() {
bytes.append(2, 0); //应答填充项
crc32 = crc32_calc((uint8_t*)bytes.data()+2, bytes.length()-2);
bytes.append(crc32>>24).append(crc32>>16).append(crc32>>8).append(crc32);
bytes.append(i>>24).append(i>>16).append(i>>8).append(i);
bytes.append(idx>>24).append(idx>>16).append(idx>>8).append(idx);
idx++;
bytes.append((const char*)bits + i * bytesPerLine + j, dataLen - 4);
crc32 = crc32_calc((uint8_t*)bytes.data()+bytes.length()-dataLen, dataLen);
bytes.append(crc32>>24).append(crc32>>16).append(crc32>>8).append(crc32);
@ -321,9 +338,9 @@ void VideoSendThread::run() {
onErr(QString("添加结束失败: ")+pcap_geterr(pcap));
goto end;
}
int res;
u_int res;
if((res = pcap_sendqueue_transmit(pcap, queue, 0)) < queue->len) {
onErr(QString::asprintf("发送包出错: %s. 仅发了 %d bytes", pcap_geterr(pcap), res));
onErr(QString::asprintf("发送包出错: %s. 仅发了 %d / %d bytes", pcap_geterr(pcap), res, queue->len));
goto end;
}
}
@ -332,6 +349,27 @@ void VideoSendThread::run() {
}
}
/* Callback function invoked by libpcap for every incoming packet */
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) {
struct tm ltime;
char timestr[16];
time_t local_tv_sec;
/*
* unused variables
*/
(VOID)(param);
(VOID)(pkt_data);
/* convert the timestamp to readable format */
local_tv_sec = header->ts.tv_sec;
localtime_s(&ltime, &local_tv_sec);
strftime( timestr, sizeof timestr, "%H:%M:%S", &ltime);
printf("%s,%.6d len:%d\n", timestr, header->ts.tv_usec, header->len);
}
VideoRecThread::VideoRecThread(pcap_t *pcap) : pcap(pcap) {
connect(this, &QThread::finished, this, &QThread::deleteLater);
}
@ -340,21 +378,41 @@ void VideoRecThread::run() {
const u_char *data;
QImage img;
int res;
int lastIdx = -1;
int lostTimes{0}, lostPkts{0};
while((res = pcap_next_ex(pcap, &header, &data)) >= 0) {
if(status==2) return;
if(status==1 || res == 0) continue; //超时
if(header->caplen<24) continue;
if(data[0]!=0x55 || data[1]!=0x55) continue;
if(data[2]==0x9a && data[3]==0x3d) {
if(data[17]==0xBB) img = QImage(((int)data[24] << 8) + data[25], ((int)data[26] << 8) + data[27], QImage::Format_RGB888);
else if(data[17]==0xCC) emit onMsg(img);
if(data[17]==0xBB) {
img = QImage(((int)data[24] << 8) + data[25], ((int)data[26] << 8) + data[27], QImage::Format_RGB888);
lastIdx = -1;
lostTimes = 0;
lostPkts = 0;
} else if(data[17]==0xCC) emit onMsg(img, lostTimes, lostPkts);
continue;
}
if(data[2]!=0x1 || data[3]!=0x33) continue;
int len = ((int)data[4] << 8) + data[5];
int row = ((int)data[14] << 8) + data[15];
int col = ((int)data[16] << 8) + data[17];
quint32 idx = ((quint32)data[24] << 24) + ((quint32)data[25] << 16) + ((quint32)data[26] << 8) + data[27];
//auto epoch = chrono::duration_cast<chrono::microseconds>(chrono::steady_clock::now().time_since_epoch()).count();
memcpy(img.bits()+row*img.bytesPerLine()+col, &data[28], len-4);
int diff = idx - lastIdx - 1;
lastIdx = idx;
if(diff > 0) {
//qDebug()<<"丢包"<<diff;
lostTimes++;
lostPkts += diff;
}
}
emit onErr(pcap_geterr(pcap));
}
void Canvas::paintEvent(QPaintEvent *event) {
QPainter painter(this);
painter.drawImage(0, 0, img);
}

View File

@ -44,10 +44,17 @@ public:
protected:
void run();
signals:
void onMsg(QImage);
void onMsg(QImage, int, int);
void onErr(char *);
};
class Canvas : public QWidget {
public:
QImage img;
protected:
void paintEvent(QPaintEvent *event);
};
class VideoWin : public BaseWin {
Q_OBJECT
public:
@ -65,9 +72,10 @@ public:
int timerId{0};
QSpinBox *fdWidth, *fdHeight;
QRadioButton *fdEnd;
QLabel *fdInfo;
QLabel *fdInfo, *fdLostTimes, *fdLostPkts;
QString info;
qint64 last_epoch{0};
int lostTimes{0}, lostPkts{0};
protected:
void timerEvent(QTimerEvent *event) override;
};