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

  1. #include "precomp.h"
  2. #define MAGIC_CPU_DO_NOT_EXCEED_PERCENTAGE 50 //Don't use more than this % of the CPU for encoding (also in audiocpl.cpp)
  3. /***************************************************************************
  4. Name : GetQOSCPULimit
  5. Purpose : Gets the total allowed CPU percentage use from QoS
  6. Parameters: None
  7. Returns : How much of the CPU can be used, in percents. 0 means failure
  8. Comment :
  9. ***************************************************************************/
  10. ULONG GetQOSCPULimit(void)
  11. {
  12. #define MSECS_PER_SEC 900
  13. IQoS *pQoS=NULL;
  14. LPRESOURCELIST pResourceList=NULL;
  15. ULONG ulCPUPercents=0;
  16. ULONG i;
  17. HRESULT hr=NOERROR;
  18. // create the QoS object and get the IQoS interface
  19. // CoInitialize is called in conf.cpp
  20. hr = CoCreateInstance( CLSID_QoS,
  21. NULL,
  22. CLSCTX_INPROC_SERVER,
  23. IID_IQoS,
  24. (void **) &pQoS);
  25. if (FAILED(hr) || !pQoS)
  26. {
  27. // this means that QoS was not instantiated yet. Use predefined value
  28. // ASSERT, because I want to know if this happens
  29. ASSERT(pQoS);
  30. ulCPUPercents = MSECS_PER_SEC;
  31. goto out;
  32. }
  33. // get a list of all resources from QoS
  34. hr = pQoS->GetResources(&pResourceList);
  35. if (FAILED(hr) || !pResourceList)
  36. {
  37. ERROR_OUT(("GetQoSCPULimit: GetReosurces failed"));
  38. goto out;
  39. }
  40. // find the CPU resource
  41. for (i=0; i < pResourceList->cResources; i++)
  42. {
  43. if (pResourceList->aResources[i].resourceID == RESOURCE_CPU_CYCLES)
  44. {
  45. // QoS keps the CPU units as the number of ms in a sec that the
  46. // CPU can be used. Need to divide by 10 to get percents
  47. ulCPUPercents = pResourceList->aResources[i].nUnits / 10;
  48. break;
  49. }
  50. }
  51. out:
  52. if (pResourceList)
  53. pQoS->FreeBuffer(pResourceList);
  54. if (pQoS)
  55. pQoS->Release();
  56. return ulCPUPercents;
  57. }
  58. HRESULT CapsCtl::ComputeCapabilitySets (DWORD dwBitsPerSec)
  59. {
  60. HRESULT hr = hrSuccess;
  61. UINT nAud = 0;
  62. UINT nAudCaps = 0;
  63. UINT nVid = 0;
  64. UINT nVidCaps = 0;
  65. UINT x, y, nSets = 0;
  66. BASIC_AUDCAP_INFO *pac = NULL;
  67. BASIC_VIDCAP_INFO *pvc = NULL;
  68. MEDIA_FORMAT_ID *AdvList = NULL;
  69. int CPULimit;
  70. LPAPPCAPPIF pAudIF = NULL;
  71. LPAPPVIDCAPPIF pVidIF = NULL;
  72. if (pAudCaps)
  73. {
  74. hr = pAudCaps->QueryInterface(IID_IAppAudioCap, (void **)&pAudIF);
  75. if(!HR_SUCCEEDED(hr))
  76. {
  77. goto ComputeDone;
  78. }
  79. }
  80. if (pVidCaps)
  81. {
  82. hr = pVidCaps->QueryInterface(IID_IAppVidCap, (void **)&pVidIF);
  83. if(!HR_SUCCEEDED(hr))
  84. {
  85. goto ComputeDone;
  86. }
  87. }
  88. //Save away the Bandwidth
  89. dwConSpeed=dwBitsPerSec;
  90. // Create the default PTERMCAPDESCRIPTORS set
  91. // Get the number of BASIC_VIDCAP_INFO and BASIC_AUDCAP_INFO structures
  92. // available
  93. if (pVidIF)
  94. pVidIF->GetNumFormats(&nVidCaps);
  95. if (pAudIF)
  96. pAudIF->GetNumFormats(&nAudCaps);
  97. if (nAudCaps)
  98. {
  99. // Allocate some memory to hold the list in
  100. if (pac = (BASIC_AUDCAP_INFO*)MemAlloc(sizeof(BASIC_AUDCAP_INFO) * nAudCaps))
  101. {
  102. // Get the list
  103. if ((hr = pAudIF->EnumFormats(pac, nAudCaps * sizeof (BASIC_AUDCAP_INFO), (UINT*)&nAudCaps)) != hrSuccess)
  104. goto ComputeDone;
  105. }
  106. else
  107. {
  108. hr = CAPS_E_SYSTEM_ERROR;
  109. goto ComputeDone;
  110. }
  111. }
  112. if (nVidCaps)
  113. {
  114. // Allocate some memory to hold the video list in
  115. if (pvc = (BASIC_VIDCAP_INFO*) MemAlloc(sizeof(BASIC_VIDCAP_INFO) * nVidCaps))
  116. {
  117. // Get the list
  118. if ((hr = pVidIF->EnumFormats(pvc, nVidCaps * sizeof (BASIC_VIDCAP_INFO), (UINT*)&nVidCaps)) != hrSuccess)
  119. goto ComputeDone;
  120. }
  121. else
  122. {
  123. hr = CAPS_E_SYSTEM_ERROR;
  124. goto ComputeDone;
  125. }
  126. }
  127. //Allocate memory for the defined list of Codecs, so we can track them
  128. if (nAudCaps)
  129. {
  130. AdvList = (MEDIA_FORMAT_ID*) MemAlloc(sizeof(MEDIA_FORMAT_ID) * nAudCaps);
  131. if (!AdvList)
  132. {
  133. hr = CAPS_E_SYSTEM_ERROR;
  134. goto ComputeDone;
  135. }
  136. }
  137. if (pAdvertisedSets && pAdvertisedSets->wLength)
  138. {
  139. ResetCombinedEntries();
  140. }
  141. // We're about to write over pSetIDs, make sure it's freed.
  142. if (pSetIDs)
  143. {
  144. MemFree(pSetIDs);
  145. pSetIDs = NULL;
  146. }
  147. //Allocate nVidCaps+1 Set Ids
  148. ASSERT(!pSetIDs);
  149. pSetIDs = (DWORD*) MemAlloc(sizeof(DWORD) * (nVidCaps + 1));
  150. if (!pSetIDs)
  151. {
  152. hr = CAPS_E_SYSTEM_ERROR;
  153. goto ComputeDone;
  154. }
  155. //
  156. // If we can get a % limit from the QOS, then use that as the upper bound of
  157. // CPU consumption for a Codec. If it exceeds this bound, do not enable it.
  158. //
  159. CPULimit= (int) GetQOSCPULimit();
  160. if (CPULimit == 0)
  161. CPULimit = MAGIC_CPU_DO_NOT_EXCEED_PERCENTAGE;
  162. //
  163. // Now, sort that list, according to preference
  164. // This function adds the sets to the advertised list. It sorts audio
  165. // by each video codec.
  166. //
  167. for (x=0; ((x<nVidCaps) && (nVid < H245_MAX_ALTCAPS));x++)
  168. {
  169. //Check to make sure the video codec can be advertised.
  170. if ((pvc[x].wCPUUtilizationDecode < CPULimit)
  171. && pvc[x].bRecvEnabled
  172. && pVidCaps->IsFormatPublic(pvc[x].Id))
  173. {
  174. nVid++;
  175. // Loop through the Audio codecs, checking to see if they can
  176. // fit alongside the video codec
  177. // BUGBUG - we only check the total BW and CPU because we rely on
  178. // QOS to scale back the video in favor of audio. in other words,
  179. // video can be scaled down to zero BW and CPU.
  180. for (y=0;((y<nAudCaps) && (nAud < H245_MAX_ALTCAPS)) ;y++)
  181. {
  182. if ((pac[y].wCPUUtilizationDecode < CPULimit) &&
  183. ((pac[y].uAvgBitrate <= dwBitsPerSec && pac[y].bRecvEnabled)
  184. && pAudCaps->IsFormatPublic(pac[y].Id)))
  185. {
  186. // going to advertise this ID in this
  187. AdvList[nAud++]=pac[y].Id;
  188. }
  189. }
  190. //Advertise this set, if we can do audio and video
  191. if (nAud)
  192. {
  193. hr = AddCombinedEntry (AdvList,nAud,&pvc[x].Id,1,&pSetIDs[nSets++]);
  194. if(!HR_SUCCEEDED(hr))
  195. {
  196. goto ComputeDone;
  197. }
  198. }
  199. nAud = 0;
  200. }
  201. }
  202. //#if(0)
  203. // Advertising only one media type in a simcaps set is redundant.
  204. //Now, do the no-video case. If we couldn't advertise above.-- Which implies, in this iteration
  205. // A problem with all the video codecs. We don't do any "combined" compares, so we know
  206. // it's a video problem (if it's audio, well we won't have anything to advertise anyways)
  207. if (!nSets)
  208. {
  209. for (y=0;y<nAudCaps;y++)
  210. {
  211. if ((pac[y].wCPUUtilizationDecode < CPULimit) &&
  212. ((pac[y].uAvgBitrate <= dwBitsPerSec && pac[y].bRecvEnabled)
  213. && pAudCaps->IsFormatPublic(pac[y].Id)))
  214. {
  215. //Advertise this ID
  216. AdvList[nAud++]=pac[y].Id;
  217. }
  218. }
  219. //Advertise this set, if we can do any audio codecs alone
  220. if (nAud)
  221. {
  222. //Since the set is 0 based the nVidCaps+1th entry is nVidcaps...
  223. hr=AddCombinedEntry (AdvList,nAud,NULL,0,&pSetIDs[nSets++]);
  224. if(!HR_SUCCEEDED(hr))
  225. {
  226. goto ComputeDone;
  227. }
  228. }
  229. }
  230. //#endif // if(0)
  231. ComputeDone:
  232. if (pVidIF)
  233. {
  234. pVidIF->Release();
  235. }
  236. if (pAudIF)
  237. {
  238. pAudIF->Release();
  239. }
  240. if (AdvList)
  241. {
  242. MemFree(AdvList);
  243. }
  244. if (pvc)
  245. {
  246. MemFree(pvc);
  247. }
  248. if (pac)
  249. {
  250. MemFree(pac);
  251. }
  252. return(hr);
  253. }