In this tutorial, I will show you the system I built to stream OpenCV videos over TCP/IP network. The system was tested on both Windows and BSD. Experiments show that the system runs very well and smooth on both systems.
One of the most asked questions by OpenCV users is, "How can I stream videos over the network so I can process it on different computer?" OpenCV does not provide such a function by nature (or so I thought), so we have to write custom code to accomplish this task.
If you have experiences with network programming before, this should be quite easy. Just like when you send text files over the network, the same apply for this one. only this time we need to convert the received data into OpenCV's IplImage format.
In this tutorial, I will explain to you the system I built to stream OpenCV videos over TCP/IP network. Keep in mind that there are many ways to achieve this. Not to mention the freely available video streaming library such as ffmpeg and VLC. This is not about "this one is better", it is just about sharing the knowledge.
The system follows the client-server model. The computer that has the video input acts as the server. It waits for a client to connect and stream the videos once the connection has established. The diagram is shown below.

The diagram above shows several clients connect to the server and receive the streaming video simultaneously. However, to keep things simple, I made it that the server only accepts one client at a time.
If we look deeper into the server side, it should consists from two parts. One who read the video input in a loop, and one who waits for the client and send the video frames. It is impossible to have both parts as a single block of code, since they have to run simultaneously at the same time. To overcome this, we have to write a multi-threaded program.
The same also apply for the client side.
But another problem occurs, Windows and Unix-like systems have different way for handling with threads. While it is possible to write a code that compile and runs on both systems (using C preprocessor), it doesn't necessarily to. Let's just use Unix and throw Windows away.
In addition, I use Berkeley Sockets that is widely available on Unix-like systems for the networking code.
In summary, to make this as simplest as possible we keep these things in mind:
The server side is the computer that has the video input to be streamed. And like I mentioned before, it consists of two parts. One who read the video input in a loop, and the other waits for the client to connect and send the video frames.

In the diagram above, we see two threads running on the server side: Frame Grabber and Stream Server. The input is taken from a webcam, but you can use other resources too, like an avi file.
Frame Grabber grabs a frame from the webcam and stores it to a global variable img. Stream Server waits for a client to connect. Once the connection has established, it sends img to the client repeatedly whenever a newer version of img is available.
The full listing of the server side is in stream_server.c. Next we'll see the detail of both threads.
This is the main thread of the server-side. Its just like the usual code to display video from webcam. Below is the code snippet from stream_server.c.
Listing 1: Frame Grabber
The code above should somehow look familiar with you. It grabs a frame in a loop, save it to a global variable img1, and wait until the user press the 'q' button.
But there are also some additional lines you should have notices. When the program starts, it creates a new thread for the streaming server by the line:
pthread_create(&thread_s, NULL, streamServer, NULL);
After that, the function streamServer runs simultaneously at the same time with the main code. When the program finish (the user pressed the 'q' button) the main code terminates the streamServer thread:
pthread_cancel(thread_s);
Also note that the global variable img1 is used by both threads. Frame Grabber writes it, while Stream Server reads it. It is important to avoid both threads access img1 at the same time, since it will give unwanted result. So we add a lock mechanism when writing img1.
pthread_mutex_lock(&mutex);
cvCvtColor(img0, img1, CV_BGR2GRAY);
is_data_ready = 1;
pthread_mutex_unlock(&mutex);
Just that simple. Now we move to the Stream Server code.
This thread waits for a client to connect to server on a predefined port. Once the connection has established, it sends the global variable img1 repeatedly whenever a newer version is available.
The code snippet of the main loop is shown below.
Listing 2: Stream Server
In the main loop above, the raw data of img1 is sent over the network if a newer version is available.
if (is_data_ready) {
bytes = send(clientsock, img1->imageData, imgsize, 0);
is_data_ready = 0;
}
Note that we make it thread safe by enclosing the lines above with pthread_mutex_lock().
The return value of send() is the number of bytes actually sent, or -1 on error. We need to check the return value in case something wrong has happened, like the client closing the connection. To make things simple, we're just restart the connection if something isn't right.
if (bytes != imgsize) {
close(clientsock);
if ((clientsock = accept(serversock, NULL, NULL)) == -1) {
quit("accept() failed", 1);
}
}
And the line:
pthread_testcancel();
checks if main code has issued pthread_cancel() to terminate this thread.
With the server now has set up and ready to accept connection, now we want to write a client to receive and display the streaming video.
Just like the code at the server side, this one consists of two parts. One who connects to the server and receives the frames, and the other display the received frame whenever a newer version exist.

From the diagram above, we see that there are 2 threads running at the client code. Stream Client receives frames from server and store it to img, meanwhile Video Player reads img and display it in a player window.
Since the client receives frames from a TCP/IP network, it must specify the server's IP address and port number. They are passed as command line arguments when we run the code:
./stream_client 192.168.0.1 8888 320 240
The last 2 arguments are the width and the height of the expected frame. Keep in mind that the server sends only the data, without the image header. So the client must know the width and the height of the expected frame.
Q: Why don't we make it that the image header also being sent?
A: For the sake of code simplicity.
Q: Where do we find the width and the height of the expected frame?
A: From stream_server.c. It prints out the width and the height of the frame it captured.
Q: What if I put numbers that don't match with the received frame?
A: It will give unpredictable results, if you're lucky.
The full listing of the client side is in stream_client.c. Now we move into the details of the client side.
This thread connects to the server, given its IP address and port number. Once the connection has established, it receives the frames sent from server.
Below is the code snippet from stream_client.c.
Listing 3: Stream Client
In the loop above, the client receives the data sent by server with recv() function. However, there is a chance that the delivery of an image is divided into several packets. So we put recv() in a loop to guarantee that we receive a complete image.
for (i = 0; i < imgsize; i += bytes) {
if ((bytes = recv(sock, sockdata + i, imgsize - i, 0)) == -1) {
quit("recv failed", 1);
}
}
If nothing went wrong, now we have the image data in sockdata. We convert the data to OpenCV's IplImage format by copying it to img.
for (i = 0, k = 0; i < img->height; i++) {
for (j = 0; j < img->width; j++) {
((uchar*)(img->imageData + i * img->widthStep))[j] = sockdata[k++];
}
}
The frame has successfully transmitted! Now its the turn for Video Player to read img and display it in a player window.
This should be the easiest part from the whole system. Basically it just display the image in a loop.
Listing 4: Video Player
First, run the Stream Client thread:
pthread_create(&thread_c, NULL, streamClient, NULL);
After that, Stream Client does its job nicely. It receives the frames and store it in the global variable img. And displaying the video cannot be simpler:
cvShowImage("stream_client", img);
Don't forget to terminate Stream Client when the program finished:
pthread_cancel(thread_c);
What else?
With stream_server.c and stream_client.c now in hand, we want to compile and try to stream our cool videos over the network. Here it is.
Compiling in *nix:
$ gcc stream_server.c -o stream_server \
`pkg-config --cflags opencv` \
`pkg-config --libs opencv` -lpthread
$ gcc stream_client.c -o stream_client \
`pkg-config --cflags opencv` \
`pkg-config --libs opencv` -lpthread
Compiling in Windows (under Cygwin):
$ gcc stream_server.c -o stream_server \
-I"C:\OpenCV\cxcore\include" \
-I"C:\OpenCV\cv\include" \
-I"C:\OpenCV\otherlibs\highgui" \
-L"C:\OpenCV\lib" -lcxcore -lcv -lhighgui -lpthread
$ gcc stream_client.c -o stream_client \
-I"C:\OpenCV\cxcore\include" \
-I"C:\OpenCV\cv\include" \
-I"C:\OpenCV\otherlibs\highgui" \
-L"C:\OpenCV\lib" -lcxcore -lcv -lhighgui -lpthread
Replace C:\OpenCV with the directory where you installed OpenCV.
I tested the system on both Windows and BSD operating systems. The thing is, I only got one laptop, so I use VMWare to obtain virtual PCs and simulate TCP/IP network.
In my first test, I ran the stream server and stream client on Windows. The input was taken from an avi file which I obtained from Learning OpenCV's code samples. The screenshot is shown below. Click it to view its original size.
In my second test, I ran the stream server on Windows and stream client on BSD. The input was taken from webcam. Here it is.
Note that I added face detection code at the client side. Obviously, you can do any image/video processing to the received video. That's the point of this project.
In my third test, I ran the stream server and stream client on BSD. The input was the movie 300, in MPEG format. Note that you should compile OpenCV with ffmpeg for reading MPEG files.
And the last, BSD - Windows streaming server. The input was the movie Defiance, in MPEG format. Again, I added face detection code at the client side.
As you can see, the system runs very well and smooth. However, this streaming system uses a lot of bandwidth. This is true since the server streams raw data. You may have to add some video compression if you want to use the system on the Internet.
In this article, I have showed you how to stream your OpenCV videos over TCP/IP network. With this system, you can have your webcam attached on a computer, and your video processing program resides on different computer.
While the project is far from perfect, generally it is all about ideas. Here are some other things that I'm planning to add to the code:
If you encounter any problem compiling and running the code above, feel free to mail me [at] nashruddin.com. Feedbacks are highly appreciated.
Programming with POSIX® Threads
By: David R. Butenhof
This book is a programmer's guide to using and programming POSIX threads, commonly known as Pthreads. A "Coder's book", this title tells how to use Pthreads in the real world, making efficient and portable applications.
BSD Sockets Programming from a Multi-Language Perspective
This book is about socket programming using the standard BSD API. It covers socket programming from the perspective of a number of languages, including C, Python, Perl, Ruby, and Tcl. The techniques covered are applicable to numerous operating system including Linux, Windows/Cygwin, embedded RTOS stacks, and any other system that offers a socket API.
Learning OpenCV: Computer Vision with the OpenCV Library
By: Gary Bradski, Adrian Kaehler
This book is the "de facto" OpenCV User's Manual. It provides a practical, pragmatic, accessible book on computer vision, with algorithmic explanation and concrete example code snippets. Written by the creators of OpenCV, no doubt you should obtain a copy.
rusman on Sep 26, 2009:
Nash on Sep 27, 2009:
Wirasto S. Karim on Sep 30, 2009:
Nash on Sep 30, 2009:
Wirasto S. Karim on Oct 3, 2009:
Nash on Oct 3, 2009:
Wirasto S. Karim on Oct 3, 2009:
Nash on Oct 5, 2009:
Avi on Oct 29, 2009:
Nash on Oct 29, 2009:
rinoa on Feb 25, 2010:
Tybo on May 11, 2010:
Alex on Jun 20, 2010:
| Tel. | +62 31 8662872 +62 856 338 6017 |
| ICQ | 489571630 |
| Skype | dede_bl4ckheart |
| Yahoo | dede_bl4ckheart |
| nashruddin.amin |
Kailash Rathi on Sep 16, 2009:
My website is under construction.
We have baby centers where there are lots of kids / infants.
Center have PCs with multiple webcams for different rooms attached via cables to a PC.
I want to integrate these webcams on my website (.php based website hosted on Linux server)
I want to monitor the kids LIVE (through WEBCAMS) through my websites from REMOTE locations by logging to my website.
I want to control the user access to cameras .. through admin panel I want to assign camera or cameras to user and that user can access / view those webcam(s) only which are assigned in his/her profile.
So in short remote LIVE view of webcameras through logging to website.
We do NOT require any - PAY PER VIEW / PAY PER HOUR etc.. functions. We are not into that work.
This is purely to monitor kids and we will assign cameras to user profile who will get the access of those cameras.
PLEASE HELP ME IN THIS
Regards
Kailash Rathi