Здравствуйте, есть устройство, передающее в хост изображения размером 640Х480 пикселей (каждый пискель — 4 байта)
со скоростью 50 кадров в секунду по протоколу Udp. У пикселя один байт в оттенках серого, остальные три — это rgb.
Первая версия принимала пакеты в главном потоке, в результате чего замерзало окно приложения.
Перенос readPendingDatagrams в рабочую нить привел к тому, что приложение перестало принимать пакеты.
Wireshark видит, что пакеты приходят к хосту от устройства, а приложение пакеты не видит.
Вот фрагменты кода
class Worker2 : public QObject
{
Q_OBJECT
public:
QMutex mutex;
QWaitCondition wtc_worker;
// QPixmap pixmap_copy;
bool wait_cnd;
bool b_counter;
bool c_variable=true;
int data_quant=81920;
QByteArray another_qba;
QUdpSocket *socket;
quint16 package_num;
quint16 str_num;
int color_shift=0;
int i_counter=0;
explicit Worker2()
{
//i_counter=0;
another_qba.resize(2000000/*1228800*/);
socket=new QUdpSocket(this);
bool result;
QVariant value1;
value1=QVariant(2000000/*100000*/);
qDebug() << "QVariant-value1 " << value1.toInt();
result=socket->bind(QHostAddress(QString("192.168.0.1" /*"127.0.0.1"*/)) /*QHostAddress::AnyIPv4*/ /*LocalHost*/,61000/*50011*/);
QString algostr;
algostr=QString(tr("bind returned %1")).arg(result);
qDebug() << algostr;
qDebug() << result;
if(result)
{
qDebug() << "PASS";
}
else
{
qDebug() << "FAIL";
qDebug() << "error" << socket->error();
qDebug() << socket->errorString().toLocal8Bit();
}
socket->setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption,value1);
value1=socket->socketOption(QAbstractSocket::ReceiveBufferSizeSocketOption);
qDebug() << "QVariant-value1_ is " << value1.toInt();
// do_send_result(algostr);
connect(socket, &QUdpSocket::readyRead,this,&/*UDPresource*/Worker2::readPendingDatagrams);
qDebug() << "connect-readPendingDatagrams";
connect(this,&Worker2::writeUdpData,this,&Worker2::setUdpData,Qt::QueuedConnection);
qDebug() << "connect-setUdpData";
}
void /*Window::*/writeData(const QByteArray& qba)
{
QString str;
QString filename("binaryData.bin");
QFile file;
QDataStream dstrm;
int data_quant=0;
QByteArray qba_local;
qba_local.resize(64);
file.setFileName(filename);
if(false==file.open(QIODevice::/*WriteOnly*/Append))
{
str.append(" *** ОШИБКА: не удалось открыть выбранный файл");
/*appendtoLogListBox*/do_send_result(str);
return;
}
dstrm.setDevice(&file);
//data_quant=dstrm.readRawData((char *)&buffer_vect[0],fileSize);
data_quant=dstrm.writeRawData(qba.constData(),qba.size());
file.close();
}
public slots:
void doWork(const QString ¶meter) {
QString result;
bool booL_condition=true;
b_counter=false;
// another_qba.resize(data_quant);
// result=QString(tr("--- another_qba _cnd 2 _ is resized, size is %1")).arg(data_quant);
// do_send_result(result);
/* ... here is the expensive or blocking operation ... */
while(booL_condition)
{
mutex.lock();
wait_cnd=wtc_worker.wait(&mutex, 5400000/*one_and_a_half_hour_wait*/);
// emit resultReady(result);
// do_send_result(result);
// mutex.unlock();
if(false==wait_cnd)
{
result=QString(tr("*** wait_cnd 2 Worker _ is false"));
do_send_result(result);
mutex.unlock();
continue;
}
else if(true==wait_cnd)
{
// while(c_variable)
// {
// if(i_counter==0)
// prepare_generate_data();
// ::Sleep(20);
// }
observe_data();
result=QString(tr("--- wait_cnd 2 _ is true"));
do_send_result(result);
;
//::Sleep(30);
mutex.unlock();
}
}
}
public:
void observe_data()
{
QString str;//ReadOnly
QString filename("binaryData.bin");
QString filenameout("dataOut.bin");
QFile file,file_2;
QDataStream dstrm;
QDataStream dstrm_2;
int data_quant=0;
QByteArray qba_local;
qba_local.resize(648);
;
file.setFileName(filename);
file_2.setFileName(filenameout);
if(false==file.open(QIODevice::/*WriteOnly*//*Append*/ReadOnly))
{
str.append(" *** ОШИБКА 2: не удалось открыть выбранный файл");
/*appendtoLogListBox*/do_send_result(str);
return;
}
if(false==file_2.open(QIODevice::WriteOnly/*Append*//*ReadOnly*/))
{
str.append(" *** ОШИБКА 3: не удалось открыть выбранный файл");
/*appendtoLogListBox*/do_send_result(str);
return;
}
dstrm.setDevice(&file);
dstrm_2.setDevice(&file_2);
while(false==dstrm.atEnd())
{
data_quant=dstrm.readRawData(qba_local.data(),qba_local.size());
// if(data_quant!=8)
// qDebug() << "data_quant != 8";
// // file.seek(640);
data_quant=dstrm_2.writeRawData(qba_local.constData(),qba_local.size()-640);
}
file.close();
file_2.close();
return;
}
public slots:
void readPendingDatagrams()
{
int size_of_data=0;
qint64 ret_value=0;
QByteArray buffer;
QString str;
while(socket->hasPendingDatagrams())
{
size_of_data=socket->pendingDatagramSize();
if(-1==size_of_data) continue;
buffer.resize(/*81920*/ /*64*1024*/ socket->pendingDatagramSize());
QHostAddress sender;
quint16 senderPort;
ret_value=socket->readDatagram(buffer.data(),buffer.size(),&sender,&senderPort);
if(-1==ret_value)
{
str=QString(tr("readDatagram failed"));
qDebug() << str;
do_send_result(str);
// appendtoLogListBox(str);
continue;
}
qDebug() << "Message from: " << sender;
qDebug() << "Message port: " << senderPort;
quint32 value; bool ok;
value=sender.toIPv4Address(&ok);
if(true==ok)
{
str=QString(tr("address is %1 port %2")).arg(value,0,16).arg(senderPort);
//qDebug() << str;
// do_send_result(str);
// appendtoLogListBox(str);
}
writeData(buffer);
emit writeUdpData(buffer);
//qDebug() << "emit writeUdpData(buffer)";
}
}
void /*Window::*/setUdpData(const QByteArray& qba)
{
QString result;
int block=0;
//result=QString(tr("--- Window _ setUdpData slot"));
//appendtoLogListBox(result);
// do_send_result(result);
quint8 kadr_num=qba.at(3);
quint16 str_num=MAKEWORD(qba.at(5),qba.at(4));
quint16 package_num=MAKEWORD(qba.at(7),qba.at(6));
// new commented at 06.03.2024
//int data_quant=81920;
int data_quant=/*1228800*/ 307200;
//qDebug() << "receiveUdpData slot";
// if(qba.size() %648 == 0)qDebug() << "setUdpData qba slot";
if(qba[0]==0x01 && qba[1]==0 && qba[2]==0 )
for(int i=0;i<640;i++)
{
block=/*i+*/8+color_shift;
if(block<648)
{
another_qba[i_counter]=qba.at(/*i+8*/block);
i_counter++;
color_shift+=4;
}
}
if(i_counter==data_quant)
{
color_shift=0;
// wtc_worker.wakeOne();
// c_variable=false;
prepare_generate_data();
i_counter=0;
}
// qDebug() << "i_counter" << i_counter;
return;
}
public:
void prepare_generate_data()
{
QString str;
// str.append(" --- slot button6Clicked() ");
// appendtoLogListBox(str);
QString filePath;
QFile file;
QDataStream dstrm;
int n=0;
int data_quant=0;
std::vector<unsigned short> buffer_vect;
// QSize rct_size(320,256);
QSize rct_size(640,480);
// QPixmap myPixmap;
QImage loc_img(rct_size,QImage::Format_RGB32 /*QImage::Format_RGBX8888*/);
QRgb *line;
// pixmap_vect.clear();
// QBuffer hr;
unsigned long/* long */ start_time=GetTickCount();
// for(int k=0;k<100;k++)
// for(int i=0;i<256;i++)
// {
for(int y=0;y<loc_img.height();y++)
{
// QRgb *line=reinterpret_cast<QRgb*>(loc_img.scanLine(y));
line=static_cast<QRgb *>(static_cast<void *>(loc_img.scanLine(y)));
for(int x=0;x<loc_img.width();x++)
{
line[x]=qRgb(another_qba[n],another_qba[n],another_qba[n]);
n++;
}
}
// pixmap_copy=QPixmap::fromImage( loc_img);
if(b_counter==false)
{
b_counter=true;
}
else
{
//::Sleep(1);
}
;
emit sendData(loc_img/*pixmap_copy*/);
// }
unsigned long/* long */ end_time=GetTickCount();
unsigned long/* long */ loc_delta=end_time-start_time;
// str=QString(tr(" --- loc_delta = %1")).arg(loc_delta);
// do_send_result(str);
// loc_list.clear();
return;
}
signals:
void resultReady(const QString &result);
void sendData(const /*QPixmap*/QImage &image);
void writeUdpData(const QByteArray & );
};
class Controller2 : public QObject
{
Q_OBJECT
QThread workerThread;
Worker2 *worker;
// UDPresource *resource;
public:
Controller2() {
/*Worker * */worker = new Worker2();
// resource = new UDPresource();
worker->moveToThread(&workerThread);
// resource->moveToThread(&workerThread);
connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
connect(this, &Controller2::operate, worker, &Worker2::doWork);//main foo
connect(worker, &Worker2::resultReady, this, &Controller2::handleResults);//print
connect(worker, &Worker2::sendData, this, &Controller2::handlePicture);
// connect(this,&Controller2::writeUdpPacket, resource,&UDPresource::writeToUdp);
connect(this,&Controller2::sign_UdpData, worker, &Worker2::receiveUdpData,Qt::QueuedConnection);
// connect(resource,&UDPresource::resultReady, this,&Controller2::handleResults);//print
// // workerThread.start();
}
~Controller2() {
workerThread.quit();
workerThread.wait();
}
void do_start(const QString ¶m )
{
workerThread.start();
// worker->doWork(QString(tr(" --- Controller: (1) do_start")));
// do_contrl_send_msg(QString(tr(" --- Controller: (2) do_start")));
do_contrl_send_msg(param);
}
void do_contrl_send_msg(const QString &msg)
{
emit operate(msg);
}
void processWaitCond()
{
worker->wtc_worker.wakeOne();
}
public slots:
void handleResults(const QString &str1)
{
emit writeResults(str1);
}
void handlePicture(const QImage/*QPixmap*/ &image)
{
emit writePicture(image);
}
void handleUdpData(const QByteArray& qBinArray)
{
emit sign_UdpData(qBinArray);
qDebug() << "handleUdpData, sign_UdpData(qBinArray) is emited";
}
// void handleWriteData(const QByteArray& qBinArray)
// {
// emit writeUdpPacket(qBinArray);
// }
signals:
void operate(const QString &);
void writeResults(const QString &);
void writePicture(const QImage/*QPixmap*/ &image);
void sign_UdpData(const QByteArray& data);
// void writeUdpPacket(const QByteArray& qBinArray);
};
и
Window::Window()
{
timer->start(10);
QString str,str2,string3;
str.append(" --- Worker");
cntrl=new Controller();
if(nullptr!=cntrl)
{
cntrl->do_start(str);
// b_blocking_res_value=false;
}
cntrl_2=new Controller2();
str2.append(" --- Worker2");
if(nullptr!=cntrl_2)
{
cntrl_2->do_start(str2);
string3=QString(tr("Controller2 is started"));
qDebug() << string3;
// b_blocking_res_value=false;
}
connect(this->cntrl,&Controller::writeResults,this,&Window::appendtoLogListBox);
// connect(this->cntrl,&Controller::writePicture,this,&MainWindow::displayPixmap,Qt::QueuedConnection);
//connect(button,&QPushButton::clicked,this,&Window::launch);
connect(button, SIGNAL(clicked()), this, SLOT(launch()));
connect(button_2, SIGNAL(clicked()), listWidget, SLOT(clear()));
connect(this->cntrl,&Controller::writePicture,this,&Window::displayImage,Qt::QueuedConnection);
// connect(this->cntrl_2,&Controller2::writeResults,this,&Window::appendtoLogListBox);
connect(button_3,SIGNAL(clicked()),this,SLOT(processUdpData()));
connect(button_4,SIGNAL(clicked()),this,SLOT(launchRead()));
connect(this->cntrl_2,&Controller2::writeResults,this,&Window::appendtoLogListBox);//print
connect(this->cntrl_2,&Controller2::writePicture,this,&Window::displayImage,Qt::QueuedConnection);
}