1 Media Session
1.1 ServerMediaSession
ServerMediaSession是媒体流的抽象。它可以包括多个子媒体流,也就是ServerMediaSubsession实例。
- 成员fStreamName是客户端请求的媒体源名字。
- 成员fSubsessionsHead指向子媒体流的链表。
- 成员fSubsessionCounter是对通道编号(也就是ServerMediaSubsession实例)的计数,从1开始。
- ServerMediaSubsession的成员fTrackNumber保存它的通道编号。ServerMediaSession::addSubsession()会设置这个值。

1.2 ServerMediaSubsession
ServerMediaSubsession实现媒体流接口。
- 成员fTrackNumber是通道编号,
- 成员函数trackId()得到通道编号字符串。如通道编号为1,则trackId()就是”track1”。这个值将打包在RTCP应答中,返回给客户端。
- 成员函数sdpLines()构建sdp描述字符串。
- getStreamParameter()构建媒体流。
- startStream()、seekStream()、pauseStream()、deleteStream()分别启动、定位、暂停、和停止媒体流。
ServerMediaSubsession定义如下虚拟函数,以便它的派生类定制自己的行为。
- createNewStreamSource()创建数据源,这是一个FramedSource实例。
- createGroupsock()创建发布数据的UDP socket组,这是一个Groupsock实例。
- createNewRTPSink()创建操作数据源的入口,这是一个RTPSink实例。
- createRTCP()创建RTCPInstance实例。

OnDemandServerMediaSubsession是客户端可以交互的媒体流。客户端开始接收媒体流后,可以启动、暂停、定位、停止媒体流。
PassiveServerMediaSubsession的媒体流,客户端可以加入、退出流,不能控制它。
1.3 OnDemandServerMediaSubsession
对于OnDemandServerMediaSubsession,
- 成员fDestinationHashTable中,这是一个Destinations的Hash表,保存目标地址信息,key值是client session id。
- 创建媒体流(包括FramedSource、RTPSink等)之后,OnDemandServerMediaSubsession把管理它的工作委托给StreamState。

对于StreamState,
- 成员函数startPlaying()、pause()、和endPlaying()分别负责开始播放,暂停、结束播放。
- 成员函数sendRTCPAppPacket()发送指定数据包,这是跟媒体流有关的信息。
关于Destinations,
- 地址可以是TCP地址,也可以是UDP地址。成员isTCP指明这一点。
- 如果是TCP地址,则成员tcpSocketNum指明socket句柄,rtpChannelId和rtcpChannelId指明TCP连接的channel编号
- 如果是UDP地址,则成员addr指明组播地址,成员rtpPort和rtcpPort指明组播地址的端口号。
1.4 MP3AudioFileServerMediaSubsession
FileServerMediaSubsession只是增加成员fFileName。这是媒体源的文件名。
MP3AudioFileServerMediaSubsession定义了MP3音频媒体源。

MP3AudioFileServerMediaSubsession::createNew()创建它的实例。
- 调用HashTable::create()创建成员fDestinationsHashTable。它存放一组目标地址。
- 调用gethostname()得到本地主机名。构造RTCP包时需要用到这个名字。

这里说明MP3AudioFileServerMediaSubsession对虚拟函数的定制。
虚拟函数createNewStreamSource()实现如下。
- 调用MP3FileSource::createNew(),创建MP3FileSource实例。这里使用的文件名是FileServerMediaSubsession的成员fFileName。
- 调用createNewStreamSourceCommon()。 其中基于MP3FileSource创建ADUFromMP3Source实例,基于后者又创建MP3FromADUSource实例。

最后得到如下图所示的链。MP3AudioServerMediaSubsession看到的是MP3FromADUSource。

虚拟函数createNewRTPSink()的实现如下。
- 创建MPEG1or2AudioRTPSink实例。

虚拟函数seekStreamSource()实现如下。
- 调用getBaseStreams(),从FramedSource链中得到链末端的FramedSoure,这里是基于文件的MP3FileSource。
- 调用MP3FileSource::seekWithinFile()定位。

1.5 创建、启动、停止媒体流
以MP3AudioServerMediaSubsession说明。
成员函数getStreamParameters()负责创建流。
- 调用MP3AudioServerMediaSubsession::createNewStreamSource()创建媒体源。
- 调用MP3AudioFileServerMediaSubsession::createNewRTPSink()创建RTPSink实例。
- 调用createGroupsock()创建Groupsock实例。
- 调用全局函数increaseSendBufferTo()设置Groupsock的socket的发送缓存大小。
- 基于前面创建的FramedSource、RTPSink、Groupsock实例,创建StreamState实例。
- 创建Destination实例保存地址信息。对于TCP是socket和channel,对于UDP,是组播地址和端口号。
- 将Destination实例加入成员fDestinationHashTable。

seekStream()负责在流中定位。
- 将工作委托给MP3AudioFileServerMediaSubsession::seekStreamSource()。

startStream()启动流。
- 调用HashTable::lookup(),根据client session id在成员fDestinationsHashTable中找到对应Destinations实例,其中包括目标地址信息,如若干组组播地址及端口等。
- 调用StreamState::startPlaying(),参数是这个Destinations实例。
- 调用OnDemandServerMediaSubsession::createRTCP()创建RTCPInstance实例。
- 调用RTCPInstance::setAppHandler()和RTCPInstance::setSpecificRRHandler(),设置回调函数,以便接收数据。
- 用成员fRTPSink实例,调用MediaSink::startPlaying()。

网友评论