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

List:       helix-datatype-cvs
Subject:    [Datatype-cvs] httplive/fileformat httpliveff.cpp,1.4,1.5
From:       qluo () helixcommunity ! org
Date:       2010-04-30 12:20:15
Message-ID: 201004301220.o3UCKkeV016468 () mailer ! progressive-comp ! com
[Download RAW message or body]

Update of /cvsroot/datatype/httplive/fileformat
In directory cvs01.internal.helixcommunity.org:/tmp/cvs-serv1372

Modified Files:
	httpliveff.cpp 
Log Message:
initial implementation.


Index: httpliveff.cpp
===================================================================
RCS file: /cvsroot/datatype/httplive/fileformat/httpliveff.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- httpliveff.cpp	29 Apr 2010 20:42:04 -0000	1.4
+++ httpliveff.cpp	30 Apr 2010 12:20:13 -0000	1.5
@@ -108,13 +108,10 @@
     , m_LastError(HXR_OK)
     , m_pContext(NULL)
     , m_pScheduler(NULL)
-    , m_pPlaylistDownloadCallback(NULL)
+    , m_pCallbacks(NULL)
     , m_pRequest(NULL)
     , m_pFFResponse(NULL)
     , m_pPlaylistFileObject(NULL)
-    , m_pSegmentFileObject(NULL)
-    , m_pCurrentFileFormat(NULL)
-    , m_pNextFileFormat(NULL)
     , m_pCurrentFileFormatInfo(NULL)
     , m_pNextFileFormatInfo(NULL)
     , m_ulNumFileFormatInitDonePending(0)
@@ -128,6 +125,7 @@
     , m_ulNumStreamHeadersSent(0)
     , m_nPendingStreamHeaderNumber(0)
     , m_nTotalPendingHeaders(0)
+    , m_bPendingGetPacketArray(NULL)
     , m_bStreamSwitchingPending(FALSE)
     , m_ulDetectedBandwidth(0)
     , m_ulDuration(0)
@@ -159,10 +157,10 @@
         m_pContext->QueryInterface(IID_IHXScheduler, (void**) &m_pScheduler);
         if (m_pScheduler)
         {
-            m_pPlaylistDownloadCallback = new CHXGenericCallback((void*) this, \
                PlaylistDownloadCallbackFunc);
-	    if (m_pPlaylistDownloadCallback)
+            m_pCallbacks = new CHXGenericCallback((void*) this, CallbackFunction);
+	    if (m_pCallbacks)
 	    {
-	        m_pPlaylistDownloadCallback->AddRef();
+	        m_pCallbacks->AddRef();
                 retVal =  HXR_OK;
 	    }
         }
@@ -261,11 +259,11 @@
 STDMETHODIMP CHttpLiveFileFormat::Close(void)
 {
     // cancel pending playlist download
-    if (m_pPlaylistDownloadCallback && \
m_pPlaylistDownloadCallback->IsCallbackPending()) +    if (m_pCallbacks && \
m_pCallbacks->IsCallbackPending())  {
-        m_pPlaylistDownloadCallback->Cancel(m_pScheduler);
+        m_pCallbacks->Cancel(m_pScheduler);
     }
-    HX_DELETE(m_pPlaylistDownloadCallback);
+    HX_DELETE(m_pCallbacks);
 
     // delete scheduler 
     HX_RELEASE(m_pScheduler);
@@ -277,18 +275,6 @@
         HX_RELEASE(m_pPlaylistFileObject);
     }
 
-    // close actual ts file formats
-    if (m_pCurrentFileFormat)
-    {
-        m_pCurrentFileFormat->Close();
-        HX_RELEASE(m_pCurrentFileFormat);
-    }
-    if (m_pNextFileFormat)
-    {
-        m_pNextFileFormat->Close();
-        HX_RELEASE(m_pNextFileFormat);
-    }
-
     if (m_pCurrentFileFormatInfo)
     {
         // todo:
@@ -300,13 +286,6 @@
         HX_DELETE(m_pNextFileFormatInfo);
     }
 
-    // release Segment file object
-    if (m_pSegmentFileObject != NULL)
-    {
-        m_pSegmentFileObject->Close();
-        HX_RELEASE(m_pSegmentFileObject);
-    }
-
     // delete the parser
     HX_DELETE(m_pPlaylistParser);
 
@@ -497,12 +476,12 @@
 
     if (m_pCurrentFileFormatInfo->pStreamsDoneArray[usStreamNo] == FALSE)
     {
-        m_pCurrentFileFormatInfo->bPacketPending = TRUE;
+        m_pCurrentFileFormatInfo->ulNumPacketPending++;
         m_LastError = \
m_pCurrentFileFormatInfo->pFileFormatObject->GetPacket(usStreamNo);  }
     else if (m_pNextFileFormatInfo && \
m_pCurrentFileFormatInfo->pStreamsDoneArray[usStreamNo] == FALSE)  {
-        m_pNextFileFormatInfo->bPacketPending = TRUE;
+        m_pNextFileFormatInfo->ulNumPacketPending++;
         m_LastError = \
m_pNextFileFormatInfo->pFileFormatObject->GetPacket(usStreamNo);  }
 
@@ -568,6 +547,7 @@
         // InitDone() from file format object
         if (m_ulNumFileFormatInitDonePending > 0)
         {
+            m_ulNumFileFormatInitDonePending--;
             if (m_pCurrentFileFormatInfo->bInitDonePending)
             {
                 m_pCurrentFileFormatInfo->bInitDonePending = FALSE;
@@ -575,13 +555,14 @@
             else if (m_pNextFileFormatInfo->bInitDonePending)
             {
                 m_pNextFileFormatInfo->bInitDonePending = FALSE;
+                m_pNextFileFormatInfo->bFileHeaderPending = TRUE;
+                m_LastError = \
m_pNextFileFormatInfo->pFileFormatObject->GetFileHeader();  }
             else
             {
                 HX_ASSERT(FALSE);
             }
 
-            m_ulNumFileFormatInitDonePending--;
             if (m_eStatus == InitDoneResponsePending && \
m_ulNumFileFormatInitDonePending == 0)  {
                 // all file format objects are ready, InitDone is pending,
@@ -725,9 +706,10 @@
         pCurrentAltStream->pAbsolutePlaylistURL = new \
CHXString(m_StrAbsolutePlaylistURL);  
         // schedule playlist download
-        if (!m_pPlaylistDownloadCallback->IsCallbackPending())
+        if (!m_pCallbacks->IsCallbackPending())
         {
-            m_pPlaylistDownloadCallback->ScheduleRelative(m_pScheduler, 0);
+            m_eCallbackType = eTypePlaylistDownload;
+            m_pCallbacks->ScheduleRelative(m_pScheduler, 0);
         }
     }
     else if (SUCCEEDED(m_LastError))
@@ -769,6 +751,13 @@
         pHeader->GetPropertyULONG32("StreamCount", m_ulStreamCount);
     }
 
+    // Save segment duration
+    UINT32 ulSegmentDuration = 0;
+    if (SUCCEEDED(status) && pHeader)
+    {
+        pHeader->GetPropertyULONG32("Duration", ulSegmentDuration);
+    }
+
     // save DTS base offset and setup for the selected FileFormatInfo
     if (SUCCEEDED(status))
     {
@@ -781,6 +770,7 @@
             {
                 m_pCurrentFileFormatInfo->bFileHeaderPending = FALSE;
                 m_pCurrentFileFormatInfo->u64DTSBaseOffset = u64DTSBaseOffset;
+                m_pCurrentFileFormatInfo->ulSegmentDuration = ulSegmentDuration;
                 if (m_bStreamSwitchingPending)
                 {
                     pNewVariantStreamFFInfo = m_pCurrentFileFormatInfo;
@@ -791,6 +781,7 @@
             {
                 m_pNextFileFormatInfo->bFileHeaderPending = FALSE;
                 m_pNextFileFormatInfo->u64DTSBaseOffset = u64DTSBaseOffset;
+                m_pCurrentFileFormatInfo->ulSegmentDuration = ulSegmentDuration;
                 if (m_bStreamSwitchingPending)
                 {
                     pNewVariantStreamFFInfo = m_pNextFileFormatInfo;
@@ -809,8 +800,12 @@
     {
         if (SUCCEEDED(status) && pHeader)
         {
-            // save m_ulStreamCount
-            pHeader->GetPropertyULONG32("StreamCount", m_ulStreamCount);
+            // alloc m_bPendingGetPacketArray
+            if (!m_bPendingGetPacketArray)
+            {
+                m_bPendingGetPacketArray = new HXBOOL[m_ulStreamCount];
+                memset(m_bPendingGetPacketArray, 0, m_ulStreamCount * \
sizeof(HXBOOL)); +            }
 
             // save DTS base offset
             m_u64FirstDTSBaseOffset = u64DTSBaseOffset;
@@ -912,6 +907,7 @@
 STDMETHODIMP CHttpLiveFileFormat::PacketReady(HX_RESULT status, IHXPacket* pPacket)
 {
     HX_RESULT retVal = HXR_OK;
+    HXBOOL bInitializeNext = FALSE;
 
     IHXRTPPacket* pRTPPacket = NULL;
 
@@ -941,16 +937,22 @@
         UINT64 u64CurrentDTSBaseOffset = 0;
         if (SUCCEEDED(retVal))
         {
-            if (m_pCurrentFileFormatInfo->bPacketPending &&
+            if (m_pCurrentFileFormatInfo->ulNumPacketPending > 0 &&
                 m_pCurrentFileFormatInfo->pStreamsDoneArray[usStreamNumber] == \
FALSE)  {
-                m_pCurrentFileFormatInfo->bPacketPending = FALSE;
+                m_pCurrentFileFormatInfo->ulNumPacketPending--;
                 u64CurrentDTSBaseOffset = \
m_pCurrentFileFormatInfo->u64DTSBaseOffset; +
+                // should we start initializing the next file format?
+                if (m_pNextFileFormatInfo->bInitCalled == FALSE && (ulDecodingTS * 2 \
> m_pCurrentFileFormatInfo->ulSegmentDuration)) +                {
+                    bInitializeNext = TRUE;
+                }
             }
-            else if (m_pNextFileFormatInfo->bPacketPending &&
+            else if (m_pNextFileFormatInfo->ulNumPacketPending > 0 &&
                      m_pNextFileFormatInfo->pStreamsDoneArray[usStreamNumber] == \
FALSE)  {
-                m_pNextFileFormatInfo->bPacketPending = FALSE;
+                m_pNextFileFormatInfo->ulNumPacketPending--;
                 u64CurrentDTSBaseOffset = m_pNextFileFormatInfo->u64DTSBaseOffset;
             }
             else
@@ -990,6 +992,17 @@
         m_LastError = retVal;
     }
 
+    // schedule for initializing next file format
+    if (SUCCEEDED(m_LastError) && bInitializeNext)
+    {
+        m_pNextFileFormatInfo->bInitCalled = TRUE;
+        if (!m_pCallbacks->IsCallbackPending())
+        {
+            m_eCallbackType = eTypeInitNextFileFormat;
+            m_pCallbacks->ScheduleRelative(m_pScheduler, 0);
+        }
+    }
+
     // propagate pPacket
     if (SUCCEEDED(m_LastError))
     {
@@ -1006,23 +1019,74 @@
 
 STDMETHODIMP CHttpLiveFileFormat::StreamDone(UINT16 usStreamNumber)
 {
-    // we only propagate StreamDone for the last ts segment in the playlist
-    // 1) if streams are not all done for the current ts segment, do nothing
-    // 2) if all streams are done for the current ts segment and there is next ts:
-    //    a) close the current ts file format
-    //    b) assign  m_pNextFileFormat to m_pCurrentFileFormat
-    //    c) create new file object, m_pNextFileFormat and call InitFileFormat()
-    // 3) if there is no next ts segment, propagate StreamDone() via response
+    HXBOOL bAllCurrentStreamsDone = FALSE;
 
-    if (m_pNextFileFormat == NULL)
+    // stream done callback is always from the current fileformat
+    if (m_pCurrentFileFormatInfo->ulNumPacketPending > 0)
     {
+        m_pCurrentFileFormatInfo->ulNumPacketPending--;
+
+        // mark slot in m_bPendingGetPacketArray for GetPacket()
+        m_bPendingGetPacketArray[usStreamNumber] = TRUE;
+
+        // mark this stream as done
+        m_pCurrentFileFormatInfo->pStreamsDoneArray[usStreamNumber] = TRUE;
+
+        // are we done with all streams in this segment?
+        if(AreAllStreamsDone(m_pCurrentFileFormatInfo))
+        {
+            bAllCurrentStreamsDone = TRUE;
+        }
+    }
+
+    // 1) if there is no next segment file, propagate StreamDone()
+    // 2) if there are more segment file(s)
+    //    a) if streams are not all done, ccall GetPacket() using next fileformat
+    //    b) if the streams are all done, then
+    //       -- swap current and next FileFormatInfos
+    //       -- call GetPacket() using current file format
+    //       -- if live, schedule reload playlist callback
+    //       -- make new next fileformat
+
+    if (m_pNextFileFormatInfo->pFileFormatObject == NULL)
+    {
+        // propagate StreamDone()
         m_pFFResponse->StreamDone(usStreamNumber);
     }
-    else
+    else if (bAllCurrentStreamsDone == FALSE)
     {
-        // todo:
+        // ccall GetPacket() using next fileformat
+        m_pNextFileFormatInfo->ulNumPacketPending++;
+        m_pNextFileFormatInfo->pFileFormatObject->GetPacket(usStreamNumber);
 
     }
+    else if(bAllCurrentStreamsDone == TRUE)
+    {
+        // advance m_pPlaylistStatus->ulCurrentSequenceNum
+        m_pPlaylistStatus->ulCurrentSequenceNum++;
+
+        // swap file format current<-->next
+        FileFormatInfo_t* pTemp = m_pCurrentFileFormatInfo;
+        m_pCurrentFileFormatInfo = m_pNextFileFormatInfo;
+        m_pNextFileFormatInfo = pTemp;
+
+        // next segment
+        SetupFileFormatInfo(m_pNextFileFormatInfo, \
m_pPlaylistStatus->ulCurrentSequenceNum + 1); +
+        // schedule playlist update
+        if (m_pPlaylistInfo->bIsLive)
+        {
+            if (!m_pCallbacks->IsCallbackPending())
+            {
+                m_eCallbackType = eTypePlaylistDownload;
+                m_pCallbacks->ScheduleRelative(m_pScheduler, 10);
+            }
+        }
+
+        // GetPacket() via new current file format
+        m_pCurrentFileFormatInfo->ulNumPacketPending++;
+        m_pCurrentFileFormatInfo->pFileFormatObject->GetPacket(usStreamNumber);
+    }
 
     return HXR_OK;
 }
@@ -1031,37 +1095,49 @@
  *  CHttpLiveFileFormat functions
  */
 void
-CHttpLiveFileFormat::PlaylistDownloadCallbackFunc(void* pParam)
+CHttpLiveFileFormat::CallbackFunction(void* pParam)
 {
     if (pParam)
     {
         CHttpLiveFileFormat* pObj = (CHttpLiveFileFormat*) pParam;
-        pObj->HandlePlaylistDownloadCallback();
+        pObj->HandleCallbacks();
     }
 }
 
 void
-CHttpLiveFileFormat::HandlePlaylistDownloadCallback(void)
+CHttpLiveFileFormat::HandleCallbacks(void)
 {
     if (FAILED(m_LastError))
     {
         return;
     }
 
-    // release current file object
-    if (m_pPlaylistFileObject)
+    // playlist download
+    if (m_eCallbackType == eTypePlaylistDownload)
     {
-        m_pPlaylistFileObject->Close();
-        HX_RELEASE(m_pPlaylistFileObject);
-    }
+        // release current file object
+        if (m_pPlaylistFileObject)
+        {
+            m_pPlaylistFileObject->Close();
+            HX_RELEASE(m_pPlaylistFileObject);
+        }
 
-    // create new file object
-    m_LastError = CHXHttpFileObjectMaker::CreateHTTPFileObjectWithURL(m_pContext, \
(const char*)m_StrAbsolutePlaylistURL, m_pPlaylistFileObject); +        // create new \
file object +        m_LastError = \
CHXHttpFileObjectMaker::CreateHTTPFileObjectWithURL(m_pContext, (const \
char*)m_StrAbsolutePlaylistURL, m_pPlaylistFileObject);  
-    // kickoff download
-    if (SUCCEEDED(m_LastError))
+        // kickoff download
+        if (SUCCEEDED(m_LastError))
+        {
+            m_LastError = m_pPlaylistFileObject->Init(HX_FILE_READ | HX_FILE_BINARY, \
this); +        }
+    }
+
+    // initialize next file format
+    else if (m_eCallbackType == eTypeInitNextFileFormat)
     {
-        m_LastError = m_pPlaylistFileObject->Init(HX_FILE_READ | HX_FILE_BINARY, \
this); +        m_ulNumFileFormatInitDonePending++;
+        m_pNextFileFormatInfo->bInitDonePending = TRUE;
+        m_LastError = \
m_pNextFileFormatInfo->pFileFormatObject->InitFileFormat(m_pNextFileFormatInfo->pRequest, \
this, m_pNextFileFormatInfo->pFileObject);  }
 }
 
@@ -1083,10 +1159,10 @@
     {
         // we have finished downloading all vriant playlists. we need to
         // 1) sellect a variant playlist and init m_pPlaylistStatus
-        // 2) create a FileFormatSwitcher_t, m_pCurrentFileFormat 
+        // 2) create a FileFormatSwitcher_t, m_pCurrentFileFormatInfo 
         //    for the 1st file segment from the sellected list
         // 3) cerate a ts FF and call InitFileFormat
-        // 4) create m_pNextFileFormat to be ready for segment to segment transition
+        // 4) create m_pNextFileFormatInfo to be ready for segment to segment \
transition  
         // sellect a vriant stream
         UINT32 ulStreamIndex = 0;
@@ -1277,8 +1353,6 @@
     // close file format
     if (pFileFormatInfo)
     {
-        pFileFormatInfo->u64DTSBaseOffset = 0;
-
         if (pFileFormatInfo->pFileFormatObject)
         {
             pFileFormatInfo->pFileFormatObject->Close();
@@ -1296,7 +1370,7 @@
     // close file object
     if (SUCCEEDED(retVal) && pFileFormatInfo->pFileObject)
     {
-        // todo: proxy file system
+        // don't need release
         pFileFormatInfo->pFileObject = NULL;
     }
 
@@ -1314,6 +1388,15 @@
     {
         memset(pFileFormatInfo->pStreamsDoneArray, 0, sizeof(HXBOOL) * \
m_ulStreamCount);  }
+    
+    // reset values
+    pFileFormatInfo->ulSegmentDuration          = 0;
+    pFileFormatInfo->u64DTSBaseOffset           = 0;
+    pFileFormatInfo->bInitDonePending           = FALSE;
+    pFileFormatInfo->bInitCalled                = FALSE;
+    pFileFormatInfo->bFileHeaderPending         = FALSE;
+    pFileFormatInfo->ulNumPendingStreamHeaders  = 0;
+    pFileFormatInfo->ulNumPacketPending         = 0;
 
     return retVal;
 }
@@ -1420,3 +1503,19 @@
     return retVal;
 }
 
+HXBOOL
+CHttpLiveFileFormat::AreAllStreamsDone(FileFormatInfo_t* pFileFormatInfo)
+{
+    HXBOOL bDone = TRUE;
+
+    for (UINT32 i=0; i<m_ulStreamCount; i++)
+    {
+        if (pFileFormatInfo->pStreamsDoneArray[i] == FALSE)
+        {
+            bDone = FALSE;
+            break;
+        }
+    }
+
+    return bDone;
+}


_______________________________________________
Datatype-cvs mailing list
Datatype-cvs@helixcommunity.org
http://lists.helixcommunity.org/mailman/listinfo/datatype-cvs


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

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