Live555中重要对象的生命期

Live555中重要对象的生命期
live555 中很多类,类与类之间的关系复杂,从属关系不明显,层次上看起来也有些乱.所
以源代码读起来比较困难,对于一些对象生命的来龙去脉也很难厘清.
但这并不能说明 live555 的架构不好,最适合的才是最好的,对于流媒体的处理来说,live555
架构已是相当精巧,当然,这是在你深入了解它的基础上才会有的体会.
live555 作为服务器,大家都很关心对内存的利用效率,是否过多的吃内存?是否造成太多
的内存碎片?
我个人认为不必太担心这方面的事,live555 对于内存的使用效率还是比较高的,当然要求
太高的可能要自己实现内存池之类的东西.
然而,我在使用它的过程中,还是发现了一点小小的问题,这个问题只在某些情况下起作用.
在此不对内存管理做全面的阐述,只是探讨一下live555 中一些重要类的对象实体是怎样被
销毁的,同时说明那点小问题.
首先说创世者:是RTSPServer:它需永存,其余对象都是由它创建或由它引起了它们的创
建.
RTSPServer 直接掌管的是ServerMediaSession 和RTSPClientSession(只主其生,不掌其
死).
ServerMediaSession 对应一个媒体文件,而RTSPClientSession 对应一个RTSP 客户连
接.RTSPClientSession 在客户发出RTSP 的TCP 连接时建立,而ServerMediaSession
在客户发出对一个新文件的DESCRIBE 时建立.建立ServerMediaSession 的同时也建立
了ServerMediaSubsession 们,被ServerMediaSession 所管理,代表一个文件中的track
们.
ServerMediaSession 的建立规则值得一说:RTSPClientSession 在收到客户的DESCRIBE
请求时,跟据地址中的媒体名字,去查找ServerMediaSession 的列表,如果已有对应此媒
体名字的ServerMediaSession,则利用它获取SDP 信息.如果没找到,则跟据媒体名字中
的扩展名部分,建立对应此类媒体的新ServerMediaSession 对象.所以可以明确一点:一
个ServerMediaSubsession 对应一个文件!
但是,如果测试,你会发现当一个文件播放完毕之后,并没有删除对应的
ServerMediaSession.同时,与ServerMediaSubsession 相关的那一坨东西(Demux 和
ServerMediaSubsession)也没有被销毁.但是它们终究还是要面临死亡的.什么时候死呢?
RTSPServer 销毁的什候(或对应的文件不存在了时)!哦,看到问题了吧?如果你做点播
服务器,每打开一个文件就会创建一个ServerMediaSession 以及相关的一坨东西们,如果
文件太多,内存终究有用完的时候.
再说一下 RTSPClientSession,RTSPClientSession 有两种结束生命的方式,一是在对应
流(StreamState)接收不到RTCP 数据了,还记得前面讲过RTCPInstance 的
setSpecificRRHandler()吗?RTSPClientSession 就是通过它来监视客户端的心跳的.二种
方式是收到客户端的TEARDOWN 请求时自杀.RTSPClientSession 自杀的同时会把流对
象StreamState 以及流上的Source 和sink 全干掉.
所以说,除了RTSPClientSession 那一坨之外,其余的对象还是可以在适当的时候销毁的.基
本上是代表静态数据的对象不销毁,而代表动态数据的对象销毁.
如果你做的是实时流媒体,那么这正是所需要的.而做点播服务呢?总不能文件关了,代表
文件的对象还在内存中吧?
那我们如何去改呢?
其实很简单,我们只要在没有任何对ServerMediaSession 的引用时把它删除不就行了.而
且ServerMediaSession 中已经实现了引用计数
1. unsigned referenceCount() const
2. {
3. return fReferenceCount;
4. }
5. void incrementReferenceCount()
6. {
7. ++fReferenceCount;
8. }
9. void decrementReferenceCount()
10. {
11. if (fReferenceCount > 0)
12. --fReferenceCount;
13. }
现在的问题是何时减少这个引用计数.可以想象,基本情况是在建立一个新的StreamState
时或建立RTSPClientSession 时,ServerMediaSession 的引用就会增加1.那么理应在
RTSPClientSession 关闭时减去1.我们看看源码,是否是这样做了?
经查找,是在建立新的 StreamState 时.在函数void
RTSPServer::RTSPClientSession::handleCmd_SETUP(char const* cseq,char const*
urlPreSuffix, char const* urlSuffix,char const* fullRequestStr)中可以看到.再找一下减少引
用的代码:
[cpp] view plaincopyprint?
1. RTSPServer::RTSPClientSession::~RTSPClientSession()
2. {
3. closeSockets();
4.
5.
6. if (fSessionCookie != NULL)
7. {
8. // We were being used for RTSP-over-HTTP tunneling. Remove ourselves
from the 'session cookie' hash table before we go:
9. fOurServer.fClientSessionsForHTTPTunneling->Remove(fSessionCookie);
10. delete[] fSessionCookie;
11. }
12.
13.
14. reclaimStreamStates();
15.
16.
17. if (fOurServerMediaSession != NULL)
18. {
19. fOurServerMediaSession->decrementReferenceCount();
20. if (fOurServerMediaSession->referenceCount() == 0
21. && fOurServerMediaSession->deleteWhenUnreferenced())
22. {
23. fOurServer.removeServerMediaSession(fOurServerMediaSession);
24. fOurServerMediaSession = NULL;
25. }
26. }
27. }
是在RTSPClientSession 销毁时减少引用.同时我们还看到
[cpp] view plaincopyprint?
1. if (fOurServerMediaSession->referenceCount() == 0
2. && fOurServerMediaSession->deleteWhenUnreferenced())
3. {
4. fOurServer.removeServerMediaSession(fOurServerMediaSession);
5. fOurServerMediaSession = NULL;
6. }
这样的语句,翻译过来就是:当引用为0并且可以在引用为0时删除,那么就删除它!原来
在这里!我们只要让他deleteWhenUnreferenced()能返回True 就解决上面所说的那个小问
题了.
等等,似乎还有问题,ServerMediaSession 是RTSPClientSession 在建立StreamState 时
增加引用,而在RTSPClientSession 销毁时减少引用,如果有多个Track,StreamState 是
要被创建多次的?好像引用增加与减少对不起来啊!真的是这样吗?我没测试我不敢说,嘿
嘿,那就先留个悬念吧.

你可能感兴趣的:(Live555中重要对象的生命期)