⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vbrdepack.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* ***** 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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -