[prev in list] [next in list] [prev in thread] [next in thread] 

List:       helix-server-cvs
Subject:    [Server-cvs] engine/session clientsession.cpp,1.205.4.4,1.205.4.5
From:       yijil () helixcommunity ! org
Date:       2013-06-27 2:42:28
[Download RAW message or body]

Update of /cvsroot/server/engine/session
In directory cvs01.internal.helixcommunity.org:/tmp/cvs-serv25694

Modified Files:
      Tag: SERVER_15_1_0
	clientsession.cpp 
Log Message:
Committed to: HEAD, SERVER_15_1_0_RN

Reviewed by: Richard

Synopsis
========
HLXSRV-382  [Vhost][SSPL]Seek a playlist file has error

Branches: HEAD, SERVER_15_1_0_RN

Reviewer: Anyone

Description
===========
 Repro:
 1. Server vhost configuration
 <List Name="Vhost">
 <Var EnableVhost="1"/>
 <Var EnableCnameOnly="1"/>
 <Var UserName="real"/>
 <Var Password="real"/>
 <Var VhostDirectory="/var/hms/Vhost/"/>
 <Var CalcDiskInterval="60000"/>
 <List Name="briantest">
 <Var IdentifyString="briantest"/>
 <Var CNAME="www.briantest.rhel5.com"/>
 </List>
 <List Name="Account1">
 <Var IdentifyString="account1"/>
 <Var CNAME="www.account1.rhel5.com"/>
 </List>
 2. Enable the FCS and SSPL in rmvhost.cfg  3. Request a playlist file in server  \
rtsp://www.briantest.rhel5.com/briantest/mix/playlist_mp4.hpl  4. Seek it once
 Expected:
 Could play the clip form the seek point to the end of playlist
 Actual:
 Play the clip form the seek point, but the playback will hanging when the current \
clip played over  Other Comments:

ROOT CAUSE:
After seek to clip2 as example, clip2 will be player successfully, but after clip2, \
it needs to switch to clip3. But it failed.

CSessionSourceControl::StreamDone()
{
	...
	m_pClientSession->ClipStreamDoneCalled();
	...
}

void ClientSession::ClipStreamDoneCalled()
{
    DPRINTF(D_ENTRY, ("ClientSession::ClipStreamDoneCalled() url\n"));
    //XXXJJ If we get StreamDone here, the pending switch will not get
    //the right packet to switch. We need to switch here.
    if(m_pPacketShim && m_pPacketShim->IsSwitchPending())
    {
        m_pPacketShim->SwitchSourceNow();
    }
    else if(m_pPlaylistControl)
    {
        m_pPlaylistControl->GetNextMediaClip();
    }
    else if (!m_bDone && m_pCurrentSwitch) // if it is a valid fcs switch
    {
        SwitchSource();
    }
}

BasePacketShim::Switch(IUnknown* pSource, HX_SWITCH_TYPE switch_type, 
                       IHXStreamMapper* pMapper) {
    ...
    m_bSwitchPending = TRUE;
	...
}

In my test, "CSessionSourceControl::StreamDone" will be called before \
"BasePacketShim::Switch()" is called. In "BasePacketShim::Switch", it will set \
"m_bSwitchPending" to TRUE. When it occurs, "m_pPlaylistControl->GetNextMediaClip();" \
will be called in "ClientSession::ClipStreamDoneCalled" but \
"m_pPacketShim->SwitchSourceNow();". "m_pPlaylistControl->GetNextMediaClip();" will \
switch to clip4, but the right one is clip3. Which cause the playing failed.

MY FIX:
When " ClientSession::ClipStreamDoneCalled " is called, it not call code " \
m_pPacketShim->SwitchSourceNow();" and " m_pPlaylistControl->GetNextMediaClip();" \
directly. It will schedule a call back function to make sure "BasePacketShim::Switch" \
be called first.

Files Affected
==============
server/engine/session/clientsession.cpp
server/engine/session/pub/clientsession.h

Testing Performed
=================
Integration Tests




Index: clientsession.cpp
===================================================================
RCS file: /cvsroot/server/engine/session/clientsession.cpp,v
retrieving revision 1.205.4.4
retrieving revision 1.205.4.5
diff -u -d -r1.205.4.4 -r1.205.4.5
--- clientsession.cpp	18 Jun 2013 10:31:58 -0000	1.205.4.4
+++ clientsession.cpp	27 Jun 2013 02:42:20 -0000	1.205.4.5
@@ -255,6 +255,7 @@
       , m_bNPTStartTimeSet(FALSE)
       , m_aulSelectedRates (NULL)
       , m_bSessionStartTimeSet(FALSE)
+      , m_nSwitchCallbackTimes(0)
 {
     m_pClient->AddRef();
 
@@ -6281,6 +6282,104 @@
     return HXR_OK;
 }
 
+ClientSession::SwitchCallback::SwitchCallback(ClientSession* pOwner) :
+    m_ulRefCount(0),
+    m_pOwner(pOwner)
+{
+    HX_ASSERT(m_pOwner != NULL);
+    m_pOwner->AddRef();
+}
+
+ClientSession::SwitchCallback::~SwitchCallback()
+{
+    HX_RELEASE(m_pOwner);
+}
+
+STDMETHODIMP
+ClientSession::SwitchCallback::QueryInterface(REFIID riid, void** ppvObj)
+{
+    if (IsEqualIID(riid, IID_IUnknown))
+    {
+        AddRef();
+        *ppvObj = this;
+        return HXR_OK;
+    }
+    else if (IsEqualIID(riid, IID_IHXCallback))
+    {
+        AddRef();
+        *ppvObj = (IHXCallback*)this;
+        return HXR_OK;
+    }
+
+    *ppvObj = NULL;
+    return HXR_NOINTERFACE;
+}
+
+/////////////////////////////////////////////////////////////////////////
+//  Method:
+//      IUnknown::AddRef
+//  Purpose:
+//      Everyone usually implements this the same... feel free to use
+//      this implementation.
+//
+STDMETHODIMP_(ULONG32)
+ClientSession::SwitchCallback::AddRef()
+{
+    return InterlockedIncrement(&m_ulRefCount);
+}
+
+/////////////////////////////////////////////////////////////////////////
+//  Method:
+//      IUnknown::Release
+//  Purpose:
+//      Everyone usually implements this the same... feel free to use
+//      this implementation.
+//
+STDMETHODIMP_(ULONG32)
+ClientSession::SwitchCallback::Release()
+{
+    if (InterlockedDecrement(&m_ulRefCount) > 0)
+    {
+        return m_ulRefCount;
+    }
+
+    delete this;
+    return 0;
+}
+
+STDMETHODIMP
+ClientSession::SwitchCallback::Func()
+{
+    m_pOwner->Switch();
+    return HXR_OK;
+}
+
+void
+ClientSession::Switch()
+{
+    m_nSwitchCallbackTimes++;
+    
+    if(m_pPacketShim)
+    {
+        if (m_pPacketShim->IsSwitchPending())
+        {
+            m_nSwitchCallbackTimes = 0;
+            m_pPacketShim->SwitchSourceNow();
+        }
+        else if (m_nSwitchCallbackTimes <= 10)
+        {
+            SwitchCallback* pCallback = new SwitchCallback(this);
+            m_pClient->m_pProc->pc->engine->ischedule.enter(m_pClient->m_pProc->pc->engine->now
 +                + Timeval(100000), pCallback);
+        }
+        else if(m_pPlaylistControl)
+        {
+            m_pPlaylistControl->GetNextMediaClip();
+            m_nSwitchCallbackTimes = 0;
+        }
+    }
+}
+
 HX_RESULT
 ClientSession::SessionSendControlBuffer(IHXBuffer* pBuffer)
 {
@@ -7748,7 +7847,7 @@
     {
         if (m_pClientSession->IsStreamSetup(unStreamNumber))
         {
-        m_usStreamDoneCalled++;
+            m_usStreamDoneCalled++;
         }
 
         if(m_usStreamDoneCalled == m_usNumOfStreams)
@@ -8321,17 +8420,22 @@
     DPRINTF(D_ENTRY, ("ClientSession::ClipStreamDoneCalled() url\n"));
     //XXXJJ If we get StreamDone here, the pending switch will not get
     //the right packet to switch. We need to switch here.
-    if(m_pPacketShim && m_pPacketShim->IsSwitchPending())
-    {
-        m_pPacketShim->SwitchSourceNow();
-    }
-    else if(m_pPlaylistControl)
+    if (!m_pPlaylistControl && !m_bDone && m_pCurrentSwitch) // if it is a valid fcs \
switch  {
-        m_pPlaylistControl->GetNextMediaClip();
+        SwitchSource();
     }
-    else if (!m_bDone && m_pCurrentSwitch) // if it is a valid fcs switch
+    else if (m_pPacketShim)
     {
-        SwitchSource();
+        if (!m_pPacketShim->IsSwitchPending())
+        {
+            SwitchCallback* pCallback = new SwitchCallback(this);
+            m_pClient->m_pProc->pc->engine->ischedule.enter(m_pClient->m_pProc->pc->engine->now
 +                + Timeval(100000), pCallback);
+        }
+        else
+        {
+            m_pPacketShim->SwitchSourceNow();
+        }
     }
 }
 


_______________________________________________
Server-cvs mailing list
Server-cvs@helixcommunity.org
http://lists.helixcommunity.org/mailman/listinfo/server-cvs


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic