C++ 手动QUdpSocket实现是否适合图像流?还是有更好的方法?
我正在为一个图像处理应用程序创建一个远程查看器,需要通过网络发送结果,以便记录它们。我目前正在尝试使用基于QUpdSocket的UDP套接字流式传输图像。UDP很好,因为我不需要每个图像,所以我可以处理潜在的数据包丢失。在localhost上测试下面的实现时,我可以获得>20 fps的速度,这远远超过了我在实际应用程序中需要的速度。但当我移动到网络上的2台电脑时,我几乎没有收到任何图像。我知道数据包正在通过,因为我可以看到网络活动,但我正在丢弃负载,或者解码/渲染过程中发生了一些奇怪的事情 该实现非常基本,因此任何指针都将受到欢迎。或者我不应该自己做这件事,因为有很好的图书馆可以做这类事情 发件人: 等待接收者发送数据包并识别自身,在找到一个数据包后,捕捉图像,将其拆分为数据报大小(此处为508),然后发送x个数据报C++ 手动QUdpSocket实现是否适合图像流?还是有更好的方法?,c++,qt,udp,streaming,qudpsocket,C++,Qt,Udp,Streaming,Qudpsocket,我正在为一个图像处理应用程序创建一个远程查看器,需要通过网络发送结果,以便记录它们。我目前正在尝试使用基于QUpdSocket的UDP套接字流式传输图像。UDP很好,因为我不需要每个图像,所以我可以处理潜在的数据包丢失。在localhost上测试下面的实现时,我可以获得>20 fps的速度,这远远超过了我在实际应用程序中需要的速度。但当我移动到网络上的2台电脑时,我几乎没有收到任何图像。我知道数据包正在通过,因为我可以看到网络活动,但我正在丢弃负载,或者解码/渲染过程中发生了一些奇怪的事情 该实
while (!foundReceiver) {
while (!socket.waitForReadyRead(500));
QByteArray buffer;
buffer.resize(socket.pendingDatagramSize());
socket.readDatagram(buffer.data(), buffer.size(), &sender, nullptr);
if (strcmp("RECEIVER", buffer) == 0) {
foundReceiver = true;
printf_s("Found receiver on : %s", sender.toString().toStdString().c_str());
}
}
printf_s("ctrl-c to quit\n");
while (!socket.hasPendingDatagrams()) {
cv::Mat img = ih->getLatestImage();
if (!img.empty()) {
std::vector<uint8_t> buf;
std::vector<int> params;
params.push_back(IMWRITE_JPEG_QUALITY);
params.push_back(80);
cv::imencode(".jpg", img, buf, params);
char imgDetails[28];
int numPackets = std::ceil((float)buf.size() / (float)datagramSize);
sprintf_s(imgDetails, "START %04d %04d %04d %06d", img.rows, img.cols, numPackets, datagramSize);
bool result = socket.writeDatagram(imgDetails, sizeof(imgDetails), sender, 9000);
for (int i = 0; i < numPackets; i++) {
int start = i * datagramSize;
int end = ((i + 1) * datagramSize);
if (end > buf.size())
end = buf.size();
std::vector<uint8_t> shortBuff((end - start) + 4);
char np[5];
sprintf_s(np, "%04d", i);
for (int j = 0; j < 4; j++)
shortBuff[j] = np[j];
std::copy(buf.begin() + start, buf.begin() + end, shortBuff.begin() + 4);
bool result = socket.writeDatagram((char*)shortBuff.data(), shortBuff.size(), sender, 9000);
}
}
camera.ExecuteSoftwareTrigger();
}
QByteArray buffer;
buffer.resize(socket.pendingDatagramSize());
socket.readDatagram(buffer.data(), buffer.size(), &sender, nullptr);
if (strcmp("RECEIVER DISCONNECT", buffer) == 0) {
foundReceiver = false;
printf_s("Receiver %s disconnected", sender.toString().toStdString().c_str());
}
}
while(!foundReceiver){
而(!socket.waitForReadyRead(500));
QByteArray缓冲区;
resize(socket.pendingDatagramSize());
socket.readDatagram(buffer.data()、buffer.size()、&发送方、nullptr);
如果(strcmp(“接收器”,缓冲器)==0){
foundReceiver=true;
printf_s(“在%s上找到接收方”,sender.toString().tostString().c_str());
}
}
printf_s(“ctrl-c退出”);
而(!socket.hasPendingDatagrams()){
cv::Mat img=ih->getLatestImage();
如果(!img.empty()){
std::载体buf;
std::向量参数;
参数推回(IMWRITE_JPEG_质量);
参数推回(80);
cv::imencode(“.jpg”、img、buf、参数);
charimgdetails[28];
int numPackets=std::ceil((float)buf.size()/(float)datagramSize);
sprintf_s(imgDetails,“开始%04d%04d%04d%06d”,img.rows,img.cols,numPackets,datagramSize);
bool result=socket.writedagram(imgDetails,sizeof(imgDetails),sender,9000);
对于(int i=0;ibuf.size())
end=buf.size();
std::向量shortBuff((结束-开始)+4);
charnp[5];
sprintf_s(np,“%04d”,i);
对于(int j=0;j<4;j++)
shortBuff[j]=np[j];
复制(buf.begin()+开始,buf.begin()+结束,shortBuff.begin()+4);
bool result=socket.writedagram((char*)shortBuff.data(),shortBuff.size(),sender,9000);
}
}
camera.ExecuteSoftwareTrigger();
}
QByteArray缓冲区;
resize(socket.pendingDatagramSize());
socket.readDatagram(buffer.data()、buffer.size()、&发送方、nullptr);
如果(strcmp(“接收器断开”,缓冲器)==0){
foundReceiver=false;
printf_s(“接收器%s已断开”,发送方.toString().tostString().c_str());
}
}
接收人:
QUdpSocket调用datagramPending,datagramPending读取数据报,将数据报发送给precessDatagram,后者决定是报头还是图像包。如果是,则图像数据包将内容移动到数据包开头4位数字指定位置的缓冲区中。当接收到所有图像数据包时,将缓冲区转换为图像
void UDPSocket::datagramPending() {
while (socket->hasPendingDatagrams()) {
QByteArray buffer;
buffer.resize(socket->pendingDatagramSize());
QHostAddress sender;
socket->readDatagram(buffer.data(), buffer.size(), &sender, nullptr);
emit receivedDatagram(buffer, sender);
}
}
void Receiver::processDatagram(QByteArray buff, QHostAddress address) {
if (buff.size() > 0) {
ImageHeader ih = isStartPacket(buff);
if (ih.startPacket) {
streamStarted = true;
senderAddress = address;
currentImageRows = ih.rows;
currentImageCols = ih.cols;
currentImageNumPackets = ih.numPackets;
currentImagePacketSize = ih.packetSize;
rawBuffer = std::vector<uint8_t>(currentImagePacketSize * currentImageNumPackets);
numReceivedPackets = 0;
}
else {
if (rawBuffer.size() > 0) {
std::vector<uint8_t> packetNumChar(5);
std::move(buff.begin(), buff.begin() + 4, packetNumChar.begin());
int packetNumber;
packetNumChar[4] = '\0';
sscanf_s((const char*)packetNumChar.data(), "%04d", &packetNumber);
int start = packetNumber * currentImagePacketSize;
if ((start + buff.size()) < rawBuffer.size())
std::move(buff.begin() + 4, buff.end(), rawBuffer.begin() + start);
numReceivedPackets++;
if (numReceivedPackets == currentImageNumPackets)
emit receivedImage(rawBuffer);
}
}
}
}
ImageHeader Receiver::isStartPacket(QByteArray buff) {
int rows = 0, cols = 0, numPackets = 0, packetSize = 0;
bool startPacket = false;
if (strncmp(buff.data(), startHeader, 5) == 0)
startPacket = true;
if (startPacket)
sscanf_s(buff.data(), "START %04d %04d %04d %06d", &rows, &cols, &numPackets, &packetSize);
ImageHeader ih = { startPacket, rows, cols, numPackets, packetSize };
return ih;
}
void Receiver::receivedImage(std::vector<uint8_t> buff) {
rawImageData = cv::Mat(1, buff.size(), CV_8UC1, buff.data());
currentImage = cv::imdecode(rawImageData, IMREAD_COLOR);
}
void UDPSocket::datagramPending(){
while(套接字->hasPendingDatagrams()){
QByteArray缓冲区;
resize(socket->pendingDatagramSize());
QHostAddress发送者;
socket->readDatagram(buffer.data(),buffer.size(),&sender,nullptr);
发出接收数据(缓冲器、发送器);
}
}
无效接收器::processDatagram(QByteArray buff,QHostAddress){
如果(buff.size()>0){
ImageHeader ih=isStartPacket(buff);
如果(ih.启动包){
streamStarted=true;
senderAddress=地址;
currentImageRows=ih.rows;
currentImageCols=ih.cols;
CurrentImageNumpackes=ih.Numpackes;
currentImagePacketSize=ih.packetSize;
rawBuffer=std::vector(currentImagePacketSize*currentImageNumPackets);
numReceivedPackets=0;
}
否则{
如果(rawBuffer.size()>0){
std::向量包数(5);
移动(buff.begin(),buff.begin()+4,packetNumChar.begin());
国际包裹编号;
packetNumChar[4]='\0';
sscanf_s((const char*)packetNumChar.data(),“%04d”和packetNumber);
int start=packetNumber*currentImagePacketSize;
如果((start+buff.size())