100ask_imx6ull视频监控项目-MJPG-Streamer方案的实现(二)
一、MJPG介绍
使用MJPG
不考虑前后图片得出差异,直接整个上传
采用其他的格式如H264视频格式只会把手部变化的部分上传,但是比较耗CPU资源
可以将rgb格式转换程MJPG格式发布出去
二、配置环境编译镜像文件
我们来配置一下开发板,使用配置好的开发环境后进入buildroot文件目录下
make menuconfig
搜索mjpg
选上即可
执行make
在output/images里面有镜像
烧写emmc.img即可
三、启动板子
mjpg_streamer -i "input_uvc.so -d /dev/video1" -o "output_http.so"
通过input_uvc.so这个动态库打开视频信息,输出到output_http.so通过http发送出去
面对电源线这一端左边网卡是eth0右边是1
开发板上执行这个命令:
mjpg_streamer -i "/usr/lib/mjpg-streamer/input_uvc.so -d /dev/video1 -f 30 -q 90 -n" -o "/usr/lib/mjpg-streamer/output_http.so -w /usr/share/mjpg-streamer/www"
浏览器访问开发的ip:8080
我们回到buildroot的dl/mjpg-streamer
四、分析mjpg应用代码过程:
里面有源码我们提取到windows上解压后查看代码:
我们用到的命令:
mjpg_streamer -i "/usr/lib/mjpg-streamer/input_uvc.so -d /dev/video1 -f 30 -q 90 -n" -o "/usr/lib/mjpg-streamer/output_http.so -w /usr/share/mjpg-streamer/www"
首先-i 参数指定一个动态库(/usr/lib/mjpg-streamer/input_uvc.so) 用来处理读取摄像头数据
-o参数指定另一个动态库(/usr/lib/mjpg-streamer/output_http.so) 用来处理输出数据,输出给浏览器
-d /dev/video1 -f 30 -q 90 -n这是-i的参数给input_uvc.so用的
-w /usr/share/mjpg-streamer/www这是-o的参数给output_http.so用的
上面的图片框架可以看到左边调用input_uvc的动态库
创建一个线程调用uvcGrab读取摄像头读取一帧的数据,如果这个数据不是JPEG格式的话还要转换成JPEG格式的图片,再把数据写入一个全局的buffer。
全局的buffer等待别人来处理
output_http创建一个server_thread线程等待别人来连接
可以使用浏览器来连接开发板的IP,一旦连接了数据发给server_thread
server_thread会创建一个client_thread客户端线程,client_thread会取出global_buffer扔给浏览器
以上就是上面框架的分析!
这个程序涉及多线程编程,线程之间设计唤醒 休眠以及同步操作。涉及网络编程、动态库的使用。
进程有main线程、cam线程 、server线程、 client线程
我们再来把上面的命令后面加上&后台执行
ps一下
进程号345
cd /proc/345/task/
ls一下
有3个线程
现在浏览器连接一下
再连接一下多了一个线程 这个365线程就是我们的client线程
再添加一个浏览器界面连接都会创建一个新的线程
分析代码:
1. main.c中
-i和-o参数的文件保存在对应的数组里面
2.输入插件里面会执行init和run函数
通过dlsym获取init函数和run函数。
3.在input_init里面 有 -d参数,把读到的设备文件名读出来
4.input_run函数会创建线程cam_thread
5.output插件也一样
有init和run函数
6.在input_uvc.c函数中有cam_thread
uvcGrab:获取一帧数据
如果得到的不是JPEG则转换成JPEG
否则直接memcpy_picture就可以了
7.再来分析client 在output_http.c里面
有output_run创建server线程
server_thread在httpd.c文件里面 d通常代表服务器的意思。创建了一个mini的http服务器
底下的代码就写到给每一个连接创建线程
select等待连接:
一旦有数据就add_client
并且创建client_thread
client_thread会从全局的buffer里面读数据发送给浏览器
如果在浏览器上点击stream就会触发这个操作
send_stream里面
有一个死循环,等待新鲜的数据
通过wirte函数写到某个socket文件里面发送出去
代码分析就到这里!
其他用法
我们用input_uvc.so是通过摄像头的数据发送给浏览器
我们也可以通过input_file.so插件从某个目录里面作为MJPG的来源
当然要用output_file.so将数据存为一堆文件
查看帮助:
mjpg_streamer -o "/usr/lib/mjpg-streamer/output_file.so --help"
mjpg_streamer -i "/usr/lib/mjpg-streamer/input_file.so --help"
把摄像头数据存为JPG文件: (-f 指定保存的目录)
mjpg_streamer -i "/usr/lib/mjpg-streamer/input_uvc.so -d /dev/video1 -f 30 -q 90 -n" -o "/usr/lib/mjpg-streamer/output_file.so -f /tmp"
把JPG文件输出到浏览器:(-e 是指定现有的文件如果不加只会取新的文件)
mjpg_streamer -i "/usr/lib/mjpg-streamer/input_file.so -e -f /tmp" -o "/usr/lib/mjpg-streamer/output_http.so -w /usr/share/mjpg-streamer/www"
mjpg_streamer -i "/usr/lib/mjpg-streamer/input_file.so -e -f /home/picture" -o "/usr/lib/mjpg-streamer/output_http.so -w /usr/share/mjpg-streamer/www"
delay1s把图片一张一张的显示
mjpg_streamer -i "/usr/lib/mjpg-streamer/input_file.so -e -f /home/picture" -o "/usr/lib/mjpg-streamer/output_http.so -w /usr/share/mjpg-streamer/www"
我们用上面的命令把板子上现有的图片通过mjpg-streamer通过浏览器查看
并且1s刷新一次