📄 rarender.cpp
字号:
FALSE);
}
}
#endif /* #if defined(HELIX_FEATURE_AUDIO_CODEC_RAAC) */
HXAudioFormat audioFmt;
m_pRaFormats[i]->GetAudioFormat(audioFmt);
if ((bMaxSampleRate && audioFmt.ulSamplesPerSec > ulCurrentSampleRate) ||
(!bMaxSampleRate && audioFmt.ulSamplesPerSec < ulCurrentSampleRate))
{
ulCurrentSampleRate = audioFmt.ulSamplesPerSec;
uCurrentNumChannels = audioFmt.uChannels;
nFirstStreamToInit = i;
}
else if (audioFmt.ulSamplesPerSec == ulCurrentSampleRate &&
audioFmt.uChannels > uCurrentNumChannels)
{
uCurrentNumChannels = audioFmt.uChannels;
nFirstStreamToInit = i;
}
}
// mask out DECODER_NOT_FOUND so we can try all of the streams and find
// all of the decoders that aren't installed and upgrade them all at once
if (retVal == HXR_DEC_NOT_FOUND)
{
#if defined(HELIX_CONFIG_SLUGGISHAUTOUPGRADE)
if( m_pRuleMap )
{
if( m_pStream && !m_pASMStream )
{
if( m_pStream->QueryInterface(IID_IHXASMStream2,
(void**)&m_pASMStream) == HXR_OK )
{
m_pASMStream->AddRef();
}
}
if( m_pASMStream )
{
// Find all rules for this stream
for( int ii=0; ii<m_uNumOfRules; ii++ )
{
if( m_pRuleMap[ii] == i )
{
m_pASMStream->Disable( ii );
numRulesToBlock++;
}
}
}
} // if m_pRuleMap
if( ( numRulesToBlock == m_uNumOfRules ) || ( numRulesToBlock == 1 && m_uNumOfRules == 0 ) )
{
bDecoderNotFound = TRUE;
}
retVal = HXR_OK;
#else
retVal = HXR_OK;
bDecoderNotFound = TRUE;
#endif
}
pCursor += ulBytesRead;
ulBufferSize -= ulBytesRead;
}
#if defined(HELIX_CONFIG_SLUGGISHAUTOUPGRADE)
if( m_pASMStream && bDecoderNotFound == FALSE )
{
HX_RESULT retVal = m_pASMStream->ReCompute();
if( retVal == HXR_FAIL )
{
bDecoderNotFound = TRUE;
}
}
#endif // (HELIX_CONFIG_SLUGGISHAUTOUPGRADE)
// write all codecs list to registry
#if defined(HELIX_FEATURE_STATS)
WriteCodecsToRegistry(pAllCodecs);
// clean up char array
HX_VECTOR_DELETE(pAllCodecs);
#endif // HELIX_FEATURE_STATS
// if we don't have any other errors but we are missing one or more
// decoders, reset the result code to decoder not found so upgrade
// gets kicked off.
if (HXR_OK == retVal && bDecoderNotFound)
{
retVal = HXR_DEC_NOT_FOUND;
}
// This helps insure we get the audio device opened at the
// sampling rate and # channels we want.
if (HXR_OK == retVal)
{
retVal = InitAudioStream(m_pRaFormats[nFirstStreamToInit], pHeader,
&m_pAudioStreams[nFirstStreamToInit]);
for (i = 0; retVal == HXR_OK &&
i < m_uNumOfSubStreams ; i++)
{
if (i != nFirstStreamToInit)
{
retVal = InitAudioStream(m_pRaFormats[i], pHeader,
&m_pAudioStreams[i]);
}
}
}
// add the default dry notification when we are all done
if (HXR_OK == retVal)
{
AddDryNotification(DEFAULT_DRY_NOTIFICATION);
}
#if defined(HELIX_FEATURE_SETSRCPROPS)
// Do we have more than one substream?
if (m_uNumOfSubStreams > 1)
{
// Here we need to find the highest bitrate stream
UINT32 ulMaxBps = 0;
for (UINT32 i = 0; i < m_uNumOfSubStreams; i++)
{
UINT32 ulBps = m_pRaFormats[i]->GetBitRate();
if (ulBps > ulMaxBps)
{
ulMaxBps = ulBps;
ulSubStream = i;
}
}
}
// Save the highest bitrate substream index
m_ulSrcPropertySubStream = ulSubStream;
#endif /* #if defined(HELIX_FEATURE_SETSRCPROPS) */
cleanup:
if (retVal == HXR_OK && !m_pMutex)
{
#ifdef THREADS_SUPPORTED
HXMutex::MakeMutex(m_pMutex);
#else
HXMutex::MakeStubMutex(m_pMutex);
#endif
}
HX_RELEASE(pUpgradeCollection);
HX_RELEASE(pOpaqueData);
return retVal;
}
CRaFormat* CRealAudioRenderer::CreateRaFormat(UINT16 uStreamNum)
{
return new CRaFormat(m_pContext,
m_pCommonClassFactory,
m_pErrorMessages,
m_pRuleToFlagMap ?
m_pRuleToFlagMap->rule_to_flag_map : NULL,
uStreamNum);
}
/////////////////////////////////////////////////////////////////////////////
// Method:
// CRealAudioRenderer::CheckStreamVersions
HX_RESULT
CRealAudioRenderer::CheckStreamVersions(IHXValues* pHeader)
{
// check stream and content versions so an upgrade can
// be called if necessary...
HX_RESULT pnr = HXR_OK;
#if defined(HELIX_FEATURE_AUTOUPGRADE)
BOOL bVersionOK = TRUE;
UINT32 ulStreamVersion = 0;
UINT32 ulContentVersion = 0;
if(HXR_OK == pHeader->GetPropertyULONG32("StreamVersion",
ulStreamVersion))
{
UINT32 ulMajorVersion = HX_GET_MAJOR_VERSION(ulStreamVersion);
UINT32 ulMinorVersion = HX_GET_MINOR_VERSION(ulStreamVersion);
if((ulMajorVersion > STREAM_MAJOR_VERSION) ||
(ulMinorVersion > STREAM_MINOR_VERSION &&
ulMajorVersion == STREAM_MAJOR_VERSION))
{
bVersionOK = FALSE;
}
}
if(bVersionOK &&
HXR_OK == pHeader->GetPropertyULONG32("ContentVersion",
ulContentVersion))
{
UINT32 ulMajorVersion = HX_GET_MAJOR_VERSION(ulContentVersion);
UINT32 ulMinorVersion = HX_GET_MINOR_VERSION(ulContentVersion);
if((ulMajorVersion > CONTENT_MAJOR_VERSION) ||
(ulMinorVersion > CONTENT_MINOR_VERSION &&
ulMajorVersion == CONTENT_MAJOR_VERSION))
{
bVersionOK = FALSE;
}
}
if(!bVersionOK)
{
IHXUpgradeCollection* pUpColl = NULL;
if(m_pContext &&
(HXR_OK == m_pContext->QueryInterface(IID_IHXUpgradeCollection,
(void**)&pUpColl)))
{
CHXBuffer* pBuffer = NULL;
m_pCommonClassFactory->CreateInstance(IID_IHXBuffer, (void**) &pBuffer);
if (pBuffer)
{
//XXXEH- in future, we may want to distinguish between
// "unknown content version" & "unknown stream version".
// For now, just treat both as "unknown content version":
LONG32 bufsize = strlen(zm_pStreamMimeTypes[0]) +
strlen(zm_pAdditionalAutoUpgradeInfo[
unknownRAContentVersion]) + 1;
pBuffer->Set((BYTE*)zm_pStreamMimeTypes[0], bufsize);
unsigned char* pBuf = pBuffer->GetBuffer();
pBuf[strlen(zm_pStreamMimeTypes[0])] = '\0';
SafeStrCat((char *)pBuf, zm_pAdditionalAutoUpgradeInfo[ /* Flawfinder: ignore */
unknownRAContentVersion], pBuffer->GetSize());
pUpColl->Add(eUT_Required, pBuffer, 0, 0);
HX_RELEASE(pBuffer);
HX_RELEASE(pUpColl);
}
}
pnr = HXR_FAIL;
}
#endif /* #if defined(HELIX_FEATURE_AUTOUPGRADE) */
return pnr;
}
/////////////////////////////////////////////////////////////////////////////
// Method:
// CRealAudioRenderer::InitAudioStream
HX_RESULT
CRealAudioRenderer::InitAudioStream(CRaFormat* pRaFormat, IHXValues* pHeader,
IHXAudioStream** ppAudioStream)
{
HX_RESULT retVal;
// init so we can HX_RELEASE on error.
*ppAudioStream = NULL;
pRaFormat->m_pAudioSync = NULL;
retVal = m_pAudioPlayer->CreateAudioStream(ppAudioStream);
if (HXR_OK == retVal)
{
retVal = (*ppAudioStream)->QueryInterface(IID_IHXRealAudioSync,
(void**)&(pRaFormat->m_pAudioSync));
if (HXR_OK == retVal)
{
IHXCommonClassFactory* pCommonClassFactory;
if (HXR_OK == (*ppAudioStream)->QueryInterface(IID_IHXCommonClassFactory,
(void**)&pCommonClassFactory))
{
// if we can get a class factory from the ccf, it's
// a redstone or later core
m_bPreRedstonePlayer = FALSE;
pRaFormat->OverrideFactory(pCommonClassFactory);
pCommonClassFactory->Release();
}
HXAudioFormat audioFmt;
pRaFormat->GetAudioFormat(audioFmt);
/* Add default dry notification BEFORE initializing the audio
* stream. This is so that if we are started mid presentation
* and there was no audio present earlier, the timeline will
* change from being a fake timeline to audio timeline and
* the audio services will write audio for initial pushdown
* time. We need to get dry notifications so that we can halt
* the timeline, if the renderer does not have enough data.
*/
retVal = (*ppAudioStream)->Init(&audioFmt, pHeader);
}
}
if (HXR_OK != retVal)
{
HX_RELEASE((*ppAudioStream));
HX_RELEASE(pRaFormat->m_pAudioSync);
}
return retVal;
}
/////////////////////////////////////////////////////////////////////////////
// Method:
// CRealAudioRenderer::AddDryNotification
HX_RESULT
CRealAudioRenderer::AddDryNotification(UINT16 usStreamNumber)
{
HX_RESULT pnr = HXR_OK;
if (m_pAudioStreams == NULL)
{
pnr = HXR_FAILED;
}
if ((HXR_OK == pnr) &&
(usStreamNumber != m_usCurrentDryNotificationStream))
{
if (m_usCurrentDryNotificationStream != NO_STREAM_SET)
{
HX_ASSERT(m_pAudioStreams[m_usCurrentDryNotificationStream] != NULL);
QueueUnregisterSync(m_usCurrentDryNotificationStream,
m_ulLatestActualTime);
RemoveCurrentDryNotification();
DEBUG_OUT(m_pErrorMessages, DOL_REALAUDIO,
(s, "Switching FROM: %u - Removing DryNotification",
m_usCurrentDryNotificationStream));
}
IHXDryNotification* pDryNot = NULL;
QueryInterface(IID_IHXDryNotification, (void**)&pDryNot);
HX_ASSERT(m_pAudioStreams[usStreamNumber] != NULL);
if (pDryNot)
{
pnr = m_pAudioStreams[usStreamNumber]->AddDryNotification(pDryNot);
}
DEBUG_OUTF_IDX(usStreamNumber, RA_FLOW_FILE,
(s, "Dry-Notif. Start: %s\n", (pnr == HXR_OK) ? "OK" : "FAIL"));
HX_ASSERT(SUCCEEDED(pnr));
m_usCurrentDryNotificationStream = usStreamNumber;
DEBUG_OUT(m_pErrorMessages, DOL_REALAUDIO,
(s, "Switching TO: %u - Adding DryNotification",
m_usCurrentDryNotificationStream));
// fix up the granularity for this stream
// we want to be called twice as frequently as our block size. That
// way we will "over write" to audio services if we have extra data.
// This will allow build up of an audio pushdown.
ULONG32 ulNewGranularity =
(UINT32) (m_pRaFormats[usStreamNumber]->GetMSPerBlock() / 2);
if (ulNewGranularity != m_ulCurrentGranularity)
{
m_ulCurrentGranularity = ulNewGranularity;
m_pStream->SetGranularity(m_ulCurrentGranularity);
DEBUG_OUTF_IDX(usStreamNumber, RA_FLOW_FILE,
(s, "Granularity Set: %u\n",
m_ulCurrentGranularity));
}
HX_RELEASE(pDryNot);
}
if (pnr == HXR_OK)
{
DoSyncRegister(m_usCurrentDryNotificationStream);
}
return pnr;
}
/////////////////////////////////////////////////////////////////////////////
// Method:
// CRealAudioRenderer::DoSyncRegister
void CRealAudioRenderer::DoSyncRegister(UINT16 uStreamNumber)
{
if (m_pRaFormats &&
m_pRaFormats[uStreamNumber]->m_pAudioSync &&
(!m_pRaFormats[uStreamNumber]->m_bRegistered))
{
DEBUG_OUTF_IDX(uStreamNumber, RA_FLOW_FILE,
(s, "Sync Start\n"));
m_pRaFormats[uStreamNumber]->m_bRegistered = TRUE;
m_pRaFormats[uStreamNumber]->m_pAudioSync->Register();
}
}
void CRealAudioRenderer::UnregisterTimeSyncs(UINT32 ulCurrentTime)
{
UINT16 uCurrentStream = m_uSyncUnregisterStream;
if (uCurrentStream != NO_STREAM_SET)
{
BOOL bStreamDone = m_pRaFormats[uCurrentStream]->IsStreamDone();
if ((m_bAllStreamsToBeUnregistered &&
(IsTimeGreaterOrEqual(ulCurrentTime, m_ulDuration) ||
bStreamDone)) ||
((m_ulSyncUnregisterTime == NO_TIME_SET) &&
IsTimeGreaterOrEqual(ulCurrentTime,
m_ulSyncUnregisterTime)))
{
CRealAudioRenderer::QueueUnregisterSync(uCurrentStream,
NO_TIME_SET);
}
}
}
/////////////////////////////////////////////////////////////////////////////
// Method:
// CRealAudioRenderer::QueueUnregisterSync
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -