在 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 源码分析:播放启动