pxgifrnd.cpp

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

CPP
1,936
字号

    // If we are in between OnPreSeek() and OnPostSeek(), we will ignore 
    // packets
    if (m_bIgnorePackets || m_bImageBombed)
    {
        return HXR_OK;
    }

    // Check if the packet is lost
    if (pPacket->IsLost())
    {
        m_pGIFCodec->PacketLost();
        return HXR_OK;
    }

    // Get the IHXBuffer from the packet
    IHXBuffer *pBuffer = pPacket->GetBuffer();
    if (pBuffer == NULL)
    {
        return HXR_INVALID_PARAMETER;
    }

    BYTE*  pData      = pBuffer->GetBuffer();
    UINT32 ulDataSize = pBuffer->GetSize();

    // Retrieve the flags
    UINT32 ulFlags = 0;
    UnPack32(pData, ulFlags);

    // Is this packet the beginning of a new image?
    BOOL bFirstInImage = FALSE;
    if (ulFlags & 0x01)
    {
        bFirstInImage = TRUE;
    }

    // Comment extensions at the end of the file could mean we receive packets
    // after we are finished decoding. In this case, we just return
    if (m_pGIFCodec->DecompressFinished())
    {
        HX_RELEASE(pBuffer);
        return HXR_OK;
    }

    // Pass the data on to the CGIFCodec
    HX_RESULT retVal = m_pGIFCodec->Decompress(pBuffer->GetBuffer() + 4,
                                               pBuffer->GetSize()   - 4,
                                               bFirstInImage);
    if (retVal != HXR_OK)
    {
        CopyBombImage();
    }

    // Release our reference to the IHXBuffer
    HX_RELEASE(pBuffer);

    return HXR_OK;
}

STDMETHODIMP CGIFRenderer::OnTimeSync(UINT32 ulTime)
{
    MLOG_TIMING(m_pErrorMessages,
              "0x%08x::OnTimeSync(%lu)\n",
              this, ulTime);
    HX_RESULT retVal = HXR_OK;

    if (m_bFirstTimeSync || m_bPaused)
    {
        // Clear the first timesync flag
        m_bFirstTimeSync = FALSE;
        // Clear the paused flag
        m_bPaused = FALSE;
        // Adjust the time according to the
        // offset passed in through OnPacket()
        INT32  lAdjustedTime  = ((INT32) ulTime) + m_lTimeOffset;
        UINT32 ulAdjustedTime = (UINT32) (lAdjustedTime >= 0 ? lAdjustedTime : 0);
        // Set the current scheduler time base
        if (m_pScheduler)
        {
            // Compute time in milliseconds
            m_tSchedulerTimeBase = m_pScheduler->GetCurrentSchedulerTime();
//            m_ulSchedulerTimeBase = (cTime.tv_sec * 1000) + ((cTime.tv_usec + 500) / 1000);
            m_ulTimeAtSchedulerTimeBase = ulAdjustedTime;
        }
        // Update the display
        UpdateDisplay(ulAdjustedTime);
    }

    return retVal;
}

HX_RESULT CGIFRenderer::UpdateDisplay(UINT32 ulTime)
{
    MLOG_MISC(m_pErrorMessages,
              "%lu UpdateDisplay(%lu) this=0x%08x\n",
              HX_GET_BETTERTICKCOUNT(), ulTime, this);

    HX_RESULT retVal = HXR_OK;

    // Do we have a valid CGIFCodec?
    if (m_pGIFCodec && !m_bImageBombed)
    {
        // Reset the damage flag
        BOOL bDoDamage = FALSE;
        // Compute which frame we should be on at this time
        UINT32 ulFrameIndex = 0;
        if (m_pGIFCodec->GetNumImages() > 1)
        {
            // Get the modulo time
            UINT32 ulModTime   = 0;
            UINT32 ulCycleTime = GetCycleTime();
            if (ulCycleTime)
            {
                UINT32 ulIter      = ulTime / ulCycleTime;
                UINT32 ulIterStart = ulIter * ulCycleTime;
                ulModTime          = ulTime - ulIterStart;
            }
            UINT32 ulRunSum    = 0;
            UINT32 ulNumFrames = m_pGIFCodec->GetNumImages();
            for (UINT32 i = 0; i < ulNumFrames; i++)
            {
                // Get the delay for this frame
                UINT32     ulFrameDelay = 0;
                CGIFImage* pImage       = m_pGIFCodec->GetImage(i);
                if (pImage)
                {
                    ulFrameDelay = pImage->GetDelayTime() * 10;
                }
                // Check if our time is in this frame
                if (ulModTime >= ulRunSum &&
                    ulModTime <  ulRunSum + ulFrameDelay)
                {
                    ulFrameIndex = i;
                    break;
                }
                // Add the delay for this frame to the running sum
                ulRunSum += ulFrameDelay;
            }
        }
        // Is the frame currently in the buffer the same
        // as our computed frame? If it is, then we don't
        // need to update our buffer
        BOOL bFinished         = FALSE;
        BOOL bWouldHaveSkipped = FALSE;
        if (ulFrameIndex != m_ulCurFrameIndex)
        {
            // Make sure we don't skip frames
            UINT32 ulFrameIndexNoSkip = ulFrameIndex;
            if (m_ulCurFrameIndex != 0xFFFFFFFF)
            {
                UINT32 ulFrameDiff = 0;
                if (ulFrameIndex >= m_ulCurFrameIndex)
                {
                    ulFrameDiff = ulFrameIndex - m_ulCurFrameIndex;
                }
                else
                {
                    ulFrameDiff = m_pGIFCodec->GetNumImages() -
                                  m_ulCurFrameIndex + ulFrameIndex;
                }
                if (ulFrameDiff > 1)
                {
                    ulFrameIndexNoSkip = m_ulCurFrameIndex + 1;
                    if (ulFrameIndexNoSkip >= m_pGIFCodec->GetNumImages())
                    {
                        ulFrameIndexNoSkip = 0;
                    }
                }
            }
            // Enforce no skipping of frames, but set a flag if
            // we did have to change the frame, so that we can
            // use that to update our callback interval
            if (ulFrameIndexNoSkip != ulFrameIndex)
            {
                // Yes, we are having to force not to skip a frame
                bWouldHaveSkipped = TRUE;
                ulFrameIndex      = ulFrameIndexNoSkip;
            }
            // Is the image we want to draw done? If it's not finished,
            // we DON'T want to draw but we DO want another callback
            CGIFImage* pCurImage = m_pGIFCodec->GetImage(ulFrameIndex);
            if (pCurImage)
            {
                bFinished = pCurImage->Finished();
            }
            // Do we need to update?
            if (bFinished)
            {
                // Yes, we need to update, so first we get the image
                m_pGIFCodec->GetRGBImageEx((m_ulCurFrameIndex == 0xFFFFFFFF ? -1 : (INT32) m_ulCurFrameIndex),
                                           ulFrameIndex,
                                           m_pOutputBuffer->GetBuffer(),
                                           m_pGIFCodec->GetLogicalScreenWidth(),
                                           m_pGIFCodec->GetLogicalScreenHeight(),
                                           m_ulPadWidth,
                                           m_ulBytesPerPixel,
                                           m_bRowsInverted,
                                           m_bRGBOrdering,
                                           m_ulBackgroundColor,
                                           (m_ulMediaOpacity == 255 ? FALSE : TRUE),
                                           m_ulMediaOpacity,
                                           m_bMediaChromaKeySpecified,
                                           m_ulMediaChromaKey,
                                           m_ulMediaChromaKeyTolerance,
                                           m_ulMediaChromaKeyOpacity);
                // XXXMEH - do dumb assignment for now. We should later check
                // chroma key to find if any colors were actually encountered.
                if (m_ulBackgroundOpacity < 255 ||
                    m_ulMediaOpacity < 255      ||
                    m_bMediaChromaKeySpecified)
                {
                    m_bUsesAlphaChannel = TRUE;
                }
                // Set the damage flag
                bDoDamage = TRUE;
                // We need to damage the rect. If we are bltting off
                // of HX_SURFACE_UPDATE2, then we should damage the
                // rect of both the current frame and the previous frame.
                // If we are still bltting off of HX_SURFACE_UPDATE, then
                // we need to damage the whole logical screen area.
                if (m_bCanBltSubRects)
                {
                    // Damage the rect of the previous frame
                    DamageFrameRect(m_ulCurFrameIndex);
                    // Damage the rect of the current frame
                    DamageFrameRect(ulFrameIndex);
                    // Force a redraw
                    if (m_pMISUSSite)
                    {
                        m_pMISUSSite->ForceRedraw();
                    }
                }
                else
                {
                    // Damage entire site area
                    if (m_pMISUSSite)
                    {
                        // Get the size of the site
                        HXxSize cSize = {0, 0};
                        m_pMISUSSite->GetSize(cSize);
                        // Get the damage rect
                        HXxRect cRect = {0, 0, cSize.cx, cSize.cy};
                        MLOG_MISC(m_pErrorMessages,
                                  "%lu     Damaging entire logical screen: "
                                  "(%ld,%ld,%ld,%ld) (%ld x %ld)\n",
                                  HX_GET_BETTERTICKCOUNT(),
                                  cRect.left,  cRect.top,
                                  cRect.right, cRect.bottom,
                                  HXxRECT_WIDTH(cRect),
                                  HXxRECT_HEIGHT(cRect));
                        m_pMISUSSite->DamageRect(cRect);
                        m_pMISUSSite->ForceRedraw();
                    }
                }
                // Check if we just completed a loop. If the frame
                // index that we just drew into the buffer is LOWER
                // than the frame index that USED to be there, then
                // we will assume we just wrapped around
                if ((m_ulCurFrameIndex           == 0xFFFFFFFF &&
                     m_pGIFCodec->GetNumImages() == 1) ||
                    (m_ulCurFrameIndex           != 0xFFFFFFFF &&
                     ulFrameIndex                <  m_ulCurFrameIndex))
                {
                    m_ulLoopsDone++;
                }
                // Update the current frame index
                m_ulCurFrameIndex = ulFrameIndex;
            }
        }

        // Do we need to schedule another callback?
        if (m_bSiteAttached &&                                        // only schedule another callback if site is attached
            m_pCallback    &&                                         // can't do it without a callback object
            (m_bPreserveMediaRepeat ||
             (!m_bPreserveMediaRepeat && m_ulLoopsDone == 0)) &&
            ((bFinished == FALSE)               ||                    // GIF isn't finished yet
            (m_pGIFCodec->GetLoopCount() == 0) ||                     // GIF says to loop infinitely
             (m_pGIFCodec->GetLoopCount() > 0 &&                      // GIF says to loop a finite number of
              m_ulLoopsDone < m_pGIFCodec->GetLoopCount())))          //   times and we're not finished
        {
            // If we just drew the image, then don't schedule a callback until
            // the delay time from now. If we didn't draw, then schedule one
            // kCallbackInterval milliseconds from now
            BOOL       bRelative     = TRUE;
            UINT32     ulTimeFromNow = kCallbackInterval;
            HXTimeval cTime         = {0, 0};
            // Was the frame finished?
            if (bFinished)
            {
                // Did we draw and would have skipped a frame?
                if (bDoDamage && bWouldHaveSkipped)
                {
                    // Schedule a short relative callback
                    bRelative     = TRUE;
                    ulTimeFromNow = kMinCallbackInterval;
                }
                else
                {
                    // Get the time that the next frame would display
                    UINT32 ulNextFrameTime = GetNextFrameTime(ulTime);
                    // If the difference is small enough, then schedule
                    // a short relative callback. Otherwise schedule
                    // an absolute callback
                    if (ulNextFrameTime - ulTime > kMinCallbackInterval)
                    {
                        // Get the time difference between the next frame
                        // time and the time at the scheduler time base
                        UINT32 ulDiff = 0;
                        if (ulNextFrameTime >= m_ulTimeAtSchedulerTimeBase)
                        {
                            ulDiff = ulNextFrameTime - m_ulTimeAtSchedulerTimeBase;
                        }
                        else
                        {
                            ulDiff = 0xFFFFFFFF - m_ulTimeAtSchedulerTimeBase + ulNextFrameTime;
                        }
                        // Compute the difference in seconds and microseconds
                        HXTimeval cDiff = {0, 0};
                        cDiff.tv_sec  = ulDiff / 1000;
                        cDiff.tv_usec = (ulDiff - (cDiff.tv_sec * 1000)) * 1000;
                        // Add this difference to the scheduler time base
                        cTime.tv_sec  = m_tSchedulerTimeBase.tv_sec  + cDiff.tv_sec;
                        cTime.tv_usec = m_tSchedulerTimeBase.tv_usec + cDiff.tv_usec;
                        // Wrap the usec if necessary
                        if (cTime.tv_usec >= 1000000)
                        {
                            cTime.tv_usec -= 1000000;
                            cTime.tv_sec  += 1;
                        }
                        // Clear the relative flag
                        bRelative = FALSE;
                    }
                    else
                    {
                        bRelative     = TRUE;
                        ulTimeFromNow = kMinCallbackInterval;
                    }
                }
            }
            else
            {
                // Frame had not completed decoding - schedule a
                // relative callback
                bRelative     = TRUE;
                ulTimeFromNow = kNotFinishedInterval;
            }
            // Schedule the next callback
            if (bRelative)
            {
                m_pCallback->ScheduleRelativeCallback(ulTimeFromNow);
            }
            else
            {
                m_pCallback->ScheduleAbsoluteCallback(cTime);
            }
        }
    }

    return retVal;
}

STDMETHODIMP CGIFRenderer::OnPreSeek(UINT32 ulTimeBefore, UINT32 ulTimeAfter)
{
    MLOG_MISC(m_pErrorMessages,
              "0x%08x::OnPreSeek(%lu,%lu)\n",
              this, ulTimeBefore, ulTimeAfter);

    // Set the ignore packets flag
    m_bIgnorePackets = TRUE;

    return HXR_OK;
}

STDMETHODIMP CGIFRenderer::OnPostSeek(UINT32 ulTimeBefore, UINT32 ulTimeAfter)
{
    MLOG_MISC(m_pErrorMessages,
              "0x%08x::OnPostSeek(%lu,%lu)\n",
              this, ulTimeBefore, ulTimeAfter);

    HX_RESULT retVal = HXR_OK;

    if (m_pStreamHeaderBuffer && !m_bImageBombed)
    {
        // Determine if the seek-to time is past our ending time.
        // We only need to blow away everything if we are going to
        // be getting packets all over again. That will happen only
        // if the seek-to time is < our end time.
        if (ulTimeAfter < m_ulEndTime)

⌨️ 快捷键说明

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