ServerMediaSession::generateSDPDescription分析
//顾名思义,就是用来生成sdp描述信息的。
char* ServerMediaSession::generateSDPDescription() {
//获取本地IP地址
AddressString ipAddressStr(ourIPAddress(envir()));
unsigned ipAddressStrSize = strlen(ipAddressStr.val()); //不会执行到ssm里面,还不知道SSM是什么
// For a SSM sessions, we need a "a=source-filter: incl ..." line also:
char* sourceFilterLine;
if (fIsSSM) {
char const* const sourceFilterFmt =
"a=source-filter: incl IN IP4 * %s\r\n"
"a=rtcp-unicast: reflection\r\n";
unsigned const sourceFilterFmtSize = strlen(sourceFilterFmt) + ipAddressStrSize + ; sourceFilterLine = new char[sourceFilterFmtSize];
sprintf(sourceFilterLine, sourceFilterFmt, ipAddressStr.val());
} else {
sourceFilterLine = strDup("");
} char* rangeLine = NULL; // for now
char* sdp = NULL; // for now /*
* 有2种级别的sdp信息,一个叫子媒体级别的sdp,一个叫会话级别的sdp。
* 先计算保存sdp可能需要的内存空间大小,然后再格式化生成sdp字符串放入内存中保存起来。
*/
do {
// Count the lengths of each subsession's media-level SDP lines.
// (We do this first, because the call to "subsession->sdpLines()"
// causes correct subsession 'duration()'s to be calculated later.)
unsigned sdpLength = ;
ServerMediaSubsession* subsession;
for (subsession = fSubsessionsHead; subsession != NULL;
subsession = subsession->fNext) {
//遍历子媒体会话,获取各个子会话的sdp描述信息长度。
char const* sdpLines = subsession->sdpLines();
if (sdpLines == NULL) continue; // the media's not available
sdpLength += strlen(sdpLines);
}
if (sdpLength == ) break; // the session has no usable subsessions //获取媒体时长的sdp描述
// Unless subsessions have differing durations, we also have a "a=range:" line:
float dur = duration();
if (dur == 0.0) {
rangeLine = strDup("a=range:npt=0-\r\n");
} else if (dur > 0.0) {
char buf[];
sprintf(buf, "a=range:npt=0-%.3f\r\n", dur);
rangeLine = strDup(buf);
} else { // subsessions have differing durations, so "a=range:" lines go there
rangeLine = strDup("");
} //根会话级别的sdp固定格式
char const* const sdpPrefixFmt =
"v=0\r\n"
"o=- %ld%06ld %d IN IP4 %s\r\n"
"s=%s\r\n"
"i=%s\r\n"
"t=0 0\r\n"
"a=tool:%s%s\r\n"
"a=type:broadcast\r\n"
"a=control:*\r\n"
"%s"
"%s"
"a=x-qt-text-nam:%s\r\n"
"a=x-qt-text-inf:%s\r\n"
"%s"; //计算需要多大的内存空间来存储生成的完整sdp信息。
sdpLength += strlen(sdpPrefixFmt)
+ + + + ipAddressStrSize
+ strlen(fDescriptionSDPString)
+ strlen(fInfoSDPString)
+ strlen(libNameStr) + strlen(libVersionStr)
+ strlen(sourceFilterLine)
+ strlen(rangeLine)
+ strlen(fDescriptionSDPString)
+ strlen(fInfoSDPString)
+ strlen(fMiscSDPLines);
//适度地增加一点内存空间,防止后面子会话级别sdp和上面计算的长度不同。
sdpLength += ; // in case the length of the "subsession->sdpLines()" calls below change
//申请一段内存空间,用来存放后面生成的整个sdp字符串。
sdp = new char[sdpLength];
if (sdp == NULL) break; /*
* 完整的sdp的组成格式是:一个根会话sdp + 多个子媒体sdp。
*
*/ //格式化生成根媒体会话sdp
// Generate the SDP prefix (session-level lines):
snprintf(sdp, sdpLength, sdpPrefixFmt,
fCreationTime.tv_sec, fCreationTime.tv_usec, // o= <session id>
, // o= <version> // (needs to change if params are modified)
ipAddressStr.val(), // o= <address>
fDescriptionSDPString, // s= <description>
fInfoSDPString, // i= <info>
libNameStr, libVersionStr, // a=tool:
sourceFilterLine, // a=source-filter: incl (if a SSM session)
rangeLine, // a=range: line
fDescriptionSDPString, // a=x-qt-text-nam: line
fInfoSDPString, // a=x-qt-text-inf: line
fMiscSDPLines); // miscellaneous session SDP lines (if any) //接着,把全部的子媒体级别sdp拼接起来,放到跟会话级别sdp的后面。
// Then, add the (media-level) lines for each subsession:
char* mediaSDP = sdp;
for (subsession = fSubsessionsHead; subsession != NULL;
subsession = subsession->fNext) {
unsigned mediaSDPLength = strlen(mediaSDP);
mediaSDP += mediaSDPLength;
sdpLength -= mediaSDPLength;
if (sdpLength <= ) break; // the SDP has somehow become too long //获取子媒体sdp
char const* sdpLines = subsession->sdpLines();
if (sdpLines != NULL) snprintf(mediaSDP, sdpLength, "%s", sdpLines);
}
} while (); delete[] rangeLine; delete[] sourceFilterLine;
//返回完整sdp信息。
return sdp;
}
完。
ServerMediaSession::generateSDPDescription分析的更多相关文章
- rtsp 学习之路一
http://baijiahao.baidu.com/s?id=1587715130853990653&wfr=spider&for=pc https://www.cnblogs.co ...
- (转)live555学习笔记9-h264 RTP传输详解(1)
九 h264 RTP传输详解(1) 前几章对Server端的介绍中有个比较重要的问题没有仔细探究:如何打开文件并获得其SDP信息.我们就从这里入手吧. 当RTSPServer收到对某个媒体的DESCR ...
- 【视频开发】RTSP SERVER(基于live555)详细设计
/* *本文基于LIVE555的嵌入式的RTSP流媒体服务器一个设计文档,个中细节现剖于此,有需者可参考指正,同时也方便后期自己查阅.(本版本是基于2011年的live555) 作者:llf_17@q ...
- (转)基于live555的流媒体代理转发服务器
对于并发量并不大而且对性能要求不是很高的流媒体传输模块,live555还是很好的选择,下面说一下我所实现的流媒体代理服务器(目前只能实现对H264单视频的转发)代理转发主要 对于并发量并不大而且对性能 ...
- Live555 分析(一):类介绍
从程序的结构来看,live项目包括了四个基本库.程序入口类(在mediaServer中)和一些测试代码(在testProgs中). 四个基本静态库是UsageEnvironment.BasicUsag ...
- Live555 分析(二):服务端
live555支持单播和组播,我们先分析单播的流媒体服务端,后面分析组播的流媒体服务端. 一.单播的流媒体服务端: // Create the RTSP server: RTSPServer* rts ...
- live555 源代码简单分析1:主程序
live555是使用十分广泛的开源流媒体服务器,之前也看过其他人写的live555的学习笔记,在这里自己简单总结下. live555源代码有以下几个明显的特点: 1.头文件是.hh后缀的,但没觉得和. ...
- (转)Live555中RTSPClient分析
有RTSPServer,当然就要有RTSPClient. 如果按照Server端的架构,想一下Client端各部分的组成可能是这样:因为要连接RTSP server,所以RTSPClient要有TCP ...
- 【VS开发】【Live555-rtsp】RTSP服务器实例live555源代码分析
原文地址:RTSP服务器实例live555源代码分析作者:mozheer 1. RTSP连接的建立过程 RTSPServer类用于构建一个RTSP服务器,该类同时在其内部定义了一个RTSPClient ...
随机推荐
- sql server 还原数据库时提示数据库正在使用,无法进行操作的解决方法
这个问题的原因在于有用户连接了当前要做还原的数据库,这里的用户甚至包括当前要做还原的用户.解决办法就是关闭与要还原数据库的所有连接. 脚本之家小编推荐的一个方法:到服务里面重启下sqlserver服务 ...
- ArcBruTile 0.2.2
在ArcGIS中加载OpenStreetMap和Google.Bing的影像是不是很酷?用ArcBruTile 0.2.2可以实现.安装注册步骤如下.
- [QT]抄—影像显示实验
QtCreator新建一个Qt Application,命名为ImageView 在项目文件夹下添加gdal库,统一放在ImageView\gdal目录下. 右键单击项目,选择添加库命令,添加gdal ...
- Vue.2.0.5-过渡状态
过渡状态 Vue 的过渡系统提供了非常多简单的方法设置进入.离开和列表的动效.那么对于数据元素本身的动效呢,比如: 数字和运算 颜色的显示 SVG 节点的位置 元素的大小和其他的属性 所有的原始数字都 ...
- bootstrap ace treeview树表
html部分 <div class="widget-main padding-8" style="height:400px;overflow-y: scroll;& ...
- 连接sql server数据库的两种方式
class DB { private static SqlConnection conn; public static SqlConnection getConn() { //conn = n ...
- Lintcode: Matrix Zigzag Traversal
Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in ZigZag-or ...
- Leetcode: Strobogrammatic Number III
A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside ...
- Java初学--无限循环
利用for循环和while循环分别做到,从键盘读取任意数,输入0自动跳出无限循环,并判断有几个正数几个负数. 1.for循环的无限循环: import java.util.Scanner;//引用Sc ...
- hduoj 4706 Children's Day 2013 ACM/ICPC Asia Regional Online —— Warmup
http://acm.hdu.edu.cn/showproblem.php?pid=4706 Children's Day Time Limit: 2000/1000 MS (Java/Others) ...