📄 fbbufctl.cpp
字号:
HX_RELEASE(m_pPrefs); HX_RELEASE(m_pStatus); ChangeState(csNotInitialized); return HXR_OK;}/************************************************************************ * Method: * IHXCallback::Func * Purpose: * This is the function that will be called when a callback is * to be executed. */STDMETHODIMP HXFeedbackBufferControl::Func(THIS){ DEBUG_OUT(m_pErrMsg, DOL_BUFFER_CONTROL, (s, "FBBC::Func")); if (Initialized()) { UINT32 ulNewBandwidth = 0; if (csPlaying == m_state) { UINT32 ulTotalBits = 0; UINT32 ulControlBits = 0; UINT32 ulNewBandwidth = 0; GetControlData(ulTotalBits, ulControlBits); if (HXR_OK == Control(ulControlBits, ulNewBandwidth)) { SetBandwidth(ulNewBandwidth); } } else if (csBuffering == m_state) { // Bandwidth used during buffering and seeking SetBandwidth(m_ulClipBw); } ScheduleCallback(); } return HXR_OK;}void HXFeedbackBufferControl::ChangeState(ControlState newState){ if (csError != m_state) { DEBUG_OUT(m_pErrMsg, DOL_BUFFER_CONTROL, (s, "FBBC::CS : %lu %d -> %d", HX_GET_TICKCOUNT(), m_state, newState)); m_state = newState; } else { DEBUG_OUT(m_pErrMsg, DOL_BUFFER_CONTROL, (s, "FBBC::CS : Tried to leave error state")); HX_ASSERT(csError == m_state); }}void HXFeedbackBufferControl::ScheduleCallback(){ if (m_pScheduler) { UINT32 uDelayInMs = (UINT32)(m_control.SamplePeriod() * 1000); m_lastTime.tv_sec += uDelayInMs / 1000; m_lastTime.tv_usec += (uDelayInMs * 1000) * 1000; m_callbackHandle = m_pScheduler->AbsoluteEnter(this, m_lastTime); }}void HXFeedbackBufferControl::StartCallback(){ if (m_pScheduler) { m_lastTime = m_pScheduler->GetCurrentSchedulerTime(); ScheduleCallback(); }}void HXFeedbackBufferControl::StopCallback(){ if (m_pScheduler && m_callbackHandle) { m_pScheduler->Remove(m_callbackHandle); m_callbackHandle = 0; }}HX_RESULT HXFeedbackBufferControl::GetBwInfo(REF(UINT32) ulClipBw, REF(UINT16) nControlStream, REF(UINT32) ulControlBw){ HX_RESULT res = HXR_OK; if (!m_pSource) { res = HXR_FAILED; } else if (m_pSource->GetStreamCount() == 0) { res = HXR_NO_DATA; } else { ulClipBw = 0; nControlStream = 0; ulControlBw = 0; UINT32 ulHighestBw = 0; UINT16 nHighestBwStream = 0; BOOL bFoundAudio = FALSE; UINT32 ulLowAudioBw = 0; UINT16 nLowestBwAudioStream = 0; for (UINT16 i = 0; (HXR_OK == res) && (i < m_pSource->GetStreamCount()); i++) { UINT32 ulStreamBw = 0; if (HXR_OK == GetStreamBw(i, ulStreamBw)) { if (ulStreamBw > ulHighestBw) { ulHighestBw = ulStreamBw; nHighestBwStream = i; } if (IsAudioStream(i) && (!bFoundAudio || (ulStreamBw < ulLowAudioBw))) { bFoundAudio = TRUE; ulLowAudioBw = ulStreamBw; nLowestBwAudioStream = i; } ulClipBw += ulStreamBw; } } if (bFoundAudio) { nControlStream = nLowestBwAudioStream; ulControlBw = ulLowAudioBw; } else { nControlStream = nHighestBwStream; ulControlBw = ulHighestBw; } } return res;}HX_RESULT HXFeedbackBufferControl::GetStreamBw(UINT16 uStreamNumber, REF(UINT32) ulBandwidth){ HX_RESULT res = HXR_FAILED; if (m_pSource) { IUnknown* pUnk = NULL; res = m_pSource->GetStream(uStreamNumber, pUnk); if (HXR_OK == res) { IHXASMProps* pProps = NULL; res = pUnk->QueryInterface(IID_IHXASMProps, (void**)&pProps); if (HXR_OK == res) { res = pProps->GetBandwidth(ulBandwidth); pProps->Release(); } pUnk->Release(); } } return res;}BOOL HXFeedbackBufferControl::IsAudioStream(UINT16 uStreamNumber){ BOOL bRet = FALSE; if (m_pSource) { IUnknown* pUnk = NULL; IHXStream* pStream = NULL; IHXValues* pHeader = NULL; IHXBuffer* pMimetype = NULL; if ((HXR_OK == m_pSource->GetStream(uStreamNumber, pUnk)) && (HXR_OK == pUnk->QueryInterface(IID_IHXStream, (void**)&pStream))&& (NULL != (pHeader = pStream->GetHeader())) && (HXR_OK == pHeader->GetPropertyCString("MimeType", pMimetype)) && (!strncasecmp("audio", (char*)pMimetype->GetBuffer(), 5))) { bRet = TRUE; } HX_RELEASE(pMimetype); HX_RELEASE(pHeader); HX_RELEASE(pStream); HX_RELEASE(pUnk); } return bRet;}void HXFeedbackBufferControl::GetControlData(REF(UINT32) ulTotalBits, REF(UINT32) ulControlBits){ ulTotalBits = 0; ulControlBits = 0; for (UINT16 i = 0; i < m_pSource->GetStreamCount(); i++) { UINT32 ulBytes; HX_RESULT res = HXR_FAILED; INT64 llLowTS; INT64 llHighTS; BOOL bDone; res = m_pBufferStats->GetTotalBuffering(i, llLowTS, llHighTS, ulBytes, bDone); if (HXR_OK == res) { ulTotalBits += 8 * ulBytes; if (i == m_nControlStream) { ulControlBits = 8 * ulBytes; } } }}HX_RESULT HXFeedbackBufferControl::Control(UINT32 ulControlBits, REF(UINT32) ulNewBandwidth){ UINT32 ulSetPoint = m_control.SetPoint(); INT32 error = (INT32)ulSetPoint - (INT32)ulControlBits; double errorFactor = error; ulNewBandwidth = m_control.Control(ulControlBits); ulNewBandwidth = ControlToTotal(ulNewBandwidth); if (ulSetPoint) { errorFactor = (double)error / (double)ulSetPoint; } DEBUG_OUT(m_pErrMsg, DOL_BUFFER_CONTROL, (s, "FBBC::CTL %lu %d %lu %lu %2.4f", HX_GET_TICKCOUNT(), error, ulNewBandwidth, ulControlBits, errorFactor)); return HXR_OK;}void HXFeedbackBufferControl::SetBandwidth(UINT32 ulBandwidth){ DEBUG_OUT(m_pErrMsg, DOL_BUFFER_CONTROL, (s, "FBBC::SB %lu %lu ", HX_GET_TICKCOUNT(), ulBandwidth)); if (m_pThin) { m_pThin->SetDeliveryBandwidth(ulBandwidth, 0); }}HX_RESULT HXFeedbackBufferControl::ReadPrefSettings(){ HX_RESULT res = HXR_FAILED; UINT32 ulMin = 1000; UINT32 ulMax = 0; ReadPrefINT32(m_pPrefs, "MinDelBandwidth", ulMin); /* Get initial bandwidth guess from Prefs */ if (HXR_OK == ReadPrefINT32(m_pPrefs, "Bandwidth", ulMax)) { UINT32 ulSustainFactor = 0; /* See if we have a sustainable bandwidth factor */ if (HXR_OK == ReadPrefINT32(m_pPrefs, "SustainableBwFactor", ulSustainFactor)) { /* clamp value to 0 <= ulTemp <= 100 range */ if (ulSustainFactor > 100) { ulSustainFactor = 100; } /* Apply factor */ ulMax = (((ulMax / 100) * ulSustainFactor) + (((ulMax % 100) * ulSustainFactor) / 100)); } if (ulMax > 0) { if (ulMin > ulMax) { // Make the minimum bandwidh 1% of the max // rounded up to the next bit/second ulMin = (ulMax + 99) / 100; } m_control.SetLimits(ulMin, ulMax); res = HXR_OK; } } return res;}void HXFeedbackBufferControl::SetTransportByteLimits(UINT32 ulClipBw){ UINT32 ulTotalByteLimit = 0; IHXTransportBufferLimit* pBufLimit = NULL; ReadPrefINT32(m_pPrefs, "TransportByteLimit", ulTotalByteLimit); if (m_pSource && (HXR_OK == m_pSource->QueryInterface(IID_IHXTransportBufferLimit, (void**)&pBufLimit))) { // Divide the byte limit amoung the streams for (UINT16 i = 0; i < m_pSource->GetStreamCount(); i++) { UINT32 ulStreamBw = 0; if (HXR_OK == GetStreamBw(i, ulStreamBw)) { // Byte limit for this stream is // (ulTotalByteLimit * ulStreamBw) / ulClipBw UINT32 ulByteLimit = MulDiv(ulTotalByteLimit, ulStreamBw, ulClipBw); if ((ulByteLimit == 0) && (ulTotalByteLimit != 0)) { // Make sure all streams have a byte limit // if ulTotalByteLimit is non-zero. This is done // because a byte limit of 0 means unlimited // buffering is allowed ulByteLimit = 1; } pBufLimit->SetByteLimit(i, ulByteLimit); } } } HX_RELEASE(pBufLimit);}HX_RESULT HXFeedbackBufferControl::InitTesting(IUnknown* pContext){ HX_RESULT res = HXR_OK; IHXRequest* pRequest = NULL; const char* pURL = 0; if (HXR_OK == pContext->QueryInterface(IID_IHXRequest, (void**)&pRequest) && HXR_OK == pRequest->GetURL(pURL)) { CHXURL url(pURL, pContext); DEBUG_OUT(m_pErrMsg, DOL_BUFFER_CONTROL, (s, "FBBC : url %s", pURL)); IHXValues* pOptions = url.GetOptions(); ULONG32 ulTmp; if (pOptions) { if (HXR_OK == pOptions->GetPropertyULONG32("FBBC-total_control", ulTmp)) { DEBUG_OUT(m_pErrMsg, DOL_BUFFER_CONTROL, (s, "FBBC : total control %lu", ulTmp)); m_bControlTotal = (ulTmp > 0) ? TRUE : FALSE; } } HX_RELEASE(pOptions); HX_RELEASE(pRequest); } return res;}BOOL HXFeedbackBufferControl::IsBuffering(){ BOOL bRet = FALSE; IHXBuffer* pStatusDesc = NULL; UINT16 unStatusCode = 0; UINT16 unPercentDone = 0; if (m_pStatus && (HXR_OK == m_pStatus->GetStatus(unStatusCode, pStatusDesc, unPercentDone)) && (unStatusCode == HX_STATUS_BUFFERING)) { bRet = TRUE; } HX_RELEASE(pStatusDesc); return bRet;}UINT32 HXFeedbackBufferControl::ClampBandwidth(UINT32 ulBandwidth) const{ UINT32 ulRet = ulBandwidth; if (ulRet < m_control.Min()) { ulRet = m_control.Min(); } else if (ulRet > m_control.Max()) { ulRet = m_control.Max(); } return ulRet;}UINT32 HXFeedbackBufferControl::ControlToTotal(UINT32 ulValue){ return MulDiv(ulValue, m_ulClipBw, m_ulControlBw);}UINT32 HXFeedbackBufferControl::TotalToControl(UINT32 ulValue){ return MulDiv(ulValue, m_ulControlBw, m_ulClipBw);}UINT32 HXFeedbackBufferControl::MulDiv(UINT32 ulValue, UINT32 ulMult, UINT32 ulDiv){ return (((ulValue / ulDiv) * ulMult) + ((ulValue % ulDiv) * ulMult) / ulDiv);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -