资源下载地址:https://download.csdn.net/download/sheziqiong/85996746
资源下载地址:https://download.csdn.net/download/sheziqiong/85996746
我们实现了一个软件系统:它可以通过Wi-Fi Direct建立一个网络,自主发现网络中的某一设备并向该设备发送音频信号。该设备收到音频信号后,如果有多个来源,将对这些音频信号混频。最终这个设备讲接收的音频信号播放。
目录
摘要 1
一、 Wi-Fi Direct技术 1
二、 服务发现协议、心跳协议和音频控制协议 1
三、 RTP协议和RTCP协议 3
在该部分,我们称音频信号的发送者为Client端,音频信号的接受者为Server端。
在我们设想的情景中,Server端可能是网络中的任意一台设备,因此Server端的地址是不确定的。如果让用户自行寻找Server端的地址,这显然是一件不合理的事情,因此我们需要设计一个服务发现协议,让Client端可以自动的发现网络中的Server端。同时,为了确保通信的正确进行,我们需要Server端和Client端每隔一段时间都去确认双方是否都还在当前网路中。为此我们设计了心跳协议。
为了方便Server端接收并播放音频流,Client端在开始发送音频前和停止发送音频后,都应该向Server端告知自身当前的播放状态。因此我们设计了音频控制协议。
服务发现协议和心跳协议如图1所示。其过程大致如下:
Client端:向网络广播消息“client”,表示有新的Client加入网络中。
Server端:在接受到广播消息后,向广播源(即对应的Client)发送消息“server”,表明自己的身份。
心跳协议由Client端定时执行。其过程大致如下:
Client端:向Server发送心跳消息“server?”并等待回复。如果不能在较短时间内接收到Server的回复,则认为该Server已经离开网络。
Server端:接收到Client的心跳消息后回复消息“serverYes”。如果在规定时间内没有接收到Client的心跳消息,则认为该Client已经离开网络。
图1:服务发现协议和心跳协议
音频控制协议如图2所示。音频控制协议包含两种子协议:请求播放和请求暂停。其过程大致如下:
请求播放:
Client端:向Server发送消息“play”。
Server端:接收到消息后,准备好接收音频流,并向Client发送消息“playOk”。
Client端:接收到消息后,通过RTP协议向Server发送音频信号。
请求暂停:
图2:音频控制协议
我们项目中对音频信号的传输是通过RTP实现的。RTP协议详细说明了在互联网上传输音频和视频的标准数据包格式,常用于流媒体系统中,是一个多播协议但也可以用于单播应用中,非常符合我们项目的需求。
RTP协议是一种基于UDP的无连接的传输协议,和RTCP控制协议一起使用。RTP协议为Internet上端到端的实时传输提供时间信息和流同步,但它并不保证服务质量。服务质量控制功能由RTCP协议来提供。
图3展示了一个典型流媒体应用的体系结构。RTP协议被划分在传输层,建立在UDP上。因此,同UDP协议一样,为了实现实时传输功能,RTP也有固定的封装形式,接下来将具体介绍RTP数据包的封装结构。
图3:典型流媒体应用的体系结构
图4展示了RTP报文的头部格式。其各部分含义如下:
图4:RTP报文的头部格式
RTCP也是基于UDP进行传送的,封装的主要是一些控制信息,用于检测与反馈服务质量、同步媒体、标识多播组中的成员等等。在RTP会话期间,各参与者周期性地传送RTCP包。RTCP包中含有已发送的数据包的数量、丢失的数据包的数量等统计资料,各参与者可以利用这些信息动态地改变传输速率。RTP和RTCP配合使用,它们能以有效的反馈和最小的开销使传输效率最佳化,因而特别适合传送网上的实时数据。
由于RTCP仅包含一些控制信息,因此分组长度很短,可以将很多RTCP分组封装在一个UDP包中。RTCP有如下五种分组类型:
类型 | 缩写表示 | 用途 |
---|---|---|
200 | SR(Sender Report) | 发送端报告 |
201 | RR(Receiver Report) | 接收端报告 |
202 | SDES(Source Description Items) | 源点描述 |
203 | BYE | 结束传输 |
204 | APP | 特定应用 |
上述五种封装类型的内部结构基本相同,下面以SR为例进行介绍:
发送端报告分组SR用于使发送端以多播的方式向所有接收端报告发送情况,主要内容包括:相应RTP流的SSRC值、RTP流中最新产生的RTP分组的时间戳、RTP流包含的分组数、RTP流包含的字节数等。图5展示了RTCP SR头的结构,其中各部分的含义如下:
图5:RTCP SR头的结构
当应用程序建立一个RTP会话时,需要首先确定一对目的传输地址,包含一个网络IP地址以及一对端口号。这对端口号一个用于RTP包,一个用于RTCP包,其中RTP数据发向偶数的UDP端口,RTCP包发向相邻的奇数UDP端口,这样就构成了一个UDP端口对。图6展示了RTP包发送的过程。接收过程与此相反。
图6:RTP包的发送流程
处理数据前,我们会把音频数据解码为PCM格式。发送端读取音频文件获取音频输入流,将音频流切割为指定的块大小,然后通过RTP发送。接收端收到字节流后对其进行处理,通过已打开的相应格式的源数据行将处理过的字节流写入数据行中,通过混频器传递到输出端口。图7展示了这个过程。
图7:音频数据的传输过程
对于每个发送者,动态添加新的与之对应的接收buffer和混合buffer,所有buffer大小一定。每次接收到数据时将数据存入到该数据发送者对应的接收buffer中(I),当接收buffer满,数据转移到混合buffer中。如果混合buffer为空,直接转移(II),若混合buffer满,考虑到两个及以上个发送者时,进一步检测是否所有的buffer均满(III)。若所有的混合buffer均满,将当前所有发送者的混合buffer进行混音,发送到输出端口进行播放,并清空当前所有发送者的混合buffer(IV);若有混合buffer未满,则丢弃当前接收者混合buffer中的数据,直接将接收buffer数据转移(V)。图8和图9分别展示了单发送端和多发送端的这一处理过程。
同时,在每一轮接收数据过程中,检测每一个发送者多少轮没发送过数据。若一定轮次里均没有发送过数据,则动态删除该发送者的接收和混合buffer。
图8:单发送端处理过程
图8:多发送端处理过程
我们采用的是带符号位的PCM编码方式,每一字节数据在-128~127之间。混音时,取两个数据包的每一字节,进行以下运算。这样两个声音就可以混合起来。
技术细节
在我们的实现中,心跳协议的重复时间间隔为30秒,Client端等待时间为1秒。考虑到网络传输的延时,Server端等待时间为30.5秒。
为了实现RTP包的封装,我们使用jlibrtp库。图9展示了jlibrtp库的使用过程:
图9:jlibrtp库的使用过程
在实现音频数据处理和混频过程中,我们选择每个数据块的大小为1024字节,buffer的大小为30个数据块。发送者30轮未发送数据后将会被删除。
buffer的大小会影响丢包率。如果buffer过小,会导致丢包率升高。buffer过大,则会浪费大量的内存空间。
安卓端 Server 和 Client 由同一软件完成,如图10所示。在初始界面运行服务发现协议,由一台终端发起连接 (Create New Network) 与其它终端互联 (Search)。在网络中终端互相成功发现后,每个终端可以通过按钮切换在音频传输中担任的角色 (Server/Client)。通常每一组网络中有且仅有一个终端为音频 Server,用来接收网络中 Client 的音频数据并混音播放。
图10:安卓终端界面
图11:PC终端界面
PC端在进入软件开始便选择自身音频传输中的身份 (Server/Client)。Server 端可以直接启动并持续监听网络中是否有 Client 传送数据。Client 端则需要搜索网络中存在的 Server,主动与其连接并选择音频文件进行发送。
资源下载地址:https://download.csdn.net/download/sheziqiong/85996746
资源下载地址:https://download.csdn.net/download/sheziqiong/85996746