a subforum for "Thermal Imaging"
Hi cynfab,
after terrible hours with a self compiled kernel driver (v4l2loopback.so) for ARM systems
$ find / -name v4l2loopback.ko 2>/dev/zero
/lib/modules/3.18.0-trunk-rpi2/extra/v4l2loopback.ko
/lib/modules/3.18.13-v7+/extra/v4l2loopback.ko
... I suggest new concept for using MJPEG Streamer with our Flir One:
Create a RAMDisk and use the input_file.so module of mjpg_streamer.
It works great with the low powered raspberry pi and you
don't need the loopback devices /dev/videoX(1) create a small ramdisk of 20MB
$ sudo mkdir /mnt/RAMDisk
$ sudo chmod 777 /mnt/RAMDisk
$ sudo mount -t tmpfs -o size=20m none /mnt/RAMDisk
$ df
Filesystem 1K-blocks Used Available Use% Mounted on
none 20480 20480 0 100% /mnt/RAMDisk
(2) compile the code flir8k.c from attachment
check your packages
$ sudo apt-get install libusb-1.0-0
$ sudo apt-get install libusb-1.0-0-dev
$ sudo apt-get install libjpeg-dev
$ make
gcc -I/usr/include/libusb-1.0 -c -o flir8k.o flir8k.c
gcc -I/usr/include/libusb-1.0 -o flir8k Palettes.o flir8k.o -lusb-1.0 -ljpeg -lm -Wall
(3) start the binary
now the binary writes the two images
real.jpg and thermal.jpg to /mnt/RAMDisk/ with 8 fps
$ sudo ./flir8k
Successfully find the Flir One G2 device
Successfully set usb configuration 3
Successfully claimed interface 0,1,2
stop interface 2 FRAME
stop interface 1 FILEIO
start interface 1 FILEIO
:xx Sun Jan 10 16:30:27 2016
: Sun Jan 10 16:30:27 2016
bulk read EP 0x81, actual length 101
HEX:
cc 01 00 00 01 00 00 00 55 00 00 00 30 73 8c df 7b 22 74 79 70 65 22 3a 22 62 61 74 74 65 72 79 56 6f 6c 74 61 67 65 55 70 64 61 74 65 22 2c 22 64 61 74 61 22 3a 7b 22 76 6f 6c 74 61 67 65 22 3a 34 2e 31 37 30 30 30 30 30 37 36 32 39 33 39 35 2c 22 70 65 72 63 65 6e 74 61 67 65 22 3a 31 30 30 7d 7d 00
STRING:
?U0s??{"type":"batteryVoltageUpdate","data":{"voltage":4.17000007629395,"percentage":100}}
: Sun Jan 10 16:30:27 2016
>>>>>>>>>>>>>>>>>bulk transfer (in) 0x83:-7 LIBUSB_ERROR_TIMEOUT
ask for CameraFiles.zip on EP 0x83:
: Sun Jan 10 16:30:28 2016
EP 0x02 to be sent Hexcode: 16 Bytes[ cc 01 00 00 01 00 00 00 41 00 00 00 f8 b3 f7 00 ]
Write successful!
EP 0x02 to be sent: {"type":"openFile","data":{"mode":"r","path":"CameraFiles.zip"}}
Write successful!
Sent 65 bytes with string: {"type":"openFile","data":{"mode":"r","path":"CameraFiles.zip"}}
EP 0x02 to be sent Hexcode: 16 Bytes[ cc 01 00 00 01 00 00 00 33 00 00 00 ef db c1 c1 ]
Write successful!
EP 0x02 to be sent 51 Bytes: {"type":"readFile","data":{"streamIdentifier":10}}
Write successful!
Sent 51 bytes with string: {"type":"readFile","data":{"streamIdentifier":10}}
: Sun Jan 10 16:30:28 2016
Ask for video stream, start EP 0x85:
: Sun Jan 10 16:30:28 2016
>>>>>>>>>>>>>>>>>bulk transfer (in) 0x81:-7 LIBUSB_ERROR_TIMEOUT
#000001 0/10 fps:{"shutterState":"ON","shutterTemperature":310.179992675781,"usbNotifiedTimestamp":1177004833.33163,"usbEnqueuedTimestamp":1177004833.33369,"ffcState":"FFC_VALID_RAD"}
#000002 0/10 fps:{"shutterState":"FFC","shutterTemperature":308.640014648438,"usbNotifiedTimestamp":1177004852.00896,"usbEnqueuedTimestamp":1177004852.01061,"ffcState":"FFC_RAD_APPROX"}
: Sun Jan 10 16:30:47 2016
bulk read EP 0x81, actual length 206
HEX:
cc 01 00 00 01 00 00 00 55 00 00 00 30 73 8c df 7b 22 74 79 70 65 22 3a 22 62 61 74 74 65 72 79 56 6f 6c 74 61 67 65 55 70 64 61 74 65 22 2c 22 64 61 74 61 22 3a 7b 22 76 6f 6c 74 61 67 65 22 3a 34 2e 31 37 30 30 30 30 30 37 36 32 39 33 39 35 2c 22 70 65 72 63 65 6e 74 61 67 65 22 3a 31 30 30 7d 7d 00 cc 01 00 00 01 00 00 00 59 00 00 00 88 cc 5a 95 7b 22 74 79 70 65 22 3a 22 62 61 74 74 65 72 79 43 68 61 72 67 69 6e 67 53 74 61 74 65 55 70 64 61 74 65 22 2c 22 64 61 74 61 22 3a 7b 22 63 68 61 72 67 69 6e 67 53 74 61 74 65 22 3a 22 73 74 61 74 65 43 68 61 72 67 69 6e 67 53 6d 61 72 74 50 68 6f
STRING:
?U0s??{"type":"batteryVoltageUpdate","data":{"voltage":4.17000007629395,"percentage":100}}?Y??Z?{"type":"batteryChargingStateUpdate","data":{"chargingState":"stateChargingSmartPho
#000003 0/10 fps:{"shutterState":"FFC","shutterTemperature":308.640014648438,"usbNotifiedTimestamp":1177004852.57983,"usbEnqueuedTimestamp":1177004852.58155,"ffcState":"FFC_RAD_APPROX"}
#000004 3/10 fps:{"shutterState":"FFC","shutterTemperature":308.640014648438,"usbNotifiedTimestamp":1177004852.69227,"usbEnqueuedTimestamp":1177004852.69411,"ffcState":"FFC_RAD_APPROX"}
#000005 8/10 fps:{"shutterState":"ON","shutterTemperature":308.640014648438,"usbNotifiedTimestamp":1177004852.80562,"usbEnqueuedTimestamp":1177004852.80794,"ffcState":"FFC_RAD_APPROX"}
#000006 11/10 fps:{"shutterState":"ON","shutterTemperature":308.640014648438,"usbNotifiedTimestamp":1177004852.91994,"usbEnqueuedTimestamp":1177004852.92159,"ffcState":"FFC_RAD_APPROX"}
#000007 14/10 fps:{"shutterState":"ON","shutterTemperature":308.640014648438,"usbNotifiedTimestamp":1177004853.03383,"usbEnqueuedTimestamp":1177004853.03595,"ffcState":"FFC_RAD_APPROX"}
#000008 18/10 fps:{"shutterState":"ON","shutterTemperature":308.640014648438,"usbNotifiedTimestamp":1177004853.14999,"usbEnqueuedTimestamp":1177004853.15202,"ffcState":"FFC_RAD_APPROX"}
#000009 20/10 fps:{"shutterState":"ON","shutterTemperature":308.75,"usbNotifiedTimestamp":1177004853.26203,"usbEnqueuedTimestamp":1177004853.26407,"ffcState":"FFC_RAD_APPROX"}
#000010 23/10 fps:{"shutterState":"ON","shutterTemperature":308.75,"usbNotifiedTimestamp":1177004853.37733,"usbEnqueuedTimestamp":1177004853.37923,"ffcState":"FFC_RAD_APPROX"}
#000011 26/10 fps:{"shutterState":"ON","shutterTemperature":308.75,"usbNotifiedTimestamp":1177004853.49003,"usbEnqueuedTimestamp":1177004853.49223,"ffcState":"FFC_RAD_APPROX"}
#000012 28/10 fps:{"shutterState":"ON","shutterTemperature":308.769989013672,"usbNotifiedTimestamp":1177004853.60389,"usbEnqueuedTimestamp":1177004853.60574,"ffcState":"FFC_RAD_APPROX"}
...
#003170 86/10 fps:{"shutterState":"ON","shutterTemperature":310.679992675781,"usbNotifiedTimestamp":1177004033.54082,"usbEnqueuedTimestamp":1177004033.542,"ffcState":"FFC_VALID_RAD"}
#003171 84/10 fps:{"shutterState":"ON","shutterTemperature":310.679992675781,"usbNotifiedTimestamp":1177004033.65724,"usbEnqueuedTimestamp":1177004033.6585,"ffcState":"FFC_VALID_RAD"}
#003172 83/10 fps:{"shutterState":"ON","shutterTemperature":310.679992675781,"usbNotifiedTimestamp":1177004033.76884,"usbEnqueuedTimestamp":1177004033.77,"ffcState":"FFC_VALID_RAD"}
#003173 83/10 fps:{"shutterState":"ON","shutterTemperature":310.679992675781,"usbNotifiedTimestamp":1177004033.88303,"usbEnqueuedTimestamp":1177004033.89359,"ffcState":"FFC_VALID_RAD"}
#003174 84/10 fps:{"shutterState":"ON","shutterTemperature":310.679992675781,"usbNotifiedTimestamp":1177004034.00084,"usbEnqueuedTimestamp":1177004034.00196,"ffcState":"FFC_VALID_RAD"}
#003175 84/10 fps:{"shutterState":"ON","shutterTemperature":310.679992675781,"usbNotifiedTimestamp":1177004034.11106,"usbEnqueuedTimestamp":1177004034.11261,"ffcState":"FFC_VALID_RAD"}
#003176 84/10 fps:{"shutterState":"ON","shutterTemperature":310.679992675781,"usbNotifiedTimestamp":1177004034.2256,"usbEnqueuedTimestamp":1177004034.22683,"ffcState":"FFC_VALID_RAD"}
(4) run a web server on /var/www/
- like apache
$ sudo apt-get install apache2
- link the two files real.jpg and thermal.jpg from RAMDISK to web folder
- check your web folder (current apache on raspi is /var/www/
html/thermal.jpg
$ sudo ln -s /mnt/RAMDisk/thermal.jpg /var/www/thermal.jpg
$ sudo ln -s /mnt/RAMDisk/real.jpg /var/www/real.jpg
// don't forget the "sudo chmod 777 /mnt/RAMDisk" from (1)
now you can see the two images in your web browser
http://192.168.1.70/real.jpg
http://192.168.1.70/thermal.jpg
my raspberry pi has the address 192.168.1.70
(5) View video stream on an iDevice / Smartphone
load from apple app store ore google play store the free app
IP Cam Viewer Lite from NibblesnBits
http://elinux.org/RPi-Cam-Web-Interface#View_video_stream_on_an_iDevice_.2F_SmartphoneSelect the menu icon
Press Manage Cameras
Select Add Camera then Generic URL
Give your cam a name
For Type choose Generic Video URL
Enter your URL, e.g. http://192.168.0.1:80/thermal.jpg
Press Test
If it works, press Save
You can to it twice for thermal.jpg and real.jpg and then you see the two streams parallel.
It's a little bit rough for the large image real.jpg with 9fps over WLAN, but thermal.jpg works fine
(6) create two MJPEG streams for real and thermal image
compile mjpg-streamer from source
mjpg-streamer needs imagemagick
$ sudo apt-get install imagemagick
$ sudo apt-get install subversion
$ svn co svn://svn.code.sf.net/p/mjpg-streamer/code/ mjpg-streamer
...
Checked out revision 182.
$ cd mjpg-streamer/mjpg-streamer
$ make
gcc -D'SVN_REV="3:172"' -O2 -DLINUX -D_GNU_SOURCE -Wall -c -o mjpg_streamer.o mjpg_streamer.c
gcc -D'SVN_REV="3:172"' -O2 -DLINUX -D_GNU_SOURCE -Wall -c -o utils.o utils.c
gcc -D'SVN_REV="3:172"' -O2 -DLINUX -D_GNU_SOURCE -Wall mjpg_streamer.o utils.o -lpthread -ldl -o mjpg_streamer
chmod 755 mjpg_streamer
make -C plugins/input_uvc all
...
cp plugins/input_file/input_file.so
$ ls -al
total 412
drwxr-xr-x 5 pi pi 4096 Jan 10 17:24 .
drwxr-xr-x 10 pi pi 4096 Jan 10 17:22 ..
-rw-r--r-- 1 pi pi 102 Jan 10 17:22 CHANGELOG
-rwxr-xr-x 1 pi pi 14331 Jan 10 17:24 input_file.so
-rwxr-xr-x 1 pi pi 168606 Jan 10 17:24 input_testpicture.so
-rwxr-xr-x 1 pi pi 30905 Jan 10 17:24 input_uvc.so
-rw-r--r-- 1 pi pi 17987 Jan 10 17:22 LICENSE
-rw-r--r-- 1 pi pi 5107 Jan 10 17:22 Makefile
-rwxr-xr-x 1 pi pi 16104 Jan 10 17:24 mjpg_streamer
-rw-r--r-- 1 pi pi 15738 Jan 10 17:22 mjpg_streamer.c
-rw-r--r-- 1 pi pi 3617 Jan 10 17:22 mjpg_streamer.h
-rw-r--r-- 1 pi pi 9800 Jan 10 17:24 mjpg_streamer.o
-rwxr-xr-x 1 pi pi 20284 Jan 10 17:24 output_file.so
-rwxr-xr-x 1 pi pi 32436 Jan 10 17:24 output_http.so
-rwxr-xr-x 1 pi pi 14891 Jan 10 17:24 output_udp.so
drwxr-xr-x 13 pi pi 4096 Jan 10 17:22 plugins
-rw-r--r-- 1 pi pi 2631 Jan 10 17:22 README
drwxr-xr-x 2 pi pi 4096 Jan 10 17:22 scripts
-rwxr-xr-x 1 pi pi 4630 Jan 10 17:22 start.sh
-rw-r--r-- 1 pi pi 285 Jan 10 17:22 TODO
-rw-r--r-- 1 pi pi 2866 Jan 10 17:22 utils.c
-rw-r--r-- 1 pi pi 2399 Jan 10 17:22 utils.h
-rw-r--r-- 1 pi pi 1804 Jan 10 17:24 utils.o
drwxr-xr-x 2 pi pi 4096 Jan 10 17:22 www
You don't need a "sudo make install". Stay in current folder, the are all required binaries included.
test the mjpg_streamer and get the help
$ LD_LIBRARY_PATH=./ ./mjpg_streamer -i "input_file.so -h"
MJPG Streamer Version: svn rev: 3:172
---------------------------------------------------------------
Help for input plugin..: FILE input plugin
---------------------------------------------------------------
The following parameters can be passed to this plugin:
[-d | --delay ]........: delay to pause between frames
[-f | --folder ].......: folder to watch for new JPEG files
[-r | --remove ].......: remove/delete JPEG file after reading
[-n | --name ].........: ignore changes unless filename matches
---------------------------------------------------------------
$ LD_LIBRARY_PATH=./ ./mjpg_streamer -o "output_http.so -h"
MJPG Streamer Version: svn rev: 3:172
---------------------------------------------------------------
Help for output plugin..: HTTP output plugin
---------------------------------------------------------------
The following parameters can be passed to this plugin:
[-w | --www ]...........: folder that contains webpages in
flat hierarchy (no subfolders)
[-p | --port ]..........: TCP port for this HTTP server
[-c | --credentials ]...: ask for "username:password" on connect
[-n | --nocommands ]....: disable execution of commands
---------------------------------------------------------------
write a start script start1.sh (there is already a start.sh)
$ cat ./start1.sh
export LD_LIBRARY_PATH=./
./mjpg_streamer -i "input_file.so -f /mnt/RAMDisk/ -n thermal.jpg" -o "output_http.so -p 8080 -w /usr/local/www" &
./mjpg_streamer -i "input_file.so -d 250 -f /mnt/RAMDisk/ -n real.jpg" -o "output_http.so -p 8081 -w /usr/local/www"
Please note, that I reduced with "-d 250"ms the frame rate of the visible image to 4 fps, to reduce the WLAN bandwidth
and start the script
$ ./start1.sh
MJPG Streamer Version: svn rev: 3:172M
i: folder to watch...: /mnt/RAMDisk/
i: forced delay......: 250
i: delete file.......: no, do not delete
i: filename must be..: real.jpg
o: www-folder-path...: /usr/local/www/
o: HTTP TCP port.....: 8081
MJPG Streamer Version: svn rev: 3:172M
o: username:password.: disabled
o: commands..........: enabled
i: folder to watch...: /mnt/RAMDisk/
i: forced delay......: 0
i: delete file.......: no, do not delete
i: filename must be..: thermal.jpg
o: www-folder-path...: /usr/local/www/
o: HTTP TCP port.....: 8080
o: username:password.: disabled
o: commands..........: enabled
now we have two MJPEG live streams
see the
two web front ends for informations
http://192.168.1.70:8080
http://192.168.1.70:8081
test it with VLC or mplayer etc.
http://192.168.1.70:8080/?action=stream
http://192.168.1.70:8081/?action=stream
(7) a simple html web front endcreate a index.html in your web folder /var/www
$ cat /var/www/index.html
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
body {
text-align:center;
background-color:#000000;
}
.container {
width:100%;
}
.motion1 {
border: 0;
width: 40%;
height: auto;
}
.motion2 {
border: 0;
width: 40%;
height: auto;
}
.clear {
clear:both;
}
</style>
</head>
<body>
<a href="http://192.168.1.70:8080"><img class="motion1" src="http://192.168.1.70:8080/?action=stream" /></a>
<a href="http://192.168.1.70:8081"><img class="motion2" src="http://192.168.1.70:8081/?action=stream" /></a>
</body>
</html>
load the site:
http://192.168.1.70