37、mipg-streamer的使用讲解
讲解mjpg-streamer
其功能:
1、控制摄像头采集数据(通过ioctl采集数据,所有不支持CMOS,CMOS之前写驱动的时候是通过read,所有需要修改mjpg-streamer的源码或者CMOS驱动);
2、把采集的数据传输到路由器上或者无线网卡上;
我们的JZ2440可以接一个usb-hub,上面接上无线网卡和摄像头,可以一起使用
1. 如何将mjpg-streamer移植到开发板上
文件系统:fs_mini_mdev_new_auto_wifi_ap.tar.bz2
(1) libjpeg 的移植
tar xzvf libjpeg-turbo-1.2.1.tar.gz
cd libjpeg-turbo-1.2.1
mkdir tmp
./configure --prefix=/work/jz2440/libjpeg-turbo-1.2.1/tmp --host=arm-linux
make
make install
cp /work/jz2440/libjpeg-turbo-1.2.1/tmp/lib/*so* /work/nfs_root/fs_mini_mdev_new/lib/ -d
(2) mjpg-streamer 的移植:
tar xvf mjpg-streamer-r63.tar.gz
cd mjpg-streamer-r63
修改所有的Makefile
--(1) 将 CC=gcc 修改为 CC=arm-linux-gcc
--(2) 修改plugins/input_uvc/Makfile
a. 将
CFLAGS += -O2 -DLINUX -D_GNU_SOURCE -Wall -shared -fPIC
改为
CFLAGS += -O2 -DLINUX -D_GNU_SOURCE -Wall -shared -fPIC -I /work/jz2440/libjpeg-turbo-1.2.1/tmp/include
注意:
-I /work/jz2440/libjpeg-turbo-1.2.1/tmp/include // 是编译libjpeg 生成的文件
b. 将
input_uvc.so: $(OTHER_HEADERS) input_uvc.c v4l2uvc.lo jpeg_utils.lo dynctrl.lo
$(CC) $(CFLAGS) -ljpeg -o $@ input_uvc.c v4l2uvc.lo
jpeg_utils.lo dynctrl.lo
改为
input_uvc.so: $(OTHER_HEADERS) input_uvc.c v4l2uvc.lo jpeg_utils.lo dynctrl.lo
$(CC) $(CFLAGS) -ljpeg -L /work/jz2440/libjpeg-turbo-1.2.1/tmp/lib -o
$@ input_uvc.c v4l2uvc.lo jpeg_utils.lo dynctrl.lo
make
cp mjpg_streamer /work/nfs_root/fs_mini_mdev_new/bin/
cp *so* /work/nfs_root/fs_mini_mdev_new/lib/ -d
运行指令:
二合一摄像头(-i表示输入渠道,-o表示输出渠道)
mjpg_streamer -i "input_uvc.so -f 10 -r 320*240" -o "output_http.so -w www"
一般摄像头
mjpg_streamer -i "input_uvc.so -f 10 -r 320*240 -y" -o "output_http.so -w www"(-y表示压缩图片成jpeg格式,方便传输)
2.分析源码
摄像头数据地址buf、源地址input 、目的地址output,都保存在Mipg_streamer.h这个头文件中的_globals结构体中
编译mjpg-streamer生成的so库中input开头的表示各个输入渠道,out开头的用于表示各个输出渠道
通过-i和-o指定输入和输出渠道后,每个input和output表示一个结构体:这个结构体有init函数、open函数、cmd函数、stop函数
举例:当执行mjpg_streamer -i "input_uvc.so -f 10 -r 320*240" -o "output_http.so -w www"指令时,对应的输入源代码参考input._uvc.c文件,里面有各个函数:
input_init
init_videoIn(videoIn,dev,width,height,fps,format)//设置图像长、宽、帧率、格式
设置vdIn结构体
init_v4l2//里面就是v4l2应用程序的框架
open()//打开摄像头的设备节点,根据传入的参数或者默认参数决定
ioctl(VIDIOC_QUERYCAP)//查看打开的设备的属性,下面会判断是否是视频捕获设备
ioctl(VIDIOC_S_FMT)//设置摄像头的输出格式(分辨率、输出格式)
ioctl(VIDIOC_S_PARM)//设置摄像头的参数,比如输出帧率
ioctl(VIDIOC_REQBUFS)//申请缓存
for(缓存个数)
ioctl(VIDIOC_QUERYBUF)//获取内核空间的视频缓冲区的信息
mmap()//根据获得的信息做映射操作
for(缓存个数)
ioctl(VIDIOC_QBUF)//将一个空的缓冲区放入视频缓冲区队列
分配临时缓冲区(vd->framebuffer)用来接收摄像头数据,MJPEG需要分配两个,见代码
if(dynctrls)//动态控制摄像头功能初始化
initDynCtrls
input_cmd()//通过命令行动态控制摄像头参数,比如高级摄像头的焦距控制
input_run
分配一段buf用来存储视频数据(仓库)
pthread_create(cam_thread)//创建线程,线程函数是cam_thread
cam_thread
while(!pglobal->stop)//stop会在按下CTRL+C的时候会被置1
uvcGrab//获得一帧数据
video_enable//使能视频捕获设备
ioctl(VIDIOC_STREANMON)//将一个空的缓冲区放入视频缓冲区队列
ioctl(VIDIOC_DQBUF)//从视频缓冲区队列取出一个已经存有一帧视频数据的缓冲区buf
根据获得的信息处理数据及根据视频格式把数据复制到init阶段创建的vd->framebuffer中去,MJPEG格式稍微有点不同,其是放到tempbuffer中
ioctl(VIDIOC_QBUF)//把这个已获得数据的空的缓冲区放入视频缓冲区队列
判断数据的格式是YUV或者jpeg,如果是jpeg这直接放入globl里面的buf(仓库),否则将YUV转换为jpeg后在保存在buf
pthread_cond_broadcase(&pglobal->db_update)//通知输出通道可以去数据发出了
对于output_http.so,就是使用sock编程还模拟http协议,查看源码,其中init函数做socket的初始化,run函数从buf中取出数据,然后发送数据
(见output_http.c)
output_init()
仅解析指令参数,然后给相应的变量赋值
output_run()
pthread_create(server_thread)//创建线程,线程函数是server_thread
server_thread
socket(PF_INET,SOCK_STREAM,0)//创建一个socket(其是作为服务器)
setsockopt()//当端口被其他进程使用时,通过这个函数里面指定的参数可以设置重复使用同一个IP和端口号
bind()//绑定端口和IP地址
listen()//启动检测数据,第二个参数表示最多客户端数量
while((!pglobal->stop))//同input_run里面的分析
分配一个cfd结构体
accept()//休眠等待客户端连接,并建立连接
pthread_create(client_thread)//创建线程,线程函数是client_thread
client_thread//参数是上面设置的cfd结构体
init_iobuffer(&iobuf)//初始化一个iobuf,在后面仅是一个临时缓存
init_request(&req)//http协议,需要客户端给服务器发送一个请求,而request就是用来保存请求的
_readline()//从客户端接受一些数据,用来表示客户端发来的请求,才知道给客户发什么数据
这个函数里面调用select函数,当客户端发来数据或者超时的时候返回去调用read函
数从客户端获得数据并保存在iobuf中,接着从iobuf中将数据拷贝到buffer中(这个过程
并不是简单的复制,可以查看代码分析)
因此客户端必须发送一个请求字符串,以换行符作为结束,比如当使用浏览器输入URL
的时候http://192.168.1.17:8080/?action=stream(action=stream这个就表示请求)
从buffer中提取请求并保存在request中
·· do
_readline() 再次读取一次客户端发送过来的字符串
处理buffer中的数据并保存,比如如果有用户名,则保存到req.client;有密码保存到req.credential
如果服务器有账户和密码,则比较客户端传入的账户密码是否匹配
根据第一次客户端发来的请求做不同动作
case A_SNAPSHOT(拍照请求)
send_snapshot(发送照片)
pthread_cond_wait(等待input通道通知有数据可取了)
分配一帧缓冲区,并从global->buf(仓库)中取出数据保存
构造一个http数据头在buffer数据,并将这个数据发送出去(这个数据头表示请求)
如果上一步成功,就把一帧图片发送出去
case A_STREAM
send_stream
构造一个http数据头在buffer数据,并将这个数据发送出去(这个数据头表示请求)
while(!pglobal->stop)
pthread_cond_wait(等待input通道通知有数据可取了)
如果帧framer空间不够就分配空间,并从global->buf(仓库)中取出数据保存
构造一个http数据头(报文)在buffer数据,并将这个数据发送出去(这个数据头表示请求,里面有下面发送帧图片数据大小)
如果上一步成功,就把一帧图片发送出去
接着发送一个“boundarydonotcross”字符串,表示一帧数据已接受完
input_init();
output_init();
input_run();
output_run();
3.自己写客服端(在“在LCD上显示摄像头”的7th_pc上修改程序)
(1).发送一个请求字符串
"GET /?action=snapshot\n"
"GET /?action=stream\n"
"GET /?action=command\n"
(2).再发送一次字符串
如果我们不使用登录密码功能!则只需发送任意长度为小于2字节的字符串,就会跳过处理账户和密码的代码比如:
"f\n"
如果发送的请求是:"GET /?action=snapshot\n"
(3).需要接收一次字符串(是服务器发过来的报文)
(4).接收一帧图片
如果发送的请求是:"GET /?action=stream\n"
(3).需要接收一次字符串(是服务器发过来的报文)
while(1)
{
(4).再接收一次报文,解析它,得到一帧图片的大小(size)
(5).接收size个字节的数据
}
1、在ubuntu上连接2440上无线网卡的wifi热点
2、按住ctrl+Alt+F1进入文本模式,输入用户名和密码
3、运行客户端程序( ./应用程序 开发板IP地址)
4、ctrl+Alt+F4
启动内核:
set ipaddr 192.168.7.122 && set serverip 192.168.7.111 && tftp 0x30000000 uImage
set bootargs root=/dev/nfs nfsroot=192.168.7.202:/work/nfs_root/fs_mini_mdev_new ip=192.168.7.17 console=ttySAC0,115200 && bootm 0x30000000
37、mipg-streamer的使用讲解的更多相关文章
- 【37】池化层讲解(Pooling layers)
池化层(Pooling layers) 除了卷积层,卷积网络也经常使用池化层来缩减模型的大小,提高计算速度,同时提高所提取特征的鲁棒性,我们来看一下. 先举一个池化层的例子,然后我们再讨论池化层的 ...
- 使用sklearn进行K_Means聚类算法
首先附上官网说明 [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html#examples-usin ...
- mahout安装和测试
Mahout 是 Apache Software Foundation(ASF) 旗下的一个开源项目,提供一些可扩展的机器学习领域经典算法的实现,旨在帮助开发者更加方便快捷地创建智能应用程序.Apac ...
- 设计模式课程 设计模式精讲 3-7 接口隔离原则讲解及Coding
1 主讲内容 1.1 核心内容 1.2 优点 1.3 课程记录 2 代码演练 2.1 接口隔离原则反比 2.2 接口隔离原则正比 1 主讲内容 1.1 核心内容 总结:细粒度可以进行再组装,粗粒度不可 ...
- CSharpGL(37)创建和使用VBO的最佳方式
CSharpGL(37)创建和使用VBO的最佳方式 开始 近日在OpenGL红宝书上看到这样的讲解. 其核心意思是,在创建VBO时用 glBufferData(GL_ARRAY_BUFFER, len ...
- KMP的原理详细讲解
1.kmp算法的原理: 本部分内容转自:http://www.cnblogs.com/c-cloud/p/3224788.html及 http:// ...
- 使用Jquery+EasyUI 进行框架项目开发案例讲解之五 模块(菜单)管理源码分享
http://www.cnblogs.com/huyong/p/3454012.html 使用Jquery+EasyUI 进行框架项目开发案例讲解之五 模块(菜单)管理源码分享 在上四篇文章 ...
- 使用Jquery+EasyUI 进行框架项目开发案例讲解之四 组织机构管理源码分享
http://www.cnblogs.com/huyong/p/3404647.html 在上三篇文章 <使用Jquery+EasyUI进行框架项目开发案例讲解之一---员工管理源码分享> ...
- Easyui部分组件讲解
Easyui部分组件讲解 目 录 1.... Accordion(可折叠标签)... 2 1.1 实例... 2 1.2 参数... 3 2.... DateBo ...
随机推荐
- jquery14 on() trigger() : 事件操作的相关方法
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...
- Android 学习笔记进阶14之像素操作
在我们玩的游戏中我们会经常见到一些图像的特效,比如半透明等效果.要实现这种半透明效果其实并不难,需要我们懂得图像像素的操作. 不要怕,其实在Android中Bitmap为我们提供了操作像素的基本方法. ...
- 49.Node.js RESTful API
转自:http://www.runoob.com/nodejs/nodejs-express-framework.html 什么是 REST? REST即表述性状态传递(英文:Representati ...
- Atcoder ABC 070 B、C、D
B - Two Switches Time limit : 2sec / Memory limit : 256MB Score : 200 points Problem Statement Alice ...
- .Net 程序在自定义位置查找托管/非托管 dll 的几种方法
原文:.Net 程序在自定义位置查找托管/非托管 dll 的几种方法 一.自定义托管 dll 程序集的查找位置 目前(.Net4.7)能用的有2种: #define DEFAULT_IMPLEMENT ...
- CODEVS——T 3013 单词背诵
http://codevs.cn/problem/3013/ 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 De ...
- HDU 3072--Intelligence System【SCC缩点新构图 && 求连通全部SCC的最小费用】
Intelligence System Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- js35
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...
- java和javascript日期校验和闰年问题分析和解决方式
1.闰年的介绍 地球绕太阳执行周期为365天5小时48分46秒(合365.24219天)即一回归年.公历的平年仅仅有365日,比回归年短约0.2422 日,所余下的时间约为四年累计一天.故四年于2月加 ...
- eclipse中导入zico Maven项目
zico源代码地址:https://github.com/jitlogic/zico 简单的说,git上同步的源代码需要先进行maven编译,然后导入eclipse. 如果没有配置好maven,请参考 ...