Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

297 lines
7.5 KiB

#include "precomp.h"
#define MAGIC_CPU_DO_NOT_EXCEED_PERCENTAGE 50 //Don't use more than this % of the CPU for encoding (also in audiocpl.cpp)
/***************************************************************************
Name : GetQOSCPULimit
Purpose : Gets the total allowed CPU percentage use from QoS
Parameters: None
Returns : How much of the CPU can be used, in percents. 0 means failure
Comment :
***************************************************************************/
ULONG GetQOSCPULimit(void)
{
#define MSECS_PER_SEC 900
IQoS *pQoS=NULL;
LPRESOURCELIST pResourceList=NULL;
ULONG ulCPUPercents=0;
ULONG i;
HRESULT hr=NOERROR;
// create the QoS object and get the IQoS interface
// CoInitialize is called in conf.cpp
hr = CoCreateInstance( CLSID_QoS,
NULL,
CLSCTX_INPROC_SERVER,
IID_IQoS,
(void **) &pQoS);
if (FAILED(hr) || !pQoS)
{
// this means that QoS was not instantiated yet. Use predefined value
// ASSERT, because I want to know if this happens
ASSERT(pQoS);
ulCPUPercents = MSECS_PER_SEC;
goto out;
}
// get a list of all resources from QoS
hr = pQoS->GetResources(&pResourceList);
if (FAILED(hr) || !pResourceList)
{
ERROR_OUT(("GetQoSCPULimit: GetReosurces failed"));
goto out;
}
// find the CPU resource
for (i=0; i < pResourceList->cResources; i++)
{
if (pResourceList->aResources[i].resourceID == RESOURCE_CPU_CYCLES)
{
// QoS keps the CPU units as the number of ms in a sec that the
// CPU can be used. Need to divide by 10 to get percents
ulCPUPercents = pResourceList->aResources[i].nUnits / 10;
break;
}
}
out:
if (pResourceList)
pQoS->FreeBuffer(pResourceList);
if (pQoS)
pQoS->Release();
return ulCPUPercents;
}
HRESULT CapsCtl::ComputeCapabilitySets (DWORD dwBitsPerSec)
{
HRESULT hr = hrSuccess;
UINT nAud = 0;
UINT nAudCaps = 0;
UINT nVid = 0;
UINT nVidCaps = 0;
UINT x, y, nSets = 0;
BASIC_AUDCAP_INFO *pac = NULL;
BASIC_VIDCAP_INFO *pvc = NULL;
MEDIA_FORMAT_ID *AdvList = NULL;
int CPULimit;
LPAPPCAPPIF pAudIF = NULL;
LPAPPVIDCAPPIF pVidIF = NULL;
if (pAudCaps)
{
hr = pAudCaps->QueryInterface(IID_IAppAudioCap, (void **)&pAudIF);
if(!HR_SUCCEEDED(hr))
{
goto ComputeDone;
}
}
if (pVidCaps)
{
hr = pVidCaps->QueryInterface(IID_IAppVidCap, (void **)&pVidIF);
if(!HR_SUCCEEDED(hr))
{
goto ComputeDone;
}
}
//Save away the Bandwidth
dwConSpeed=dwBitsPerSec;
// Create the default PTERMCAPDESCRIPTORS set
// Get the number of BASIC_VIDCAP_INFO and BASIC_AUDCAP_INFO structures
// available
if (pVidIF)
pVidIF->GetNumFormats(&nVidCaps);
if (pAudIF)
pAudIF->GetNumFormats(&nAudCaps);
if (nAudCaps)
{
// Allocate some memory to hold the list in
if (pac = (BASIC_AUDCAP_INFO*)MemAlloc(sizeof(BASIC_AUDCAP_INFO) * nAudCaps))
{
// Get the list
if ((hr = pAudIF->EnumFormats(pac, nAudCaps * sizeof (BASIC_AUDCAP_INFO), (UINT*)&nAudCaps)) != hrSuccess)
goto ComputeDone;
}
else
{
hr = CAPS_E_SYSTEM_ERROR;
goto ComputeDone;
}
}
if (nVidCaps)
{
// Allocate some memory to hold the video list in
if (pvc = (BASIC_VIDCAP_INFO*) MemAlloc(sizeof(BASIC_VIDCAP_INFO) * nVidCaps))
{
// Get the list
if ((hr = pVidIF->EnumFormats(pvc, nVidCaps * sizeof (BASIC_VIDCAP_INFO), (UINT*)&nVidCaps)) != hrSuccess)
goto ComputeDone;
}
else
{
hr = CAPS_E_SYSTEM_ERROR;
goto ComputeDone;
}
}
//Allocate memory for the defined list of Codecs, so we can track them
if (nAudCaps)
{
AdvList = (MEDIA_FORMAT_ID*) MemAlloc(sizeof(MEDIA_FORMAT_ID) * nAudCaps);
if (!AdvList)
{
hr = CAPS_E_SYSTEM_ERROR;
goto ComputeDone;
}
}
if (pAdvertisedSets && pAdvertisedSets->wLength)
{
ResetCombinedEntries();
}
// We're about to write over pSetIDs, make sure it's freed.
if (pSetIDs)
{
MemFree(pSetIDs);
pSetIDs = NULL;
}
//Allocate nVidCaps+1 Set Ids
ASSERT(!pSetIDs);
pSetIDs = (DWORD*) MemAlloc(sizeof(DWORD) * (nVidCaps + 1));
if (!pSetIDs)
{
hr = CAPS_E_SYSTEM_ERROR;
goto ComputeDone;
}
//
// If we can get a % limit from the QOS, then use that as the upper bound of
// CPU consumption for a Codec. If it exceeds this bound, do not enable it.
//
CPULimit= (int) GetQOSCPULimit();
if (CPULimit == 0)
CPULimit = MAGIC_CPU_DO_NOT_EXCEED_PERCENTAGE;
//
// Now, sort that list, according to preference
// This function adds the sets to the advertised list. It sorts audio
// by each video codec.
//
for (x=0; ((x<nVidCaps) && (nVid < H245_MAX_ALTCAPS));x++)
{
//Check to make sure the video codec can be advertised.
if ((pvc[x].wCPUUtilizationDecode < CPULimit)
&& pvc[x].bRecvEnabled
&& pVidCaps->IsFormatPublic(pvc[x].Id))
{
nVid++;
// Loop through the Audio codecs, checking to see if they can
// fit alongside the video codec
// BUGBUG - we only check the total BW and CPU because we rely on
// QOS to scale back the video in favor of audio. in other words,
// video can be scaled down to zero BW and CPU.
for (y=0;((y<nAudCaps) && (nAud < H245_MAX_ALTCAPS)) ;y++)
{
if ((pac[y].wCPUUtilizationDecode < CPULimit) &&
((pac[y].uAvgBitrate <= dwBitsPerSec && pac[y].bRecvEnabled)
&& pAudCaps->IsFormatPublic(pac[y].Id)))
{
// going to advertise this ID in this
AdvList[nAud++]=pac[y].Id;
}
}
//Advertise this set, if we can do audio and video
if (nAud)
{
hr = AddCombinedEntry (AdvList,nAud,&pvc[x].Id,1,&pSetIDs[nSets++]);
if(!HR_SUCCEEDED(hr))
{
goto ComputeDone;
}
}
nAud = 0;
}
}
//#if(0)
// Advertising only one media type in a simcaps set is redundant.
//Now, do the no-video case. If we couldn't advertise above.-- Which implies, in this iteration
// A problem with all the video codecs. We don't do any "combined" compares, so we know
// it's a video problem (if it's audio, well we won't have anything to advertise anyways)
if (!nSets)
{
for (y=0;y<nAudCaps;y++)
{
if ((pac[y].wCPUUtilizationDecode < CPULimit) &&
((pac[y].uAvgBitrate <= dwBitsPerSec && pac[y].bRecvEnabled)
&& pAudCaps->IsFormatPublic(pac[y].Id)))
{
//Advertise this ID
AdvList[nAud++]=pac[y].Id;
}
}
//Advertise this set, if we can do any audio codecs alone
if (nAud)
{
//Since the set is 0 based the nVidCaps+1th entry is nVidcaps...
hr=AddCombinedEntry (AdvList,nAud,NULL,0,&pSetIDs[nSets++]);
if(!HR_SUCCEEDED(hr))
{
goto ComputeDone;
}
}
}
//#endif // if(0)
ComputeDone:
if (pVidIF)
{
pVidIF->Release();
}
if (pAudIF)
{
pAudIF->Release();
}
if (AdvList)
{
MemFree(AdvList);
}
if (pvc)
{
MemFree(pvc);
}
if (pac)
{
MemFree(pac);
}
return(hr);
}