📄 raformat.cpp
字号:
* 0 1 2 3 4
*
*/
BOOL bDone = FALSE;
ulTimestamp = UnAdjustTimestamp(ulTimestamp, m_lTimeOffset);
m_ulCrossFadeEndTime = ulTimestamp;
// see if it's at #3
bDone = m_pPacketFeeder->SetCrossFadeEndTime(ulTimestamp);
// see if it's at #2
if (!bDone)
{
if (!m_IBufs.m_IBlockTimeRange.IsEmpty())
{
if (m_IBufs.m_IBlockTimeRange.TimeInRange(ulTimestamp))
{
DEBUG_OUTF(XFADE_FILE, (s, "SetXFadeEndTime Pos(2)\t%lu\t%lu\n", ulTimestamp, (UINT32)GetMSPerBlock()));
bDone = TRUE;
}
else
{
// check for the #4 position
if (IsTimeGreater(ulTimestamp, m_IBufs.m_IBlockTimeRange.m_ulEnd))
{
// position #4 and we're done
bDone = TRUE;
DEBUG_OUTF(XFADE_FILE, (s, "SetXFadeEndTime Pos(4 after 2)\t%lu\t%lu\n", ulTimestamp, (UINT32)GetMSPerBlock()));
}
else
{
// either 1 or 0 so flush 2
m_IBufs.FlushIBlock();
}
}
}
}
// see if it's #1
if (!bDone)
{
if (!m_IBufs.m_DBlockTimeRange.IsEmpty())
{
if (m_IBufs.m_DBlockTimeRange.TimeInRange(ulTimestamp))
{
DEBUG_OUTF(XFADE_FILE, (s, "SetXFadeEndTime Pos(1)\t%lu\t%lu\n", ulTimestamp, (UINT32)GetMSPerBlock()));
bDone = TRUE;
}
else
{
// check for the #4 position
if (IsTimeGreater(ulTimestamp, m_IBufs.m_DBlockTimeRange.m_ulEnd))
{
// position #4 and we're done
DEBUG_OUTF(XFADE_FILE, (s, "SetXFadeEndTime Pos(4 after 1)\t%lu\t%lu\n", ulTimestamp, (UINT32)GetMSPerBlock()));
bDone = TRUE;
}
else
{
//it's 0, flush the I bufs now
DEBUG_OUTF(XFADE_FILE, (s, "SetXFadeEndTime Pos(0), flushing format\t%lu\t%lu\n", ulTimestamp, (UINT32)GetMSPerBlock()));
SetupForNextTimeRange();
}
}
}
else
{
//it's 0, flush the I bufs now
DEBUG_OUTF(XFADE_FILE, (s, "SetXFadeEndTime Pos(0), flushing format\t%lu\t%lu\n", ulTimestamp, (UINT32)GetMSPerBlock()));
SetupForNextTimeRange();
}
}
}
void
CRaFormat::DiscardTillEndOfCrossFade(UINT32 ulTimestamp)
{
/*
* The ulTimestamp can be in one of these 5 positions.
* We start from 0 and go to 4 looking for some data that's
* greater than the ulTimestamp time.
*
* [DDD][III] {_,_,_,_,_,_,_,}
* ^ ^ ^ ^ ^
* | | | | |
* 0 1 2 3 4
*
*/
BOOL bDone = FALSE;
ulTimestamp = UnAdjustTimestamp(ulTimestamp, m_lTimeOffset);
// cannot equal NO_TIME_SET so we bump it up one
if (ulTimestamp == NO_TIME_SET)
{
ulTimestamp += 1;
}
m_ulForceDiscardUntilTime = ulTimestamp;
// start looking to see if it's #0 or #1
if (!m_IBufs.m_DBlockTimeRange.IsEmpty())
{
if (IsTimeGreater(m_IBufs.m_DBlockTimeRange.m_ulStart, ulTimestamp))
{
DEBUG_OUTF(DISCARDUNTIL_FILE, (s, "DiscardUntil Pos(0),\t%lu\t%lu\n", ulTimestamp, (UINT32)GetMSPerBlock()));
// time is in past and we're done, reset state variables
m_ulForceDiscardUntilTime = NO_TIME_SET;
bDone = TRUE;
}
else if (m_IBufs.m_DBlockTimeRange.TimeInRange(ulTimestamp))
{
DEBUG_OUTF(DISCARDUNTIL_FILE, (s, "DiscardUntil Pos(1),\t%lu\t%lu\n", ulTimestamp, (UINT32)GetMSPerBlock()));
bDone = TRUE;
}
else
{
DEBUG_OUTF(DISCARDUNTIL_FILE, (s, "FlushDBlock\t%lu\t%lu\t%lu\n", ulTimestamp, (UINT32)GetMSPerBlock(), m_IBufs.m_DBlockTimeRange.m_ulStart));
m_IBufs.FlushDBlock();
}
}
// see if it's at #2
if (!bDone)
{
// fill the IBlock if we can
if (!m_IBufs.IsISuperBlockFilled())
{
m_pPacketFeeder->FillISuperBlock();
}
if (!m_IBufs.m_IBlockTimeRange.IsEmpty())
{
if (IsTimeGreater(m_IBufs.m_IBlockTimeRange.m_ulStart, ulTimestamp))
{
DEBUG_OUTF(DISCARDUNTIL_FILE, (s, "DiscardUntil Pos(0),\t%lu\t%lu\n", ulTimestamp, (UINT32)GetMSPerBlock()));
// time is in past and we're done, reset state variables
m_ulForceDiscardUntilTime = NO_TIME_SET;
bDone = TRUE;
}
else if (m_IBufs.m_IBlockTimeRange.TimeInRange(ulTimestamp))
{
bDone = TRUE;
DEBUG_OUTF(DISCARDUNTIL_FILE, (s, "DiscardUntil Pos(2),\t%lu\t%lu\n", ulTimestamp, (UINT32)GetMSPerBlock()));
}
else
{
DEBUG_OUTF(DISCARDUNTIL_FILE, (s, "FlushIBlock\t%lu\t%lu\t%lu\n", ulTimestamp, (UINT32)GetMSPerBlock(), m_IBufs.m_IBlockTimeRange.m_ulStart));
m_IBufs.FlushIBlock();
}
}
}
bDone = m_pPacketFeeder->DiscardTillEndOfCrossFade(ulTimestamp, bDone);
// if still not done, it's at #4, else we found it before #4
if (!bDone)
{
m_ulForceDiscardUntilTime = NO_TIME_SET;
}
}
HX_RESULT
CRaFormat::GetNextAudioDataTime(UINT32& ulStart, UINT32& ulEnd)
{
UINT32 ulIterationCounter = 0;
HX_RESULT theError = HXR_OK;
BOOL bSuccess = FALSE;
ulStart = ulEnd = 0;
// move any data from the time range queue into the IBufs
m_pPacketFeeder->FillISuperBlock();
if (m_bEndOfPackets)
{
if (!m_IBufs.DataAvailable(AUDIO_END_OF_PACKETS))
{
// this is an "emergency" state so do this even
// if the IBlock isn't quite full
m_IBufs.DeInterleaveData();
}
}
do
{
// move any data from the time range queue into the IBufs
m_pPacketFeeder->FillISuperBlock();
// Here we always want to know the full time range of available
// time so we always ask for the crossfade time
if (m_IBufs.DataAvailable(AUDIO_CROSSFADE))
{
if (m_ulForceDiscardUntilTime != NO_TIME_SET)
{
// this will be the actual start time of
// the data returned from GetAudioData
ulStart = m_ulForceDiscardUntilTime;
DEBUG_OUTF(TIME_FILE, (s, "Force Discard Time Reported\t%lu\t%lu\n",
ulStart, (UINT32)GetMSPerBlock()));
}
else
{
ulStart = m_IBufs.m_DBlockTimeRange.m_ulStart;
// we may have data before the track start time but we will
// not return audio data prior to the track start time
if (m_bForceStartTrackTime && IsTimeLess(ulStart, m_ulTrackStartTime))
{
ulStart = m_ulTrackStartTime;
}
DEBUG_OUTF(TIME_FILE, (s, "DBlock start Time Reported\t%lu\t%lu\n",
ulStart, (UINT32)GetMSPerBlock()));
HX_ASSERT(ulStart != NO_TIME_SET);
}
ulEnd = ulStart + (UINT32)GetMSPerBlock();
if (m_bForceEndTrackTime && ulEnd > m_ulTrackEndTime)
{
ulEnd = m_ulTrackEndTime;
HX_ASSERT(ulEnd >= ulStart);
}
ulStart = AdjustTimestamp(ulStart, m_lTimeOffset);
ulEnd = AdjustTimestamp(ulEnd, m_lTimeOffset);
bSuccess = TRUE;
break;
}
else
{
// if there is a current time range, ask it if it's
// ended. We assume it's not ended.
BOOL bTimeRangeEnded = m_pPacketFeeder->IsCurrentTimeRangeEnded();
BOOL bDataInTimeRange = !m_pPacketFeeder->IsCurrentTimeRangeEmpty();
// If the D superblock is empty and there's more data to decode
// we give it a try to move the data into the D superblock to
// decode it.
if (m_IBufs.IsDSuperBlockEmpty() &&
(!m_IBufs.IsISuperBlockEmpty() || bDataInTimeRange))
{
if (m_IBufs.IsISuperBlockFilled())
{
m_IBufs.DeInterleaveData();
}
// if we don't have any data in the De-interleaved superblock
// and we failed to fill the Interleaved superblock, we
// must be out of data and we should break out of the while loop
if (m_IBufs.IsDSuperBlockEmpty() &&
(!m_pPacketFeeder->FillISuperBlock()))
{
DEBUG_OUTF(DOAUDIO_FILE, (s, "GetNextAudioDataTime\t%d\t%d\t%d\t%d\t%lu\n",
m_IBufs.IsDSuperBlockEmpty(), m_IBufs.IsISuperBlockEmpty(), m_IBufs.IsISuperBlockFilled(), bTimeRangeEnded, (UINT32)GetMSPerBlock()));
break;
}
}
else
{
// if we get here, there's no in the IBuf or the
// current time range.
HX_ASSERT(!bDataInTimeRange);
if (bTimeRangeEnded)
{
// the Time range has ended and the data from it is
// gone from the IBufs so setup the next time range
// now
SetupForNextTimeRange();
}
else
{
DEBUG_OUTF(DOAUDIO_FILE, (s, "GetNextAudioDataTime\t%d\t%d\t%d\t%d\t%lu\n",
m_IBufs.IsDSuperBlockEmpty(), m_IBufs.IsISuperBlockEmpty(), m_IBufs.IsISuperBlockFilled(), bTimeRangeEnded, (UINT32)GetMSPerBlock()));
break;
}
}
}
ulIterationCounter++;
} while (ulIterationCounter < MAX_AUDIO_DATA_ATTEMPTS);
if (bSuccess)
{
return HXR_OK;
}
else
{
return HXR_NO_DATA;
}
}
UINT32
CRaFormat::GetCurrentTimeRangeEnd()
{
UINT32 ulRet = m_pPacketFeeder->GetCurrentTimeRangeEnd();
if (ulRet == NO_TIME_SET)
{
if (!m_IBufs.m_IBlockTimeRange.IsEmpty())
{
// it will be in the IBufs
ulRet = m_IBufs.m_IBlockTimeRange.m_ulEnd;
}
else
{
ulRet = m_IBufs.m_DBlockTimeRange.m_ulEnd;
}
}
DEBUG_OUTF(TREND_FILE, (s, "%lu\t%lu\n", (UINT32)GetMSPerBlock(), ulRet));
ulRet = AdjustTimestamp(ulRet, m_lTimeOffset);
return ulRet;
}
void CRaFormat::ThrowUpgrade(const char* pszStr)
{
if (m_pCommonClassFactory && pszStr)
{
IHXBuffer* pBuffer = NULL;
m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer, (void**) &pBuffer);
if (pBuffer)
{
pBuffer->Set((BYTE*) pszStr, strlen(pszStr) + 1);
if (m_pUpgradeCollection)
{
m_pUpgradeCollection->Add(eUT_Required, pBuffer, 0, 0);
}
}
HX_RELEASE(pBuffer);
}
}
HX_RESULT
CRaFormat::OnSeek (UINT32 ulOldTime, UINT32 ulNewTime)
{
m_IBufs.OnSeek();
m_bFirstPacket = TRUE;
m_bEndOfPackets = FALSE;
m_ulCodecDelay = 0;
m_fCodecDelay = 0.0;
m_bPCMStreamStart = TRUE;
SetupForNextTimeRange();
m_pPacketFeeder->Reset();
return HXR_OK;
}
BOOL
CRaFormat::IsStreamDone()
{
if( !m_pPacketFeeder )
{
return TRUE;
}
return ((!m_pPacketFeeder->IsActive()) && m_IBufs.IsStreamDone());
}
void
CRaFormat::SetupForNextTimeRange()
{
m_pPacketFeeder->SetupForNextTimeRange();
if (m_pCodec != NULL)
{
UINT32 ulOutSize = m_ulAudioBufSize;
IHXBuffer * pBuffer = NULL;
m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer, (void**) &pBuffer);
if( pBuffer )
{
if( pBuffer->GetSize() != m_ulAudioBufSize )
{
// Yikes! This can fail if heap is low: no check!
pBuffer->SetSize( ulOutSize );
}
m_pCodec->Flush( pBuffer->GetBuffer(), &ulOutSize );
HX_RELEASE( pBuffer );
}
}
m_ulCodecDelay = 0;
m_fCodecDelay = 0.0;
m_bPCMStreamStart = TRUE;
m_ulCrossFadeEndTime = NO_TIME_SET;
m_ulForceDiscardUntilTime = NO_TIME_SET;
m_IBufs.SwitchOff();
}
void
CRaFormat::OnEndofPackets(void)
{
if( !m_pPacketFeeder )
{
m_bEndOfPackets = TRUE;
return;
}
m_pPacketFeeder->OnEndOfPackets();
m_bEndOfPackets = TRUE;
// if we've already given all of the packets to the ibufs,
// we can tell them we are done now, otherwise wait till
// we do finish the packets
if (!m_pPacketFeeder->IsActive())
{
m_IBufs.OnEndofPackets();
}
}
HX_RESULT
CRaFormat::UpdatePacketTimeOffset(INT32 lTimeOffset)
{
m_lTimeOffset -= lTimeOffset;
return HXR_OK;
}
HX_RESULT
CRaFormat::UpdatePlayTimes(IHXValues* pProps)
{
UINT32 ulStart = 0;
UINT32 ulEnd = 0;
if (HXR_OK == pProps->GetPropertyULONG32("Start", ulStart))
{
m_ulTrackStartTime = ulStart;
m_bForceStartTrackTime = TRUE;
}
if (HXR_OK == pProps->GetPropertyULONG32("End", ulEnd))
{
m_ulTrackEndTime = ulEnd;
m_bForceEndTrackTime = TRUE;
}
return HXR_OK;
}
// statistics
#if defined(HELIX_FEATURE_STATS)
HX_RESULT CRaFormat::UpdateStatistics (IHXRegistry* pRegistry, UINT32 ulRegistryID,
UINT32& ulCodecRegID, UINT32& ulCodecTextRegID,
UINT32& ulCodec4CCRegID, UINT32& ulRateRegID,
UINT32& ulChannelsRegID, UINT32& ulSurroundRegID)
{
char szRegistryEntry[MAX_DISPLAY_NAME] = {0}; /* Flawfinder: ignore */
IHXBuffer* pszRegistryName = NULL;
IHXBuffer* pValue = NULL;
CStreamParam* pParam;
HX_RESULT retVal = HXR_OK;
if (!pRegistry || !ulRegistryID || m_pCodec == NULL)
{
return HXR_FAILED;
}
pParam = &m_StreamParam;
if (!ulCodecRegID)
{
// Get the current registry key name
if (!ulCodecRegID && (HXR_OK == pRegistry->GetPropName(ulRegistryID, pszRegistryName)))
{
SafeSprintf (szRegistryEntry, MAX_DISPLAY_NAME, "%s.Codec", pszRegistryName->GetBuffer());
if (pParam->codecID)
{
m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer,
(void**) &pValue);
//
UINT16 uPropSize = 0;
void* pProp = m_pCodec->GetFlavorProperty(m_StreamParam.uFlavorIndex, FLV_PROP_NAME, &uPropSize);
if (uPropSize)
{
pValue->Set((const UCHAR*)pProp, uPropSize);
ulCodecRegID = pRegistry->AddStr(szRegistryEntry, pValue);
}
pValue->Release();
}
pszRegistryName->Release();
pszRegistryName = NULL;
}
}
else
{
if (pParam->codecID)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -