admin 管理员组

文章数量: 887021


2023年12月16日发(作者:os系统安装教程)

SDI视频转RTMP流编码器软件的开发和应用文/广西广播电视台   刘海兰 李海彬摘要 :本文重点介绍自主开发的一款RTMP推流软件及其技术要点。软件采用Delphi+VC混合开发,通过DirectShow技术获取SDI视频信号,利用X264、FAAC开发包进行视、音频编码,并将压缩后的数据封装为FLV格式,使用RTMP协议进行推送。软件支持RTMP三种推流方式Live、Record、Append,当SDI信号中断时自动输出黑场静音信号,使输出信号不会中断,在广电行业中有一定的应用价值。关键词 :DirectShow;SDI;RTMP;H.264;AAC;FLV1. 引言随着全媒体时代的到来,越来越多的电视台通过网络和新媒体发布电视节目,在进行网络直播时,需要将SDI数字电视信号转为网络直播常用的RTMP数据,通过流媒体服务器发布。在本文中,介绍自主开发的一款可以实现此功能的软件,它通过DirectShow技术从SDI采集设备上获取原始视、音频信号,重新编码后通过RTMP协议推送。2. 硬件设备选择本次开发目标是实现1080i的HD-SDI视频流推送,因此电脑配置需要高一些,以下是测试电脑的配置,见表1。71

表1 测试电脑配置主板CPU显卡内存硬盘操作系统USB接口版本Inter芯片组Intel(R)Core(TM)******************AMD Radeon R5 200 Series8.0 GB 三星 250GB SSDWindows 7 (64位)3.0PCI-E采集卡:DeckLink Mini Recorder

USB 3.0采集盒:TC-UB530 USB3.0

DirectShow是微软公司推出的基于COM的流媒体处理的开发包,使用一种叫Filter Graph的模型来管理整个数据流的处理过程,运用DirectShow,我们可以很方便地从支持WDM驱动模型的采集卡上捕获

数据。表1中SDI采集设备品牌不同,连接电脑的方式也不一样,但有一个共同点即均支持DirectorShow技术。一款是Blackmagic Design公司的内置采集卡,型号为DeckLink Mini Recorder,它通过PCI-E接口插入电脑主板;另一款是天创恒达的外置采集盒,型号为TC-USB530,它通过USB 3.0接口与电脑

连接。723. RTMP协议及工作原理RTMP协议是Real Time Message Protocol

(实时信息传输协议)的缩写,它是由Adobe公司提出的一种应用层的协议,主要应用于流媒体直播和点播,其传输层协议采用TCP,丢包后会重新发送,是基于可靠连接的协议。RTMP的核心是RTMP服务软件,常用的有Adobe

Media Server、Red5 Media Server等,一般都支持文件点播和实时视音频流的直播,但无论采用哪种工作方式,都围绕着FLV文件格式进行。在进行文件点播时,将FLV格式文件放置到RTMP

服务器指定位置存放即可,相对而言RTMP直播则复

图1 RTMP直播工作方式杂得多,RTMP直播采用推流和拉流的方式进行,其工作方式如图1所示。RTMP直播时首先将信号源的视频和音频分别进行编码,然后按FLV格式在内存中封装,最后将内存数据根据时间顺序分片通过RTMP协议发送给服务器。根据推流方式的不同(Live、Record、Append三种)RTMP服务器进行相应处理,如放入缓存或写入文件等,当RTMP接收端向服务器提出拉流申请时,RTMP服务器从缓存中将数据转发出去,因此说无论直播或点播,都是以FLV格式为基础进行。4. 软件工作流程及技术要点实现SDI数字视频信号转为RTMP流进行推送,首先需要采集SDI信号,将其图像和声音进行分离,再分别进行编码,之后按RTMP支持的协议推送到流媒体服务器,从而完成整个推流过程。在本文中实现这个过程需要用到以下技术,先简单介绍一下:■ FFmpeg:一个开源的视音频编码库,文中通过它调用DirectShow实现SDI电视信号的采集和转码;■ X264:是一个开源的H.264/MPEG-4 AVC视频编码函数库;■ FAAC:是一个MPEG-4和MPEG-2的AAC编码器;■ LibRtmp:是一个开源的支持RTMP协议发送和接收的开发包。本文程序使用Delphi和VC混合开发,Delphi主要用于前端界面处理,及通过封装FFMpeg库的第三方控件FFVCL实现视音频的采集和分离;VC用于建立DLL动态库,它将X264、FAAC、LibRtmp三个开发包所需的函数进行重新封装供Delphi前端调用。如图2所示是软件的主要工作流程。下面介绍图2各个步骤所采用的技术和实现方法,共分为5个部分说明。 图2 软件工作流程4.1 SDI信号采集和视音频分离SDI接口是数字分量串行接口,它可以将无压缩的视频和音频信号混合起来通过一根同轴电缆传输,在采用DirectShow采集后可以获得这些裸流数据。由于需要进一步的编码,在分离时通过FFMpeg将这些裸流数据进行一次转码,使视频流输出为YUV420P格式,音频流输出为PCM_S161E格式。YUV420P:一种常见的图像采样方式,其中Y表73

示亮度,UV表示色度。在图像采样时一个像素点对应一个Y,一个4x4的小方块对应一个U和V,这样本来需要12字节存储的数据,只需要6个字节即可,当然这样做是有损失的。PCM_S161E:PCM编码是将音频模拟信号每隔一定时间进行取样,使其离散化,同时将抽样值按分层单位四舍五入取整量化,并将抽样值按一组二进制码来表示抽样脉冲的幅值,它是不压缩的无损编码。PCM_S161E是FFMpeg定义的一种PCM格式,其采样精度为16Bit,存储时低8位在前,高8位在后,如有多个声道的采用交错存储。此步骤均不复杂,通过设置FFMpeg的输入输出参数即可完成采集、分离和转码,本文这部分使用Delphi+FFVCL控件开发,编码控件FFEncoder中设置输入输出参数:■ 设DirectShow采集参数。s := '-f

dshow -r 25 -s 1920x1080' ;

■ 设视频输出YUV420P,并强制去交织,将隔行扫描转为逐行扫描。 s := s +' -c:v

rawvideo -pix_fmt yuv420p -deinterlace';■ 设音频输出PCM_S161E 。s :=

s +' -c:a pcm_s16le ';输出参数“-deinterlace”非常关键,它用于将隔行扫描转为逐行扫描。国内高清1080i电视信号为隔行扫描,如果不强制转换为逐行,输出画面质量不好,有拉条的感觉。4.2 视频H.264编码视频采用开源的X264开发包将YUV420P图像编码为H.264,分为IPB三种视频帧,其中I帧称为关键帧,包含一帧画面的全部内容,解码时只需本帧数据即可;P帧表示它与前一帧(I或P帧)之间的差别,解码时需要使用前帧数据进行画面叠加才能解码;B帧是双向差别帧,记录的是本帧与前、后帧的差别,需要等待后帧解码后才能叠加。本部分使用VC开发,编码按以下步骤进行:■ 调用x264_param_default(¶m)函数获取X264默认编码参数,在此基础上进行修改,由于参数较多,下面列出几个重要的:74 param.b_repeat_headers = 0; //每个关键帧前不放SPS、PPS param.b_annexb = 1; //每个帧以0x00000001开始 param.b_sliced_threads = 1;//采用frame并行编码 ……■ 调用x264_encoder_open(¶m)函数,

打开X264编码器;■ 调用x264_encoder_headers() 函数, 创建H.264头部结构,并从返回的数据中解码出SPS、PPS信息,用于创建AVC sequence

header;■ 调用x264_encoder_encode()函数,将输入的YUV420P视频流进行编码;■ 调用x264_encoder_close()函数结束编码过程。在使用RTMP协议发送I帧视频前,需要发送一个AVC sequence header,它主要由SPS、PPS信息组成,因此创建时需要将SPS、PPS信息提取出来并按其结构重组。X264有两种并行编码模式,slice并行和frame并行,slice并行将一帧划分为多个矩形小块来编码,编码性能较低;frame并行是同时多帧编码,其需要收集N帧视频后再开始一起编码,因此有一定的延时,但编码性能较高,本文采用frame并行方式,使用8个线程同时编码,因此有8帧的视频延时。4.3 音频AAC编码音频采用开源的FAAC开发包将PCM音频裸流编码为AAC音频,FAAC编码时可选择是否带有ADTS(带ADTS的AAC文件可通过音频播放器解码),在本文中用于RTMP推流,因此选择生成不带ADTS的AAC裸流。本部分用VC开发,按此步骤进行编码:■ 调用faacEncOpen()函数,打开一个AAC编码器句柄;■ 调用faacEncGetCurrentConfiguration ()函数,获取系统默认参数后,在此基础上进行修改:

pFaacConf->bitRate=nBitRate*nChannels;

//设置比特率■ 调用faacEncClose(),结束音频编码。FAAC编码器进行编码时对输入样本的数量要求为每个声道1024个样本,如果输入的PCM样本数据不足时,会自动填充0数据(即静音);当输入的样本数据>1024个时,超出部分不进行编码,会丢失此部分音频。基于此软件使用一个1024*N的音频缓冲区暂存收到的PCM音频(N表示声道数),当音频缓冲区满时才进行编码。 pFaacConf->quantqual = nQuantqual;//设置音频质量 pFaacConf->inputFormat=FAAC_INPUT_

16BIT;//设置采样深度

pFaacConf->outputFormat = 0; //输出AAC裸流,不用带ADTS ……■ 调用faacEncSetConfiguration ()函数,使修改后的参数生效;■ 调用faacEncGetDecoderSpecificInfo()函数,取得AAC编码信息,用于创建AAC

sequence header;■ 调用faacEncEncode()函数,将PCM流编码为AAC音频;4.4 FLV封装和时间戳FLV文件由header和Body两部分组成,而Body又由多个Tag组成,Tag可以分成三种:audio,video,script,分别代表音频流,视频流,脚本流,本文只使用到前两种Tag,表2是FLV文件结构。在使用LibRtmp进行直播推流时,不需要发送中9表2 FLV文件结构文件标识:3字节,总是FLV(0x46 0x4C 0x56)FLV Header(9字节)版本号:1字节,为0x01Flags:1字节,第6位表示是否存在音频Tag;第8位表示是否存在视频TagHeader长度:4字节,一般是9Previous Tag Size #0:4字节,表示前1个Tag的长度,如是FLV的第一个Tag此值为0Tag类型:1字节,用于区分Tag类型 0x08-音频;0x09-视频;0x12-脚本数据区长度:3字节,表示真实的数据区长度,=Tag长度-15Tag Head(11字节)Tag #1时间戳:3字节,以毫秒为单位扩展时间戳:1字节,作为时间戳的高位StreamsID:3字节,一般为0可变长度,对于音频、视频Tag第1个字节定义如下。音频:编码类型(4Bit)、采样率(2Bit)、精度(1Bit)、类型(1Bit)视频:帧类型(4Bit)、视频编码(4Bit)FLV BodyTag DataPrevious Tag Size #1:Tag #1的总长度,4字节……Previous Tag Size #NTag #N75

字节的FLV Header和4字节的Previous Tag Size

#0,以Tag#1为例,其发送内容为Tag #1 Head、Tag #1 Data、Previous Tag Size #1三部分,按此结构封装后形成一个RTMP数据包后就可以发送了。视频Tag分为两种,一种是真正的H.264视频帧,包括I、P帧两种(直播不用B帧);另一种是AVC

sequence header,它在每个I帧前发送一次。音频Tag也分为两种,一种是包含了AAC编码的音频Tag;另一种AAC sequence header用于标识音频信息,只需在发送音频Tag前发一次即可。视频和音频是分开编码的,在发送时需考虑视音频同步问题,对于每个视、音频Tag要加上一个时间戳,而这个时间戳是按照视频或音频出现的时间节点进行分配的,如PAL制电视每秒传输25帧画面,其两帧画面之间的间隔为40毫秒,因此视频Tag的时间戳从0开始,以40毫秒递增。但每个音频Tag的时间间隔则需要根据其采样率来确定,主要原因是FAAC编码时每个声道的样本数固定为1024个,对应11.025KHz、22.05KHz、44.1KHz、48KHz这几种采样率,其时间间隔分别约为92、46、23、21毫秒。在发送视音频Tag时,需要从视频、音频两个队列中,比较当前指针所指数据的时间戳,取出小的那个进行封包和发送,因此可能存在发送2个视频帧,再发送1个音频帧的情况发生。工作:■ 调用RTMP_Alloc()、RTMP_Init()函数分配RTMP空间及初始化;■ 调用RTMP_SetupURL()设置URL连接参数,其中URL由协议名称、IP地址、端口号、流名称组成,例如 rtmp://192.168.5.5:1935/live/12345;■ 调用RTMP_Connect()函数连接RTMP服务器;■ 调用RTMP_ConnectStream()函数连接RMTP流;■ 调用RTMP_Write()或RTMP_SendPacke()函数进行RTMP推流。第一次发送AAC音频Tag时需先发送一个AAC sequence

header;每一次发送视频I帧Tag前,需要先发送一个AVC sequence header。■ 调用RTMP_Close()、RTMP_Free()函数断开连接及释放相关的资源。5. 软件测试结果软件采集推流界面如图3所示。FFMpeg取得支持DirectShow采集的设备列表,在选择指定的采集设备后,自动列出其支持的输入4.5 RTMP流推送封装好的视音频Tag,可以调用LibRTMP相应函数进行推流,本文中对LibRTMP库的源代码进行了修改并重新编译,使其支持Live、Record、Append三种流推送方式。Live推流:流数据只存在于RTMP服务端的内存中,不产生FLV文件。Record推流:流数据在RTMP服务端产生FLV文件,当停止后再次推送时删除前次文件并重写。Append推流:流数据在RTMP服务端产生FLV文件,当停止后再次推送时追加到前次文件尾部。此部分用VC开发,LibRTMP按以下步骤76 图3 软件工作界面

表3 推流测试结果测试参数视频 - 编码:H.264 码率:2 Mbps 分辨率:1920 x 1080 帧频:25Hz 颜色编码:YUV420音频 - 编码:AAC 质量:中等(70) 采校率:48000Hz 声道数:2 采样深度:16 Bit设备名称DeckLink MiniRecorderTC-USB530CPU占用率视频编码延时视音频同步LiveRecord Append

27%~45%7~13帧良好成功成功成功42%~65%3~6帧良好成功成功成功分辨率。在参数设置完成后点击“启动”按钮开始通过DirectShow获取图像声音,点击“发送”按钮向指定RTMP服务器推送。如表4所示是前文所述两个设备的测试结果。经测试软件可以通过此两款设备实现全高清1080i推流,由于视频编码消耗较大,因此采用8个线程同时编码,视频与音频编码有一定的时延,但每个编码Tag加入了时间戳,故而接收端不会产生视音频不同步现象,仅仅是增加收看时的延迟时间,在网速正常情况下,一般收到信号会比发出延迟2~5秒。这样应用于电视行业:利用其将流数据以FLV文件方式存储在硬盘的特点,使RTMP服务器变成一台无人值守的视音频接收设备,自动将网络传回的RTMP数据包存成FLV文件。RTMP协议除用于网络直播外,还可以应用于电视信号传输,如果在传输过程中SDI信号中断,硬件编码器无信号输出会造成RTMP流的中断,接收端需要重新进行连接,给接收方造成一定困扰。本软件针对以上问题作了处理,支持三种推流方式;在SDI信号中断时,输出黑场静音信号,不会产生断流,解决了上述问题。6. 软件在广电行业的应用价值市场上存在的许多将SDI信号转为RTMP流的硬件编码器产品,便宜的一千多元,贵的数万元,价格的差异主要体现在品牌、功能、性能等方面,但在设计时有所欠缺,存在如下问题:■ RTMP协议Live、Record、Append三种推流方式,市售产品基本上只支持Live;■ 当输入的SDI信号中断时,编码器即停止推流,而不再输出任何信号。RTMP协议的Record、Append推流方式可以7. 结语在同等码率条件下,软件编码输出的声画质量与硬件编码器相差不大,但编码性能上相对差一些,对CPU的要求较高,当CPU性能较差时,全高清1080i编码输出会产生丢帧现象,此时只能降低输出分辨率。软件开发的意义在于其针对市售硬件编码器产品的缺点作了一定的优化处理,从而更加适合在广电行业中使用,经测试软件可以进行较长时间的稳定推流,有一定的应用价值。77


本文标签: 编码 音频 进行 视频 推流