Rhonda Software

Highest quality full cycle software development.

Expert in areas of Computer Vision, Multimedia, Messaging, Networking and others. Focused on embedded software development. Competent in building cross-platform solutions and distributed SW systems.

Offer standalone custom solutions as well as integration of existing products. Opened for outsourcing services.

Visit us at: http://www.rhondasoftware.com

Cross-platform solution for getting MJPEG stream from AXIS ip-camera (AXIS 211M)

Posted on : 29-08-2009 | By : Andrew Chen | In : OpenCV

2

This paper describes how-to get MJPEG stream from AXIS ip-camera in your C++ application. My approach is a cross-platform solution and much better than solution from http://www.computer-vision-software.com/blog/2009/04/how-to-get-mjpeg-stream-from-axis-ip-cameras-axis-211m-and-axis-214-ptz-as-camera-device-in-opencv-using-directshow/.

Dependencies

We used boost library (boost/asio, http://www.boost.org). There are very useful network interfaces:

  • boost::asio::io_service: the io_service class provides the core I/O functionality for users of the asynchronous I/O objects;
  • boost::asio::ip::tcp::socket: the socket class has a function that will retrieve the remote endpoint;
  • boost::asio::ip::tcp::resolver: the resolver class init net-connection.

Network interface implementing

I created few useful network functions over ”boost::asio”: connecting, sending and receiving packets.

The network interface will be implemented via boost objects. Definitions are:

boost::asio::io_service m_ios;
boost::asio::ip::tcp::socket m_socket(m_ios);
boost::asio::ip::tcp::resolver m_resolver(m_ios);

So, the functions like:

void connect(void)
{
    boost::asio::ip::tcp::resolver::iterator   end_point;
    boost::system::error_code                   ecode;
    boost::asio::ip::tcp::resolver::query     query(boost::asio::ip::tcp::v4(),
                                                                   “192.168.0.1”, “80”);

    end_point = m_resolver.resolve(query);
    m_socket.connect(*iterator, ecode);

    assert(!ecode);
}

int send(void *buffer, int buf_size)
{
    boost::system::error_code   ecode;
    boost::uint32_t                  sent_size = 0;

    sent_size = boost::asio::write(m_socket,
                                             boost::asio::buffer(buffer, buffer_size),
                                             boost::asio::transfer_all(),
                                             ecode);
    if(ecode)
        printf("socket write operation failed\n");

    return sent_size;
}

int receive(void *buffer, int buf_size)
{
    boost::system::error_code   ecode;
    int                                   received_size = 0;

    received_size = boost::asio::read(m_socket,
                                                  boost::asio::buffer(buffer, buffer_size),
                                                  boost::asio::transfer_at_least(1),
                                                  ecode);

    if(ecode)
        printf("socket read operation failed\n");

    return received_size;
}

Also there is disconnect function, it is written in the same manner.

Note: this is reductive version of code for better interpretation.

Getting JPEG frame from ip camera

We should send request to the camera for getting mjpeg stream. The command like:

“GET /axis-cgi/mjpg/video.cgi?resolution=<width>x<height>&fps=<fps>\r\n\r\n”,

where:

  • <width> – width of requested frame;
  • <height> – height of requested frame;
  • <fps> – the requested number of frames per second;
  • “\r\n\r\n – end marker of request.

Example is:

“GET /axis-cgi/mjpg/video.cgi?resolution=640×480&fps=15\r\n\r\n”

The device sends response: 183 bytes. We need to check the response to make sure that is ok.

E.g. successful response:

“HTTP/1.0 200 OK\r\nCache-Control: no-cache\r\nPragma: no-cache\r\nExpires: Thu, 01 Dec 1994 16:00:00 GSM\r\nConnection: close\r\nContent-Type: multipart/x-mixed-replace; boundary=–myboundary”

E.g. unsuccessful response:

“HTTP/1.0 501 Not implemented\r\nDate: Sat, 29 Aug 2009 14:00:10 GSM\r\nAccept-Ranges: bytes\r\nConnection: close\r\n…”

As you can see, the successful response must contain “HTTP/1.0 200 OK” string at beginning.

The value of “boundary” (“–myboundary”) field is most important, because this string will be used as separator further.

The frame will be received part by part. The first packet size is 67 bytes it is meta-information. E.g.:

“–myboundary\r\nContent-Type: image/jpeg\r\nContent-Length: 56296\r\n\r\n”

“–myboundary” string at the begin is confirmation of beginning of new frame. Also, we should read and save value of the field “Content-Length” (56296). It is size of  compressed jpeg frame. The second and following packets are jpeg-picture essentially. We receive few packets with jpg data and save each packet to memory buffer and calculate total size of received packets, and if the total size is equal to value of “Content-Length”, it means that full picture is received and the memory buffer contains it. Now, you can save the memory buffer to the disc-storage (into “123.jpg” file e.g.), and open it with any graphic-viewer and make sure that is usual jpg image.

Note: the jpeg picture should contain the end marker “\r\n” (2 bytes), so I recommend you to receive 2 bytes more.

Next frame can be received with the same aproach: the first package size is 67 bytes…

Note:  symbols “\r\n” – 2 byte 0×0A and 0×0D accordingly.

Also, I recommend to develop separated thread for getting JPG frames from ip camera in order to avoid losing of connection…

We tested this solution under MS Windows, Linux, Intel P4 and also under Intel Atom and ARM Cortex-A8. All works fine.

We are using this approach in my module which decodes each JPG frame from Axis camera and convertes it to OpenCV IplImage (BGR frame).

P.S. Besides, we developed solutions for Arecont and ACTi ip-cameras. Sure, the implementations are different, but common idea is the same.

Comments (2)

How are you able to get through the authentication of camera ? You have to provide username and password; else it will return no-access t0 ‘GET’ command. How to send this username and password over http command ? Please let me know. Thanks in advance

We didn’t use user/password for AXIS camera. For other cameras, we did reverse engineering or found api docs.

Write a comment

Spam Protection by WP-SpamFree