robpktparse.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:18k
- /* ***** BEGIN LICENSE BLOCK *****
- * Version: RCSL 1.0/RPSL 1.0
- *
- * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file, are
- * subject to the current version of the RealNetworks Public Source License
- * Version 1.0 (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the RealNetworks Community Source License Version 1.0
- * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
- * in which case the RCSL will apply. You may also obtain the license terms
- * directly from RealNetworks. You may not use this file except in
- * compliance with the RPSL or, if you have a valid RCSL with RealNetworks
- * applicable to this file, the RCSL. Please see the applicable RPSL or
- * RCSL for the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the portions
- * it created.
- *
- * This file, and the files included with this file, is distributed and made
- * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- #include "hxtypes.h"
- #include "hlxclib/stdio.h"
- #include "hlxosstr.h"
- #include "hxcom.h" // IUnknown
- #include "hxcomm.h" // IHXCommonClassFactory
- #include "ihxpckts.h" // IHXBuffer, IHXPacket, IHXValues
- #include "hxplugn.h" // IHXPlugin
- #include "hxrendr.h" // IHXRenderer
- #include "hxengin.h" // IHXInterruptSafe
- #include "hxcore.h" // IHXStream
- #include "hxausvc.h" // Audio Services
- #include "hxmon.h" // IHXStatistics
- #include "hxupgrd.h" // IHXUpgradeCollection
- #include "hxslist.h" // CHXSimpleList
- #include "carray.h" // CHXPtrArray
- #include "tconverter.h" // CHXTimestampConverter
- #include "hxstrutl.h"
- #include "mpadecobj.h" // MPEG Audio Decoder (selects fixed-pt or floating-pt based on HELIX_CONFIG_FIXEDPOINT)
- #include "mp3format.h" // MP3 formatter
- #ifdef DEMUXER
- #include "xmddemuxer.h" // Demuxer
- #include "xmdtypes.h"
- #endif
- #include "mp3rend.h" // CRnMp3Ren
- #include "pktparse.h" // CPacketParser
- #include "robpktparse.h" // CRobustPacketParser
- CRobustPacketParser::CRobustPacketParser() :
- CPacketParser(),
- m_ulIndex(0),
- m_bFirstFrame(TRUE),
- m_pTsConvert(NULL)
- // m_dNextFrameTime(0.0),
- // m_dFrameTime(0.0)
- {
- m_bReformatted = TRUE;
- }
- CRobustPacketParser::~CRobustPacketParser()
- {
- m_Cycles.DeleteAll();
- HX_DELETE(m_pTsConvert);
- }
- HX_RESULT
- CRobustPacketParser::AddPacket(IHXPacket* pPacket, INT32 streamOffsetTime)
- {
- if(pPacket == NULL)
- return HXR_INVALID_PARAMETER;
- // Get the buffer.
- IHXBuffer* pPacketBuf = pPacket->GetBuffer();
- if(pPacketBuf == NULL || pPacketBuf->GetSize() == 0)
- {
- HX_RELEASE(pPacketBuf);
- return HXR_INVALID_PARAMETER;
- }
- double dTime;
- // Get the packet time
- IHXRTPPacket *pRtpPacket = NULL;
- pPacket->QueryInterface(IID_IHXRTPPacket, (void**)&pRtpPacket);
- if (pRtpPacket)
- {
- if (!m_pTsConvert)
- {
- m_pTsConvert = new CHXTimestampConverter(CHXTimestampConverter::FACTORS,
- 1,
- 90);
- if (m_pTsConvert)
- {
- m_pTsConvert->setHXAnchor(pPacket->GetTime());
- }
- }
- if (m_pTsConvert)
- {
- dTime = m_pTsConvert->rtp2hxa(pRtpPacket->GetRTPTime());
- }
- else
- {
- dTime = pRtpPacket->GetRTPTime() / 90.0;
- }
- pRtpPacket->Release();
- }
- else
- {
- //dTime = pPacket->GetTime();
- dTime = pPacket->GetTime();
- }
- if(streamOffsetTime > dTime)
- {
- dTime = 0;
- }
- else
- {
- dTime -= streamOffsetTime;
- }
- // Set the time for the first frame in the packet
- UINT32 ulOffset = GetFrameInfo(pPacketBuf, 0, dTime);
-
- while(ulOffset < pPacketBuf->GetSize())
- {
- ulOffset = GetFrameInfo(pPacketBuf, ulOffset, -1);
- }
- return HXR_OK;
- }
- UINT32
- CRobustPacketParser::GetFrame(UCHAR*& pFrameBuffer, double& dTime, BOOL& bLost)
- {
- pFrameBuffer = NULL;
- dTime = 0.0;
- bLost = FALSE;
- // If we don't have any frames yet
- if(m_Cycles.IsEmpty())
- {
- return 0;
- }
- SCycle* pCycle = NULL;
- BOOL bNextCycle = TRUE;
- BOOL bCheckLoss = FALSE;
- SFrameInfo* pFrameInfo = NULL;
- UINT32 ulIndex = m_ulIndex;
- pCycle = (SCycle*)m_Cycles.GetHead();
- while(bNextCycle)
- {
- // This will never be NULL since we never add NULL
- HX_ASSERT(pCycle != NULL);
- pFrameInfo = pCycle->pFrames[ulIndex];
- if(pFrameInfo && pFrameInfo->bComplete)
- {
- // we have a frame ready!
- bNextCycle = FALSE;
- }
- else
- {
- // we haven't got to the next cycle yet, keep waiting
- if(m_Cycles.GetCount() <= 1 && !m_bEndOfPackets)
- {
- m_ulIndex = ulIndex;
- return 0;
- }
- // this frame is lost (we still have more this cycle)
- if(ulIndex < (UINT32)pCycle->nMaxIndex)
- {
- #if defined(WIN32) && defined(_DEBUG)
- char str[256]; /* Flawfinder: ignore */
- SafeSprintf(str, 256, "Known packet loss: Index: %d, Cycle: %d, "
- "Frag: %cn", ulIndex, pCycle->nCycleIndex,
- pFrameInfo ? 'y' : 'n');
- OutputDebugString(OS_STRING(str));
- #endif // defined(WIN32) && defined(_DEBUG)
- // If we have a partial frame, release it
- HX_DELETE(pCycle->pFrames[ulIndex]);
- if(m_bFirstFrame)
- {
- #if defined(WIN32) && defined(_DEBUG)
- OutputDebugString(OS_STRING("First frame missing. Ignoring.n"));
- #endif // defined(WIN32) && defined(_DEBUG)
-
- // If this was the first frame, ignore it and keep looking
- while(++ulIndex <= (UINT32)pCycle->nMaxIndex && bNextCycle)
- {
- pFrameInfo = pCycle->pFrames[ulIndex];
- if(pFrameInfo && pFrameInfo->bComplete)
- {
- // we have a frame ready!
- bNextCycle = FALSE;
- break;
- }
- HX_DELETE(pCycle->pFrames[ulIndex]);
- }
- }
- else
- {
- m_ulIndex++;
- bLost = TRUE;
- bNextCycle = FALSE;
- }
- }
- if(bNextCycle)
- {
- // We're done with this cycle, so get rid of it and
- // go to the next
- m_Cycles.RemoveHead();
- delete pCycle;
- ulIndex = 0;
- if(m_Cycles.GetCount() > 0)
- {
- pCycle = (SCycle*)(m_Cycles.GetHead());
- }
- else if (m_bEndOfPackets)
- {
- m_ulIndex = 0;
- return 0;
- }
- }
- }
- }
-
- // Try to get the frame presentation time
- double dPresTime;
- // If it's lost, go with the default time
- if(bLost)
- {
- dPresTime = m_dNextPts;
- }
- // Else if this frame has a time stamp, use it
- else if(pFrameInfo->dTime >= 0)
- {
- dPresTime = pFrameInfo->dTime;
- }
- // Else if we have calculated the start time of this cycle
- // (based on another frame with a timestamp) calculate this one
- else if(pCycle->dStartTime >= 0)
- {
- dPresTime = pCycle->dStartTime + m_dFrameTime*ulIndex;
- }
- // Else we have no time stamps for any frames in this cycle yet.
- // Check if we have later cycles with timestamps
- else
- {
- dPresTime = -1.0;
- SCycle* pTmpCycle = pCycle;
- while((pTmpCycle = m_Cycles.GetNext(pTmpCycle)) != 0)
- {
- if(pTmpCycle->dStartTime >= 0)
- {
- // uh-oh, we got a full cycle without any time stamps!
- // either massive packet loss or a really crappy
- // interleaving algorithm. assume it's supposed to go now
- // and any unaccounted for loss is at the end of the cycle
- dPresTime = m_dNextPts;
- pCycle->dStartTime = dPresTime - m_dFrameTime*ulIndex;
- }
- }
- }
- // If we haven't gotten any timestamps yet this cycle, wait for
- // the next packet.
- if(dPresTime < 0)
- {
- if(!m_bEndOfPackets)
- {
- m_ulIndex = ulIndex;
- return 0;
- }
-
- // We don't have a time stamp, but there are no more packets coming
- dPresTime = m_dNextPts;
- }
- // If this is the first frame, set the time accordingly
- if(m_bFirstFrame)
- {
- #if defined(WIN32) && defined(_DEBUG)
- char str[256]; /* Flawfinder: ignore */
- SafeSprintf(str, 256, "First decode, setting time to %lfn", dPresTime);
- OutputDebugString(OS_STRING(str));
- #endif // defined(WIN32) && defined(_DEBUG)
- m_dNextPts = dPresTime;
- }
- if(!m_bFirstFrame && dPresTime - m_dNextPts >= m_dFrameTime)
- {
- // We have frames lost before this one
- #if defined(WIN32) && defined(_DEBUG)
- char str[256]; /* Flawfinder: ignore */
- SafeSprintf(str, 256, "Apparent packet loss: Index: %d, Cycle: %d, "
- "PresTime: %lf, NextPts: %lf, FrameTime: %lfn",
- ulIndex, pCycle->nCycleIndex, dPresTime, m_dNextPts,
- m_dFrameTime);
- OutputDebugString(OS_STRING(str));
- #endif // defined(WIN32) && defined(_DEBUG)
- bLost = TRUE;
- }
- if(pFrameInfo && pFrameInfo->ulADUSize < 2)
- {
- // this frame is too small. skip it and do loss recovery
- HX_DELETE(pCycle->pFrames[ulIndex]);
- m_ulIndex = ulIndex + 1;
- bLost = TRUE;
- }
- // If the frame was lost, we reuse the one already in the buffer,
- // so don't need to copy or anything
- if(!bLost)
- {
- IHXBuffer* pPacketBuf;
- SFrameData* pFrameData;
- UINT32 ulSize;
- UCHAR* pBuf;
- UCHAR* pDecBuf = m_pDecBuffer;
- m_ulDecBufBytes = 0;
- // Copy the frame into the decode buffer
- for(pFrameData= pFrameInfo->pFrameData; pFrameData != NULL;
- pFrameData = pFrameData->pNext)
- {
- pPacketBuf = pFrameData->pPacketBuf;
- if(pPacketBuf)
- {
- pPacketBuf->Get(pBuf, ulSize);
- if(pBuf && ulSize >= pFrameData->ulOffset + 2)
- {
- // seek to the frame offset
- ulSize -= pFrameData->ulOffset;
- pBuf += pFrameData->ulOffset;
-
- if(pFrameInfo->ulADUSize < ulSize)
- {
- ulSize = pFrameInfo->ulADUSize;
- }
- // Make sure it will actually fit
- if(ulSize > DEC_BUFFER_SIZE - m_ulDecBufBytes)
- {
- ulSize = DEC_BUFFER_SIZE - m_ulDecBufBytes;
- }
-
- memcpy(pDecBuf, pBuf, ulSize); /* Flawfinder: ignore */
- m_ulDecBufBytes += ulSize;
- pDecBuf += ulSize;
- }
- }
- }
- HX_DELETE(pCycle->pFrames[ulIndex]);
- m_ulIndex = ulIndex + 1;
-
- // Clear the main_data_begin (since we're reformatted)
- m_pFmt->ClearMainDataBegin(m_pDecBuffer);
- }
- pFrameBuffer = m_pDecBuffer;
- dTime = dPresTime;
- m_dNextPts = dPresTime + m_dFrameTime;
- m_bFirstFrame = FALSE;
- return m_ulDecBufBytes;
- }
- UINT32 CRobustPacketParser::GetFrameInfo(IHXBuffer* pPacket, UINT32 ulOffset,
- double dTime)
- {
- if(pPacket->GetSize() <= ulOffset)
- {
- return pPacket->GetSize();
- }
- UCHAR* pBuf = pPacket->GetBuffer() + ulOffset;
- // bit 0: continuation bit
- BOOL bCont = (pBuf[0] & 0x80) == 0 ? FALSE : TRUE;
- // bit 1: Descriptor type flag
- int nDescSize = (pBuf[0] & 0x40) == 0 ? 1 : 2;
-
- if(pPacket->GetSize() - ulOffset < (UINT32)nDescSize + 2)
- {
- return pPacket->GetSize();
- }
- UINT32 ulADUSize;
- int nIndex;
- int nCycle;
- // in a one byte descriptor, bits 2-7 are the ADU size
- // in a two byte descriptor, bits 2-15 are the size
- ulADUSize = nDescSize == 1 ? (pBuf[0] & 0x3F) :
- ((UINT32)(pBuf[0] & 0x3F) << 8) + pBuf[1];
-
- pBuf += nDescSize;
-
- // MPEG audio sync word is the first 12 bits, first 11 always set.
- // if the sync word is in tact, we are not reordered
- if(pBuf[0] == 0xFF && (pBuf[1] & 0xE0) == 0xE0)
- {
- nIndex = 0;
- nCycle = -1;
- }
- // otherwise, the first 11 bits of the sync word are re-used to
- // identify the frame order
- else
- {
- // bits 0-7: frame index
- nIndex = pBuf[0];
- // bits 8-10: cycle
- nCycle = (pBuf[1] & 0xE0) >> 5;
- }
-
- SCycle* pCycle = m_Cycles.IsEmpty() ? NULL : (SCycle*)m_Cycles.GetTail();
- if(!pCycle || nCycle != pCycle->nCycleIndex || nCycle < 0)
- {
- // This is a new cycle
- pCycle = new SCycle(nCycle);
- if(pCycle == NULL)
- {
- return pPacket->GetSize();
- }
- pCycle->nMaxIndex = nIndex;
- m_Cycles.AddTail(pCycle);
- }
- else if(nIndex > pCycle->nMaxIndex)
- {
- pCycle->nMaxIndex = nIndex;
- }
- SFrameData* pFrameData = new SFrameData();
- SFrameData* pIterator;
- pPacket->AddRef();
- pFrameData->pPacketBuf = pPacket;
- pFrameData->ulOffset = ulOffset + nDescSize;
- pFrameData->bCont = bCont;
-
- SFrameInfo* pInfo = pCycle->pFrames[nIndex];
- if(pInfo != NULL)
- {
- // We have a frag. Note that the spec only accounts for a frame being
- // split accross two packets when reordered. If one is split across
- // more than two packets, we will assume the cont frags are in order
- if(bCont || (pCycle->pFrames[nIndex]->pFrameData &&
- !pCycle->pFrames[nIndex]->pFrameData->bCont))
- {
- pIterator = pCycle->pFrames[nIndex]->pFrameData;
- if(pIterator)
- {
- while(pIterator->pNext != NULL)
- pIterator = pIterator->pNext;
- pFrameData->pNext = NULL;
- pIterator->pNext = pFrameData;
- }
- else
- {
- pFrameData->pNext = pCycle->pFrames[nIndex]->pFrameData;
- pCycle->pFrames[nIndex]->pFrameData = pFrameData;
- }
- }
- // If this is not a continuation frame, it is the first frag
- else
- {
- pFrameData->pNext = pCycle->pFrames[nIndex]->pFrameData;
- pCycle->pFrames[nIndex]->pFrameData = pFrameData;
- }
- }
- else
- {
- pFrameData->pNext = NULL;
- pInfo = new SFrameInfo();
- pInfo->nIndex = nIndex;
- pInfo->ulADUSize = ulADUSize;
- pInfo->pFrameData = pFrameData;
- pInfo->dTime = dTime;
- pCycle->pFrames[nIndex] = pInfo;
- }
- UINT32 ulSize = 0;
- for(pIterator = pCycle->pFrames[nIndex]->pFrameData; pIterator!= NULL;
- pIterator = pIterator->pNext)
- {
- HX_ASSERT(pIterator->pPacketBuf);
- ulSize += pIterator->pPacketBuf->GetSize() - pIterator->ulOffset;
- }
-
- pInfo->bComplete = ulSize >= pInfo->ulADUSize ? TRUE : FALSE;
- // Set first 11 bits
- pBuf[0] = 0xFF;
- pBuf[1] |= 0xE0;
- // Init our decoder if needed
- if(m_pDecoder || InitDecoder(pBuf, pPacket->GetSize() - ulOffset, FALSE))
- {
- // set the first frame's presentation time
- if(dTime >= 0)
- {
- if(pCycle->dStartTime < 0)
- {
- pCycle->dStartTime = dTime - m_dFrameTime*(nIndex);
- }
- }
- }
- return min(pFrameData->ulOffset + ulADUSize, pPacket->GetSize());
- }
- HX_RESULT
- CRobustPacketParser::RenderAll()
- {
- if(!m_pRenderer || !m_pFmt)
- {
- return HXR_FAIL;
- }
- UCHAR* pFrameBuf;
- UINT32 ulSize;
- BOOL bPacketLoss;
- double dTime;
- for(;;)
- {
- ulSize = GetFrame(pFrameBuf, dTime, bPacketLoss);
- if(!pFrameBuf || !ulSize)
- {
- return HXR_OK;
- }
- if(!m_pDecoder && !InitDecoder(pFrameBuf, ulSize, TRUE))
- {
- return HXR_FAIL;
- }
- DecodeAndRender(pFrameBuf, ulSize, dTime, bPacketLoss);
- }
- }
- void
- CRobustPacketParser::PreSeek()
- {
- m_Cycles.DeleteAll();
- m_ulIndex = 0;
- m_bFirstFrame = TRUE;
- CPacketParser::PreSeek();
- }
- void
- CRobustPacketParser::PostSeek(UINT32 time)
- {
- m_Cycles.DeleteAll();
- m_ulIndex = 0;
- m_bFirstFrame = TRUE;
- CPacketParser::PostSeek(time);
- HX_DELETE(m_pTsConvert);
- }
- void
- CRobustPacketParser::EndOfPackets()
- {
- m_bEndOfPackets = TRUE;
- // Decode and render any frames left queued.
- RenderAll();
- }