LIVE555 采用 标准的DSP 标准作为文件的描述, 其说明在前文《LIVE555阶段一之二SDP协议描述》.
客户端链接进来,请求获取我多媒体资源的数据的描述的时候, live555 采用读取一小段文件分析生成多媒体信息并且传输出去。
void RTSPServer::RTSPClientConnection
::handleCmd_DESCRIBE(char const* urlPreSuffix, char const* urlSuffix, char const* fullRequestStr)
handleCmd_DESCRIBE 函数 处理客户端的 “多媒体资源描述信息” 请求函数。
一: 匹配选择已经注册过的多媒体资源。
session = fOurServer.lookupServerMediaSession(urlTotalSuffix);
urlTotalSuffix 为 RTSP 链接请求的文件。 根据这个文件的名称,搜索之前注册的多媒体。
二:动态生成多媒体文件的描述信息SDP
sdpDescription = session->generateSDPDescription();
那么重点 就是 详细分析
二:动态生成多媒体文件的描述信息SDP
generateSDPDescription 函数
要想获取完整的SDP描述 ,有两种方式 1.必须要先对文件进行解析。 2.直接写死不在动态生成。 live555 采用分析文件的形式。 就必须涉及到SINK 、SourceFrame 类的相关。
2.1 因此 首先要 创建 FramedSource* inputSource。
FramedSource* inputSource = createNewStreamSource(0, estBitrate);
2.2 其次 创建 RTPSink* dummyRTPSink
RTPSink* dummyRTPSink = createNewRTPSink(dummyGroupsock, rtpPayloadType, inputSource);
2.3当 inputSource 和 dummyRTPSink 都创建成功后。 就开始调用 setSDPLinesFromRTPSink函数开始分析。
2.3.1 获取媒体流类型
char const* mediaType = rtpSink->sdpMediaType();
2.3.2 获取媒体数据负载类型
unsigned char rtpPayloadType = rtpSink->rtpPayloadType();
2.3.3 获取多媒体类型负载类型描述rtpmap
char* rtpmapLine = rtpSink->rtpmapLine();
2.3.4. 获取多媒体类型起始和结束时间
char const* rangeLine = rangeSDPLine();
2.3.5. 获取多媒体类型的 a=fmtp: 数据(这里是核心,涉及文件的读取解析)
char const* auxSDPLine = getAuxSDPLine(rtpSink, inputSource);
该函数为基类 OnDemandServerMediaSubsession 中的 定义的虚函数 其调用关系如下
H264视频文件 中则有 H264VideoFileServerMediaSubsession 实现解析功能.
2.3.5.1 启动数据读取解析
这里以后可以改写为 双线程通信的机制 一个进行循环等待 一个进行解析放入共享内存里面。
fDummyRTPSink->startPlaying(*inputSource, afterPlayingDummy, this);
等待FrameSoure 读取解析编码SPS PPS的输出
2.3.5.2 检测等待数据是否解析成功
checkForAuxSDPLine(this);
2.3.6. 数据组合生成最终SDP描述
sprintf(sdpLines, sdpFmt,
那么 getAuxSDPLine其流程如下
则第二节 动态生成多媒体文件的描述信息SDP的的整体流程如下
三:将SDP 描述 作为返回消息的附带内容
snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
"RTSP/1.0 200 OK
CSeq: %s
"
"%s"
"Content-Base: %s/
"
"Content-Type: application/sdp
"
"Content-Length: %d
"
"%s",
fCurrentCSeq,
dateHeader(),
rtspURL,
sdpDescriptionSize,
sdpDescription);
} while (0);
四: 返回客户端 数据
send(fClientOutputSocket, (char const*)fResponseBuffer, strlen((char*)fResponseBuffer), 0);