diff --git a/ledset/videowin.cpp b/ledset/videowin.cpp index 3cd0150..bafef73 100644 --- a/ledset/videowin.cpp +++ b/ledset/videowin.cpp @@ -11,6 +11,7 @@ #include #include #include +#include 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 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 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(<ime, &local_tv_sec); + strftime( timestr, sizeof timestr, "%H:%M:%S", <ime); + + 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::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()<<"丢包"<