使用live555 直播来自v4l2的摄像头数据,在我的这个工程中,基本思路是:使用V4L2采集摄像头数据,然后使用x264库对摄像头数据进行编码,编成H264数据格式,然后把数据写入到命名管道中。最后使用live555 从管道中读出数据发送出去,实现视频的直播。

在我的工程调试过程中,使用的是罗技C270摄像头,出来的是YUYV数据格式。x264和live555 使用最新的库。工程目录如下:

├── H264FramedLiveSource.cpp
├── H264VideoStreamer.cpp
├── include
│   ├── encoder
│   │   ├── encoder_define.hh
│   │   ├── H264FramedLiveSource.hh
│   │   └── stdint.h
│   ├── live555
│   │   ├── basicUsageEnvironment
│   │   ├── groupsock
│   │   ├── liveMedia
│   │   └── usageEnvironment
│   └── x264
│       ├── x264_config.h
│       └── x264.h
├── lib
│   ├── livelib
│   │   ├── libBasicUsageEnvironment.a
│   │   ├── libgroupsock.a
│   │   ├── libliveMedia.a
│   │   └── libUsageEnvironment.a
│   └── x264lib
│       ├── libx264.a
│       └── libx264.so.148
└── Makefile

H264FramedLiveSource.cpp 中新建了一个Device 类,用来实现v4l2数据的采集和x264编码的实现。其函数定义如下:

/*=============================================================================* #     FileName: H264FramedLiveSource.hh* #         Desc: * #               * #       Author: licaibiao* #      Version: * #   LastChange: 2017-02-24 * =============================================================================*/
#ifndef _H264FRAMEDLIVESOURCE_HH
#define _H264FRAMEDLIVESOURCE_HH
#include <FramedSource.hh>
#include <UsageEnvironment.hh>
#include "encoder_define.hh"class Device
{
public:void init_mmap(void);void init_camera(void);void init_encoder(void);void open_camera(void);  void close_camera(void);void read_one_frame(void);void getnextframe(void);void start_capture(void);void stop_capture(void);void close_encoder(); int  camera_able_read(void);void compress_begin(Encoder *en, int width, int height);int  compress_frame(Encoder *en, int type, char *in, int len, char *out);void compress_end(Encoder *en);void Init();void intoloop();;void Destory();
public:int fd;FILE *save_fd;int n_nal;int frame_len;char *h264_buf;unsigned int n_buffer;Encoder en;FILE *h264_fp;BUFTYPE *usr_buf;FILE *pipe_fd;
};
#endif

H264VideoStreamer.cpp 实现RTSP的创建。其代码实现如下:

/**********
This library is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 3 of the License, or (at your
option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
more details.You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
**********/
// Copyright (c) 1996-2017, Live Networks, Inc.  All rights reserved
// A test program that reads a H.264 Elementary Stream video file
// and streams it using RTP
// main program
//
// NOTE: For this application to work, the H.264 Elementary Stream video file *must* contain SPS and PPS NAL units,
// ideally at or near the start of the file.  These SPS and PPS NAL units are used to specify 'configuration' information
// that is set in the output stream's SDP description (by the RTSP server that is built in to this application).
// Note also that - unlike some other "*Streamer" demo applications - the resulting stream can be received only using a
// RTSP client (such as "openRTSP")#include <liveMedia.hh>
#include <BasicUsageEnvironment.hh>
#include <GroupsockHelper.hh>
#include <H264FramedLiveSource.hh>
#include <sys/types.h>
#include <sys/stat.h> UsageEnvironment* env;
char const* inputFileName = "/tmp/fifo";
char *ptr;
H264VideoStreamFramer* videoSource;
RTPSink* videoSink;
class Device Camera; void play(); // forwardEventTriggerId DeviceSource::eventTriggerId = 0;int main(int argc, char** argv) {// Begin by setting up our usage environment:TaskScheduler* scheduler = BasicTaskScheduler::createNew();env = BasicUsageEnvironment::createNew(*scheduler);// Create 'groupsocks' for RTP and RTCP:struct in_addr destinationAddress;destinationAddress.s_addr = chooseRandomIPv4SSMAddress(*env);// Note: This is a multicast address.  If you wish instead to stream// using unicast, then you should use the "testOnDemandRTSPServer"// test program - not this test program - as a model.const unsigned short rtpPortNum = 18888;const unsigned short rtcpPortNum = rtpPortNum+1;const unsigned char ttl = 255;const Port rtpPort(rtpPortNum);const Port rtcpPort(rtcpPortNum);Camera.Init();mkfifo(inputFileName, 0777);if(0 == fork()){Camera.pipe_fd = fopen(inputFileName, "w");if(NULL == Camera.pipe_fd){printf("===============child process open pipe err =======\n ");}while(1){usleep(15000);Camera.getnextframe();}}Groupsock rtpGroupsock(*env, destinationAddress, rtpPort, ttl);rtpGroupsock.multicastSendOnly(); // we're a SSM sourceGroupsock rtcpGroupsock(*env, destinationAddress, rtcpPort, ttl);rtcpGroupsock.multicastSendOnly(); // we're a SSM source// Create a 'H264 Video RTP' sink from the RTP 'groupsock':OutPacketBuffer::maxSize = 600000;videoSink = H264VideoRTPSink::createNew(*env, &rtpGroupsock, 96);// Create (and start) a 'RTCP instance' for this RTP sink:const unsigned estimatedSessionBandwidth = 10000; // in kbps; for RTCP b/w shareconst unsigned maxCNAMElen = 100;unsigned char CNAME[maxCNAMElen+1];gethostname((char*)CNAME, maxCNAMElen);CNAME[maxCNAMElen] = '\0'; // just in caseRTCPInstance* rtcp= RTCPInstance::createNew(*env, &rtcpGroupsock,estimatedSessionBandwidth, CNAME,videoSink, NULL /* we're a server */,True /* we're a SSM source */);// Note: This starts RTCP running automaticallyRTSPServer* rtspServer = RTSPServer::createNew(*env, 8554);if (rtspServer == NULL) {*env << "Failed to create RTSP server: " << env->getResultMsg() << "\n";exit(1);}ServerMediaSession* sms= ServerMediaSession::createNew(*env, "testStream", inputFileName,"Session streamed by \"testH264VideoStreamer\"",True /*SSM*/);sms->addSubsession(PassiveServerMediaSubsession::createNew(*videoSink, rtcp));rtspServer->addServerMediaSession(sms);char* url = rtspServer->rtspURL(sms);*env << "Play this stream using the URL \"" << url << "\"\n";delete[] url;// Start the streaming:*env << "Beginning streaming...\n";play();env->taskScheduler().doEventLoop(); // does not returnreturn 0; // only to prevent compiler warning
}void afterPlaying(void* /*clientData*/) {*env << "...done reading from file\n";videoSink->stopPlaying();Medium::close(videoSource);Camera.Destory();// Note that this also closes the input file that this source read from.// Start playing once again:play();
}void play() {// Open the input file as a 'byte-stream file source':ByteStreamFileSource* fileSource= ByteStreamFileSource::createNew(*env, inputFileName);if (fileSource == NULL) {*env << "Unable to open file \"" << inputFileName<< "\" as a byte-stream file source\n";exit(1);}FramedSource* videoES = fileSource;// Create a framer for the Video Elementary Stream:videoSource = H264VideoStreamFramer::createNew(*env, videoES);// Finally, start playing:*env << "Beginning to read from file...\n";videoSink->startPlaying(*videoSource, afterPlaying, videoSink);
}

x264 和live555库的下载编译安装,在前面的博客中已经讲过,这里不再重复。编译运行整个工程如下:

[root@redhat pipelive]# ls
H264FramedLiveSource.cpp  H264FramedLiveSource.o  H264VideoStreamer  H264VideoStreamer.cpp  H264VideoStreamer.o  include  lib  Makefile
[root@redhat pipelive]# ./H264VideoStreamercamera driver name is : uvcvideo
camera device name is : UVC Camera (046d:0825)
camera bus information: usb-0000:00:1a.0-1.1
n_buffer = 4
x264 [warning]: lookaheadless mb-tree requires intra refresh or infinite keyint
x264 [info]: using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX
x264 [info]: profile High 4:2:2, level 3.0, 4:2:2 8-bit
Play this stream using the URL "rtsp://192.168.0.127:8554/testStream"
Beginning streaming...
Beginning to read from file...

在VLC 播放器中打开网络流rtsp://192.168.0.127:8554/testStream 可以看到摄像头中的数据:

实际测试,使用管道来传输摄像头数据会出现一些延时,如果图片尺寸设置在320*240 延时会很小,但是图片尺寸设置在640*480,延时现象就会非常明显。这与我使用的摄像头也有关系,UVC摄像头读取数据相对会比较慢。

完整的工程可以从这里下载:live555直播来自v4l2 的摄像头数据

================2018-03-16 更新==================

因为工程中包含x264动态库等文件,某网友下载工程文件后被他电脑某杀毒软件报病毒......

结果那家伙居然回来举报我........  艹    被举报之后下载链接就失效了.......

如果有需要工程代码做参考的可以在评论区留个邮箱,看到后会邮件发送给有需要者。

=================2018-05-14更新======================

代码可以到GitHub 上自行获取, 代码路径:https://github.com/licaibiao/live555_rtsp_live_v4l2

=================2020-01-16更新======================

更新GitHub地址:GitHub - licaibiao/v4l2_video_audio_encode_live

之前代码仓目录已经被调整了。

------------------------------------------2022.08.21------------------------------------------

该博客将停止更新

新的文章内容和附件工程文件

请到 liwen01博客首页信息查询

------------------------------------------2022.08.21------------------------------------------

使用live555 直播来自v4l2的摄像头数据相关推荐

  1. 使用 live555 直播来自 v4l2 的摄像头图像

    结合前面的 采集 v4l2 视频, 使用 live555, 通过 rtsp 发布实时流. capture.h, capture.cpp, vcompress.h, vcompress.cpp 需要参考 ...

  2. FFMPEG(一) 从V4L2捕获摄像头数据

    系列相关博文: FFMPEG(一) 从V4L2捕获摄像头数据 FFMPEG(二) v4l2 数据格式装换 FFMPEG(三) v4l2 数据编码H264 最近在学习FFMPEG,发现网上的很多例子都是 ...

  3. V4L2视频采集与H264编码1—V4L2采集JPEG数据

    最近在做视频编码,经过一段时间的折腾,终于可以把V4L2采集到的图片数据编码成H264视频,并且成功将工程移植到了ARM开发板上.无奈开发板性能太低,每秒钟只能编码一帧数据,查看CPU已经跑到100% ...

  4. live555 直播

    摄像头采集,264编码,live555直播(1) http://www.cnblogs.com/mlj318/archive/2013/01/23/2872932.html 重载FrameSource ...

  5. CenterFusion:融合雷达与摄像头数据的高精度3D目标检测

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 编辑丨我爱计算机视觉 介绍一篇新出的论文 CenterFusion: Center-based Rad ...

  6. 【Android RTMP】NV21 图像旋转处理 ( 快速搭建 RTMP 服务器 Shell 脚本 | 创建 RTMP 服务器镜像 | 浏览器观看直播 | 前置 / 后置摄像头图像旋转效果展示 )

    文章目录 安卓直播推流专栏博客总结 一. 编写快速搭建 RTMP 服务器 Shell 脚本 二. RTMP 快速搭建方法 三.创建阿里云 RTMP 服务器镜像 四.浏览器查看直播内容 五.前置 / 后 ...

  7. V4L2采集视频数据

    Video for Linux two(Video4Linux2)简称V4L2,是V4L的改进版.V4L2是linux操作系统下用于采集图片.视频和音频数据的API接口,配合适当的视频采集设备和相应的 ...

  8. ffmpeg推流摄像头数据至公网服务器

    完整的推流代码已经托管到个人的Gitee,如有需要请自取 https://gitee.com/MonsterAKALei/push_video.git ffmpeg推流摄像头数据 昨天实现用API分别 ...

  9. win摄像头怎么在linux,如何利用Video4Linux获取摄像头数据

    Video4Linux是Linux下用于获取视频和音频数据的API接口,在这篇文章中,着重阐述如何利用Video4Linux获取摄像头数据,以实现连续影像的播放. 1. 摄像头的安装 在 Linux下 ...

最新文章

  1. SparkSQL入门_1
  2. stitching detail输出的dot图含义
  3. 手工部署Sqlserver CLR程序集
  4. 为什么不用简书写文章
  5. axios (get post请求、头部参数添加)傻瓜式入门axios
  6. java arraylist length,在Java中调整ArrayList的大小时,无法理解溢出的可能性
  7. js 中的属性以数字开头的属性和取值
  8. 无人车创业正驶入分水岭
  9. android系统签名
  10. Pandas速查手册中文版(转)
  11. Unity中使用VideoPlayer控制播放暂停进度条
  12. 五、鼎捷T100生产管理之报工
  13. Unity实现打地鼠游戏操作步骤、总结、问题及解决办法
  14. this在什么时候为undefined
  15. 文献阅读——梅州佛教香花的结构、文本与变体
  16. echart 环形饼图设置中心固定信息
  17. 如何将阿里云旧服务器上的数据转移到新服务器上
  18. shell的转义字符
  19. 6.网络安全渗透测试—[信息收集篇6]—[Email信息收集]
  20. [C语言]输出100以内的所有素数(质数)

热门文章

  1. 迈普路由器访问控制列表配置命令_迈普路由器常用使用功能讲解.ppt
  2. 【3dsmax2016】安装图文教程、破解注册以及切换语言方法
  3. 3dsMax2016卡死的一种解决办法
  4. java实现尾递归优化,你们都知道递归,尾递归呢?什么又是尾递归优化?
  5. 计算机电脑类比,2020年广西公务员考试类比推理专项练习(91)
  6. 老二牛车Axure夜话:程序员眼中的原型设计视频教程之书到用时方恨少
  7. 学计算机与学英语作文,myfamily英语作文范文学习
  8. CCF-CSP 202112-2 序列查询新解
  9. java递归实现多级树
  10. Pikachu靶场通过记录