[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