您的位置:首页 > 其它

Live555中重要对象的生命期

2013-11-19 19:20 405 查看
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 是

要被创建多次的?好像引用增加与减少对不起来啊!真的是这样吗?我没测试我不敢说,嘿

嘿,那就先留个悬念吧.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: