基于web的远程视频传输软件平台

项目名称:基于web的远程视频传输

软件平台:Ubuntu
硬件平台:NanoPi Duo2
备注:硬件平台选择性很多,mini2440、NanoPi系列、树莓派等等。

mjpg-streamerMJPG-streamer
是一款开源基于IP地址的视频流服务器,它的输入插件从摄像头读取视频数据,这个输入插件产生视频数据并将视频数据复制到内存中。它有多个输出插件将这些视频数据经过处理,其中最重要的输出插件是网站服务器插件,它将视频数据传送到用户浏览器中。MJPG-streamer的工作就是将其中的一个输入插件和多个输出插件绑定在一起,所有的工作都是通过它的各个插件完成的。

第一步:

下载源码源码地址:https://sourceforge.net/p/mjpg-streamer/code/HEAD/tree/
可以直接下载源码包的压缩文件:mjpg-streamer-code-r182.zip
或者通过 svn 下载:svn checkout https://svn.code.sf.net/p/mjpg-streamer/code/ mjpg-streamer-code
备注:环境中需要先安装 svn

如果不想麻烦,百度网盘:链接:https://pan.baidu.com/s/1B29YOHRYDkzGpkD0h8HsmA提取码:qjpd,直接获取!

安装mjpg-streamer 需要先安装 libjpeg,libjpeg源码地址https://sourceforge.net/projects/libjpeg/可以使用 wget 直接下载。

第二步:

交叉编译
1、安装交叉编译环境(以NanoPi Duo2平台为例)
* 下载交叉编译器
arm-cortexa9-linux-gnueabihf-4.9.3-20160512.tar.xz
注:NanoPi官网提供下载链接
* 放至 Ubuntu 的 opt 目录下,并且解压

tar -xf arm-cortexa9-linux-gnueabihf-4.9.3-20160512.tar.xz
* 修改文件 /root/.bashrc
* 在最后加上export PATH=$PATH:/opt/4.9.3/bin
* 使修改的文件生效source /root/.bashrc

2、编译 libjpeg
* 解压后进入目录;
* 配置编译环境
./configure --host=arm-linux- --prefix=/home/jpeg-install
* 编译make
* 安装make install
* 安装完毕会在/home目录下看见jpeg-install目录。

3、编译 mjpg-streamer

  • 修改顶层 Makefile
    CC=arm-linux-gcc

  • 修改插件的 Makefile(plugins/input_uvc/Makefile)
    CC=arm-linux-gcc以及动态库路径$(CC) $(CFLAGS) -L /home/jpeg-install -ljpeg -o $@ input_uvc.so

  • 修改插件 Makefile (plugins/output_http/Makefile)
    CC=arm-linux-gcc

    • 编译make

最终生成的文件打包复制到开发板上,需要安装 libjpeg,mjpg-streamer不需要安装。

第三步:

运行
1、配置网络,保证 NanoPi 和电脑可以组成一个局域网;
ifconfig

wlan0Link encap:Ethernet HWaddr c0:84:7d:a0:27:14 
inetaddr:192.168.0.105 Bcast:192.168.0.255 
Mask:255.255.255.0inet6addr: fe80::9e9a:8bbc:69f1:24f0/64 
Scope:LinkUPBROADCAST RUNNING MULTICAST MTU:1500 Metric:1RXpackets:8731 errors:0 dropped:0 
overruns:0 frame:0TXpackets:3727 errors:0 dropped:0 
overruns:0 carrier:0collisions:0 txqueuelen:1000 
RXbytes:6593454 (6.5 MB) TX bytes:502413 (502.4 KB)

开发板的地址是:192.168.0.105,这个很重要。

2、打开笔记本的浏览器,输入:http://192.168.0.105:8080/选择 Stream

源码分析
1、几个重要文件

  • input_testpicture.so:这是一个图像测试插件,它将预设好的图像编译成一个头文件,可以在没有摄像头的情况下传输图像,从而方便调试程序。
  • input_uvc.so:此文件调用USB摄像头驱动程序 V4L2,从摄像头读取视频数据。
  • output_http.so:这是一个功能齐全的网站服务器,它不仅可以从单一文件夹中处理文件,还可以执行一定的命令,它可以从输入插件中处理一幅图像,也可以将输入插件的视频文件根据现有M-JPEG标准以HTTP视频数据服务流形式输出。
  • input_control.so:这个文件实现对摄像头参数的控制。
  • output_file.so:这个插件的功能是将输入插件的JPEG图像存储到特定的文件夹下,它可以用来抓取图像。

2、命令解析

intmain(int argc, char *argv[]){char *input = "input_uvc.so --resolution 640x480 --fps 5 --device /dev/video0";
char *output[MAX_OUTPUT_PLUGINS];//10int daemon=0, i; size_t tmp=0;output[0] = "output_http.so --port 8080";
global.outcnt = 0;global.control = control;/* parameter parsing */while(1) {int option_index = 0, c=0;
staticstruct option long_options[] = \ { {"h", no_argument, 0, 0}, {"help", no_argument, 0, 0}, {"i", required_argument, 0, 0}, {"input", required_argument, 0, 0}, {"o", required_argument, 0, 0}, {"output", required_argument, 0, 0}, {"v", no_argument, 0, 0}, {"version", no_argument, 0, 0}, {"b", no_argument, 0, 0}, {"background", no_argument, 0, 0}, {0, 0, 0, 0} };c = getopt_long_only(argc, argv, "", long_options, &option_index);

这里主要遇到一个功能函数getopt_long_only(),该函数功能主要是解析命令行选项,也就是将input中的-h -i -o -v -b的参数解析出来,该函数具体如何使用,可参照getopt_long_only

3、调用输入插件

/* open input plugin */ tmp = (size_t)(strchr(input, ' ')-input);global.in.plugin = (tmp > 0)?strndup(input, tmp):strdup(input);global.in.handle = dlopen(global.in.plugin, RTLD_LAZY);if ( !global.in.handle ) { LOG("ERROR: could not find input plugin\n"); LOG(" Perhaps you want to adjust the search path with:\n"); LOG(" # export LD_LIBRARY_PATH=/path/to/plugin/folder\n"); LOG(" dlopen: %s\n", dlerror() ); closelog(); exit(EXIT_FAILURE); }global.in.init = dlsym(global.in.handle, "input_init");if ( global.in.init == NULL ) { LOG("%s\n", dlerror()); exit(EXIT_FAILURE); }global.in.stop = dlsym(global.in.handle, "input_stop");if ( global.in.stop == NULL ) { LOG("%s\n", dlerror()); exit(EXIT_FAILURE); }global.in.run = dlsym(global.in.handle, "input_run");if ( global.in.run == NULL ) { LOG("%s\n", dlerror()); exit(EXIT_FAILURE); }dlopen()函数负责打开 *.so 插件,dlsym() 负责调用插件中的相关函数。当输入./mjpg_streamer -i "./input_uvc.so"系统将会调用 input_uvc.so 中的 input_init 函数,对输入设备进行初始化。

4、调用输出插件

/* open output plugin */for (i=0; i<global.outcnt; i++) { tmp = (size_t)(strchr(output[i], ' ')-output[i]);global.out[i].plugin = (tmp > 0)?strndup(output[i], tmp):strdup(output[i]);global.out[i].handle = dlopen(global.out[i].plugin, RTLD_LAZY);if ( !global.out[i].handle ) { LOG("ERROR: could not find output plugin %s\n", global.out[i].plugin); LOG(" Perhaps you want to adjust the search path with:\n"); LOG(" # export LD_LIBRARY_PATH=/path/to/plugin/folder\n"); LOG(" dlopen: %s\n", dlerror() ); closelog(); exit(EXIT_FAILURE); }global.out[i].init = dlsym(global.out[i].handle, "output_init");if ( global.out[i].init == NULL ) { LOG("%s\n", dlerror()); exit(EXIT_FAILURE); }global.out[i].stop = dlsym(global.out[i].handle, "output_stop");if ( global.out[i].stop == NULL ) { LOG("%s\n", dlerror()); exit(EXIT_FAILURE); }if ( global.out[i].stop == NULL ) { LOG("%s\n", dlerror()); exit(EXIT_FAILURE); }global.out[i].run = dlsym(global.out[i].handle, "output_run");if ( global.out[i].run == NULL ) { LOG("%s\n", dlerror()); exit(EXIT_FAILURE); }

5、输入功能分析
intinput_init(input_parameter *param)
这个函数代码实现对 usb 摄像头的格式、帧、请求buf,队列buf等的一些设置,
主要实现也是在函数

init_videoIn(videoIn, dev, width, height, fps, format, 1)
int input_stop(void) 
{ 
 	DBG("will cancel input thread\n"); 
	pthread_cancel(cam); 
	return 0;
} 

输入停止,主要是取消线程。

6、输出功能

intoutput_init(output_parameter *param)
int output_stop(intid)
int output_run(intid)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值