如何通过RTP接口类,在.Net中创建你自己的广播系统(原创翻译,有源码)
序:最近一个项目需要用到RTP,接收视频流,看到codeproject上这个关于RTP的源码,做的类似教学中的同屏广播软件。使用的是微软的开源软件“Conference XP”中的RTP组件(也就看到他用微软的东西我才仔细研究了一番)。这个是本人第一次翻译,如果有不足之处请见谅欢迎指导(透露一下,本人曾经光荣得连续考了两次四级——没过⊙﹏⊙b汗)
注:
1.文章中用(@@)标注的为我自己添加上的。
2.(英文)为我认为我可能翻译不准确的专业名词(仅仅限专有名词)
3.除此之外,都是翻译内容。
4.本人为意译非逐字翻译,不要在这方面挑我的错。我会把长句子拆成短句子,改变句子的顺序,省掉我认为是影响阅读的词汇,文章加上方便阅读的标点符号。比如,我认为他一句是补充说明用的,我在翻译的时候采用“(注:我认为是补充说句子的翻译)”形式。
5.译文的整体结构跟原文一致。
7.图片中文字没有翻译,都是些简单的图,也不需要翻译了。
6.译者:天天(edzjx)。如果转载请注明原文出处和本译文出处及属名,请不要用于商业行为,本人保留本译文最终解释权。
简介:
在此文中,我将介绍RTP协议(Real Time Transport Protocol实时传输协议),讨论RTP 管理类:微软Conference XP项目中一个RTP组件,原用于Conference XP项目中广播JPEG格式的图像用的。更多关于RTP开发请关注:http://www.socketcoder.com/.(@@这个网站我没怎么看)。
在网络中音视频数据的传输关键是RTP协议和它的配型方法及数据包格式。在互联网中,RTP协议用于传输实时多媒体数据(如音视频)是非常有用的。它提供的功能有:实时接收(timing recovery),损失侦测(loss detection)和校正,处理负载(payload)和数据源认定(source identification),接收质量反馈(reception quality feedback),媒体数据同步(media synchronization),成员管理(membership management)(@@这些专业名词我实在不行,有错请指正)。原来设计RTP是用于远程会议(multicast conferences),使用轻量级的会话模式。从那儿后,RTP被证实可以用于越来越多的有线和无线网络应用:H.323格式的视频会议,网页广播,网络电视。RTP协议已经被证明可以用于成千上万规模的会话的广播应用。
背景知识
RTP是怎么工作的?
发送端负责将采集音视频数据并转化成RTP数据包(注:通过接收端反馈的信息,发送端也需要参与到数据校正与流量控制)。数据传送前,数据侦会被装入到RTP包中。如果数据帧很大话,它们会被分割装入到几个RTP包中,同样如果数据帧很小,它们会被一起装入同一RTP包中。根据纠错规则,信道编码器(channel coder)产生纠错的包或者是可重发的包。当RTP数据包被发送时,那些用于纠错或者可重发包将最后被释放。发送端不需要立刻丢弃才发送数据包,因为这个数据包要和它相关联的数据包一起用于数据纠错或者其他处理。发送端必须缓冲那些相互关联的数据包,直到它们全部发送出去。这些跟使用的编码器与纠错规则有关。由于同步的需求,发送端负责生成它生成的数据的状态报告用于同步功能。发送端从其他客户端上获取接收质量的反馈,来调节它数据的传送。
接收端负责从网络上接收RTP包,校正丢失的包,恢复时间,解码媒体,将媒体数据展示给用户。它发送接收质量反馈给发送端,让发送端调节数据传输。接收端还需要管理一个数据库,这个数据库存储会话中其他接收端的信息。一个显示接收进度的进度框^^。当然可以根据需要添加相应的功能。
在以后文章中,我会介绍更多关于RTP传输音频和视频的知识。更多有关RTP的信息,请看下面的链接:
使用RTP接口库编程
微软已经实现了RTP相关操作在它的Conference XP项目中。下图说明了Conference XP 3.0中RTP组件的结构:
下面将简单地介绍下如何在你广播项目中使用这个RTP组件:
1.使用RtpSession类和
RtpParticipant
类:
一个会话有一组是哟个RTP通信的参与者组成。一个参与者在一个程序中可能拥有多个RTP会话:一个会话用于传输音频数据一个会话用于传输视频数据。会话通过网址确认,同时拥有两对端口一个用于发送一个用于接收(注:接收与发送也肯能用同一对端口)。为什么是一对端口呢?每对端口由两个数字上相邻的端口组成:一个偶数端口用于传输RTP数据包,另一个较大的奇数端口用于RTCP控制传输数据包(@@原作者没有介绍RTCP,RTP其实由两个协议组成一个RTP专门传数据用的,一个RTCP专门控制传输数据用的)。这个组件默认端口号为5004和5005,传输层协议是UDP。但是许多程序在会话建立的时候会动态分配端口不一定使用默认端口号。RTP会话设计初是为了单一媒体类型的传输,所以在多媒体传输中(@@多媒体即多个媒体类型,比如视频与音频)则需要将每种媒体类型分到不同的RTP会话中传输。我们使用RtpSession
和RtpParticipant
类:
在通信中,我们关注RTP组件一些事件,看它们在RTP API处理中发生了什么。它们是:
// Manage the join to the session Ex.Add/Remove a User To/From the RTP Session RtpEvents.RtpParticipantAdded += new RtpEvents.RtpParticipantAddedEventHandler(RtpParticipantAdded); RtpEvents.RtpParticipantRemoved += new RtpEvents.RtpParticipantRemovedEventHandler(RtpParticipantRemoved);
//Rtp参与者增加事件 private void RtpParticipantAdded(object sender, RtpEvents.RtpParticipantEventArgs ea) { MessageBox.Show (ea.RtpParticipant.Name + " has joined to the session"); } //RTP参与者离开事件 private void RtpParticipantRemoved(object sender, RtpEvents.RtpParticipantEventArgs ea) { MessageBox.Show(ea.RtpParticipant.Name + " has left the session"); } // Manage (Add/Remove)Sessions Ex.Activeate multiple RTP sessions RtpEvents.RtpStreamAdded += new RtpEvents.RtpStreamAddedEventHandler(RtpStreamAdded); RtpEvents.RtpStreamRemoved += new RtpEvents.RtpStreamRemovedEventHandler(RtpStreamRemoved); //RTP数据流增加事件 private void RtpStreamAdded(object sender, RtpEvents.RtpStreamEventArgs ea) { ea.RtpStream.FrameReceived += new RtpStream.FrameReceivedEventHandler(FrameReceived); } //RTP数据流移除事件 private void RtpStreamRemoved(object sender, RtpEvents.RtpStreamEventArgs ea) { ea.RtpStream.FrameReceived -= new RtpStream.FrameReceivedEventHandler(FrameReceived); }
加入RTP会话,我们必须指令一种RTP包负载类型,每个会话只能包含一种负载类型:
RtpSession rtpSession; //加入RTP会话事件 private void JoinRtpSession(string SessionName,string name) { rtpSession = new RtpSession(ep, new RtpParticipant(SessionName, name), true, true); rtpSender = rtpSession.CreateRtpSenderFec(name, PayloadType.JPEG, null, 0, 200); } //离开RTP会话事件 private void LeaveRtpSession() { // Clean up all outstanding objects owned by the RtpSession rtpSession.Dispose(); }
在加入到RTP会话后,我们能够获取RTP缓存中的数据流,看下面的代码:
//数据帧获取事件 private void FrameReceived(object sender, RtpStream.FrameReceivedEventArgs ea) { System.IO.MemoryStream ms = new MemoryStream(ea.Frame.Buffer); pictureBox_Receive.Image = Image.FromStream(ms); }
2.使用RtpSender
和RtpListener
类:
发送端负责捕获数据以及生产RTP包(注:本示例的数据可以从截图或者图片文件获取;为提高传输速度需要压缩缩数据例如将BitMap格式的图片转换成JPEG格式的图片,如同本示例程序。)发送端先读取媒体数据比如视频帧,将媒体数据放入缓存,放入缓存是缓存可以对媒体数据进行编码如JPEG。在RTP组件库中,RtpSender
类被用于如下工作:
在发生错误时,发送数据或者不发送
RTPListener
完成的工作:
一个线程将数据包转换适合的数据流给程序处理
使用RTPSender
的代码如下:
RtpSender rtpSender; MemoryStream ms = new MemoryStream(); // Compressed the captured image as JPEG image format pictureBox_sender.Image.Save(ms, ImageFormat.Jpeg); // Send The The Comressed Image as Bytes stream rtpSender.Send(ms.GetBuffer());
RTCP 管理:RTCP 包在RTP协议中的定义是:接收端报告,发送端报告,源描述,成员关系管理,应用定义(receiver report (RR), sender report (SR), source description (SDES), membership management (BYE), and application-defined (APP))。(@@专有名词,烦)RTCP sender 常常在下面场合发送RTCP数据:
针对网络状态的发送端报告和接收端报告
RtcpListener
类常常用于:
针对网络状态的发送端报告和接收端报告
网络状态的接收端报告和发送端报告
3.工作技术器
用于跟踪网络传输数据计数,例如字节数,包书,每秒帧数,丢包数,重新接收数。这些都包含在RTP组件的属性中。
提高网络利用率的方式:(@@非RTP相关的内容了)
在我的例子中随着用户的增多,我使用一种办法仅仅发送新的截屏即跟上次截屏不同的图片才发送。这个可以减少网络使用的资源。我在图片发送前与之前发送图片的像素进行比较。为了提高比较速度,我将图片压缩到100x100分辨率是比较每个像素。代码如下:
原文链接:http://www.codeproject.com/KB/IP/Using_RTP_in_Multicasting.aspx
本文链接:http://www.cnblogs.com/edzjx/archive/2010/03/29/1699974.html
源码下载:https://files.cnblogs.com/edzjx/RTPPresenter.zip
后记:
这个程序提供简单RTP收费模式,其实这个东西并不是很好用。微软的这个RPT组件感觉好像不是很支持RTP协议的标准,不知道是否是正对它那个软件的还是别的什么原因。发现的问题是:我试图使用此组件接收一个标准RTP包时,无法接收到,这个发送端不是我写的,是别人提供给我的一个数据获取的借口。后来搜索到另一个组件RTP.NET,简单好用,我在后面的文章进行了入门介绍:RTP.NET入门 ,最好用的RTP组件,免费哦。