讲解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的使用讲解的更多相关文章

  1. 【37】池化层讲解(Pooling layers)

    池化层(Pooling layers) 除了卷积层,卷积网络也经常使用池化层来缩减模型的大小,提高计算速度,同时提高所提取特征的鲁棒性,我们来看一下.   先举一个池化层的例子,然后我们再讨论池化层的 ...

  2. 使用sklearn进行K_Means聚类算法

    首先附上官网说明 [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html#examples-usin ...

  3. mahout安装和测试

    Mahout 是 Apache Software Foundation(ASF) 旗下的一个开源项目,提供一些可扩展的机器学习领域经典算法的实现,旨在帮助开发者更加方便快捷地创建智能应用程序.Apac ...

  4. 设计模式课程 设计模式精讲 3-7 接口隔离原则讲解及Coding

    1 主讲内容 1.1 核心内容 1.2 优点 1.3 课程记录 2 代码演练 2.1 接口隔离原则反比 2.2 接口隔离原则正比 1 主讲内容 1.1 核心内容 总结:细粒度可以进行再组装,粗粒度不可 ...

  5. CSharpGL(37)创建和使用VBO的最佳方式

    CSharpGL(37)创建和使用VBO的最佳方式 开始 近日在OpenGL红宝书上看到这样的讲解. 其核心意思是,在创建VBO时用 glBufferData(GL_ARRAY_BUFFER, len ...

  6. KMP的原理详细讲解

    1.kmp算法的原理: 本部分内容转自:http://www.cnblogs.com/c-cloud/p/3224788.html及                           http:// ...

  7. 使用Jquery+EasyUI 进行框架项目开发案例讲解之五 模块(菜单)管理源码分享

    http://www.cnblogs.com/huyong/p/3454012.html 使用Jquery+EasyUI 进行框架项目开发案例讲解之五  模块(菜单)管理源码分享    在上四篇文章 ...

  8. 使用Jquery+EasyUI 进行框架项目开发案例讲解之四 组织机构管理源码分享

    http://www.cnblogs.com/huyong/p/3404647.html 在上三篇文章  <使用Jquery+EasyUI进行框架项目开发案例讲解之一---员工管理源码分享> ...

  9. Easyui部分组件讲解

    Easyui部分组件讲解 目  录 1.... Accordion(可折叠标签)... 2 1.1          实例... 2 1.2          参数... 3 2.... DateBo ...

随机推荐

  1. jquery14 on() trigger() : 事件操作的相关方法

    <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...

  2. Android 学习笔记进阶14之像素操作

    在我们玩的游戏中我们会经常见到一些图像的特效,比如半透明等效果.要实现这种半透明效果其实并不难,需要我们懂得图像像素的操作. 不要怕,其实在Android中Bitmap为我们提供了操作像素的基本方法. ...

  3. 49.Node.js RESTful API

    转自:http://www.runoob.com/nodejs/nodejs-express-framework.html 什么是 REST? REST即表述性状态传递(英文:Representati ...

  4. Atcoder ABC 070 B、C、D

    B - Two Switches Time limit : 2sec / Memory limit : 256MB Score : 200 points Problem Statement Alice ...

  5. .Net 程序在自定义位置查找托管/非托管 dll 的几种方法

    原文:.Net 程序在自定义位置查找托管/非托管 dll 的几种方法 一.自定义托管 dll 程序集的查找位置 目前(.Net4.7)能用的有2种: #define DEFAULT_IMPLEMENT ...

  6. CODEVS——T 3013 单词背诵

    http://codevs.cn/problem/3013/  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解  查看运行结果     题目描述 De ...

  7. HDU 3072--Intelligence System【SCC缩点新构图 &amp;&amp; 求连通全部SCC的最小费用】

    Intelligence System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  8. js35

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...

  9. java和javascript日期校验和闰年问题分析和解决方式

    1.闰年的介绍 地球绕太阳执行周期为365天5小时48分46秒(合365.24219天)即一回归年.公历的平年仅仅有365日,比回归年短约0.2422 日,所余下的时间约为四年累计一天.故四年于2月加 ...

  10. eclipse中导入zico Maven项目

    zico源代码地址:https://github.com/jitlogic/zico 简单的说,git上同步的源代码需要先进行maven编译,然后导入eclipse. 如果没有配置好maven,请参考 ...