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

📄 vbrdepack.cpp

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

⌨️ 快捷键说明

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