【Live555】live555源码详解(九)(ServerMediaSession、ServerMediaSubsession、live555MediaServer)

【Live555】live555源码详解系列笔记
继承协作关系图 下面红色表示本博客将要介绍的三个类所在的位置:
ServerMediaSession、ServerMediaSubsession、DynamicRTSPServer
DynamicRTSPServer是live555MediaServer中实现的类,用来创建RTSP服务器
【Live555】live555源码详解(九)(ServerMediaSession、ServerMediaSubsession、live555MediaServer)
文章图片

17、ServerMediaSession ServerMediaSession 继承自 Medium,继承关系图:
【Live555】live555源码详解(九)(ServerMediaSession、ServerMediaSubsession、live555MediaServer)
文章图片

协作图:
【Live555】live555源码详解(九)(ServerMediaSession、ServerMediaSubsession、live555MediaServer)
文章图片

class ServerMediaSession: public Medium { public: / 创建服务端媒体会话 ServerMediaSession static ServerMediaSession* createNew(UsageEnvironment& env, char const* streamName = NULL, char const* info = NULL, char const* description = NULL, Boolean isSSM = False, char const* miscSDPLines = NULL); / 通过名字获取服务端媒体会话 ServerMediaSession static Boolean lookupByName(UsageEnvironment& env, char const* mediumName, ServerMediaSession*& resultSession); / 生成会话描述,注意:调用者负责释放返回的字符串 char* generateSDPDescription(); / 返回流名称,例如媒体文件名 char const* streamName() const { return fStreamName; } / 添加子会话 Boolean addSubsession(ServerMediaSubsession* subsession); / 返回子会话数量 unsigned numSubsessions() const { return fSubsessionCounter; } / 将“scale”设置为实际支持的比例:RTSP PLAY命令中的scale,通过调整这个数值,可以用来控制播放速度,也用来实现回放 void testScaleFactor(float& scale); / 结果== 0表示:无限制会话(默认值) / 结果<0表示:子会话持续时间不同; 结果是-(最大的)。 / 结果>0表示:这是有界会话的持续时间 float duration() const; / 当客户端访问此媒体时调用。 / 默认实现什么都不做,但是子类可以重新定义它——例如,如果你想从服务器上删除长期未使用的“ServerMediaSession”。 virtual void noteLiveness(); / 返回引用数量,当引用数为0时,才可以删除 unsigned referenceCount() const { return fReferenceCount; } / 增加引用 void incrementReferenceCount() { ++fReferenceCount; } / 减少引用 void decrementReferenceCount() { if (fReferenceCount > 0) --fReferenceCount; } / 判读是否可以删除 Boolean& deleteWhenUnreferenced() { return fDeleteWhenUnreferenced; } / 删除所有由“addSubsession()”添加的子会话,返回到“空”状态 / 注意:如果你已经添加了这个"ServerMediaSession"到"RTSPServer", / 那么,在调用这个函数之前,你必须先通过调用"RTSPServer::closeAllClientSessionsForServerMediaSession()"来关闭使用它的客户端连接。 void deleteAllSubsessions();

18、ServerMediaSubsession ServerMediaSubsession 是一个纯虚类,继承自 Medium,继承关系图:
【Live555】live555源码详解(九)(ServerMediaSession、ServerMediaSubsession、live555MediaServer)
文章图片

协作图:
【Live555】live555源码详解(九)(ServerMediaSession、ServerMediaSubsession、live555MediaServer)
文章图片

class ServerMediaSubsession: public Medium { public: / 返回子会话处理的是哪个轨道的数据(例如:音频、视频、字幕等) unsigned trackNumber() const { return fTrackNumber; } / 以字符串形式返回轨道信息:track%d char const* trackId(); / 返回SDP媒体会话的所有描述内容 virtual char const* sdpLines() = 0; / 获取流参数 virtual void getStreamParameters(unsigned clientSessionId, // in netAddressBits clientAddress, // in Port const& clientRTPPort, // in Port const& clientRTCPPort, // in int tcpSocketNum, // in (-1 means use UDP, not TCP) unsigned char rtpChannelId, // in (used if TCP) unsigned char rtcpChannelId, // in (used if TCP) netAddressBits& destinationAddress, // in out u_int8_t& destinationTTL, // in out Boolean& isMulticast, // out Port& serverRTPPort, // out Port& serverRTCPPort, // out void*& streamToken // out ) = 0; / 启动流 virtual void startStream(unsigned clientSessionId, void* streamToken, TaskFunc* rtcpRRHandler, void* rtcpRRHandlerClientData, unsigned short& rtpSeqNum, unsigned& rtpTimestamp, ServerRequestAlternativeByteHandler* serverRequestAlternativeByteHandler, void* serverRequestAlternativeByteHandlerClientData) = 0; / 暂停流 virtual void pauseStream(unsigned clientSessionId, void* streamToken); / 跳帧播放 virtual void seekStream(unsigned clientSessionId, void* streamToken, double& seekNPT,double streamDuration, u_int64_t& numBytes); virtual void seekStream(unsigned clientSessionId, void* streamToken, char*& absStart, char*& absEnd); / 在"PLAY"命令没有指定的开始时间时调用??? virtual void nullSeekStream(unsigned clientSessionId, void* streamToken, double streamEndTime, u_int64_t& numBytes); / 设置播放速度 virtual void setStreamScale(unsigned clientSessionId, void* streamToken, float scale); /获取当前正常播放时间NPT(Normal playing time) virtual float getCurrentNPT(void* streamToken); / 获取源 virtual FramedSource* getStreamSource(void* streamToken); / 返回指向“streamToken”的“RTPSink”和“RTCPInstance”对象的指针。 / 例如,如果您想要获得关联的“Groupsock”对象,这就很有用。 / 您不能删除这些对象,或开始/停止播放它们; 相反,这是使用“startStream()”和“deleteStream()”函数完成的。 virtual void getRTPSinkandRTCP(void* streamToken, RTPSink const*& rtpSink, RTCPInstance const*& rtcp) = 0; virtual void deleteStream(unsigned clientSessionId, void*& streamToken); / 将“scale”设置为实际支持的比例:RTSP PLAY命令中的scale,通过调整这个数值,可以用来控制播放速度,也用来实现回放 virtual void testScaleFactor(float& scale); // sets "scale" to the actual supported scale / 返回值 = 0 :持续播放 / 返回值 > 0 :播放持续时间 virtual float duration() const; / 子类可以通过“绝对”时间重新实现它们所支持的。 virtual void getAbsoluteTimeRange(char*& absStartTime, char*& absEndTime) const; / (例如)SIP服务器可以调用以下命令,将SDP描述中的地址和端口号字段设置为非零: void setServerAddressAndPortForSDP(netAddressBits addressBits,portNumBits portBits);

19、UserAuthenticationDatabase 用于可选用户/密码身份验证的数据结构,协作关系图:
【Live555】live555源码详解(九)(ServerMediaSession、ServerMediaSubsession、live555MediaServer)
文章图片

class UserAuthenticationDatabase { public: / 如果"passwordsAreMD5"为真,则存储到数据库或从数据库中删除的每个密码实际上都是md5计算的值(::<实际-密码>)。 UserAuthenticationDatabase(char const* realm = NULL, Boolean passwordsAreMD5 = False); virtual ~UserAuthenticationDatabase(); / 添加用户记录 virtual void addUserRecord(char const* username, char const* password); / 删除用户记录 virtual void removeUserRecord(char const* username); / 获取密码,如果用户名不存在,则返回NULL virtual char const* lookupPassword(char const* username); / 默认值是"LIVE555 Streaming Media"。(不清楚什么作用) char const* realm() { return fRealm; } / 判读密码是否经过MD5加密 Boolean passwordsAreMD5() { return fPasswordsAreMD5; } }

live555MediaServer源码分析 1、主流程 1.1 创建任务调度器和环境
TaskScheduler* scheduler = BasicTaskScheduler::createNew(); UsageEnvironment* env = BasicUsageEnvironment::createNew(*scheduler);

1.2 创建 RTSPServer
UserAuthenticationDatabase* authDB = NULL; portNumBits rtspServerPortNum = 554; RTSPServer* rtspServer = DynamicRTSPServer::createNew(*env, rtspServerPortNum, authDB);

1.3 尝试为 RTSP-over-HTTP 隧道创建一个HTTP服务器。
rtspServer->setUpTunnelingOverHTTP(80) // 尝试其它端口号:8000 8080

1.4 启动任务调度的事件循环
env->taskScheduler().doEventLoop();

2、DynamicRTSPServer 类分析 【【Live555】live555源码详解(九)(ServerMediaSession、ServerMediaSubsession、live555MediaServer)】DynamicRTSPServer 继承自 RTSPServer
主要接口:
createNew :静态函数,调用 GenericMediaServer::setUpOurSocket ,然后创建 DynamicRTSPServer

重新实现的虚函数:
lookupServerMediaSession :获取 ServerMediaSession live555MediaServer是将当前目录下的媒体文件通过RTSPServer发布出去。 lookupServerMediaSession 中首先根据名字streamName判读文件是否存在,如果存在,搜索 ServerMediaSession 是否已经创建, 结合其它条件,执行删除、创建、添加 ServerMediaSession 的操作

静态函数:
createNewSMS:创建服务会话 首先使用 ServerMediaSession::createNew 新建会话 ServerMediaSession *sms; 然后根据文件名的后缀创建不同的子会话,添加到会话sms中:sms->addSubsession(ADTSAudioFileServerMediaSubsession::createNew(...))

【Live555】live555源码详解系列笔记

    推荐阅读