📄 pxgifrnd.cpp
字号:
// 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) { // We are going to start receiving packets all over again, so // we need to blow away the CGIFCodec class and start over // again. We will need to reinit it with the stream header // buffer. // // Delete the old CGIFCodec HX_DELETE(m_pGIFCodec); // Create a new one m_pGIFCodec = new CGIFCodec(); if (m_pGIFCodec) { // Get the stream header pointer BYTE* pData = m_pStreamHeaderBuffer->GetBuffer() + m_ulStreamHeaderOffset; // Initialize the CGIFCodec for decompression retVal = m_pGIFCodec->InitDecompress(m_pStreamHeaderBuffer->GetBuffer() + m_ulStreamHeaderOffset, m_pStreamHeaderBuffer->GetSize() - m_ulStreamHeaderOffset); if (SUCCEEDED(retVal)) { // Initialize the rendering members m_ulCurImg = 0; m_ulCurImgRenderTime = 0; m_ulCurDelayTime = 0; m_lLastImg = -1; // Initialize the loop done count m_ulLoopsDone = 0; // Clear the ignore packets flag m_bIgnorePackets = FALSE; } } else { retVal = HXR_OUTOFMEMORY; } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -