使用live555类库实现的网络直播系统——直播H264文件

2024-03-02 04:40

本文主要是介绍使用live555类库实现的网络直播系统——直播H264文件,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

    下载live555最新代码,编译生成live555 的库文件:libBasicUsageEnvironment.a  libgroupsock.a  libliveMedia.a  libUsageEnvironment.a ,使用这4个库再加上live555 自带的测试程序,可以很简单的实现live555 的直播。live555提供的直播程序是只能直播之前已经录制好的视频(与点播不同)。代码如下:

/*=============================================================================FileName: h264live.cDesc: use the lib of live555 to do liveAuthor: licaibiaoVersion: LastChange: 2017-02-23 
*=============================================================================*/
#include "h264live.hh"UsageEnvironment* env;
char const* inputFileName = "test.264";
H264VideoStreamFramer* videoSource;
RTPSink* videoSink;void play(); // forwardint 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);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 = 100000;videoSink = H264VideoRTPSink::createNew(*env, &rtpGroupsock, 96);// Create (and start) a 'RTCP instance' for this RTP sink:const unsigned estimatedSessionBandwidth = 500; // 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);// 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);
}

Makefile 文件如下:

INCLUDES 	 = -I./include/usageEnvironment/ -I./include/groupsock/ -I.include/liveMedia/ -I.include/BasicUsageEnvironment
COMPILE_OPTS =      $(INCLUDES) -I. -O2 -DSOCKLEN_T=socklen_t -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64
C 			 =         c
C_COMPILER   =        cc
C_FLAGS 	 =       $(COMPILE_OPTS) $(CPPFLAGS) $(CFLAGS)
CPP 		 =           cpp
CPLUSPLUS_COMPILER =    c++
CPLUSPLUS_FLAGS =   $(COMPILE_OPTS) -Wall -DBSD=1 $(CPPFLAGS) $(CXXFLAGS)
OBJ 		 =           o
LINK 		 =          c++ -o
LINK_OPTS    =     -L. $(LDFLAGS)
CONSOLE_LINK_OPTS = $(LINK_OPTS)USAGE_ENVIRONMENT_LIB = ./lib/libUsageEnvironment.a
BASIC_USAGE_ENVIRONMENT_LIB = ./lib/libBasicUsageEnvironment.a
LIVEMEDIA_LIB = ./lib/libliveMedia.a
GROUPSOCK_LIB = ./lib/libgroupsock.a
LOCAL_LIBS 	  =  $(LIVEMEDIA_LIB) $(GROUPSOCK_LIB) $(BASIC_USAGE_ENVIRONMENT_LIB) $(USAGE_ENVIRONMENT_LIB)
LIBS          =  $(LOCAL_LIBS) MEDIA_SERVER_OBJS = h264live.$(OBJ)
APP = h264live.$(C).$(OBJ):$(C_COMPILER) -c $(C_FLAGS) $<
.$(CPP).$(OBJ):$(CPLUSPLUS_COMPILER) -c $(CPLUSPLUS_FLAGS) $<h264live: $(MEDIA_SERVER_OBJS) $(LOCAL_LIBS)$(LINK)$@ $(CONSOLE_LINK_OPTS) $(MEDIA_SERVER_OBJS) $(LIBS)clean:-rm -rf *.$(OBJ) $(APP) core *.core *~ include/*~

工程目录如下:

[root@redhat h264live]# tree -L 2
.
├── h264live
├── h264live.cpp
├── h264live.hh
├── h264live.o
├── include
│   ├── basicUsageEnvironment
│   ├── groupsock
│   ├── liveMedia
│   └── usageEnvironment
├── lib
│   ├── libBasicUsageEnvironment.a
│   ├── libgroupsock.a
│   ├── libliveMedia.a
│   └── libUsageEnvironment.a
├── Makefile
└── test.264


直接运行h264live文件,然后在客户端打开URL: "rtsp://192.168.0.127:8554/testStream"  就可以收看直播视频。

完整的工程代码:live555实现h264文件直播工程

 

这篇关于使用live555类库实现的网络直播系统——直播H264文件的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/764934

相关文章

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

C++中unordered_set哈希集合的实现

《C++中unordered_set哈希集合的实现》std::unordered_set是C++标准库中的无序关联容器,基于哈希表实现,具有元素唯一性和无序性特点,本文就来详细的介绍一下unorder... 目录一、概述二、头文件与命名空间三、常用方法与示例1. 构造与析构2. 迭代器与遍历3. 容量相关4

Linux join命令的使用及说明

《Linuxjoin命令的使用及说明》`join`命令用于在Linux中按字段将两个文件进行连接,类似于SQL的JOIN,它需要两个文件按用于匹配的字段排序,并且第一个文件的换行符必须是LF,`jo... 目录一. 基本语法二. 数据准备三. 指定文件的连接key四.-a输出指定文件的所有行五.-o指定输出

Linux jq命令的使用解读

《Linuxjq命令的使用解读》jq是一个强大的命令行工具,用于处理JSON数据,它可以用来查看、过滤、修改、格式化JSON数据,通过使用各种选项和过滤器,可以实现复杂的JSON处理任务... 目录一. 简介二. 选项2.1.2.2-c2.3-r2.4-R三. 字段提取3.1 普通字段3.2 数组字段四.

C++中悬垂引用(Dangling Reference) 的实现

《C++中悬垂引用(DanglingReference)的实现》C++中的悬垂引用指引用绑定的对象被销毁后引用仍存在的情况,会导致访问无效内存,下面就来详细的介绍一下产生的原因以及如何避免,感兴趣... 目录悬垂引用的产生原因1. 引用绑定到局部变量,变量超出作用域后销毁2. 引用绑定到动态分配的对象,对象

Linux kill正在执行的后台任务 kill进程组使用详解

《Linuxkill正在执行的后台任务kill进程组使用详解》文章介绍了两个脚本的功能和区别,以及执行这些脚本时遇到的进程管理问题,通过查看进程树、使用`kill`命令和`lsof`命令,分析了子... 目录零. 用到的命令一. 待执行的脚本二. 执行含子进程的脚本,并kill2.1 进程查看2.2 遇到的

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置