Saturday, November 22, 2014

Undefined References to Boost Libraries - Solution

Yesterday, I was trying to compile a C++ source that uses Gnuplot-iostream interface. I issued the following compilation command:
$ g++ -std=c++11 -lboost_iostreams -lboost_system -lboost_filesystem ProcessScheduler.cpp 
/tmp/cchNNC8H.o: In function `__static_initialization_and_destruction_0(int, int)':
ProcessScheduler.cpp:(.text+0xc52): undefined reference to `boost::system::generic_category()'
ProcessScheduler.cpp:(.text+0xc5e): undefined reference to `boost::system::generic_category()'
ProcessScheduler.cpp:(.text+0xc6a): undefined reference to `boost::system::system_category()'
collect2: error: ld returned 1 exit status
I even had libboost-system-dev, libboost-filesystem-dev and libboost-iostreams-dev installed.
After searching for over an hour, I found that the problem was with how new g++ treated the command-line options.

The solution was to change the position of arguments.
$ g++ -std=c++11  ProcessScheduler.cpp  -lboost_iostreams -lboost_system -lboost_filesystem
So, adding linker parameters after source file worked.
The page at Link Options - GCC states that:
-l library [...] It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, ‘foo.o -lz bar.o’ searches library ‘z’ after file foo.o but before bar.o. If bar.o refers to functions in ‘z’, those functions may not be loaded. [...]

Saturday, June 28, 2014

Streaming USB webcam on Raspberry PI

I had a USB webcam lying around and a Raspberry Pi. And, I wanted to stream it over my local WiFi network. To do this, I picked up MJPEG-Streamer. Connecting the webcam and issuing 'lsmod' showed this:
$ lsmod
.
.
Bus 001 Device 004: ID 0ac8:3420 Z-Star Microelectronics Corp. Venus USB2.0 Camera
The device is supported by UVC driver.
ls /dev/vid*
/dev/video0
So, we have '/dev/video0' as our webcam.
Let's install some required packages.
On a RPi, I have faced multiple issues trying to install packages without first upgrading the system to the latest state. So, let's upgrade the system first.
$ sudo apt-get update && sudo apt-get upgrade
And, some requirements for MJPEG-Streamer
$ sudo apt-get install subversion imagemagick libjpeg8-dev
Now, let's download the latest source
$ svn co https://svn.code.sf.net/p/mjpg-streamer/code/mjpg-streamer/ mjpg-streamer
$ make
When it finishes, it leaves "mjpeg-streamer" binary to the folder. This may be added to path variable. Now, let's stream. 15fps with hardware MJPEG Compression
$ ./mjpg_streamer -i "./input_uvc.so -d /dev/video0 -f 15 " -o "./output_http.so -w ./www"
If you get the error like this:
The input device does not supports MJPEG mode
You may also try the YUV mode (-yuv option), but it requires a much more CPU power
 Init v4L2 failed !! exit fatal 
 i: init_VideoIn failed
Then we need to add '-y' argument to fallback to software mode.
$ ./mjpg_streamer -i "./input_uvc.so -d /dev/video0 -y -f 15" -o "./output_http.so -w ./www"
You can access the web interface at http://<ip>:8080/ where 'ip' is the IP of the Raspberry Pi server. The frame rate can also be changed by specifying the custom value instead of 15. To stream at different resolution with 30fps:
$ ./mjpg_streamer -i "./input_uvc.so -d /dev/video0 -f 15 -r 960x720" -o "./output_http.so -w ./www"
The best part of MJPEG-Streamer is that you can also use VLC or any other streaming player to watch the stream and you are not limited to a web interface.
Happy streaming.