1.【流媒体客户端】RTMP拉流保存h264(flv保存为h264)
2.RTMP推流方案总结
3.想要搭建一款稳定的源码直播平台,直播源码怎么安装啊?源码
4.nginx-rtmp-module学习
5.SRS(simple-rtmp-server)流媒体服务器源码分析--RTMP消息play
6.RTMP 视频数据封装
【流媒体客户端】RTMP拉流保存h264(flv保存为h264)
librtmp是通过调用int RTMP_Read(RTMP *r, char *buf, int size); 来拉取流,直接得到的源码流是flv格式,保存后即可播放。源码
RTMP_Read内部调用Read_1_Packet,源码其功能是源码jeecg 源码从网络上读取一个RTMPPacket的数据,RTMP_Read在此基础上增加了个字节的源码flv头。
在librtmp的源码源码中,可以看到flv头信息。源码
flv头实际只有9个字节,源码但为何是源码个字节?因为除了9个字节的flv头外,还有多个Tag,源码每个Tag的源码开头有4个字节表示上一个Tag的长度,即使是源码第一个Tag也需填充这4个字节,以匹配源码中的源码flvHeader。
srs_librtmp是通过srs v2.0-r6版本(v2.0-r7版本加入了ipv6功能,但连接rtmp服务器时总是失败,可能是个人使用不当)来拉流并保存为flv文件。
从srs导出的srs_librtmp客户端详情见github.com/ossrs/srs/wiki...,导出后,在research/librtmp下有作者编写的demo,其中srs_rtmp_dump.c用于从rtmp服务器拉流并保存为flv文件。
以下是简化版的demo源码,我注释了自己的理解,若有错误请指正。在vs下此代码能编译运行,但在linux下能正常播放。
主要讲述了flv头信息的结构,srs_librtmp源码中srs_flv_write_tag通过data封装成Tag并写入flv文件,srs_rtmp_read_packet读取的数据是flv文件中的tag data。
Tag data分为Audio、Video、Script三种,这里仅讲解Video Tag Data。
VideoTagHeader的第一个字节包含了视频帧类型及视频CodecID的基本信息。VideoTagHeader之后跟着的是VIDEODATA数据,即video payload,对于H.格式的mosquitto源码入口视频,VideoTagHeader会额外包含4个字节的信息。
AVCPacketType和CompositionTime。AVCPacketType表示VIDEODATA的内容类型:若AVCPacketType为0,则为AVCDecoderConfigurationRecord(H.序列头);若为1,则为一个或多个NALU(完整帧是必需的)。
AVCDecoderConfigurationRecord包含H.解码相关的sps和pps信息,解码器在送数据流之前必须送出sps和pps信息,否则解码器不能正常解码。在解码器停止后再次开始之前,如seek、快进快退状态切换等,都需要重新送出sps和pps的信息。AVCDecoderConfigurationRecord在FLV文件中通常只出现一次,即第一个video tag,但有些视频流的sps和pps可能会发生变化,所以可能会出现多次。
Composition Time用于告知渲染器视频帧进入解码器后多长时间在设备上显示。在flv格式中,timestamp用于告知帧何时提供给解码器,单位为毫秒。Composition Time告诉渲染器视频帧显示的时间,因此compositionTime = (PTS - DTS) / .0。
总结如下:使用srs_librtmp拉流,拉取的数据为一个又一个的Tag Data,可通过type与宏值比较判断Tag Data是否为Video Tag Data。连接rtmp服务器拉流时收到的第一个Video Tag Data通常包含PPS和SPS信息。对于每个h编码的Video Tag Data,会多出4个字节的AVCPacketType和CompositionTime,其中CompositionTime用于B帧,这里暂时忽略它,我们仅支持P帧和I帧。Frame Type在h编码中只能是1或2,Frame Type == 1表示关键帧或包含PPS和SPS信息的Video Tag Data。CodecID在h编码中只能是7(AVC)。当AVCPacketType == 0时,Video Tag Data包含SPS和PPS信息;当AVCPacketType == 1时,为帧数据。openwrt 源码编译
获取PPS和SPS信息非常关键,如果不告知解码器,根本无法播放视频。我写了一段代码,虽然技术有限,但希望能帮助到您。
AVCPacketType为1表示Video Tag Body的内容是NALU。Frame Type为1表示NALU内容是关键帧,Frame Type为2表示NALU内容是非关键帧。NALU的开头的4个字节表示NALU的长度(nalu_length),nalu_length之后是一个字节的nalu header。
nalu header中nal_ref_idc表示优先级,范围在~(2进制),值越大表示越重要。值指示NAL单元的内容不用于重建影响图像的帧间图像预测。对于nal_unit_type为6、9、、、的NAL单元,H.规范要求NRI的值应该为0。对于nal_unit_type等于7、8(指示顺序参数集或图像参数集)的NAL单元,H.编码器应设置NRI为(二进制格式)。nal_unit_type表示nalu类型,SPS开头是0x(nal_ref_idc为3,nal_unit_type为7),PPS开头是0x(nal_ref_idc为3,nal_unit_type为8),关键帧开头是0x(nal_ref_idc为3,nal_unit_type为5),非关键帧开头是0x(nal_ref_idc为2,nal_unit_type为1)。nal_unit_type为5表示idr帧,idr帧具有随机访问能力,所以每个idr帧前需要加上sps和pps。startcode起始码。仿kk 源码
H.原始码流由一个一个的NALU组成,其结构包括起始码(0x或0x,取决于编码器实现)和数据。具体何时使用3个字节的起始码,何时使用4个字节的起始码,这个我没有完全弄明白,资料中提到具体哪种开头取决于编码器实现。0x是NAL起始前缀码,解码器检测每个起始码,作为NAL的起始标识,当检测到下一个起始码时,当前NAL结束。同时H.规定,当检测到0x时,也可以表示当前NAL的结束。对于NAL中数据出现0x或0x时,H.引入了防止竞争机制,如果编码器检测到NAL数据存在0x或0x时(非起始码,而是真正的音视频数据),编码器会在最后个字节前插入一个新的字节0x,这样当遇到0x或0x时就一定是起始码了。解码器检测到0x时,把抛弃,恢复原始数据。因此,组装H的步骤如下:读取tag data并判断是否是video tag data,判断frameType和AVCPacketType,区分video tag data是AVCDecoderConfigurationRecord还是NALU,如果是AVCDecoderConfigurationRecord则解析PPS和SPS保存在内存中并加上startcode(我这里加的是0x),如果是NALU,则判断nal_unit_type(有些NALU的流比较奇怪,依然包含PPS、SPS信息,甚至还有SEI信息)。switch case根据不同的nal_unit_type来解析,并加上startcode。如果nal_unit_type == 0x,网站 值班 源码则是idr帧,需要加上PPS和SPS信息(即一个idr通常包含3个startcode,SPS一个PPS一个idr帧数据一个)。
以下是完整代码:
rtmpTo.h
rtmpTo.cpp
main.cpp
原文链接:blog.csdn.net/qq_...
RTMP推流方案总结
RTMP协议简介,其全称为Real Time Messaging Protocol,是由Adobe Systems公司为Flash播放器与服务器之间音频、视频和数据传输开发的私有协议。RTMP协议像一个容器,用于装载AMF格式的数据或FLV中的视/音频数据,一个连接可通过不同的通道传输多路网络流,通道中的包遵循固定大小的传输规则。更多协议细节请参考《rtmp specification 1.0》。
RTMP服务器的选择有多种开源方案,如Nginx的rtmp插件,用于实时流推送,具体实现可参考另一篇博客。SRS(Simple RTMP Server)是一款国人开发的优秀开源流媒体服务器软件,使用C++开发,适用于直播、录播、视频客服等场景,提供丰富的接入方案和流变换功能,GitHub源码链接为:github.com/ossrs/srs。
crtmpserver是一款由C++语言编写的开源RTMP流媒体服务器,功能相对简单,与Flash Player的兼容性较差,但代码结构良好,适用于学习RTMP协议和服务器端编程。GitHub源码链接为:github.com/shiretu/crtm...。
livego是基于Go语言的RTMP直播服务器,Go语言为服务器性能而生,开发效率高于C/C++。GitHub源码链接为:github.com/gwuhaolin/liv...
基于Go的livego服务器解决了语言级别上的并发问题。node-rtsp-rtmp-server是使用Node.js实现的RTMP服务器,GitHub源码链接为:github.com/iizukanao/nod...
测试时,推荐使用大牛直播提供的推流工具,也可以使用FFmpeg进行推流。
RTMP推流器的选择同样多样,librtmp软件包含一个基本的客户端:rtmpdump,以及提供RTMP协议支持的库。FFmpeg也能实现RTMP推流,内部集成了librtmp,官方给出了muxing.c源代码示例。srs-librtmp是srs提供的一个RTMP库,可以推送H数据,但在Windows环境下存在兼容性问题。
音视频开发相关教程与资料可免费订阅QQ群:,领取学习资源。
想要搭建一款稳定的直播平台,直播源码怎么安装啊?
一、直播平台搭建:移动直播推流端
直播推流端,即主播端,负责通过手机摄像头和麦克风采集音视频数据。采集完成后,数据会经过前处理(如美颜、添加水印)、编码(如H.)、封装,并通过传输协议(如RTMP)推流至CDN进行分发。
1. 采集:移动直播SDK能够通过手机硬件进行音视频采集。IOS平台硬件统一,较为简单;而安卓平台因硬件多样性,需实现适配多款机型。
2. 前处理:这一环节包括实现美颜效果(几乎所有直播平台必备)和水印添加(遵守国家规定),确保直播内容的合规性和美观性。
3. 编码:为了适应移动端直播的需求,音视频数据通常会经过压缩,视频编码常用H.,音频则多采用AAC格式。
4. 推流:将音视频数据封装成流数据,并通过QoS算法优化,使用如RTMP等协议推送到网络,再通过CDN分发至用户。
二、直播平台搭建:服务端处理
服务端负责处理推送上来的流媒体数据,以适配不同的终端和协议。这包括流媒体转码、截图、录制和水印等处理。
三、直播平台搭建:播放器端
1. 拉流:播放器通过支持RTMP、HLS、FLV等格式的拉流方式获取码流。RTMP作为Adobe的专利协议,在开源社区有较好的支持。
2. 解码和渲染:播放器需解码音视频数据并渲染播放。编码过程中虽有信息丢失,但各视频公司通过优化参数以保留最佳画质。
总之,构建稳定的直播平台是一个复杂的过程。多数运营级别的直播平台会选择专业开发团队进行系统开发、测试和部署。在山东布谷直播,我们开发了一套直播程序,并提供售后支持。您可以进一步了解我们的服务。
nginx-rtmp-module学习
nginx-rtmp-module是nginx中的一个用于音视频点播与直播的模块。在业务需求中,我们需实现两点功能:实时接收音频数据和rtmp客户端从头开始播放接收的音频数据。尽管模块已实现第一点,但第二点仅支持实时播放。为满足需求,需深入学习模块实现过程,基于nginx-rtmp-module进行功能扩展。
nginx为开源软件,其子模块rtmp-module同样开源,源代码可从arut/nginx-rtmp-module下载。理解rtmp客户端和服务端通信机制是关键,nginx-rtmp模块高效实现了这套机制。按照流程图,分为六个步骤完成一次完整的rtmp音视频传输。
rtmp并非仅用于直播,其本质是一种传输多媒体数据的协议。代码结构清晰,学习流程以图示为主,重点在于握手协议。位于ngx_rtmp_handshake.c文件中的握手代码,采用SSL加密,涉及摘要认证过程。客户端发起请求,经过认证后,将字节数据传至服务端。服务端响应,完成认证流程。摘要认证机制保障了客户端与服务端的握手。
总结而言,nginx-rtmp-module提供了一套实现rtmp传输的解决方案,通过深入学习其代码结构和实现细节,可进行功能拓展,满足业务需求。理解其背后的通信机制与协议原理,是掌握该模块的关键。
SRS(simple-rtmp-server)流媒体服务器源码分析--RTMP消息play
本章内容梳理了SRS在接收到RTMP信息后如何进行转发的过程。在此过程中,首先进行代码梳理,作者也在源码熟悉阶段,可能尚未完全梳理完接受到RTMP后信息如何处理、缓存以及转发给直播用户等内容。
SRS源码中的Play流程如下:
1. 进入play流程:本章内容直接从SrsRtmpConn::stream_service_cycle()方法开始梳理。
2. 在接受流程中,客户类型为SrsRtmpConnFMLEPublish “fmle publish”,而在转发流程中,客户类型为SrsRtmpConnPlay。
3. 在http_hooks_on_play()方法中,回调on_play()方法通知vhost,xxx用户已经开始play。
4. 在http_hooks_on_stop()方法中,回调on_stop()方法通知vhost,xxx用户已经停止play。
5. 最重要的是进入该函数。
在函数中:
1.1 根据客户端创建消费者对象:create_consumer(this, consumer)
1.2 为该消费者开启一个独立协程:trd.start() //此处一直不太明白,在play流程中创建一个协程用来做什么?
1.3 进入play主流程:do_playing(source, consumer, &trd);
2. 进入主play循环:do_playing()函数内容众多且非常重要,因此将函数内容全部列出。
2.1 通知消费者准备play
2.2 从消费者列表中取出Rtmp信息(SrsMessageQueue)
2.3 进入play入口
3. 进入SRS发送接口(play):在int SrsProtocol::send_and_free_messages(SrsSharedPtrMessage** msgs, int nb_msgs, int stream_id)函数中,进入int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs),该函数有一个#ifdef SRS_PERF_COMPLEX_SEND宏定义,一般rtmp协议都是要混合音视频数据,在做转发。在往后面看,
最后进入
在该函数中,最重要的一点是send message总出口writen()函数。它负责将转发给直播用户的流转发出去。
4. 最后:play总结
(1)通知client开始play
(2)从消费者列表中取出Rtmp数据
(3)从总出口writev()函数中转发出去
RTMP 视频数据封装
RTMP协议,是一个基于TCP的实时消息传输协议,由Adobe Systems公司开发,用于Flash播放器和服务器之间的音频、视频和数据传输。在国内,RTMP广泛应用于直播领域,其默认端口为,与HTTP的默认端口不同。通过阅读Adobe的协议规范并建立与服务器的TCP通信,按照协议格式生成和解析数据,即可使用RTMP进行直播操作,或者使用实现了RTMP协议的开源库来实现这一过程。
RTMPDump是一个开源工具包,专门用于处理RTMP流媒体。它能独立运行进行RTMP通信,也可以通过FFmpeg接口集成到FFmpeg中使用。RTMPDump的源代码可以从rtmpdump.mplayerhq.hu/d...下载。为了在Android中直接调用RTMPDump进行RTMP通信,需要在JNI层进行交叉编译。RTMPDump的源代码结构包括Makefile和一系列.c源文件。编译过程需要通过CMakeLists.txt进行,将其放入AS中,复制librtmp到src/main/cpp/librtmp,并编写CMakeLists.txt,导入app/CMakeLists.txt。
RTMP视频流格式与FLV很相似,理解FLV的格式文档可以帮助我们构建RTMP视频数据。RTMP中的数据由FLV的TAG中的数据区组成。在FLV中,第一个字节表示数据类型,如0x表示视频,数据大小为字节,时间戳和流ID分别由后续的字节表示,最后的字节表示数据块的总大小。在AVCVIDEOPACKET中,数据结构与类型决定了后续数据的内容,包括版本、合成时间、SPS与PPS等关键信息。在构建AVC序列头和非AVC序列头时,需要注意数据的类型区分。
H.码流在网络中传输时以NALU(Network Abstract Layer Unit)的形式进行。NALU是NAL(Network Abstract Layer)单元,是H.编码标准中的一个概念。编码后的H.数据被分割为多个NAL单元,每个单元包含了视频帧的一部分信息。在将数据封装到RTMP包中时,需要去除分隔符,然后将NAL数据加入到RTMPPacket中。完整的封包代码需要将这些步骤结合在一起实现。
综上所述,理解RTMP协议、RTMPDump的使用以及如何在不同环境下构建RTMP视频数据和封装H.数据是进行实时流媒体传输的关键步骤。正确地使用这些工具和技术,能够有效地实现直播和视频流的传输。