Code/Resource
Windows Develop
Linux-Unix program
Internet-Socket-Network
Web Server
Browser Client
Ftp Server
Ftp Client
Browser Plugins
Proxy Server
Email Server
Email Client
WEB Mail
Firewall-Security
Telnet Server
Telnet Client
ICQ-IM-Chat
Search Engine
Sniffer Package capture
Remote Control
xml-soap-webservice
P2P
WEB(ASP,PHP,...)
TCP/IP Stack
SNMP
Grid Computing
SilverLight
DNS
Cluster Service
Network Security
Communication-Mobile
Game Program
Editor
Multimedia program
Graph program
Compiler program
Compress-Decompress algrithms
Crypt_Decrypt algrithms
Mathimatics-Numerical algorithms
MultiLanguage
Disk/Storage
Java Develop
assembly language
Applications
Other systems
Database system
Embeded-SCM Develop
FlashMX/Flex
source in ebook
Delphi VCL
OS Develop
MiddleWare
MPI
MacOS develop
LabView
ELanguage
Software/Tools
E-Books
Artical/Document
vbrdepack.cpp
Package: 142_61_thumb_advanced.rar [view]
Upload User: dangjiwu
Upload Date: 2013-07-19
Package Size: 42019k
Code Size: 23k
Category:
Symbian
Development Platform:
Visual C++
- /* ***** 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 "hxcom.h"
- #include "ihxpckts.h"
- #include "hxcomm.h"
- #include "hxslist.h"
- #include "vbrdepack.h"
- CVBRSimpleDepacketizer::CVBRSimpleDepacketizer()
- {
- m_pCommonClassFactory = NULL;
- m_pFragQueue = NULL;
- m_pOutputQueue = NULL;
- m_dAUDuration = 0.0;
- m_usStreamNum = 0;
- m_usKeyFrameRuleNum = 0;
- m_ulLastQueuedPacketEndTime = 0;
- m_bSeeked = FALSE;
- m_bGenerateLossPackets = TRUE;
- }
- CVBRSimpleDepacketizer::~CVBRSimpleDepacketizer()
- {
- ClearQueue(m_pFragQueue);
- ClearQueue(m_pOutputQueue);
- HX_RELEASE(m_pCommonClassFactory);
- HX_DELETE(m_pFragQueue);
- HX_DELETE(m_pOutputQueue);
- }
- HX_RESULT CVBRSimpleDepacketizer::Init(IUnknown* pContext, double dAUDuration,
- UINT16 usStreamNum, UINT16 usKeyFrameRuleNum,
- BOOL bGenerateLossPackets)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pContext)
- {
- // Save the AU duration
- m_dAUDuration = dAUDuration;
- // Save the stream num
- m_usStreamNum = usStreamNum;
- // Save the keyframe rule num
- m_usKeyFrameRuleNum = usKeyFrameRuleNum;
- // Save the loss packets flag
- m_bGenerateLossPackets = bGenerateLossPackets;
- // Get the common class factory
- HX_RELEASE(m_pCommonClassFactory);
- retVal = pContext->QueryInterface(IID_IHXCommonClassFactory,
- (void**) &m_pCommonClassFactory);
- if (SUCCEEDED(retVal))
- {
- // Zero out the last queued packet end time
- m_ulLastQueuedPacketEndTime = 0;
- // Clear the seeked flag
- m_bSeeked = FALSE;
- }
- }
- return retVal;
- }
- HX_RESULT CVBRSimpleDepacketizer::PutPacket(IHXPacket* pPacket)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pPacket)
- {
- // Is the packet lost?
- if (!pPacket->IsLost())
- {
- // Get the IHXBuffer
- IHXBuffer* pBuffer = pPacket->GetBuffer();
- if (pBuffer)
- {
- // Get the buffer
- BYTE* pBuf = pBuffer->GetBuffer();
- if (pBuf)
- {
- // Parse the packet
- UINT32 ulNumAU = 0;
- BOOL bFragmented = FALSE;
- retVal = ParseVBRPacket(pBuf, pBuffer->GetSize(), ulNumAU, bFragmented);
- if (SUCCEEDED(retVal))
- {
- // Check if we have a gap in timestamps. However, if
- // we seeked we don't want to interpret this as a
- // gap in timestamps
- if (pPacket->GetTime() > (m_ulLastQueuedPacketEndTime + TIMESTAMP_GAP_FUDGE_FACTOR) &&
- !m_bSeeked)
- {
- // We probably had some loss, so we need to queue
- // some loss packets
- if (m_bGenerateLossPackets)
- {
- retVal = GenerateAndQueueLossPackets(m_ulLastQueuedPacketEndTime,
- pPacket->GetTime());
- }
- if (SUCCEEDED(retVal))
- {
- // Update the last queued packet end time
- m_ulLastQueuedPacketEndTime = pPacket->GetTime();
- }
- }
- // If m_bSeeked == TRUE, then this is the
- // first packet we've received after the seek.
- if (m_bSeeked)
- {
- // Clear the frag queue
- ClearQueue(m_pFragQueue);
- // Set the last queued packet end time to be
- // the current time. Otherwise, if this packet
- // is a fragmented packet, then the next packet
- // will be interpreted as loss.
- m_ulLastQueuedPacketEndTime = pPacket->GetTime();
- // Clear the seek flag
- m_bSeeked = FALSE;
- }
- // Is this a fragmented AU?
- if (bFragmented)
- {
- // Remove any packets from the frag queue
- // which do not have the same timestamp
- // as this packet. These were probably packets
- // which were left over from a previous lost
- // fragmented AU.
- RemoveDifferingPackets(pPacket->GetTime());
- // If this is a fragmented packet, then we
- // add it to the frag queue
- retVal = AddToQueue(m_pFragQueue, pPacket);
- if (SUCCEEDED(retVal))
- {
- // Attempt to defrag the AU from the packets
- // on the frag queue
- if (CanDefrag())
- {
- IHXPacket* pOutPacket = NULL;
- retVal = Defrag(pOutPacket);
- if (SUCCEEDED(retVal))
- {
- // We successfully generated a defragmented
- // packet, so we can clear the frag queue
- ClearQueue(m_pFragQueue);
- // Add the packet to the output queue
- retVal = AddToQueue(m_pOutputQueue, pOutPacket);
- if (SUCCEEDED(retVal))
- {
- // Set the end time of the last packet
- // that we put in the output queue
- m_ulLastQueuedPacketEndTime = pOutPacket->GetTime() + ((UINT32) m_dAUDuration);
- }
- }
- HX_RELEASE(pOutPacket);
- }
- }
- }
- else
- {
- // This is NOT a fragmented packet
- //
- // We can clear the frag queue. If there was no
- // loss in the last fragmented AU, then it was
- // cleared after the packet was created. If there
- // WAS loss in the last fragmented AU, then we
- // just handled it by generating loss packets.
- ClearQueue(m_pFragQueue);
- // Step through the packet creating packets
- UINT32 ulAUDataSizeSum = 0;
- for (UINT32 i = 0; i < ulNumAU && SUCCEEDED(retVal); i++)
- {
- UINT32 ulAUSize = UnPackUINT16(pBuf + 2 + (i << 1));
- UINT32 ulTSOffset = (UINT32) (i * m_dAUDuration);
- IHXPacket* pOutPacket = NULL;
- retVal = CreatePacket(pBuf + 2 + ulNumAU * 2 + ulAUDataSizeSum,
- ulAUSize,
- pPacket->GetTime() + ulTSOffset,
- FALSE,
- pOutPacket);
- if (SUCCEEDED(retVal))
- {
- // Add the packet to the output queue
- retVal = AddToQueue(m_pOutputQueue, pOutPacket);
- if (SUCCEEDED(retVal))
- {
- ulAUDataSizeSum += ulAUSize;
- }
- }
- HX_RELEASE(pOutPacket);
- }
- if (SUCCEEDED(retVal))
- {
- // Set the end time of the last packet
- // that we put in the output queue
- UINT32 ulTSOffset = (UINT32) (ulNumAU * m_dAUDuration);
- m_ulLastQueuedPacketEndTime = pPacket->GetTime() + ulTSOffset;
- }
- }
- }
- }
- }
- HX_RELEASE(pBuffer);
- }
- else
- {
- // The packet is lost, but don't return failure
- retVal = HXR_OK;
- }
- }
- return retVal;
- }
- HX_RESULT CVBRSimpleDepacketizer::GetPacket(REF(IHXPacket*) rpPacket)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (m_pOutputQueue && m_pOutputQueue->GetCount() > 0)
- {
- // Get the head packet
- IHXPacket* pPacket = (IHXPacket*) m_pOutputQueue->RemoveHead();
- if (pPacket)
- {
- HX_RELEASE(rpPacket);
- rpPacket = pPacket;
- rpPacket->AddRef();
- retVal = HXR_OK;
- }
- HX_RELEASE(pPacket);
- }
- return retVal;
- }
- HX_RESULT CVBRSimpleDepacketizer::OnSeek(UINT32 ulOldTime, UINT32 ulNewTime)
- {
- HX_RESULT retVal = HXR_OK;
- // Set the seeked flag
- m_bSeeked = TRUE;
- return retVal;
- }
- void CVBRSimpleDepacketizer::ClearQueue(CHXSimpleList* pList)
- {
- if (pList)
- {
- LISTPOSITION pos = pList->GetHeadPosition();
- while (pos)
- {
- IHXPacket* pPacket = (IHXPacket*) pList->GetNext(pos);
- HX_RELEASE(pPacket);
- }
- pList->RemoveAll();
- }
- }
- HX_RESULT CVBRSimpleDepacketizer::CreatePacket(BYTE* pBuf,
- UINT32 ulSize,
- UINT32 ulTime,
- BOOL bLost,
- REF(IHXPacket*) rpPacket)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (m_pCommonClassFactory)
- {
- // Create an IHXBuffer.
- IHXBuffer* pBuffer = NULL;
- if (!bLost)
- {
- // Packet was NOT lost so we have to have a buffer
- if (pBuf && ulSize)
- {
- retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer, (void**) &pBuffer);
- if (SUCCEEDED(retVal))
- {
- retVal = pBuffer->Set(pBuf, ulSize);
- }
- }
- }
- else
- {
- // This is a lost packet, so it's OK not
- // to have a buffer
- retVal = HXR_OK;
- }
- if (SUCCEEDED(retVal))
- {
- // Create an IHXPacket
- IHXPacket* pPacket = NULL;
- retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXPacket, (void**) &pPacket);
- if (SUCCEEDED(retVal))
- {
- // Set the packet parameters
- retVal = pPacket->Set(pBuffer,
- ulTime,
- m_usStreamNum,
- HX_ASM_SWITCH_ON,
- m_usKeyFrameRuleNum);
- if (SUCCEEDED(retVal))
- {
- // If this is a lost packet, then set
- // the lost flag
- if (bLost)
- {
- pPacket->SetAsLost();
- }
- // Set the out parameter
- HX_RELEASE(rpPacket);
- rpPacket = pPacket;
- rpPacket->AddRef();
- }
- }
- HX_RELEASE(pPacket);
- }
- HX_RELEASE(pBuffer);
- }
- return retVal;
- }
- HX_RESULT CVBRSimpleDepacketizer::GenerateAndQueueLossPackets(UINT32 ulFirstPacketStartTime,
- UINT32 ulLastPacketEndTime)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (ulLastPacketEndTime > ulFirstPacketStartTime)
- {
- // Compute the difference
- UINT32 ulDiff = ulLastPacketEndTime - ulFirstPacketStartTime;
- // Compute the number of packets
- UINT32 ulNumLossPackets = 0;
- if (m_dAUDuration != 0.0)
- {
- ulNumLossPackets = (UINT32) (ulDiff / m_dAUDuration);
- }
- // Generate loss packets
- retVal = HXR_OK;
- for (UINT32 i = 0; i < ulNumLossPackets && SUCCEEDED(retVal); i++)
- {
- UINT32 ulTSOffset = (UINT32) (i * m_dAUDuration);
- UINT32 ulTime = ulFirstPacketStartTime + ulTSOffset;
- IHXPacket* pPacket = NULL;
- retVal = CreatePacket(NULL, 0, ulTime, TRUE, pPacket);
- if (SUCCEEDED(retVal))
- {
- retVal = AddToQueue(m_pOutputQueue, pPacket);
- }
- HX_RELEASE(pPacket);
- }
- }
- return retVal;
- }
- HX_RESULT CVBRSimpleDepacketizer::AddToQueue(REF(CHXSimpleList*) rpList, IHXPacket* pPacket)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (!rpList)
- {
- rpList = new CHXSimpleList();
- }
- if (rpList)
- {
- // AddRef the packet before going on the list
- pPacket->AddRef();
- // Put the packet on the list
- rpList->AddTail((void*) pPacket);
- // Clear the return value
- retVal = HXR_OK;
- }
- return retVal;
- }
- HX_RESULT CVBRSimpleDepacketizer::ParseVBRPacket(BYTE* pBuf,
- UINT32 ulSize,
- REF(UINT32) rulNumAU,
- REF(BOOL) rbFragmented)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pBuf && ulSize)
- {
- // Compute the buf limit (for safety)
- BYTE* pBufLimit = pBuf + ulSize;
- HX_ASSERT(pBuf + 2 <= pBufLimit);
- if (pBuf + 2 <= pBufLimit)
- {
- // Get the AU header size in bits
- UINT32 ulAUHeaderSizeBits = UnPackUINT16(pBuf);
- // Convert to bytes (rounding up to next byte)
- UINT32 ulAUHeaderSize = (ulAUHeaderSizeBits + 7) >> 3;
- // Sanity check to make sure that the AU header size is
- // greater than 0 and a multiple of 2 bytes
- HX_ASSERT(ulAUHeaderSize && !(ulAUHeaderSize & 1));
- if (ulAUHeaderSize && !(ulAUHeaderSize & 1))
- {
- // Since we know that each AU header is 2 bytes, then
- // we know that the number of AU's in this packet is
- // ulAUHeaderSize / 2.
- rulNumAU = ulAUHeaderSize >> 1;
- // The audio/mpeg-generic spec says that each packet
- // can either have a complete AU, a fragment of a single
- // AU, or multiple complete AUs. Therefore, if the
- // number of AUs is greater than 1, then we know we
- // have ulNumAU *complete* AUs. Therefore, for more
- // than one AU, we know what the exact size of the
- // packet should be, and that should match up with
- // the data size of the packet.
- BYTE* pAUSize = pBuf + 2;
- UINT32 ulAUDataSize = 0;
- for (UINT32 i = 0; i < rulNumAU; i++)
- {
- HX_ASSERT(pAUSize + 2 <= pBufLimit);
- if (pAUSize + 2 <= pBufLimit)
- {
- UINT32 ulAUSize = UnPackUINT16(pAUSize);
- ulAUDataSize += ulAUSize;
- pAUSize += 2;
- }
- }
- // Compute the expected size of the packet
- UINT32 ulExpectedSize = 2 + // AU header size (16 bits)
- rulNumAU * 2 + // AU sizes
- ulAUDataSize; // the AU's themselves
- // Check this against the actual size. If we have
- // 1 AU, then the expected size can be greater than
- // the actual size due to fragmentation. If we have
- // more than more AU, then the expected size MUST
- // match the actual size.
- if (rulNumAU > 1)
- {
- if (ulExpectedSize == ulSize)
- {
- // Multiple AUs, no fragmentation
- rbFragmented = FALSE;
- retVal = HXR_OK;
- }
- }
- else if (rulNumAU == 1)
- {
- if (ulExpectedSize > ulSize)
- {
- // Fragmented single AU
- rbFragmented = TRUE;
- retVal = HXR_OK;
- }
- else
- {
- // Single AU, no fragmentation
- rbFragmented = FALSE;
- retVal = HXR_OK;
- }
- }
- }
- }
- }
- HX_ASSERT(SUCCEEDED(retVal));
- return retVal;
- }
- UINT32 CVBRSimpleDepacketizer::UnPackUINT16(BYTE* pBuf)
- {
- return (pBuf[0] << 8) | pBuf[1];
- }
- void CVBRSimpleDepacketizer::RemoveDifferingPackets(UINT32 ulTime)
- {
- if (m_pFragQueue && m_pFragQueue->GetCount() > 0)
- {
- IHXPacket* pPacket = (IHXPacket*) m_pFragQueue->GetHead();
- if (pPacket && pPacket->GetTime() < ulTime)
- {
- // There are packets on the frag queue with
- // timestamps less than this one. Therefore,
- // we need to clear the queue
- ClearQueue(m_pFragQueue);
- }
- }
- }
- BOOL CVBRSimpleDepacketizer::CanDefrag()
- {
- BOOL bRet = FALSE;
- if (m_pFragQueue && m_pFragQueue->GetCount() > 0)
- {
- IHXPacket* pPacket = (IHXPacket*) m_pFragQueue->GetHead();
- UINT32 ulActualAUDataSize = 0;
- UINT32 ulAUDataSize = GetAUSize(pPacket, ulActualAUDataSize);
- UINT32 ulActualAUDataSizeSum = 0;
- LISTPOSITION pos = m_pFragQueue->GetHeadPosition();
- while (pos)
- {
- pPacket = (IHXPacket*) m_pFragQueue->GetNext(pos);
- GetAUSize(pPacket, ulActualAUDataSize);
- ulActualAUDataSizeSum += ulActualAUDataSize;
- }
- // Check that the stated size of the AU
- // is the same as the sum of the actual
- // AU data sizes across all the fragmented packets
- if (ulAUDataSize == ulActualAUDataSizeSum)
- {
- bRet = TRUE;
- }
- }
- return bRet;
- }
- HX_RESULT CVBRSimpleDepacketizer::Defrag(REF(IHXPacket*) rpPacket)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (m_pCommonClassFactory && m_pFragQueue && m_pFragQueue->GetCount() > 0)
- {
- // Get the stated size of the AU
- IHXPacket* pFragPacket = (IHXPacket*) m_pFragQueue->GetHead();
- UINT32 ulTmp = 0;
- UINT32 ulAUSize = GetAUSize(pFragPacket, ulTmp);
- UINT32 ulTime = pFragPacket->GetTime();
- // Sanity check
- if (ulAUSize > 0)
- {
- // Create a buffer of this size
- BYTE* pBuf = new BYTE [ulAUSize];
- if (pBuf)
- {
- // Copy all the fragmented packets into this buffer
- UINT32 ulFragSizeSum = 0;
- LISTPOSITION pos = m_pFragQueue->GetHeadPosition();
- while (pos)
- {
- pFragPacket = (IHXPacket*) m_pFragQueue->GetNext(pos);
- if (pFragPacket)
- {
- IHXBuffer* pFragBuffer = pFragPacket->GetBuffer();
- if (pFragBuffer)
- {
- memcpy(pBuf + ulFragSizeSum,
- pFragBuffer->GetBuffer() + 4,
- pFragBuffer->GetSize() - 4);
- ulFragSizeSum += pFragBuffer->GetSize() - 4;
- }
- HX_RELEASE(pFragBuffer);
- }
- }
- // Create the packet
- HX_RELEASE(rpPacket);
- retVal = CreatePacket(pBuf, ulAUSize, ulTime, FALSE, rpPacket);
- }
- HX_VECTOR_DELETE(pBuf);
- }
- }
- return retVal;
- }
- UINT32 CVBRSimpleDepacketizer::GetAUSize(IHXPacket* pPacket, REF(UINT32) rulActualAUDataSize)
- {
- UINT32 ulRet = 0;
- if (pPacket)
- {
- IHXBuffer* pBuffer = pPacket->GetBuffer();
- if (pBuffer)
- {
- ulRet = UnPackUINT16(pBuffer->GetBuffer() + 2);
- rulActualAUDataSize = pBuffer->GetSize() - 4;
- }
- HX_RELEASE(pBuffer);
- }
- return ulRet;
- }