美文网首页
Record mjpeg stream to video fil

Record mjpeg stream to video fil

作者: stnevermore | 来源:发表于2019-04-24 17:36 被阅读0次

Background:

There is a device that could generate mjpeg stream via WIFI. What I need to do is to write a software to play and record the video stream as a mp4 file saved on disk.


Video Play

The main idea of this procedure :

  • Checking Network: Checking whether the network is available by using "ping" command
  • Receiving data bytes: Creating a TCP socket to receive network data bytes
  • Parsing: Parsing the mjpeg type data to get a single QImage
  • Displaying: Displaying each QImage in QLabel

Checking Network

Having searching for many methods of how could confirm the network patency. Finally, the most convenient way is using the PING command.

QStringList parameters;
parameters << "-n" << "1";
parameters << "10.10.10.254";
// exitCode is 0 represents it is alive
int exitCode = QProcess::execute("ping", parameters); 

Receiving data bytes

I am creating a QTcpSocket class named qtcpSock. Perform "connectToHost(ip, port)", "waitForConnected(3000)", "write("GET /?action=stream\r\n\r\n")" respectively.

if (exitCode == 0)  //it is alive
    {
        socket->connectToHost("10.10.10.254", 8080);
        bool isConnected = socket->waitForConnected(3000);
        if (!isConnected)
        {
            QAbstractSocket::SocketError error = socket->error();
            qDebug() << "Error: " << socket->errorString(); //socket error: The proxy type is invalid for this operation
            return -2; // you must connect the VPN, please close it and try it again
        }
        socket->write("GET /?action=stream\r\n\r\n");
        return 0;
    }

Special explanation: Since I am a Chinese code developer, a VPN is essential for in my daily working time. I need to connect the VPN all the time. While the QTcpSocket will return string as "socket error: The proxy type is invalid for this operation". I search the Internet and find this description QTcpSocket在翻墙状态下失效的问题. I have to do the tests with closing VPN down each time.

Parsing

  • mjepg data structure


    mjpeg format.png
  • parsing procedure: when it comes 0xFF byte, checking the following byte. If this byte is 0xD8, it represents the Start Of Image. We should put the bytes followed into the imageBytesBuffer repeatly. If the byte is 0xD9, it represents End Of Image. Now, we have already gotten the completed image bytes and convert them to a whole QImage and then emit it. Finally, clear the buffer and tail the start bytes of next frame.
QByteArray qba = socket->readAll();
    for (int i = 0; i < qba.count(); i++)
    {
        if (enRecv)
            imageBytesBuffer += qba[i];
        if (lastByte == (char)0xFF)
        {
            if (qba[i] == (char)0xD8)
            {
                enRecv = true;
            }
            else if (qba[i] == (char)0xD9)
            {
                if (image.loadFromData(imageBytesBuffer))
                {
                    emitNewImagePixmap(image);
                }
                imageBytesBuffer.clear();
                imageBytesBuffer += 0xFF;
                imageBytesBuffer += 0xD8;
                enRecv = false;
            }
        }
        lastByte = qba[i];
    }

Displaying

It is not very difficult to display the QImage in a QLabel widget. I just write a slot function to resize the image and show it on the widget. The QImage format is RGB32.


Circular Buffer

相关文章

网友评论

      本文标题:Record mjpeg stream to video fil

      本文链接:https://www.haomeiwen.com/subject/jnzggqtx.html