📄 rarender.cpp
字号:
cleanup:
if (HXR_OK != hr)
{
HX_RELEASE(m_pErrorMessages);
HX_RELEASE(m_pAudioPlayer);
HX_RELEASE(m_pAudioPushdown2);
}
return hr;
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IHXRenderer::EndStream
// Purpose:
// Called by client engine to inform the renderer that the stream
// is was rendering is closed.
//
STDMETHODIMP CRealAudioRenderer::EndStream()
{
#ifdef _MACINTOSH
if (m_pDryCallback != NULL)
{
m_pDryCallback->Cancel();
HX_RELEASE(m_pDryCallback);
}
#endif
if ((m_usCurrentDryNotificationStream != NO_STREAM_SET) &&
m_pAudioStreams != NULL &&
m_pAudioStreams[m_usCurrentDryNotificationStream] != NULL)
{
RemoveCurrentDryNotification();
m_usCurrentDryNotificationStream = NO_STREAM_SET;
}
m_PlayState = stopped;
FlushUnregisterQueue(TRUE);
// We're done with these...
HX_RELEASE(m_pContext);
HX_RELEASE(m_pCommonClassFactory);
#if defined(HELIX_FEATURE_STATS)
HX_RELEASE(m_pRegistry);
#endif // HELIX_FEATURE_STATS
HX_RELEASE(m_pBufferingStats);
HX_RELEASE(m_pStream);
#if defined(HELIX_CONFIG_SLUGGISHAUTOUPGRADE)
HX_RELEASE(m_pASMStream);
#endif
HX_RELEASE(m_pAudioPlayer);
HX_RELEASE(m_pAudioPushdown2);
HX_RELEASE(m_pErrorMessages);
#if defined(HELIX_FEATURE_SETSRCPROPS)
HX_RELEASE(m_pValues);
#endif /* #if defined(HELIX_FEATURE_SETSRCPROPS) */
UINT16 i = 0;
for (i = 0; i < m_uNumOfSubStreams; i++)
{
if (m_pRaFormats[i])
{
if (m_pRaFormats[i]->m_pAudioSync && m_pRaFormats[i]->m_bRegistered)
{
m_pRaFormats[i]->m_bRegistered = FALSE;
m_pRaFormats[i]->m_pAudioSync->UnRegister();
DEBUG_OUTF_IDX(i, RA_FLOW_FILE,
(s, "Sync Stop\n"));
}
HX_RELEASE(m_pRaFormats[i]->m_pAudioSync);
HX_RELEASE(m_pAudioStreams[i]);
HX_DELETE(m_pRaFormats[i]);
#if defined(HELIX_FEATURE_AUDIO_CODEC_RAAC)
HX_DELETE(m_ppVBRDepack[i]);
#endif
}
}
// we might get called twice and don't want to go through
// the above loop again.
m_uNumOfSubStreams = 0;
HX_VECTOR_DELETE(m_pRuleMap);
HX_VECTOR_DELETE(m_pAudioStreams);
HX_VECTOR_DELETE(m_pRaFormats);
#if defined(HELIX_FEATURE_AUDIO_CODEC_RAAC)
HX_VECTOR_DELETE(m_ppVBRDepack);
#endif
FlushUnregisterQueue(TRUE);
if (m_pRuleToFlagMap != NULL)
{
HX_VECTOR_DELETE(m_pRuleToFlagMap->rule_to_flag_map);
HX_DELETE(m_pRuleToFlagMap);
}
return HXR_OK;
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IHXRenderer::OnHeader
// Purpose:
// Called by client engine when a header for this renderer is
// available. The header will arrive before any packets.
//
STDMETHODIMP CRealAudioRenderer::OnHeader(IHXValues* pHeader)
{
IHXBuffer* pOpaqueData = NULL;
IHXBuffer* pRuleToFlagMapValue = NULL;
IHXUpgradeCollection* pUpgradeCollection = NULL;
BOOL bForceStartTrackTime = FALSE;
BOOL bForceEndTrackTime = FALSE;
UINT32 ulPreroll = 0;
UINT32 ulIsInterleaved = 0;
UINT32 ulBytesRead = 0;
UINT32 ulTrackStartTime = 0;
UINT32 ulTrackEndTime = 0;
UINT32 ulStreamNumber = 0;
HX_RESULT retVal = HXR_OK;
UINT32 ulBufferSize = 0;
UINT32 ulID = 0;
UINT16 i = 0;
BYTE* pCursor = NULL;
BYTE* pData = NULL;
BOOL bDecoderNotFound = FALSE;
char* pAllCodecs = NULL;
UINT32 ulSubStream = 0; // highest bitrate substream
UINT32 ulAllCodecBufLen = 0;
UINT16 usQuality = 4; // highest quality is my default.
#if defined(HELIX_FEATURE_PREFERENCES)
GetQualityPreference(usQuality);
#endif /* #if defined(HELIX_FEATURE_PREFERENCES) */
BOOL bMaxSampleRate = (usQuality >= 2); // most of the code uses this as the turn off point
UINT16 nFirstStreamToInit = 0; // init first first
UINT32 ulCurrentSampleRate = bMaxSampleRate ? 8000 : 44000; // lowest sample rate we ever want to have
UINT16 uCurrentNumChannels = 1;
INT32 lProtocolVersion = 0;
BOOL bIsPNM = FALSE;
IHXStreamSource* pSource = NULL;
ULONG32 numRulesToBlock = 0;
#if defined(HELIX_FEATURE_AUTOUPGRADE)
// check the stream versions
pHeader->AddRef();
retVal = CheckStreamVersions(pHeader);
pHeader->Release();
// if the stream versions didn't checkout, bail
if (retVal != HXR_OK)
{
goto cleanup;
}
#endif
if (SUCCEEDED(pHeader->GetPropertyULONG32("StreamNumber", ulStreamNumber)))
{
m_usThisSourceStream = (UINT16) ulStreamNumber;
}
pHeader->GetPropertyBuffer ("OpaqueData", pOpaqueData);
pHeader->GetPropertyULONG32("Preroll", ulPreroll);
// XXXgfw to fix a problem with the core not handling very small
// preroll values. This should be removed as the client audio
// services gets reworked to properly handle small preroll values.
if( ulPreroll < 500 )
{
ulPreroll = 500; //a typical value for 193kbps RA content.
pHeader->SetPropertyULONG32("Preroll", ulPreroll);
}
pHeader->GetPropertyULONG32("IsInterleaved", ulIsInterleaved);
pHeader->GetPropertyULONG32("Duration", m_ulDuration);
if (HXR_OK == pHeader->GetPropertyULONG32("TrackStartTime", ulTrackStartTime))
{
bForceStartTrackTime = TRUE;
}
pHeader->GetPropertyULONG32("Delay", m_ulDelay);
if (HXR_OK == pHeader->GetPropertyULONG32("TrackEndTime", ulTrackEndTime))
{
bForceEndTrackTime = TRUE;
}
if (HXR_OK ==
pHeader->GetPropertyBuffer(RULE_TO_FLAG_MAP_PROPERTY,
pRuleToFlagMapValue))
{
m_pRuleToFlagMap = new RuleToFlagMap;
if(!m_pRuleToFlagMap)
{
retVal = HXR_OUTOFMEMORY;
goto cleanup;
}
m_pRuleToFlagMap->unpack(pRuleToFlagMapValue->GetBuffer(),
pRuleToFlagMapValue->GetSize());
}
HX_RELEASE(pRuleToFlagMapValue);
m_ulPreroll = ulPreroll;
pData = pOpaqueData->GetBuffer();
pCursor = pData;
ulBufferSize = pOpaqueData->GetSize();
// format ID
memcpy((UCHAR*)&ulID, pCursor, sizeof(UINT32)); /* Flawfinder: ignore */
ulID = DwToHost(ulID);
if (RM_MULTIHEADER_OBJECT == ulID)
{
MultiStreamHeader multiStreamHeader;
pCursor = multiStreamHeader.unpack(pData, ulBufferSize);
ulBufferSize -= (pCursor - pData);
m_bStreamSwitchable = TRUE;
m_uNumOfSubStreams = multiStreamHeader.num_headers;
// # of rules
m_uNumOfRules = multiStreamHeader.num_rules;
m_pRuleMap = new UINT16[m_uNumOfRules];
if(!m_pRuleMap)
{
retVal = HXR_OUTOFMEMORY;
goto cleanup;
}
// retrieve the rule map
for (i = 0; i < m_uNumOfRules; i++)
{
m_pRuleMap[i] = multiStreamHeader.rule_to_header_map[i];
}
// must delete the rule map since PMC doesn't generate distructors
HX_VECTOR_DELETE(multiStreamHeader.rule_to_header_map);
}
else if (RA_FORMAT_ID == ulID)
{
m_uNumOfSubStreams = 1;
}
else
{
retVal = HXR_FAILED;
goto cleanup;
}
// allocate all of our per stream structures and initialize them
m_pRaFormats = new CRaFormat*[m_uNumOfSubStreams];
if(!m_pRaFormats)
{
retVal = HXR_OUTOFMEMORY;
goto cleanup;
}
::memset(m_pRaFormats, 0, sizeof(CRaFormat*) * m_uNumOfSubStreams);
m_pAudioStreams = new IHXAudioStream*[m_uNumOfSubStreams];
if(!m_pAudioStreams)
{
retVal = HXR_OUTOFMEMORY;
goto cleanup;
}
::memset(m_pAudioStreams, 0, sizeof(IHXAudioStream*) * m_uNumOfSubStreams);
#if defined(HELIX_FEATURE_AUDIO_CODEC_RAAC)
m_ppVBRDepack = new CVBRSimpleDepacketizer* [m_uNumOfSubStreams];
if(!m_ppVBRDepack)
{
retVal = HXR_OUTOFMEMORY;
goto cleanup;
}
::memset(m_ppVBRDepack, 0, sizeof(CVBRSimpleDepacketizer*) * m_uNumOfSubStreams);
#endif /* #if defined(HELIX_FEATURE_AUDIO_CODEC_RAAC) */
#if defined(HELIX_FEATURE_STATS)
if (m_pRegistry)
{
// Check the stats to get the protocol and protocol version
// so we can special case 3.0 and earlier servers that send
// timestamps in tenths of a second
if (HXR_OK == m_pStream->GetSource(pSource))
{
IHXRegistryID* pSourceIRegID = NULL;
if (HXR_OK == pSource->QueryInterface(IID_IHXRegistryID,
(void**)&pSourceIRegID))
{
UINT32 ulRegistryID;
if (HXR_OK == pSourceIRegID->GetID(ulRegistryID))
{
char szRegistryEntry[MAX_DISPLAY_NAME] = {0}; /* Flawfinder: ignore */
IHXBuffer* pszRegistryName = NULL;
// Get the current registry key name
if (HXR_OK == m_pRegistry->GetPropName(ulRegistryID,
pszRegistryName))
{
SafeSprintf(szRegistryEntry, MAX_DISPLAY_NAME, "%s.ProtocolVersion",
pszRegistryName->GetBuffer());
m_pRegistry->GetIntByName(szRegistryEntry,
lProtocolVersion);
IHXBuffer* pProtocolString = NULL;
SafeSprintf(szRegistryEntry, MAX_DISPLAY_NAME, "%s.Protocol",
pszRegistryName->GetBuffer());
if (HXR_OK ==
m_pRegistry->GetStrByName(szRegistryEntry,
pProtocolString) && pProtocolString != NULL)
{
bIsPNM = ( 0 == strcasecmp("PNM",
(const char*)pProtocolString->GetBuffer()));
}
HX_RELEASE(pProtocolString);
}
HX_RELEASE(pszRegistryName);
}
HX_RELEASE(pSourceIRegID);
}
HX_RELEASE(pSource);
}
}
#endif // HELIX_FEATURE_STATS
// create codecs buffer
#if defined(HELIX_FEATURE_STATS)
ulAllCodecBufLen = (m_uNumOfSubStreams * 6) + 1;
pAllCodecs = new char[ulAllCodecBufLen];
if(!pAllCodecs)
{
retVal = HXR_OUTOFMEMORY;
goto cleanup;
}
*pAllCodecs = '\0';
#endif /* #if defined(HELIX_FEATURE_STATS) */
// instantiate the RA format/audio stream objects for
// each sub-stream
for (i = 0;
(retVal == HXR_OK) && (i < m_uNumOfSubStreams);
i++)
{
m_pRaFormats[i] = CreateRaFormat(i);
// initialize the Format for this header
m_pRaFormats[i]->ForceInterleaved(ulIsInterleaved);
m_pRaFormats[i]->SetProtocolInfo(bIsPNM, lProtocolVersion);
#if defined(HELIX_FEATURE_AUDIO_CODEC_RAAC)
// Determine which ASM rule specifies a keyframe for this substream
UINT16 usKeyFrameRuleNum = 0;
for (UINT16 q = 0; q < m_pRuleToFlagMap->num_rules; q++)
{
BOOL bRuleForThisSubStream = TRUE;
if (m_bStreamSwitchable && m_pRuleMap && m_pRuleMap[q] != i)
{
bRuleForThisSubStream = FALSE;
}
if (bRuleForThisSubStream &&
m_pRuleToFlagMap->rule_to_flag_map[q] & HX_KEYFRAME_FLAG)
{
// This is the keyframe rule for this substream
usKeyFrameRuleNum = q;
break;
}
}
#endif /* #if defined(HELIX_FEATURE_AUDIO_CODEC_RAAC) */
UINT32 ulReadRAHeaderSize = ulBufferSize;
if (m_bStreamSwitchable)
{
// adjust the header size so we only read this header
ulReadRAHeaderSize = getlong(pCursor);
pCursor += sizeof(UINT32);
ulBufferSize -= sizeof(UINT32);
}
retVal = m_pRaFormats[i]->NewReadRAHeader(pCursor, ulReadRAHeaderSize,
bForceStartTrackTime, bForceEndTrackTime, ulTrackStartTime,
ulTrackEndTime, &ulBytesRead, pAllCodecs, ulAllCodecBufLen);
if (HXR_OK == retVal)
{
#if defined(HELIX_FEATURE_AUDIO_CODEC_RAAC)
// Check if this substream is RAAC and VBRS
char* pInterID = m_pRaFormats[i]->GetInterleaverName();
if (pInterID &&
(!strcmp((const char*) pInterID, RA_INTERLEAVER_VBRS_ID) ||
!strcmp((const char*) pInterID, RA_INTERLEAVER_VBRF_ID)))
{
// Create a VBR depacketizer for this sub-stream
HX_DELETE(m_ppVBRDepack[i]);
m_ppVBRDepack[i] = new CVBRSimpleDepacketizer();
if (m_ppVBRDepack[i])
{
// Init the depacketizer
retVal = m_ppVBRDepack[i]->Init(m_pContext,
m_pRaFormats[i]->GetMSPerBlock(),
m_usThisSourceStream,
usKeyFrameRuleNum,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -