live555学习笔记-几个重要对象的生命期

来源:互联网 发布:战地之王步枪之王数据 编辑:程序博客网 时间:2024/05/16 06:34
几个重要对象的生命期
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中已经实现了引用计数,见如下三个函数:
[cpp] view plain copy
  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 plain copy
  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 plain copy
  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是要被创建多次的?好像引用增加与减少对不起来啊!真的是这样吗?我没测试我不敢说,嘿嘿,那就先留个悬念吧.
0 0
原创粉丝点击