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 + -
显示快捷键?