pxgifff.cpp

来自「symbian 下的helix player源代码」· C++ 代码 · 共 1,531 行 · 第 1/4 页

CPP
1,531
字号
        HX_VECTOR_DELETE(m_plImageStartTime);
        m_plImageStartTime = new INT32 [lNumImages];
        if (!m_plImageStartTime)
        {
            return m_pFormatResponse->StreamHeaderReady(HXR_FAIL, NULL);
        }

        // Initially we fill these times with the time the image has to be displayed
        INT32 i;
        INT32 lRunningSum = 0;
        for (i = 0; i < lNumImages; i++)
        {
            m_plImageStartTime[i] = lRunningSum;
            lRunningSum          += (INT32) m_pGIFCodec->GetDelayTime(i) * 10;
        }

        // Now we go from last image to first, adjusting times
        UINT32 ulTotalBytesToSend = 0;
        INT32  lLastStartTime     = m_plImageStartTime[lNumImages - 1];
        for (i = m_pGIFCodec->GetNumImages() - 1; i >= 0; i--)
        {
            INT32 lTransmitSize   = m_pGIFCodec->GetImageDataSize(i);    // Actual bytes to transmit
            INT32 lOverheadSize   = ((lTransmitSize / 500) + 1) * 24;    // This is an estimate of packet overhead
            INT32 lTransmitTime   = ((lTransmitSize + lOverheadSize) * 8000 / m_ulBitRate) + 1; // transmit time in milliseconds
            if (lLastStartTime < m_plImageStartTime[i])
            {
                m_plImageStartTime[i]  = lLastStartTime - lTransmitTime;
            }
            else
            {
                m_plImageStartTime[i] -= lTransmitTime;
            }
            lLastStartTime = m_plImageStartTime[i];

            ulTotalBytesToSend += (UINT32) lTransmitSize;
        }

        // Now the min preroll should be the negative of the first start time
        if (m_plImageStartTime[0] >= 0)
        {
            return m_pFormatResponse->StreamHeaderReady(HXR_FAIL, NULL);
        }
        UINT32 ulMinPreroll = (UINT32) -m_plImageStartTime[0];

        // Resolve this with the requested preroll
        if (m_ulPreroll < ulMinPreroll)
        {
            m_ulPreroll = ulMinPreroll;
        }

        // Compute predata bytes
        ulPreDataBytes = m_ulBitRate * m_ulPreroll / 8000;
        if (ulPreDataBytes > ulTotalBytesToSend)
        {
            ulPreDataBytes = ulTotalBytesToSend;
        }
    }

    // Create an IHXValues object
    IHXValues *pStreamHeader = NULL;
    HX_RESULT retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXValues, (void **) &pStreamHeader);
    if (retVal != HXR_OK)
    {
        return m_pFormatResponse->StreamHeaderReady(retVal, NULL);
    }
    // Set the mime type
    char* pszStreamMimeType = (char*) m_pszStreamMimeType;
    if (m_bParseFailed)
    {
        pszStreamMimeType = (char*) m_pszBadStreamMimeType;
    }
    // Create buffer to hold MIME type
    IHXBuffer *pMimeType = NULL;
    retVal = PXUtilities::CreateStringBuffer(pszStreamMimeType,
                                             m_pContext,
                                             pMimeType);
    if (retVal != HXR_OK)
    {
        HX_RELEASE(pStreamHeader);
        return m_pFormatResponse->StreamHeaderReady(retVal, NULL);
    }

    // Generate an ASM rule book
    char szASMRuleBook[256]; /* Flawfinder: ignore */
    if (m_bReliable)
    {
        sprintf(szASMRuleBook, "AverageBandwidth=%ld,Priority=10;", m_ulBitRate); /* Flawfinder: ignore */
    }
    else
    {
        sprintf(szASMRuleBook, /* Flawfinder: ignore */
                "AverageBandwidth=%ld,Priority=5;AverageBandwidth=%ld,Priority=9;",
                m_ulBitRate, 0);
    }
    // Create buffer to hold ASM rules
    IHXBuffer *pASMRuleBook = NULL;
    retVal = PXUtilities::CreateStringBuffer((const char*) szASMRuleBook,
                                             m_pContext,
                                             pASMRuleBook);
    if (retVal != HXR_OK)
    {
        HX_RELEASE(pStreamHeader);
        HX_RELEASE(pMimeType);
        return m_pFormatResponse->StreamHeaderReady(retVal, NULL);
    }
    // Create buffer to hold intrinsic duration type string
    const char* pszIntrinsicDur = NULL;
    if (m_pGIFCodec->GetNumImages()    == 1 &&
        m_pGIFCodec->GetDelayTimeSum() == 0)
    {
        pszIntrinsicDur = "intrinsicDurationDiscrete";
    }
    else
    {
        pszIntrinsicDur = "intrinsicDurationContinuous";
    }
    IHXBuffer* pIntrinsicDur = NULL;
    retVal = PXUtilities::CreateStringBuffer(pszIntrinsicDur,
                                             m_pContext,
                                             pIntrinsicDur);
    if (retVal != HXR_OK)
    {
        HX_RELEASE(pStreamHeader);
        HX_RELEASE(pMimeType);
        HX_RELEASE(pASMRuleBook);
        return m_pFormatResponse->StreamHeaderReady(retVal, NULL);
    }
    // Create buffer to hold opaque data
    IHXBuffer *pOpaqueData = NULL;
    retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer, (void **) &pOpaqueData);
    if (retVal != HXR_OK)
    {
        HX_RELEASE(pStreamHeader);
        HX_RELEASE(pMimeType);
        HX_RELEASE(pASMRuleBook);
        HX_RELEASE(pIntrinsicDur);
        return m_pFormatResponse->StreamHeaderReady(retVal, NULL);
    }

    // Fill in the Header with the parameters
    pStreamHeader->SetPropertyULONG32("StreamNumber",          0);
    pStreamHeader->SetPropertyULONG32("MaxBitRate",            m_ulBitRate);
    pStreamHeader->SetPropertyULONG32("AvgBitRate",            m_ulBitRate);
    pStreamHeader->SetPropertyULONG32("MaxPacketSize",         600);
    pStreamHeader->SetPropertyULONG32("AvgPacketSize",         500);
    pStreamHeader->SetPropertyULONG32("StartTime",             0);
    pStreamHeader->SetPropertyULONG32("Preroll",               m_ulPreroll);
    pStreamHeader->SetPropertyULONG32("PreData",               ulPreDataBytes);
    pStreamHeader->SetPropertyULONG32("PreDataAtStart",        1);
    pStreamHeader->SetPropertyULONG32("PreRollAtStart",        0);
    pStreamHeader->SetPropertyULONG32("PreDataAfterSeek",      0);
    pStreamHeader->SetPropertyULONG32("PreRollAfterSeek",      1);
    pStreamHeader->SetPropertyULONG32("Duration",              m_ulDuration);
    pStreamHeader->SetPropertyULONG32("ContentVersion",        m_ulContentVersion);
    pStreamHeader->SetPropertyCString("MimeType",              pMimeType);
    pStreamHeader->SetPropertyCString("ASMRuleBook",           pASMRuleBook);
    pStreamHeader->SetPropertyCString("intrinsicDurationType", pIntrinsicDur);
    // The mediaRepeat attribute says whether or not to strip the native
    // repeat value from the media. We need support for mediaRepeat in
    // the GIF renderer for this to work. Therefore, if mediaRepeat specified,
    // then we also need to bump the stream version.
    UINT32 ulStreamVersion = m_ulStreamVersion;
    if (m_pMediaRepeatStr)
    {
        pStreamHeader->SetPropertyCString("mediaRepeat", m_pMediaRepeatStr);
        ulStreamVersion = MEDREP_GIFSTREAM_VERSION;
    }
    // Now set the stream version
    pStreamHeader->SetPropertyULONG32("StreamVersion", ulStreamVersion);

    // Make a renderer flags property
    UINT32 ulRendererFlags = 0;
    if (m_bParseFailed)
    {
        ulRendererFlags |= GIF_RENDERER_FLAG_PARSEFAILED;
        if (m_pGIFCodec)
        {
            pStreamHeader->SetPropertyULONG32("Width",  m_pGIFCodec->GetLogicalScreenWidth());
            pStreamHeader->SetPropertyULONG32("Height", m_pGIFCodec->GetLogicalScreenHeight());
        }
    }
    pStreamHeader->SetPropertyULONG32("RendererFlags", ulRendererFlags);

    // Ask the GIF Codec how big the header is
    UINT32 ulLength = 0;
    if (m_pGIFCodec && !m_bParseFailed)
    {
        retVal = m_pGIFCodec->GetPacketBufferLength(ulLength);
        if (retVal != HXR_OK)
        {
            HX_RELEASE(pMimeType);
            HX_RELEASE(pASMRuleBook);
            HX_RELEASE(pOpaqueData);
            HX_RELEASE(pStreamHeader);
            HX_RELEASE(pIntrinsicDur);
            return m_pFormatResponse->StreamHeaderReady(retVal, NULL);
        }
    }

    // Set the opaque data buffer to this length plus a bit more
    UINT32 ulExtraDataSize = 12 + (m_pURL ? m_pURL->GetLength() : 0) + 1;
    retVal = pOpaqueData->SetSize(ulLength + ulExtraDataSize);
    if (retVal != HXR_OK)
    {
        HX_RELEASE(pMimeType);
        HX_RELEASE(pASMRuleBook);
        HX_RELEASE(pOpaqueData);
        HX_RELEASE(pStreamHeader);
        HX_RELEASE(pIntrinsicDur);
        return m_pFormatResponse->StreamHeaderReady(retVal, NULL);
    }

    // Fill in the non-image-data information
    BYTE *pData = pOpaqueData->GetBuffer();
    Pack8(pData,      m_ucTarget);
    Pack8(pData,      m_ucURLType);
    Pack32(pData,     m_ulSeekTime);
    Pack8(pData,      (BYTE) ((m_ulBackgroundColor & 0x00FF0000) >> 16)); // R
    Pack8(pData,      (BYTE) ((m_ulBackgroundColor & 0x0000FF00) >>  8)); // G
    Pack8(pData,      (BYTE)  (m_ulBackgroundColor & 0x000000FF)       ); // B
    Pack8(pData,      (BYTE) ((m_ulBackgroundColor & 0xFF000000) >> 24)); // A
    CHXString cTmp;
    if (m_pURL)
    {
        cTmp = *m_pURL;
    }
    PackString(pData, cTmp);

    if (m_pGIFCodec && !m_bParseFailed)
    {
        // Get the opaque data
        BOOL bFirstInImage = FALSE;
        retVal = m_pGIFCodec->GetPacketBuffer(pData,
                                              pOpaqueData->GetSize() - ulExtraDataSize,
                                              bFirstInImage);
        if (retVal != HXR_OK)
        {
            HX_RELEASE(pMimeType);
            HX_RELEASE(pASMRuleBook);
            HX_RELEASE(pOpaqueData);
            HX_RELEASE(pStreamHeader);
            HX_RELEASE(pIntrinsicDur);
            return m_pFormatResponse->StreamHeaderReady(retVal, NULL);
        }
    }

    // Set the opaque data buffer property
    pStreamHeader->SetPropertyBuffer("OpaqueData", pOpaqueData);

    // Set the new state
    m_ulState = kStateStreamHeaderSent;

    // Initialize the current image index
    m_lCurImgIndex = -1;

    if (m_pGIFCodec && !m_bParseFailed)
    {
        // Go ahead and collect all the packets and hold them. We do
        // this since if we get a Seek(), we'll need to completely
        // resend all the packets. Ugh.
        retVal = MakeAllPackets();
        if (retVal != HXR_OK)
        {
            HX_RELEASE(pMimeType);
            HX_RELEASE(pASMRuleBook);
            HX_RELEASE(pOpaqueData);
            HX_RELEASE(pStreamHeader);
            HX_RELEASE(pIntrinsicDur);
            return m_pFormatResponse->StreamHeaderReady(retVal, NULL);
        }
    }

    // Now we can tell the response interface that we're done
    m_pFormatResponse->StreamHeaderReady(HXR_OK, pStreamHeader);

    // Release our references
    HX_RELEASE(pStreamHeader);
    HX_RELEASE(pMimeType);
    HX_RELEASE(pASMRuleBook);
    HX_RELEASE(pOpaqueData);
    HX_RELEASE(pIntrinsicDur);

    return HXR_OK;
}

STDMETHODIMP CGIFFileFormat::GetPacket(UINT16 usStreamNum)
{
#ifdef XXXMEH_DEBUG_LOG
    DEBUG_OUTF("pxgifff.log", (s, "0x%08x::GetPacket(%u)\n", this, usStreamNum));
#endif
    HX_RESULT retVal = HXR_OK;

    if (m_ulState == kStateStreamHeaderSent)
    {
        if (usStreamNum == 0)
        {
            // Have we sent all the packets?
            if (m_ulCurrentPacketIndex < m_ulNumPackets && !m_bParseFailed)
            {
                // Get the packet pointer
                IHXPacket* pPacket = m_ppPacket[m_ulCurrentPacketIndex];
                // Increment the packet index
                m_ulCurrentPacketIndex++;
                // Give the response interface the packet
                m_pFormatResponse->PacketReady(HXR_OK, pPacket);
            }
            else
            {
                // Set the state
                m_ulState = kStateFinished;
                // Tell the response interface we're done
                m_pFormatResponse->StreamDone(0);
            }
        }
        else
        {
            retVal = HXR_INVALID_PARAMETER;
        }
    }
    else
    {
        retVal = HXR_UNEXPECTED;
    }

    return retVal;
}

STDMETHODIMP CGIFFileFormat::SeekDone(HX_RESULT status)
{
    return HXR_UNEXPECTED;
}

STDMETHODIMP CGIFFileFormat::Seek(UINT32 ulRequestedTime)
{
    HX_RESULT retVal = HXR_OK;

    // XXXMEH - no matter WHEN we get a Seek(), we have to resend all the
    // packets again, since they are all timestamp 0.
    //
    // So all we need to do is reset the current packet index to 0.
    m_ulCurrentPacketIndex = 0;
    // Set the state
    m_ulState = kStateStreamHeaderSent;
    // Inform the response interface we're done
    m_pFormatResponse->SeekDone(HXR_OK);

    return retVal;
}

STDMETHODIMP CGIFFileFormat::Close()
{
    if (m_ppPacket && m_ulNumPackets)
    {
        for (UINT32 i = 0; i < m_ulNumPackets; i++)
        {
            HX_RELEASE(m_ppPacket[i]);
        }
        m_ulNumPackets = 0;
        HX_VECTOR_DELETE(m_ppPacket);
    }
    HX_RELEASE(m_pContext);
    HX_RELEASE(m_pFileObject);
    HX_RELEASE(m_pFileStat);
    HX_RELEASE(m_pFormatResponse);
    HX_RELEASE(m_pCommonClassFactory);
    HX_RELEASE(m_pError);
    HX_DELETE(m_pURL);
    HX_DELETE(m_pRequestURL);
    HX_RELEASE(m_pFileBuffer);
    HX_RELEASE(m_pFragFileBuffer);
    HX_DELETE(m_pGIFCodec);
    HX_VECTOR_DELETE(m_plImageStartTime);
    HX_RELEASE(m_pMediaRepeatStr);

    m_ulBitRate     = 0;
    m_ulPreroll     = 0;
    m_ulDuration    = 0;
    m_lCurrentTime  = 0;
    m_ulState       = kStateConstructed;
    m_ulFileSize    = 0;

    return HXR_OK;
}

⌨️ 快捷键说明

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