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

7

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 0x0A and 0x0D 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 (7)

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.

Hi,

Presently i am working on AXIS M1031-W IP Camera for accessing the live streams. Now I would like to get the MJPEG streams. Do you have any solution how to upload them into a server and accessing the streams in android smart phone. Kindly help me in this context if you have any ideas.

Thanks & Regards,
Karumanchi

Hi Karumanchi,

If the solution is required only for one camera, you could configure ip camera with external ip (internet address) or configure NAT, and then find some MJPEG client for android (http://www.google.com/#hl=en&source=hp&q=android+MJPEG+client&aq=f&aqi=&aql=&oq=&gs_rfai=&fp=1).

Aleksey

How to get the audio in a similar way ? Any idea what is the http command for getting audio or the mpeg stream ?

can you make tutorial how to integrate opencv and gstreamer in c++?
i want to process video stream from rtsp server with opencv
thank you

Failed to access a Color CCD camera interfaced with EasyCap USB 2.0 (Audio-Video Adapter) in OpenCV

I have CCD camera with RCA connectors. Now I have to interface this CCD camera with my laptop so that i can use it as webcam. Hence i opted for Easycap USB 2.0 audio-video adapter (http://easycap.co.uk/) to get the video signal from camera RCA connector to USB so that i can plugin to my laptop. Once after installing Easycap driver, I was able to interface the camera with my laptop.

When I tried to access the same interfaced camera using openCV, it was not happening :(. But with the same piece of code , i was able to access inbuilt USB camera in my laptop. Please tell me, why im not able to read the CCD camera as device when interfaced using EasyCap. Where am’i going wrong !!!!!

he code which i used to access the CCD camera was ::

#include “stdafx.h”
#include
#include
# include
#include

int _tmain(int argc, _TCHAR* argv[])
{

CvCapture* capture = cvCaptureFromCAM(0);

cvNamedWindow(“video”, CV_WINDOW_AUTOSIZE );

IplImage *img1=NULL;

while( 1 )
{
img1 = cvQueryFrame(capture);

cvShowImage(“video”, img1);

if( (cvWaitKey(10) & 255) == 27 ) break;
}
cvReleaseCapture( &capture );
cvDestroyWindow( “video” );
return 0;
}

Hope Im clear…Thanks in advance ..

Write a comment