在 live555 中,用一个 ServerMediaSession 表示流媒体会话,它连接了 RTSPServer 和下层流媒体传输逻辑。ServerMediaSession 和 ServerMediaSubsession 共同用于执行底层流媒体传输和状态维护。而 ServerMediaSession 则是在 GenericMediaServer 中,通过 HashTable 来维护的。
在分析 live555 中处理 DESCRIBE 请求的代码( live555 源码分析:DESCRIBE 的处理)时,我们曾看到 RTSPServer::RTSPClientConnection 通过它来产生 SDP 消息。本文更详细地分析这个类的定义和实现。
ServerMediaSession
首先看一下 ServerMediaSession 的定义:
由这个定义,不难理解,它主要是 ServerMediaSubsession 的容器,并通过一个单向链表来维护它们。并提供了需要作用于整个流媒体会话所有子会话的操作,如产生 SDP 消息的 generateSDPDescription() 和设置播放快慢的 testScaleFactor()。
ServerMediaSession 对象的创建,就像 live555 中许多类的创建那样,通过一个静态的创建函数 createNew() 实现,该函数定义如下:
每个 ServerMediaSession 都由一个字符串形式的 streamName 标识,这个标识也是在 GenericMediaServer 中,通过 HashTable 来维护时,所用的 key。streamName 由调用者在创建时传入。对于 “LIVE555 Media Server” 而言,这个值为资源的路径。
调用者还可以在创建时传入 info 和 description 提供更多关于这个会话的描述信息。对于 “LIVE555 Media Server” 而言,info 同样为资源的路径,但 description 为含有流媒体类型的一个字符串,格式为 "$MediaType, streamed by the LIVE555 Media Server",比如对于 H.264 视频为 "H.264 Video, streamed by the LIVE555 Media Server"。
创建对象时,主要是用调用者传入的值来初始化状态。
像许多其它 Medium 的子类一样,ServerMediaSession 也提供了一个对象查找函数:
作为 ServerMediaSubsession 的容器,ServerMediaSession 还提供了对 ServerMediaSubsession 的添加、管理等操作:
向 ServerMediaSession 中添加子会话时,新加入的子会话总是会被放在单向链表的表头。添加子会话的时候,会根据子会话计数器 fSubsessionCounter 为子会话分配 track number。
用来产生 SDP 消息的 generateSDPDescription() 和 duration() 函数,及用来设置播放快慢的 testScaleFactor(float& scale) 函数,在 live555 源码分析:DESCRIBE 的处理 和 live555 源码分析:PLAY 的处理 中已经有较为详细地说明了,这里不再赘述。
为了便于访问 ServerMediaSubsession,live555 还提供了一个迭代器,该迭代器定义如下:
该迭代器实现如下:
可以看到 ServerMediaSession 中并没有太多的内容。大多数时候,它仅作为获得 ServerMediaSubsession 的中介而存在。
ServerMediaSubsession
在 RTSPServer::RTSPClientSession 中处理 SETUP 请求的代码中,我们看到,它从 ServerMediaSession 获得 ServerMediaSubsession 并接管了对它们的管理,并绕过 ServerMediaSession 直接对 ServerMediaSubsession 进行操作。执行流媒体单个会话的数据操作的入口也都在 ServerMediaSubsession。
对于向 “LIVE555 Media Server” 服务器请求 H.264 视频文件的情况,ServerMediaSubsession 的实际类型为 H264VideoFileServerMediaSubsession,我们以此为例来分析 ServerMediaSubsession。
H264VideoFileServerMediaSubsession 在 DynamicRTSPServer 类的 lookupServerMediaSession() 中随 ServerMediaSession 的创建一起创建,并直接被添加到 ServerMediaSession 中。
H264VideoFileServerMediaSubsession 有着如下图所示的继承体系:

在这个继承体系中,ServerMediaSubsession 定义了可以对单个流执行的操作,类的定义如下:
这些操作可以分为几类,一类是对播放进行控制的操作,包括 startStream()、pauseStream()、seekStream()、nullSeekStream()、setStreamScale()、deleteStream() 和 testScaleFactor() 等;另一类是获得用于执行 I/O 操作的 FramedSource 和 RTPSink 的 getStreamSource() 和 getRTPSinkandRTCP()。
ServerMediaSubsession 类提供了几个子会话的通用操作的实现,这主要包括用于产生字符串形式的 track id 的 trackId(),用于设置 SDP 服务器地址和端口号的 setServerAddressAndPortForSDP(),以及用于生成子会话的 SDP 行的 rangeSDPLine():
这些操作都比较简明,这里不再赘述。
对于其它众多操作单个流的接口,ServerMediaSubsession 类都只是提供了一个空的默认实现:
OnDemandServerMediaSubsession 实现由 ServerMediaSubsession 定义的流操作接口。为了实现这些操作,需要一些 I/O 操作,如解析流媒体文件,收发 RTP/RTCP 包等。这些 I/O 操作将由于具体的流媒体源类型的不同而不同,因而不会直接在 OnDemandServerMediaSubsession 中实现。OnDemandServerMediaSubsession 定义了新的虚函数,以便从子类中获得 FramedSource 和 RTPSink 对象,来执行 I/O 操作。
OnDemandServerMediaSubsession 的具体实现,暂时先不详细说明。
在 H264VideoFileServerMediaSubsession 的类继承层次结构中, FileServerMediaSubsession 用于维护资源的文件名,其定义如下:
这个定义非常简单,其实现也很简单:
H264VideoFileServerMediaSubsession 最主要的功能则是提供用于执行 I/O 操作的 FramedSource 和 RTPSink,其定义如下:
H264VideoFileServerMediaSubsession 通过实现 createNewStreamSource() 和 createNewRTPSink() 创建并返回 FramedSource 和 RTPSink:
这里返回的 FramedSource 为 H264VideoStreamFramer,返回的 RTPSink 为 H264VideoRTPSink。
除此之外,H264VideoFileServerMediaSubsession 还提供了 AUX SDP line 有关的接口实现:
打赏
Done.
live555 源码分析系列文章
live555 源码分析:简介
live555 源码分析:基础设施
live555 源码分析:MediaSever
Wireshark 抓包分析 RTSP/RTP/RTCP 基本工作过程
live555 源码分析:RTSPServer
live555 源码分析:DESCRIBE 的处理
live555 源码分析:SETUP 的处理
live555 源码分析:PLAY 的处理
live555 源码分析:RTSPServer 组件结构
live555 源码分析:ServerMediaSession
live555 源码分析:子会话 SDP 行生成
live555 源码分析:子会话 SETUP
live555 源码分析:播放启动