无线图传mjpg-streamer精简版(开源)

前言

从去年九月就有想过把mjpg-streamer的http推流精简化了,结果一直拖到现在,而且到现在也只是简单的实现了,工程仍存在bug,那不管怎么样,这个demo终归还是实现了。这个工程可以说是mjpg-streamer的极度精简版,可以将Linux下使用摄像头+WIFI传输图像,简单来说就是一个简单的无线图传。在树莓派ZERO W下测试,在网络好的情况下,达到30帧也是没问题的。

工程结构

要想实现无线图传,主要分为三个要点,一个是实现图像的获取,另一个是实现网络的传输,最后是要考虑图像获取和网络传输如何结合起来。下面的图大致地描述了整个工程的思路,主要是参考了mjpg-streamer的思路。
在这里插入图片描述
一步一步来,先从获取图像开始。

采集图像

由于主控核心板使用Linux系统平台,故本设计采集摄像头数据使用Linux下的视频采集框架V4L2(Linux for Video 2)。在Linux系统平台下,一切皆为文件,视频设备属于设备文件,可对其进行读写操作。V4L2框架提供部分摄像头的底层驱动,主要针对USB摄像头,通常情况下只需要摄像头支持UVC(USB VIDEO CAMERA)协议,即可直接通过调用V4L2的软件接口(API)进行采集。

这里有个注意的地方,如果你使用的是树莓派专用摄像头,可能会发现摄像头打开不了,即/dev下没有设备。可以参考这篇博文:树莓派无法打开摄像头问题

当时碰到一个难题,就是mjpeg保存成一张图片,使用电脑打开是看不到的。也就是说,除了把MJPEG提取出来,还需要转换成JPEG才能在电脑上显示出来,这让我使用了YUYV格式,再用libjpeg转换成JPEG,然后再进行推流。显然,这个速度是比直接采集MJPEG慢很多的,在树莓派ZERO W上跑每秒最多只有5帧,这个效果是很差的。

但是这周我又研究了一下Linux下的V4L2(Video For Linux 2),发现直接提取MJPEG并保存为JPEG格式就可以直接在电脑上显示了。这意味着我之前的代码有问题,提取出来的数据不正确。

MJPEG和JPEG的区别

在电脑能直接显示MJPEG数据的JPEG格式的图像,但这并不意味着这两种格式(MJPEG和JPEG)就没有区别,关于这个区别,在谷歌也没有很多的资料,以下是谷歌出来的区别:

1、JPEG是单页文件格式。Motion JPEG是静态照片的JPEG标准的动态视频改编。MJPEG将视频流视为一系列静态照片,单独压缩每个帧,不使用帧间压缩。

2、使用MJPG像素格式,帧率更高(约30 fps),每帧的字节6,7,8,9(从0开始索引)为’J’,‘F’,‘I’,‘F’ 。如果我使用JPEG,帧速率较低(约6 fps),相同的字节为’E’,‘x’,‘i’,‘f’

如上所述,我个人认为JPEG和MJPEG的差距只是在图像信息上有一些区别,但是在图像数据是没有太大的差异的,当然我也不清楚我这样理解是否正确,希望有知道的小伙伴能指正我的错误。

要写一个mjpg-streamer精简版,首先得获取到摄像头图像的数据。

循环获取图像结构

驱动摄像头并获得一帧图像数据有十一个步骤,分别是:打开设备、检查是否是摄像头设备、设置参数、检查参数是否设置正确、请求缓冲区存储图像数据、配置内存映射、打开摄像头输入开关、从缓冲区取出一帧图像数据、关闭摄像头输入开关、撤销映射、关闭摄像头设备。

在本系统中,仅仅采集一张图片是不够的。进行实时视频传输,则需要不断地进行图像采集、读取和传输。根据上述流程,当打开视频数据输入之后,摄像头模块不断采集数据存至缓冲区,每个缓冲区设置四块,分别代表四张图像,当使用VIDIOC_QBUF接口时,缓存采集到的最新的四张图像数据到四块缓冲块里;当用VIDIOC_DQBUF接口时,将缓冲区中的其中一块图像数据取出。使用了四次VIDIOC_DQBUF指令后,缓存区数据为空,需再次使用VIDIOC_QBUF将最新采集到的图像数据填入缓冲区。
在这里插入图片描述

获取单张图像并保存demo

为了体现效果,这里提供了获取单张图像并保存起来的demo,请读者自行尝试,以保证V4L2是否跑通。直接上代码,里面都有详细注释的。

/*
 *  name:camera.c
 *  author:Hector Cheung
 *  Time: 4, 9, 2019
 */
#include <stdio.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <linux/videodev2.h>
#include<sys/ioctl.h>
#include <setjmp.h>
#include <unistd.h>

#define CAM_DEV "/dev/video0"
#define   WIDTH   640                       // 图片的宽度
#define   HEIGHT  480                       // 图片的高度
#define  NB_BUFFER  4	//memory block number
struct pic_data 
{
   
	unsigned char *tmpbuffer[NB_BUFFER];
	unsigned int tmpbytesused[NB_BUFFER];
}pic;


int cam_fd;

/*
Description.:Initalize V4L2 driver.
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值