Помогите с вопросом
От: milkpot Россия  
Дата: 29.03.24 15:53
Оценка:
Здравствуйте, есть устройство, передающее в хост изображения размером 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 &parameter) {
        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 &param )
    {
        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);
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.