在 SETUP
请求之后,客户端会发起 PLAY
请求,以请求服务器开始传输音视频数据。在 PLAY
请求执行时,一定是已经执行过 SETUP
请求,建立好了客户端会话,因而会与其它要求客户端会话已经建立的请求一起,通过 clientSession->handleCmd_withinSession()
执行:
RTSPServer::RTSPClientSession::handleCmd_withinSession()
的定义如下:
在这个函数中,首先会找到请求的 URL 所相应的 ServerMediaSubsession
,如果查找失败,会直接返回 404 并结束处理;然后即是根据请求的具体类型,通过不同的方法进行处理。
找到的 ServerMediaSubsession
存储于 subsession
中。subsession
值为空并不表示查找失败。这里通过值为 NULL
表示操作应用于 fOurServerMediaSession
描述的整个流媒体会话。请求的资源的路径可以分为两部分,分别是资源路径前缀 urlPreSuffix
和标识具体 track 的后缀 urlSuffix
。live555 中通过 ServerMediaSession
和 ServerMediaSubsession
两级对象管理流媒体会话。
根据请求的资源的路径与流媒体会话状态的对应关系的不同,判断操作是否可以支持,以及操作应用的范围。
查找 ServerMediaSubsession
之后,PLAY
请求通过RTSPServer::RTSPClientSession::handleCmd_PLAY()
函数处理:
在具体分析这个函数之前,先来看一个 PLAY
请求/响应的示例。PLAY
请求示例:
PLAY
响应的示例:
然后来看 RTSPServer::RTSPClientSession::handleCmd_PLAY()
的具体处理过程。
第一步,解析 Scale:
头部,为流媒体会话的各个子会话设置 Scale,并构造要返回的 Scale:
头部。
用于解析 Scale:
头部的 parseScaleHeader()
定义如下:
scale
默认情况下会被设置为1.0。
解释一下 scale 值的作用。根据 RTSP 的规范 RFC 2326 12.34 Scale,scale 值是用于控制播放速度的。scale 值为 1,表示以正常的向前观看速率正常播放或记录。如果不是 1,值对应于相对于正常观看速率的比率。比如,值为 2 的比率表示两倍的正常观看速率(“快进”),而值为 0.5 的比率表示一半的观看速率。换句话说,值为 2 的比率播放的时间增长速率是墙上时钟的两倍。对于流逝的每一秒时间,将有 2 秒的内容被发送。负值表示相反的方向。
除非 Speed
参数另有要求,否则数据速率不得更改。Scale
变化的实现取决于服务器和媒体类型。对于视频,服务器可以,比如,传送一个关键帧或选择的关键帧。对于音频,它可以在保持音调的同时缩放音频,或者更不希望地传送音频片段。服务器应尝试提供近似的观看速率,但可以限制其支持的比例值范围。响应要包含服务器选择的实际的 scale。如果请求包含了 Range
参数,新的 scale 值将在此时生效。
应用于整个流媒体会话的 PLAY
请求,通过 ServerMediaSession::testScaleFactor(float& scale)
设置 scale,应用于具体子会话的 PLAY
请求,则通过 ServerMediaSubsession
的 testScaleFactor(float& scale)
设置。
对于我们的 H264VideoFileServerMediaSubsession
,testScaleFactor(float& scale)
的实现还是在 ServerMediaSubsession
中:
ServerMediaSession::testScaleFactor(float& scale)
的定义如下:
在这个函数中,执行的步骤如下:
Step 1:尝试将所有子会话的 scale 设置客户端请求的值,并记录下子会话选择的 scale 的最大值,最小值,以及与 1 最接近的值。
Step 2:第 1 步执行过程中,所有子会话选择的 scale 值相同,则将该 scale 返回给调用者。
Step 3:第 1 步执行过程中,所有子会话选择的 scale 值不同,则尝试将与 1 最接近的 scale 值设置给所有的。
Step 4:第 3 步可以成功将与 1 最接近的 scale 值设置给所有子会话,则将该 scale 返回给调用者。
Step 5:第 3 步无法将与 1 最接近的 scale 值设置给所有子会话,则将每个子会话的 scale 值设置为 1。
回到 RTSPServer::RTSPClientSession::handleCmd_PLAY()
。
第二步,解析客户端的 Range:
头部,并根据 scale 值更新 range 值。
第四步,创建 RTP-Info:
行:
第五步,在开始流式传输之前,对每个子会话进行所需的 seeking/scaling,即设置播放进度和播放速率。
第六步,创建将会在响应中发送的 Range:
头部。
第七步,启动流媒体传输,并产生最终的 RTP-Info:
行。
第八步,产生最终的响应,并释放临时分配的内存。
打赏
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 源码分析:播放启动