Leaked source code of windows server 2003
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.

1315 lines
42 KiB

  1. /*
  2. * File: h323caps.cpp
  3. *
  4. * H.323/H.245 specific implementation of Microsoft A/V capability
  5. * interface methods. (Contained in CMsiaCapability class)
  6. *
  7. * Revision History:
  8. *
  9. * 09/10/96 mikev created
  10. * 10/08/96 mikeg - created h323vidc.cpp
  11. * 11/04/96 mikev - cleanup and merge audio and video capability classes (remove
  12. * common inheritance of IH323PubCap, both audio and video implementation
  13. * classes inherit from IH323MediaCap. )
  14. */
  15. #include "precomp.h"
  16. #define SAMPLE_BASED_SAMPLES_PER_FRAME 8
  17. #define MAX_FRAME_LEN 480 //bytes - where did this value come from?
  18. #define MAX_FRAME_LEN_RECV 1440 // 180 ms at 8000hz G.711
  19. // some utility functions for calculating frame sizes and frames per packet
  20. HRESULT WINAPI CreateMediaCapability(REFGUID mediaId, LPIH323MediaCap * ppMediaCapability)
  21. {
  22. HRESULT hrLast = E_OUTOFMEMORY;
  23. if (!ppMediaCapability)
  24. return E_POINTER;
  25. if (mediaId == MEDIA_TYPE_H323AUDIO)
  26. {
  27. CMsiaCapability * pAudObj = NULL;
  28. UINT uAud;
  29. DBG_SAVE_FILE_LINE
  30. pAudObj = new CMsiaCapability;
  31. if(pAudObj)
  32. {
  33. hrLast = pAudObj->QueryInterface(IID_IH323MediaCap, (void **)ppMediaCapability);
  34. pAudObj->Release(); // this balances the refcount of "new CMsiaCapability"
  35. pAudObj = NULL;
  36. }
  37. }
  38. else if (mediaId == MEDIA_TYPE_H323VIDEO)
  39. {
  40. CMsivCapability * pVidObj = NULL;
  41. DBG_SAVE_FILE_LINE
  42. pVidObj = new CMsivCapability;
  43. if(pVidObj)
  44. {
  45. hrLast = pVidObj->QueryInterface(IID_IH323MediaCap, (void **)ppMediaCapability);
  46. pVidObj->Release(); // this balances the refcount of "new CMsivCapability"
  47. pVidObj = NULL;
  48. }
  49. }
  50. else
  51. hrLast = E_NOINTERFACE;
  52. if(HR_SUCCEEDED(hrLast))
  53. {
  54. if (!(*ppMediaCapability)->Init())
  55. {
  56. (*ppMediaCapability)->Release();
  57. hrLast = E_FAIL;
  58. *ppMediaCapability = NULL;
  59. }
  60. }
  61. return hrLast;
  62. }
  63. //
  64. // CMsiaCapability
  65. //
  66. UINT CMsiaCapability::GetLocalSendParamSize(MEDIA_FORMAT_ID dwID)
  67. {
  68. return (sizeof(AUDIO_CHANNEL_PARAMETERS));
  69. }
  70. UINT CMsiaCapability::GetLocalRecvParamSize(PCC_TERMCAP pCapability)
  71. {
  72. return (sizeof(AUDIO_CHANNEL_PARAMETERS));
  73. }
  74. HRESULT CMsiaCapability::CreateCapList(LPVOID *ppCapBuf)
  75. {
  76. UINT u;
  77. AUDCAP_DETAILS *pDecodeDetails = pLocalFormats;
  78. PCC_TERMCAPLIST pTermCapList = NULL;
  79. PPCC_TERMCAP ppCCThisTermCap = NULL;
  80. PCC_TERMCAP pCCThisCap = NULL;
  81. PNSC_AUDIO_CAPABILITY pNSCapNext = NULL;
  82. LPWAVEFORMATEX lpwfx;
  83. HRESULT hr = hrSuccess;
  84. FX_ENTRY ("CreateCapList");
  85. // validate input
  86. if(!ppCapBuf)
  87. {
  88. hr = CAPS_E_INVALID_PARAM;
  89. goto ERROR_OUT;
  90. }
  91. *ppCapBuf = NULL;
  92. if(!uNumLocalFormats || !pDecodeDetails)
  93. {
  94. hr = CAPS_E_NOCAPS;
  95. goto ERROR_OUT;
  96. }
  97. pTermCapList = (PCC_TERMCAPLIST)MemAlloc(sizeof(CC_TERMCAPLIST));
  98. if(!pTermCapList)
  99. {
  100. hr = CAPS_E_NOMEM;
  101. goto ERROR_OUT;
  102. }
  103. ppCCThisTermCap = (PPCC_TERMCAP)MemAlloc(uNumLocalFormats * sizeof(PCC_TERMCAP));
  104. if(!ppCCThisTermCap)
  105. {
  106. hr = CAPS_E_NOMEM;
  107. goto ERROR_OUT;
  108. }
  109. pTermCapList->wLength = 0;
  110. // point the CC_TERMCAPLIST pTermCapArray at the array of PCC_TERMCAP
  111. pTermCapList->pTermCapArray = ppCCThisTermCap;
  112. /*
  113. CC_TERMCAPLIST PCC_TERMCAP CC_TERMCAP
  114. pTermCapList-> {
  115. wLength
  116. pTermCapArray--->pTermCap----------->{single capability.....}
  117. }
  118. pTermCap----------->{single capability.}
  119. pTermCap----------->{single capability...}
  120. */
  121. for(u=0; u <uNumLocalFormats; u++)
  122. {
  123. // check if enabled for receive, skip if false
  124. // also skip if public version of capabilities is to be advertised via a
  125. // separate local capability entry
  126. if((!pDecodeDetails->bRecvEnabled ) || (pDecodeDetails->dwPublicRefIndex))
  127. {
  128. pDecodeDetails++;
  129. continue;
  130. }
  131. if(pDecodeDetails->H245TermCap.ClientType ==0
  132. || pDecodeDetails->H245TermCap.ClientType ==H245_CLIENT_AUD_NONSTD)
  133. {
  134. lpwfx = (LPWAVEFORMATEX)pDecodeDetails->lpLocalFormatDetails;
  135. if(!lpwfx)
  136. {
  137. pDecodeDetails++;
  138. continue;
  139. }
  140. // allocate for this one capability
  141. pCCThisCap = (PCC_TERMCAP)MemAlloc(sizeof(CC_TERMCAP));
  142. pNSCapNext = (PNSC_AUDIO_CAPABILITY)MemAlloc(sizeof(NSC_AUDIO_CAPABILITY)
  143. + lpwfx->cbSize);
  144. if((!pCCThisCap)|| (!pNSCapNext))
  145. {
  146. hr = CAPS_E_NOMEM;
  147. goto ERROR_OUT;
  148. }
  149. // set type of nonstandard capability
  150. pNSCapNext->cap_type = NSC_ACM_WAVEFORMATEX;
  151. // stuff both chunks of nonstandard capability info into buffer
  152. // first stuff the "channel parameters" (the format independent communication options)
  153. memcpy(&pNSCapNext->cap_params, &pDecodeDetails->nonstd_params, sizeof(NSC_CHANNEL_PARAMETERS));
  154. // then the ACM stuff
  155. memcpy(&pNSCapNext->cap_data.wfx, lpwfx, sizeof(WAVEFORMATEX) + lpwfx->cbSize);
  156. pCCThisCap->ClientType = H245_CLIENT_AUD_NONSTD;
  157. pCCThisCap->DataType = H245_DATA_AUDIO;
  158. // is this a "receive only" cap or a send&receive cap
  159. pCCThisCap->Dir = (pDecodeDetails->bSendEnabled && bPublicizeTXCaps)
  160. ? H245_CAPDIR_LCLRXTX :H245_CAPDIR_LCLRX;
  161. // convert index of the cap entry to the ID
  162. pCCThisCap->CapId = (USHORT)IndexToId(u);
  163. // all nonstandard identifier fields are unsigned short
  164. // two possibilities for choice are "h221NonStandard_chosen" and "object_chosen"
  165. pCCThisCap->Cap.H245Aud_NONSTD.nonStandardIdentifier.choice = h221NonStandard_chosen;
  166. // NOTE: there is some question about the correct byte order
  167. // of the codes in the h221NonStandard structure
  168. pCCThisCap->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.t35CountryCode = USA_H221_COUNTRY_CODE;
  169. pCCThisCap->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.t35Extension = USA_H221_COUNTRY_EXTENSION;
  170. pCCThisCap->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.manufacturerCode = MICROSOFT_H_221_MFG_CODE;
  171. // set size of buffer
  172. pCCThisCap->Cap.H245Aud_NONSTD.data.length = sizeof(NSC_AUDIO_CAPABILITY) + lpwfx->cbSize;
  173. pCCThisCap->Cap.H245Aud_NONSTD.data.value = (BYTE *)pNSCapNext; // point to nonstandard stuff
  174. // pNSCapNext is now referenced by the pTermCapList and will
  175. // be cleaned up via DeleteCapList(). Null the ptr so that error cleanup
  176. // won't try redundant cleanup.
  177. pNSCapNext = NULL;
  178. }
  179. else
  180. {
  181. // allocate for this one capability
  182. pCCThisCap = (PCC_TERMCAP)MemAlloc(sizeof(CC_TERMCAP));
  183. if(!pCCThisCap)
  184. {
  185. hr = CAPS_E_NOMEM;
  186. goto ERROR_OUT;
  187. }
  188. pCCThisCap->ClientType = (H245_CLIENT_T)pDecodeDetails->H245TermCap.ClientType;
  189. pCCThisCap->DataType = H245_DATA_AUDIO;
  190. // is this a "receive only" cap or a send&receive cap
  191. pCCThisCap->Dir = (pDecodeDetails->bSendEnabled && bPublicizeTXCaps)
  192. ? H245_CAPDIR_LCLRXTX :H245_CAPDIR_LCLRX;
  193. // convert the index of the cap entry to the ID
  194. pCCThisCap->CapId = (USHORT)IndexToId(u);//
  195. // Fixup capability parameters based on local details
  196. // use parameters that should have been set when codecs were enumerated
  197. // Special note for sample based codecs: H.225.0 Section 6.2.1 states
  198. // "Sample based codecs, such as G.711 and G.722 shall be considered to be
  199. // frame oriented, with a frame size of eight samples."
  200. switch (pCCThisCap->ClientType )
  201. {
  202. case H245_CLIENT_AUD_G711_ALAW64:
  203. pCCThisCap->Cap.H245Aud_G711_ALAW64 =
  204. pDecodeDetails->nonstd_params.wFramesPerPktMax
  205. / SAMPLE_BASED_SAMPLES_PER_FRAME;
  206. break;
  207. case H245_CLIENT_AUD_G711_ULAW64:
  208. pCCThisCap->Cap.H245Aud_G711_ULAW64 =
  209. pDecodeDetails->nonstd_params.wFramesPerPktMax
  210. /SAMPLE_BASED_SAMPLES_PER_FRAME ;
  211. break;
  212. case H245_CLIENT_AUD_G723:
  213. pCCThisCap->Cap.H245Aud_G723.maxAl_sduAudioFrames = //4
  214. pDecodeDetails->nonstd_params.wFramesPerPktMax;
  215. // we know that the G.723 codec can decode SID in any mode, so
  216. //could we always advertise the *capability* to do silence suppression ????
  217. pCCThisCap->Cap.H245Aud_G723.silenceSuppression = 0;
  218. // = (pDecodeDetails->nonstd_params.UseSilenceDet)?1:0;
  219. break;
  220. default:
  221. break;
  222. }
  223. }
  224. pDecodeDetails++;
  225. *ppCCThisTermCap++ = pCCThisCap;// add ptr to this capability to the array
  226. pTermCapList->wLength++; // count this entry
  227. // pCCThisCap is now referenced by the pTermCapList and will
  228. // be cleaned up via DeleteCapList(). Null the ptr so that error cleanup
  229. // won't try redundant cleanup.
  230. pCCThisCap = NULL;
  231. }
  232. *ppCapBuf = pTermCapList;
  233. return hr;
  234. ERROR_OUT:
  235. if(pTermCapList)
  236. {
  237. DeleteCapList(pTermCapList);
  238. }
  239. if(pCCThisCap)
  240. MemFree(pCCThisCap);
  241. if(pNSCapNext)
  242. MemFree(pNSCapNext);
  243. return hr;
  244. }
  245. HRESULT CMsiaCapability::DeleteCapList(LPVOID pCapBuf)
  246. {
  247. UINT u;
  248. PCC_TERMCAPLIST pTermCapList = (PCC_TERMCAPLIST)pCapBuf;
  249. PCC_TERMCAP pCCThisCap;
  250. PNSC_AUDIO_CAPABILITY pNSCap;
  251. if(!pTermCapList)
  252. {
  253. return CAPS_E_INVALID_PARAM;
  254. }
  255. if(pTermCapList->pTermCapArray)
  256. {
  257. while(pTermCapList->wLength--)
  258. {
  259. pCCThisCap = *(pTermCapList->pTermCapArray + pTermCapList->wLength);
  260. if(pCCThisCap)
  261. {
  262. if(pCCThisCap->ClientType == H245_CLIENT_AUD_NONSTD)
  263. {
  264. if(pCCThisCap->Cap.H245Aud_NONSTD.data.value)
  265. {
  266. MemFree(pCCThisCap->Cap.H245Aud_NONSTD.data.value);
  267. }
  268. }
  269. MemFree(pCCThisCap);
  270. }
  271. }
  272. MemFree(pTermCapList->pTermCapArray);
  273. }
  274. MemFree(pTermCapList);
  275. return hrSuccess;
  276. }
  277. // copies relevant fields from a real H245 TERMCAP struct
  278. // to a local H245TermCap struct
  279. void CopyTermCapInfo(PCC_TERMCAP pSrc, H245_TERMCAP *pDest)
  280. {
  281. ZeroMemory(pDest, sizeof(*pDest));
  282. pDest->Dir = pSrc->Dir;
  283. pDest->DataType = pSrc->DataType;
  284. pDest->ClientType = pSrc->ClientType;
  285. pDest->CapId = pSrc->CapId;
  286. pDest->H245_NonStd = pSrc->Cap.H245_NonStd;
  287. pDest->H245Aud_NONSTD = pSrc->Cap.H245Aud_NONSTD;
  288. pDest->H245Aud_G711_ALAW64 = pSrc->Cap.H245Aud_G711_ALAW64;
  289. pDest->H245Aud_G711_ULAW64 = pSrc->Cap.H245Aud_G711_ULAW64;
  290. pDest->H245Aud_G723 = pSrc->Cap.H245Aud_G723;
  291. return;
  292. }
  293. void CopyLocalTermCapInfo(H245_TERMCAP *pSrc, PCC_TERMCAP pDest)
  294. {
  295. ZeroMemory(pDest, sizeof(*pDest));
  296. pDest->Dir = pSrc->Dir;
  297. pDest->DataType = pSrc->DataType;
  298. pDest->ClientType = pSrc->ClientType;
  299. pDest->CapId = pSrc->CapId;
  300. pDest->Cap.H245_NonStd = pSrc->H245_NonStd;
  301. pDest->Cap.H245Aud_NONSTD = pSrc->H245Aud_NONSTD;
  302. pDest->Cap.H245Aud_G711_ALAW64 = pSrc->H245Aud_G711_ALAW64;
  303. pDest->Cap.H245Aud_G711_ULAW64 = pSrc->H245Aud_G711_ULAW64;
  304. pDest->Cap.H245Aud_G723 = pSrc->H245Aud_G723;
  305. return;
  306. }
  307. // the intent is to keep a copy of the channel parameters used to open a send channel
  308. // that the remote end can decode.
  309. AUDIO_FORMAT_ID CMsiaCapability::AddRemoteDecodeFormat(PCC_TERMCAP pCCThisCap)
  310. {
  311. FX_ENTRY ("CMsiaCapability::AddRemoteDecodeFormat");
  312. AUDCAP_DETAILS audcapdetails =
  313. {WAVE_FORMAT_UNKNOWN, NONSTD_TERMCAP, STD_CHAN_PARAMS,
  314. {RTP_DYNAMIC_MIN, 8000, 4},
  315. 0, TRUE, TRUE, 320, 32000,32000,50,0,0,0,NULL,0, NULL,""};
  316. LPVOID lpData = NULL;
  317. UINT uSize = 0;
  318. AUDCAP_DETAILS *pTemp;
  319. if(!pCCThisCap)
  320. {
  321. return INVALID_AUDIO_FORMAT;
  322. }
  323. // check room
  324. if(uRemoteDecodeFormatCapacity <= uNumRemoteDecodeFormats)
  325. {
  326. // get more mem, realloc memory by CAP_CHUNK_SIZE for pRemoteDecodeFormats
  327. pTemp = (AUDCAP_DETAILS *)MemAlloc((uNumRemoteDecodeFormats + CAP_CHUNK_SIZE)*sizeof(AUDCAP_DETAILS));
  328. if(!pTemp)
  329. goto ERROR_EXIT;
  330. // remember how much capacity we now have
  331. uRemoteDecodeFormatCapacity = uNumRemoteDecodeFormats + CAP_CHUNK_SIZE;
  332. #ifdef DEBUG
  333. if((uNumRemoteDecodeFormats && !pRemoteDecodeFormats) || (!uNumRemoteDecodeFormats && pRemoteDecodeFormats))
  334. {
  335. ERRORMESSAGE(("%s:leak! uNumRemoteDecodeFormats:0x%08lX, pRemoteDecodeFormats:0x%08lX\r\n",
  336. _fx_, uNumRemoteDecodeFormats,pRemoteDecodeFormats));
  337. }
  338. #endif
  339. // copy old stuff, discard old mem
  340. if(uNumRemoteDecodeFormats && pRemoteDecodeFormats)
  341. {
  342. memcpy(pTemp, pRemoteDecodeFormats, uNumRemoteDecodeFormats*sizeof(AUDCAP_DETAILS));
  343. MemFree(pRemoteDecodeFormats);
  344. }
  345. pRemoteDecodeFormats = pTemp;
  346. }
  347. // pTemp is where the stuff is cached
  348. pTemp = pRemoteDecodeFormats+uNumRemoteDecodeFormats;
  349. // fixup the capability structure being added. First thing: initialize defaults
  350. memcpy(pTemp, &audcapdetails, sizeof(AUDCAP_DETAILS));
  351. // next, the H245 parameters
  352. // memcpy(&pTemp->H245Cap, pCCThisCap, sizeof(pTemp->H245Cap));
  353. CopyTermCapInfo(pCCThisCap, &pTemp->H245TermCap);
  354. // Note: if nonstandard data exists, the nonstd pointers need to be fixed up
  355. if(pCCThisCap->ClientType == H245_CLIENT_AUD_NONSTD)
  356. {
  357. // do we recognize this?
  358. if(pCCThisCap->Cap.H245Aud_NONSTD.nonStandardIdentifier.choice == h221NonStandard_chosen)
  359. {
  360. if((pCCThisCap->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.t35CountryCode == USA_H221_COUNTRY_CODE)
  361. && (pCCThisCap->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.t35Extension == USA_H221_COUNTRY_EXTENSION)
  362. && (pCCThisCap->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.manufacturerCode == MICROSOFT_H_221_MFG_CODE))
  363. {
  364. // ok, this is ours so far. Now what data type is contained therein?
  365. // welllll, lets keep a copy of this regardless ????. If we can't understand
  366. // future versions of ourselves, then what???
  367. uSize = pCCThisCap->Cap.H245Aud_NONSTD.data.length;
  368. lpData = pCCThisCap->Cap.H245Aud_NONSTD.data.value;
  369. }
  370. }
  371. } else {
  372. // set up the NSC_CHANNEL_PARAMETERS struct based on the remote H245 parameters
  373. switch(pCCThisCap->ClientType ) {
  374. case H245_CLIENT_AUD_G711_ALAW64:
  375. pTemp->nonstd_params.wFramesPerPktMax = pCCThisCap->Cap.H245Aud_G711_ALAW64
  376. * SAMPLE_BASED_SAMPLES_PER_FRAME;
  377. break;
  378. case H245_CLIENT_AUD_G711_ULAW64:
  379. pTemp->nonstd_params.wFramesPerPktMax = pCCThisCap->Cap.H245Aud_G711_ULAW64
  380. * SAMPLE_BASED_SAMPLES_PER_FRAME;
  381. break;
  382. case H245_CLIENT_AUD_G723:
  383. pTemp->nonstd_params.wFramesPerPktMax =pCCThisCap->Cap.H245Aud_G723.maxAl_sduAudioFrames;
  384. // do we care about silence suppression?
  385. pTemp->nonstd_params.UseSilenceDet = pCCThisCap->Cap.H245Aud_G723.silenceSuppression;
  386. break;
  387. default:
  388. break;
  389. }
  390. }
  391. pTemp->uLocalDetailsSize = 0; // we're not keeping another copy of local encode details
  392. pTemp->lpLocalFormatDetails =0; // we're not keeping another copy of local encode details
  393. pTemp->uRemoteDetailsSize = 0; // clear this now
  394. if(uSize && lpData)
  395. {
  396. pTemp->H245TermCap.H245Aud_NONSTD.data.length = uSize;
  397. pTemp->H245TermCap.H245Aud_NONSTD.data.value = (unsigned char *)lpData;
  398. pTemp->lpRemoteFormatDetails = MemAlloc(uSize);
  399. if(pTemp->lpRemoteFormatDetails)
  400. {
  401. memcpy(pTemp->lpRemoteFormatDetails, lpData, uSize);
  402. pTemp->uRemoteDetailsSize = uSize;
  403. }
  404. #ifdef DEBUG
  405. else
  406. {
  407. ERRORMESSAGE(("%s:allocation failed!\r\n",_fx_));
  408. }
  409. #endif
  410. }
  411. else
  412. {
  413. pTemp->lpRemoteFormatDetails = NULL;
  414. pTemp->uRemoteDetailsSize =0;
  415. }
  416. uNumRemoteDecodeFormats++;
  417. // use the index as the ID
  418. return (uNumRemoteDecodeFormats-1);
  419. ERROR_EXIT:
  420. return INVALID_AUDIO_FORMAT;
  421. }
  422. BOOL CMsiaCapability::IsCapabilityRecognized(PCC_TERMCAP pCCThisCap)
  423. {
  424. FX_ENTRY ("CMsiaCapability::IsCapabilityRecognized");
  425. if(pCCThisCap->DataType != H245_DATA_AUDIO)
  426. return FALSE;
  427. if(pCCThisCap->ClientType == H245_CLIENT_AUD_NONSTD)
  428. {
  429. // do we recognize this?
  430. if(pCCThisCap->Cap.H245Aud_NONSTD.nonStandardIdentifier.choice == h221NonStandard_chosen)
  431. {
  432. if((pCCThisCap->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.t35CountryCode == USA_H221_COUNTRY_CODE)
  433. && (pCCThisCap->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.t35Extension == USA_H221_COUNTRY_EXTENSION)
  434. && (pCCThisCap->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.manufacturerCode == MICROSOFT_H_221_MFG_CODE))
  435. {
  436. // ok, this is ours so far. Now what data type is contained therein?
  437. // welllll, lets keep a copy of this regardless ????. If we can't understand
  438. // future versions of ourselves, then what???
  439. return TRUE;
  440. }
  441. else
  442. {
  443. // unrecognized nonstandard capability
  444. ERRORMESSAGE(("%s:unrecognized nonstd capability\r\n",_fx_));
  445. #ifdef DEBUG
  446. VOID DumpNonstdParameters(PCC_TERMCAP pChanCap1, PCC_TERMCAP pChanCap2);
  447. DumpNonstdParameters(NULL, pCCThisCap);
  448. #endif
  449. return FALSE;
  450. }
  451. }
  452. }
  453. return TRUE;
  454. }
  455. HRESULT CMsiaCapability::AddRemoteDecodeCaps(PCC_TERMCAPLIST pTermCapList)
  456. {
  457. FX_ENTRY ("CMsiaCapability::AddRemoteDecodeCaps");
  458. HRESULT hr = hrSuccess;
  459. PPCC_TERMCAP ppCCThisCap;
  460. PCC_TERMCAP pCCThisCap;
  461. WORD wNumCaps;
  462. //ERRORMESSAGE(("%s,\r\n", _fx_));
  463. if(!pTermCapList) // additional capability descriptors may be added
  464. { // at any time
  465. return CAPS_E_INVALID_PARAM;
  466. }
  467. // cleanup old term caps if term caps are being added and old caps exist
  468. FlushRemoteCaps();
  469. wNumCaps = pTermCapList->wLength;
  470. ppCCThisCap = pTermCapList->pTermCapArray;
  471. /*
  472. CC_TERMCAPLIST TERMCAPINFO CC_TERMCAP
  473. pTermCapList-> {
  474. wLength
  475. pTermCapInfo--->pTermCap----------->{single capability.....}
  476. }
  477. pTermCap----------->{single capability.}
  478. pTermCap----------->{single capability...}
  479. */
  480. while(wNumCaps--)
  481. {
  482. if(!(pCCThisCap = *ppCCThisCap++))
  483. {
  484. ERRORMESSAGE(("%s:null pTermCap, 0x%04x of 0x%04x\r\n",
  485. _fx_, pTermCapList->wLength - wNumCaps, pTermCapList->wLength));
  486. continue;
  487. }
  488. if(!IsCapabilityRecognized(pCCThisCap))
  489. {
  490. continue;
  491. }
  492. AddRemoteDecodeFormat(pCCThisCap);
  493. }
  494. return hr;
  495. }
  496. // Given the ID of a local format, gets the channel parameters that are sent to the
  497. // remote end as part of the capability exchange. This function is not used by the
  498. // capability exchange code (because it sends more than just these parameters).
  499. // However, this is useful information by itself - it can be used for validating the
  500. // parameters of channel open requests against the expected parameters
  501. HRESULT CMsiaCapability::GetPublicDecodeParams(LPVOID pBufOut, UINT uBufSize, AUDIO_FORMAT_ID id)
  502. {
  503. UINT uIndex = IDToIndex(id);
  504. // validate input
  505. if(!pBufOut|| (uIndex >= (UINT)uNumLocalFormats))
  506. {
  507. return CAPS_E_INVALID_PARAM;
  508. }
  509. if(uBufSize < sizeof(CC_TERMCAP))
  510. {
  511. return CAPS_E_BUFFER_TOO_SMALL;
  512. }
  513. // memcpy(pBufOut, &((pLocalFormats + uIndex)->H245Cap), sizeof(CC_TERMCAP));
  514. CopyLocalTermCapInfo(&((pLocalFormats + uIndex)->H245TermCap), (PCC_TERMCAP)pBufOut);
  515. return hrSuccess;
  516. }
  517. HRESULT CMsiaCapability::SetAudioPacketDuration(UINT uPacketDuration)
  518. {
  519. m_uPacketDuration = uPacketDuration;
  520. return S_OK;
  521. }
  522. // Given the IDs of "matching" local and remote formats, gets the preferred channel parameters
  523. // that will be used in requests to open a channel for sending to the remote.
  524. HRESULT CMsiaCapability::GetEncodeParams(LPVOID pBufOut, UINT uBufSize,LPVOID pLocalParams, UINT uSizeLocal,
  525. AUDIO_FORMAT_ID idRemote, AUDIO_FORMAT_ID idLocal)
  526. {
  527. UINT uLocalIndex = IDToIndex(idLocal);
  528. AUDCAP_DETAILS *pLocalDetails = pLocalFormats + uLocalIndex;
  529. AUDCAP_DETAILS *pFmtTheirs;
  530. AUDIO_CHANNEL_PARAMETERS local_params;
  531. PNSC_CHANNEL_PARAMETERS pNSRemoteParams;
  532. LPWAVEFORMATEX lpwfx;
  533. UINT u;
  534. PCC_TERMCAP pTermCap = (PCC_TERMCAP)pBufOut;
  535. // validate input
  536. if(!pBufOut)
  537. {
  538. return CAPS_E_INVALID_PARAM;
  539. }
  540. if(uBufSize < sizeof(CC_TERMCAP))
  541. {
  542. return CAPS_E_BUFFER_TOO_SMALL;
  543. }
  544. if(!pLocalParams|| uSizeLocal < sizeof(AUDIO_CHANNEL_PARAMETERS)
  545. ||(uLocalIndex >= (UINT)uNumLocalFormats))
  546. {
  547. return CAPS_E_INVALID_PARAM;
  548. }
  549. pFmtTheirs = pRemoteDecodeFormats; // start at the beginning of the remote formats
  550. for(u=0; u<uNumRemoteDecodeFormats; u++)
  551. {
  552. if(pFmtTheirs->H245TermCap.CapId == idRemote)
  553. {
  554. // copy CC_TERMCAP struct. Any data referenced by CC_TERMCAP now has
  555. // two references to it. i.e. pTermCap->extrablah is the same
  556. // location as pFmtTheirs->extrablah
  557. // memcpy(pBufOut, &(pFmtTheirs->H245Cap), sizeof(CC_TERMCAP));
  558. CopyLocalTermCapInfo(&(pFmtTheirs->H245TermCap), (PCC_TERMCAP)pBufOut);
  559. break;
  560. }
  561. pFmtTheirs++; // next entry in receiver's caps
  562. }
  563. // check for an unfound format
  564. if(u >= uNumRemoteDecodeFormats)
  565. goto ERROR_EXIT;
  566. // select channel parameters if appropriate. The audio formats that have variable parameters
  567. // are :
  568. // H245_CAP_G723_T H245Aud_G723;
  569. // H245_CAP_AIS11172_T H245Aud_IS11172;
  570. // H245_CAP_IS13818_T H245Aud_IS13818;
  571. // and of course all nonstandard formats
  572. // Select parameters based on local capability info
  573. // initialize local_params with default settings
  574. memcpy(&local_params.ns_params,&pLocalDetails->nonstd_params,sizeof(local_params.ns_params));
  575. // recalculate frames per packet
  576. lpwfx = (LPWAVEFORMATEX)pLocalDetails->lpLocalFormatDetails;
  577. local_params.ns_params.wFramesPerPktMax = LOWORD(MaxFramesPerPacket(lpwfx));
  578. local_params.ns_params.wFramesPerPkt = LOWORD(MinFramesPerPacket(lpwfx));
  579. if(local_params.ns_params.wFramesPerPktMin > local_params.ns_params.wFramesPerPkt)
  580. {
  581. local_params.ns_params.wFramesPerPktMin = local_params.ns_params.wFramesPerPkt;
  582. }
  583. if(pTermCap->ClientType == H245_CLIENT_AUD_G723)
  584. {
  585. // select frames per packet based on minimum latency value that is acceptable
  586. pTermCap->Cap.H245Aud_G723.maxAl_sduAudioFrames = //4
  587. min(local_params.ns_params.wFramesPerPkt, pTermCap->Cap.H245Aud_G723.maxAl_sduAudioFrames);
  588. // pLocalDetails->nonstd_params.wFramesPerPktMax;
  589. // never request silence suppression
  590. pTermCap->Cap.H245Aud_G723.silenceSuppression = 0;
  591. // (pLocalDetails->nonstd_params.UseSilenceDet)?1:0;
  592. // keep a copy of the selected parameters for use on the local side
  593. local_params.ns_params.wFramesPerPkt = local_params.ns_params.wFramesPerPktMin =
  594. local_params.ns_params.wFramesPerPktMax = pTermCap->Cap.H245Aud_G723.maxAl_sduAudioFrames;
  595. local_params.ns_params.UseSilenceDet = pTermCap->Cap.H245Aud_G723.silenceSuppression;
  596. local_params.RTP_Payload = pLocalDetails->audio_params.RTPPayload;
  597. }
  598. else if(pTermCap->ClientType == H245_CLIENT_AUD_G711_ALAW64)
  599. {
  600. // select frames per packet based on minimum latency value that is acceptable
  601. pTermCap->Cap.H245Aud_G711_ALAW64 =
  602. min(local_params.ns_params.wFramesPerPkt/SAMPLE_BASED_SAMPLES_PER_FRAME, pTermCap->Cap.H245Aud_G711_ALAW64);
  603. // keep a copy of the selected parameters for use on the local side
  604. local_params.ns_params.wFramesPerPkt = local_params.ns_params.wFramesPerPktMin =
  605. local_params.ns_params.wFramesPerPktMax = pTermCap->Cap.H245Aud_G711_ALAW64*SAMPLE_BASED_SAMPLES_PER_FRAME;
  606. local_params.ns_params.UseSilenceDet = FALSE;
  607. // note that local_params.RTP_Payload is fixed below
  608. }
  609. else if(pTermCap->ClientType == H245_CLIENT_AUD_G711_ULAW64)
  610. {
  611. // select frames per packet based on minimum latency value that is acceptable
  612. pTermCap->Cap.H245Aud_G711_ULAW64 =
  613. min(local_params.ns_params.wFramesPerPkt/SAMPLE_BASED_SAMPLES_PER_FRAME, pTermCap->Cap.H245Aud_G711_ULAW64);
  614. // keep a copy of the selected parameters for use on the local side
  615. local_params.ns_params.wFramesPerPkt = local_params.ns_params.wFramesPerPktMin =
  616. local_params.ns_params.wFramesPerPktMax = pTermCap->Cap.H245Aud_G711_ULAW64*SAMPLE_BASED_SAMPLES_PER_FRAME;
  617. local_params.ns_params.UseSilenceDet = FALSE;
  618. // note that local_params.RTP_Payload is fixed below
  619. }
  620. else if (pTermCap->ClientType == H245_CLIENT_AUD_NONSTD)
  621. {
  622. // note: "H245_CLIENT_AUD_NONSTD H245Aud_NONSTD;" also has variable parameters in the
  623. // form of a pointer to a chunk of nonstandard data. This pointer and the nonstandard
  624. // data it points to was set when remote caps were received (see AddRemoteDecodeCaps ()).
  625. // So as of this point, we just copied that nonstandard data back out into the channel
  626. // parameters. We will use these parameters to request an open channel.
  627. // once we fix up a few important parameters. set channel params based on local params
  628. pNSRemoteParams = &((PNSC_AUDIO_CAPABILITY)(pTermCap->Cap.H245Aud_NONSTD.data.value))->cap_params;
  629. // LOOKLOOK ---- which parameters do we really need to select ???
  630. // For example, if wFrameSizeMin != wFrameSizeMax, do we pick something in the range?
  631. // or own favorite value? what else?
  632. if(pNSRemoteParams->wFrameSizeMax < pNSRemoteParams->wFrameSize) // fixup bogus parameters
  633. pNSRemoteParams->wFrameSizeMax = pNSRemoteParams->wFrameSize;
  634. // note that this writes on the memory that is caching remote capabilities
  635. // set frame size to our preferred size unless remote can't take it that big
  636. pNSRemoteParams->wFrameSize =
  637. min(local_params.ns_params.wFrameSize, pNSRemoteParams->wFrameSizeMax);
  638. pNSRemoteParams->wFramesPerPkt = min( local_params.ns_params.wFramesPerPkt,
  639. pNSRemoteParams->wFramesPerPktMax);
  640. // use optional stuff only of both sides have it
  641. pNSRemoteParams->UseSilenceDet = pNSRemoteParams->UseSilenceDet && local_params.ns_params.UseSilenceDet;
  642. pNSRemoteParams->UsePostFilter = pNSRemoteParams->UsePostFilter && local_params.ns_params.UsePostFilter;
  643. // keep a copy of the selected parameters for use on the local side
  644. memcpy(&local_params.ns_params, pNSRemoteParams, sizeof(NSC_CHANNEL_PARAMETERS));
  645. }
  646. // fix payload type
  647. local_params.RTP_Payload = pLocalDetails->audio_params.RTPPayload;
  648. memcpy(pLocalParams, &local_params, sizeof(AUDIO_CHANNEL_PARAMETERS));
  649. return hrSuccess;
  650. ERROR_EXIT:
  651. return CAPS_E_INVALID_PARAM;
  652. }
  653. // Given the ID of the local format, gets the local parameters that are used to configure
  654. // the RECEIVE side of the channel
  655. HRESULT CMsiaCapability::GetLocalDecodeParams(LPVOID lpvBuf, UINT uBufSize, AUDIO_FORMAT_ID id)
  656. {
  657. // validate input
  658. if(!lpvBuf|| uBufSize < sizeof(NSC_CHANNEL_PARAMETERS) ||(id > (UINT)uNumLocalFormats))
  659. {
  660. return CAPS_E_INVALID_PARAM;
  661. }
  662. memcpy(lpvBuf, &((pLocalFormats + id)->nonstd_params), sizeof(NSC_CHANNEL_PARAMETERS));
  663. return hrSuccess;
  664. }
  665. BOOL NonstandardCapsCompareA(AUDCAP_DETAILS *pFmtMine, PNSC_AUDIO_CAPABILITY pCap2,
  666. UINT uSize2)
  667. {
  668. LPWAVEFORMATEX lpwfx;
  669. if(!pFmtMine || !pCap2)
  670. return FALSE;
  671. if(!(lpwfx = (LPWAVEFORMATEX)pFmtMine->lpLocalFormatDetails))
  672. return FALSE;
  673. if(pCap2->cap_type == NSC_ACM_WAVEFORMATEX)
  674. {
  675. // check sizes first
  676. if(lpwfx->cbSize != pCap2->cap_data.wfx.cbSize)
  677. {
  678. return FALSE;
  679. }
  680. // compare structures, including extra bytes
  681. if(memcmp(lpwfx, &pCap2->cap_data.wfx,
  682. sizeof(WAVEFORMATEX) + lpwfx->cbSize )==0)
  683. {
  684. return TRUE;
  685. }
  686. }
  687. else if(pCap2->cap_type == NSC_ACMABBREV)
  688. {
  689. if((LOWORD(pCap2->cap_data.acm_brief.dwFormatTag) == lpwfx->wFormatTag)
  690. && (pCap2->cap_data.acm_brief.dwSamplesPerSec == lpwfx->nSamplesPerSec)
  691. && (LOWORD(pCap2->cap_data.acm_brief.dwBitsPerSample) == lpwfx->wBitsPerSample))
  692. {
  693. return TRUE;
  694. }
  695. }
  696. return FALSE;
  697. }
  698. HRESULT CMsiaCapability::ResolveToLocalFormat(MEDIA_FORMAT_ID FormatIDLocal,
  699. MEDIA_FORMAT_ID * pFormatIDRemote)
  700. {
  701. AUDCAP_DETAILS *pFmtLocal;
  702. AUDCAP_DETAILS *pFmtRemote;
  703. UINT uIndex = IDToIndex(FormatIDLocal);
  704. UINT i;
  705. if(!pFormatIDRemote || (FormatIDLocal == INVALID_MEDIA_FORMAT)
  706. || (uIndex >= (UINT)uNumLocalFormats))
  707. {
  708. return CAPS_E_INVALID_PARAM;
  709. }
  710. pFmtLocal = pLocalFormats + uIndex;
  711. pFmtRemote = pRemoteDecodeFormats; // start at the beginning of the remote formats
  712. for(i=0; i<uNumRemoteDecodeFormats; i++)
  713. {
  714. if(!pFmtLocal->bSendEnabled)
  715. continue;
  716. // compare capabilities - start by comparing the format tag. a.k.a. "ClientType" in H.245 land
  717. if(pFmtLocal->H245TermCap.ClientType == pFmtRemote->H245TermCap.ClientType)
  718. {
  719. // if this is a nonstandard cap, compare nonstandard parameters
  720. if(pFmtLocal->H245TermCap.ClientType == H245_CLIENT_AUD_NONSTD)
  721. {
  722. if(NonstandardCapsCompareA(pFmtLocal,
  723. (PNSC_AUDIO_CAPABILITY)pFmtRemote->H245TermCap.H245Aud_NONSTD.data.value,
  724. pFmtRemote->H245TermCap.H245Aud_NONSTD.data.length))
  725. {
  726. goto RESOLVED_EXIT;
  727. }
  728. }
  729. else // compare standard parameters, if any
  730. {
  731. // well, so far, there aren't any parameters that are significant enough
  732. // to affect the match/no match decision
  733. goto RESOLVED_EXIT;
  734. }
  735. }
  736. pFmtRemote++; // next entry in receiver's caps
  737. }
  738. return CAPS_E_NOMATCH;
  739. RESOLVED_EXIT:
  740. // Match! return ID of remote decoding (receive fmt) caps that match our
  741. // send caps
  742. *pFormatIDRemote = pFmtRemote->H245TermCap.CapId;
  743. return hrSuccess;
  744. }
  745. // resolve using currently cached local and remote formats
  746. HRESULT CMsiaCapability::ResolveEncodeFormat(
  747. AUDIO_FORMAT_ID *pIDEncodeOut,
  748. AUDIO_FORMAT_ID *pIDRemoteDecode)
  749. {
  750. UINT i,j=0;
  751. AUDCAP_DETAILS *pFmtMine = pLocalFormats;
  752. AUDCAP_DETAILS *pFmtTheirs;
  753. // LP_CUSTOM_CAPS lpCustomRemoteCaps = (LP_CUSTOM_CAPS)lpvRemoteCustomFormats;
  754. // LP_MSIAVC_CUSTOM_CAP_ENTRY lpCustomCaps;
  755. // LPWAVEFORMATEX lpWFX;
  756. if(!pIDEncodeOut || !pIDRemoteDecode)
  757. {
  758. return CAPS_E_INVALID_PARAM;
  759. }
  760. if(!uNumLocalFormats || !pLocalFormats)
  761. {
  762. *pIDEncodeOut = *pIDRemoteDecode = INVALID_AUDIO_FORMAT;
  763. return CAPS_E_NOCAPS;
  764. }
  765. if(!pRemoteDecodeFormats || !uNumRemoteDecodeFormats)
  766. {
  767. *pIDEncodeOut = *pIDRemoteDecode = INVALID_AUDIO_FORMAT;
  768. return CAPS_E_NOMATCH;
  769. }
  770. // decide how to encode. my caps are ordered by my preference according to
  771. // the contents of IDsByRank[]
  772. //If given a salt, find the position and add it
  773. if (*pIDEncodeOut != INVALID_MEDIA_FORMAT)
  774. {
  775. UINT uIndex = IDToIndex(*pIDEncodeOut);
  776. if (uIndex > uNumLocalFormats)
  777. {
  778. return CAPS_W_NO_MORE_FORMATS;
  779. }
  780. for(i=0; i<uNumLocalFormats; i++)
  781. {
  782. if (pLocalFormats[IDsByRank[i]].H245TermCap.CapId == *pIDEncodeOut)
  783. {
  784. j=i+1;
  785. break;
  786. }
  787. }
  788. }
  789. for(i=j; i<uNumLocalFormats; i++)
  790. {
  791. pFmtMine = pLocalFormats + IDsByRank[i];
  792. // check to see if this format is enabled for encoding
  793. if(!pFmtMine->bSendEnabled)
  794. continue;
  795. pFmtTheirs = pRemoteDecodeFormats; // start at the beginning of the remote formats
  796. for(j=0; j<uNumRemoteDecodeFormats; j++)
  797. {
  798. // compare capabilities - start by comparing the format tag. a.k.a. "ClientType" in H.245 land
  799. if(pFmtMine->H245TermCap.ClientType == pFmtTheirs->H245TermCap.ClientType)
  800. {
  801. // if this is a nonstandard cap, compare nonstandard parameters
  802. if(pFmtMine->H245TermCap.ClientType == H245_CLIENT_AUD_NONSTD)
  803. {
  804. if(NonstandardCapsCompareA(pFmtMine,
  805. // (PNSC_AUDIO_CAPABILITY)pFmtMine->H245Cap.Cap.H245Aud_NONSTD.data.value,
  806. (PNSC_AUDIO_CAPABILITY)pFmtTheirs->H245TermCap.H245Aud_NONSTD.data.value,
  807. //pFmtMine->H245Cap.Cap.H245Aud_NONSTD.data.length,
  808. pFmtTheirs->H245TermCap.H245Aud_NONSTD.data.length))
  809. {
  810. goto RESOLVED_EXIT;
  811. }
  812. }
  813. else // compare standard parameters, if any
  814. {
  815. // well, so far, there aren't any parameters that are significant enough
  816. // to affect the match/no match decision
  817. goto RESOLVED_EXIT;
  818. }
  819. }
  820. pFmtTheirs++; // next entry in receiver's caps
  821. }
  822. }
  823. return CAPS_E_NOMATCH;
  824. RESOLVED_EXIT:
  825. // Match!
  826. DEBUGMSG (ZONE_CONN,("Audio resolved (SEND) to Format Tag: %d\r\n",pFmtMine->wFormatTag));
  827. // return ID of our encoding (sending fmt) caps that match
  828. *pIDEncodeOut = pFmtMine->H245TermCap.CapId;
  829. // return ID of remote decoding (receive fmt) caps that match our
  830. // send caps
  831. *pIDRemoteDecode = pFmtTheirs->H245TermCap.CapId;
  832. return hrSuccess;
  833. }
  834. HRESULT CMsiaCapability::GetDecodeParams(PCC_RX_CHANNEL_REQUEST_CALLBACK_PARAMS pChannelParams,
  835. AUDIO_FORMAT_ID * pFormatID, LPVOID lpvBuf, UINT uBufSize)
  836. {
  837. UINT i,j=0;
  838. PCC_TERMCAP pCapability;
  839. AUDCAP_DETAILS *pFmtMine = pLocalFormats;
  840. PAUDIO_CHANNEL_PARAMETERS pAudioParams = (PAUDIO_CHANNEL_PARAMETERS) lpvBuf;
  841. if(!pChannelParams || !(pCapability = pChannelParams->pChannelCapability) || !pFormatID || !lpvBuf
  842. || (uBufSize < sizeof(AUDIO_CHANNEL_PARAMETERS)))
  843. {
  844. return CAPS_E_INVALID_PARAM;
  845. }
  846. if(!uNumLocalFormats || !pLocalFormats)
  847. {
  848. return CAPS_E_NOCAPS;
  849. }
  850. for(i=0; i<uNumLocalFormats; i++)
  851. {
  852. WORD wFramesPerPkt;
  853. pFmtMine = pLocalFormats + IDsByRank[i];
  854. // compare capabilities - start by comparing the format tag. a.k.a. "ClientType" in H.245 land
  855. if(pFmtMine->H245TermCap.ClientType == pCapability->ClientType)
  856. {
  857. // if this is a nonstandard cap, compare nonstandard parameters
  858. if(pFmtMine->H245TermCap.ClientType == H245_CLIENT_AUD_NONSTD)
  859. {
  860. if(NonstandardCapsCompareA(pFmtMine,
  861. (PNSC_AUDIO_CAPABILITY)pCapability->Cap.H245Aud_NONSTD.data.value,
  862. pCapability->Cap.H245Aud_NONSTD.data.length))
  863. {
  864. PNSC_AUDIO_CAPABILITY pNSCapRemote;
  865. pNSCapRemote = (PNSC_AUDIO_CAPABILITY)pCapability->Cap.H245Aud_NONSTD.data.value;
  866. if (pNSCapRemote->cap_params.wFramesPerPkt <= pFmtMine->nonstd_params.wFramesPerPktMax)
  867. {
  868. pAudioParams->ns_params = pNSCapRemote->cap_params;
  869. goto RESOLVED_EXIT;
  870. }
  871. }
  872. }
  873. else // compare standard parameters, if any
  874. {
  875. if(pFmtMine->H245TermCap.ClientType == H245_CLIENT_AUD_G723)
  876. {
  877. // NEED TO FIND THE G.723 format that results in the largest buffer
  878. // size calculations so that the larger bitrate format can be used.
  879. // The buffer size calculations in the datapump are based on the
  880. // WAVEFORMATEX structure
  881. // search the remainder of the prioritized list, keep the best
  882. LPWAVEFORMATEX lpwf1, lpwf2;
  883. AUDCAP_DETAILS *pFmtTry;
  884. lpwf1 =(LPWAVEFORMATEX)pFmtMine->lpLocalFormatDetails;
  885. for(j = i+1; j<uNumLocalFormats; j++)
  886. {
  887. pFmtTry = pLocalFormats + IDsByRank[j];
  888. if(pFmtTry->H245TermCap.ClientType != H245_CLIENT_AUD_G723)
  889. continue;
  890. lpwf2 =(LPWAVEFORMATEX)pFmtTry->lpLocalFormatDetails;
  891. if(lpwf2->nAvgBytesPerSec > lpwf1->nAvgBytesPerSec)
  892. {
  893. //pFmtMine = pFmtTry;
  894. lpwf1 = lpwf2;
  895. // Return value is based on index i. This one is the
  896. // one we want so far
  897. i = j;
  898. }
  899. }
  900. // We know that the G.723 codec can decode SID in any mode,
  901. //
  902. //if(pFmtMine->H245Cap.Cap.H245Aud_G723.silenceSuppression ==
  903. // pCapability->Cap.H245Aud_G723.silenceSuppression)
  904. //{
  905. //}
  906. }
  907. pAudioParams->ns_params = pFmtMine->nonstd_params;
  908. // update wFramesPerPkt with the actual recv channel parameter
  909. switch (pCapability->ClientType)
  910. {
  911. default:
  912. case H245_CLIENT_AUD_G711_ALAW64:
  913. wFramesPerPkt = pCapability->Cap.H245Aud_G711_ALAW64 * SAMPLE_BASED_SAMPLES_PER_FRAME;
  914. break;
  915. case H245_CLIENT_AUD_G711_ULAW64:
  916. wFramesPerPkt = pCapability->Cap.H245Aud_G711_ULAW64 * SAMPLE_BASED_SAMPLES_PER_FRAME;
  917. break;
  918. // these have no parameters
  919. //case H245_CLIENT_AUD_G711_ULAW56:
  920. //case H245_CLIENT_AUD_G711_ALAW56:
  921. break;
  922. case H245_CLIENT_AUD_G723:
  923. wFramesPerPkt = pCapability->Cap.H245Aud_G723.maxAl_sduAudioFrames;
  924. break;
  925. }
  926. if (wFramesPerPkt <= pFmtMine->nonstd_params.wFramesPerPktMax)
  927. {
  928. pAudioParams->ns_params.wFramesPerPkt = wFramesPerPkt;
  929. goto RESOLVED_EXIT;
  930. }
  931. else
  932. {
  933. DEBUGMSG (ZONE_CONN,("Recv channel wFramesPerPkt mismatch! ours=%d, theirs=%d\r\n",pFmtMine->nonstd_params.wFramesPerPktMax,wFramesPerPkt));
  934. }
  935. }
  936. }
  937. }
  938. return CAPS_E_NOMATCH;
  939. RESOLVED_EXIT:
  940. // Match!
  941. // return ID of the decoding caps that match
  942. *pFormatID = IndexToId(IDsByRank[i]);
  943. pAudioParams->RTP_Payload = pChannelParams->bRTPPayloadType;
  944. pAudioParams->ns_params.UseSilenceDet = (BYTE)pChannelParams->bSilenceSuppression;
  945. DEBUGMSG (ZONE_CONN,("Audio resolved (RECEIVE) to Format Tag: %d\r\n",pFmtMine->wFormatTag));
  946. return hrSuccess;
  947. }
  948. DWORD CMsiaCapability::MinFramesPerPacket(WAVEFORMATEX *pwf)
  949. {
  950. UINT sblk, uSize;
  951. uSize = MinSampleSize(pwf); // this calculates the minimum # of samples
  952. // that will still fit in an 80 mS frame
  953. // calculate samples per block ( aka frame)
  954. sblk = pwf->nBlockAlign* pwf->nSamplesPerSec/ pwf->nAvgBytesPerSec;
  955. if(!sblk)
  956. return 0; // should never happen unless ACM is corrupted,
  957. // min samples per frame/samples per block = min frames/block.
  958. return uSize/sblk;
  959. }
  960. //
  961. // determine a reasonable maximum number of frames per packet.
  962. // 4x the Minimum is reasonable, so long as it doesn't make
  963. // the packet too big
  964. DWORD CMsiaCapability::MaxFramesPerPacket(WAVEFORMATEX *pwf)
  965. {
  966. DWORD dwMin, dwMax;
  967. dwMin = MinFramesPerPacket(pwf); // minimum number of frames
  968. dwMax = MAX_FRAME_LEN_RECV / (dwMin * pwf->nBlockAlign);
  969. dwMax = min((4*dwMin), dwMax*dwMin);
  970. if (dwMax < dwMin)
  971. {
  972. WARNING_OUT(("CMsiaCapability::MaxFramesPerPacket - Max value computed as less than min. Return Min for Max\r\n"));
  973. dwMax = dwMin;
  974. }
  975. return dwMax;
  976. }
  977. //
  978. // MinSampleSize() taken from datapump.cpp ChoosePacketSize()
  979. //
  980. // what else depends on it?
  981. UINT CMsiaCapability::MinSampleSize(WAVEFORMATEX *pwf)
  982. {
  983. // calculate default samples per pkt
  984. UINT spp, sblk;
  985. spp = m_uPacketDuration * pwf->nSamplesPerSec / 1000;
  986. // calculate samples per block ( aka frame)
  987. sblk = pwf->nBlockAlign* pwf->nSamplesPerSec/ pwf->nAvgBytesPerSec;
  988. if (sblk <= spp) {
  989. spp = (spp/sblk)*sblk;
  990. if ( spp*pwf->nAvgBytesPerSec/pwf->nSamplesPerSec > MAX_FRAME_LEN) {
  991. // packet too big
  992. spp = (MAX_FRAME_LEN/pwf->nBlockAlign)*sblk;
  993. }
  994. } else
  995. spp = sblk;
  996. return spp;
  997. }
  998. HRESULT CMsiaCapability::IsFormatEnabled (MEDIA_FORMAT_ID FormatID, PBOOL bRecv, PBOOL bSend)
  999. {
  1000. UINT uIndex = IDToIndex(FormatID);
  1001. // validate input
  1002. if(uIndex >= (UINT)uNumLocalFormats)
  1003. {
  1004. return CAPS_E_INVALID_PARAM;
  1005. }
  1006. *bSend=((pLocalFormats + uIndex)->bSendEnabled);
  1007. *bRecv=((pLocalFormats + uIndex)->bRecvEnabled);
  1008. return hrSuccess;
  1009. }
  1010. BOOL CMsiaCapability::IsFormatPublic (MEDIA_FORMAT_ID FormatID)
  1011. {
  1012. UINT uIndex = IDToIndex(FormatID);
  1013. // validate input
  1014. if(uIndex >= (UINT)uNumLocalFormats)
  1015. return FALSE;
  1016. // test if this is format is a duplicate of a public format
  1017. if((pLocalFormats + uIndex)->dwPublicRefIndex)
  1018. return FALSE; // then we keep this format to ourselves
  1019. else
  1020. return TRUE;
  1021. }
  1022. MEDIA_FORMAT_ID CMsiaCapability::GetPublicID(MEDIA_FORMAT_ID FormatID)
  1023. {
  1024. UINT uIndex = IDToIndex(FormatID);
  1025. // validate input
  1026. if(uIndex >= (UINT)uNumLocalFormats)
  1027. return INVALID_MEDIA_FORMAT;
  1028. if((pLocalFormats + uIndex)->dwPublicRefIndex)
  1029. {
  1030. return (pLocalFormats + ((pLocalFormats + uIndex)->dwPublicRefIndex))->H245TermCap.CapId;
  1031. }
  1032. else
  1033. {
  1034. return FormatID;
  1035. }
  1036. }
  1037. #ifdef DEBUG
  1038. VOID DumpWFX(LPWAVEFORMATEX lpwfxLocal, LPWAVEFORMATEX lpwfxRemote)
  1039. {
  1040. FX_ENTRY("DumpWFX");
  1041. ERRORMESSAGE((" -------- %s Begin --------\r\n",_fx_));
  1042. if(lpwfxLocal)
  1043. {
  1044. ERRORMESSAGE((" -------- Local --------\r\n"));
  1045. ERRORMESSAGE(("wFormatTag:\t0x%04X, nChannels:\t0x%04X\r\n",
  1046. lpwfxLocal->wFormatTag, lpwfxLocal->nChannels));
  1047. ERRORMESSAGE(("nSamplesPerSec:\t0x%08lX, nAvgBytesPerSec:\t0x%08lX\r\n",
  1048. lpwfxLocal->nSamplesPerSec, lpwfxLocal->nAvgBytesPerSec));
  1049. ERRORMESSAGE(("nBlockAlign:\t0x%04X, wBitsPerSample:\t0x%04X, cbSize:\t0x%04X\r\n",
  1050. lpwfxLocal->nBlockAlign, lpwfxLocal->wBitsPerSample, lpwfxLocal->cbSize));
  1051. }
  1052. if(lpwfxRemote)
  1053. {
  1054. ERRORMESSAGE((" -------- Remote --------\r\n"));
  1055. ERRORMESSAGE(("wFormatTag:\t0x%04X, nChannels:\t0x%04X\r\n",
  1056. lpwfxRemote->wFormatTag, lpwfxRemote->nChannels));
  1057. ERRORMESSAGE(("nSamplesPerSec:\t0x%08lX, nAvgBytesPerSec:\t0x%08lX\r\n",
  1058. lpwfxRemote->nSamplesPerSec, lpwfxRemote->nAvgBytesPerSec));
  1059. ERRORMESSAGE(("nBlockAlign:\t0x%04X, wBitsPerSample:\t0x%04X, cbSize:\t0x%04X\r\n",
  1060. lpwfxRemote->nBlockAlign, lpwfxRemote->wBitsPerSample, lpwfxRemote->cbSize));
  1061. }
  1062. ERRORMESSAGE((" -------- %s End --------\r\n",_fx_));
  1063. }
  1064. VOID DumpChannelParameters(PCC_TERMCAP pChanCap1, PCC_TERMCAP pChanCap2)
  1065. {
  1066. FX_ENTRY("DumpChannelParameters");
  1067. ERRORMESSAGE((" -------- %s Begin --------\r\n",_fx_));
  1068. if(pChanCap1)
  1069. {
  1070. ERRORMESSAGE((" -------- Local Cap --------\r\n"));
  1071. ERRORMESSAGE(("DataType:%d(d), ClientType:%d(d)\r\n",pChanCap1->DataType,pChanCap1->ClientType));
  1072. ERRORMESSAGE(("Direction:%d(d), CapId:%d(d)\r\n",pChanCap1->Dir,pChanCap1->CapId));
  1073. }
  1074. if(pChanCap2)
  1075. {
  1076. ERRORMESSAGE((" -------- Remote Cap --------\r\n"));
  1077. ERRORMESSAGE(("DataType:%d(d), ClientType:%d(d)\r\n",pChanCap2->DataType,pChanCap2->ClientType));
  1078. ERRORMESSAGE(("Direction:%d(d), CapId:%d(d)\r\n",pChanCap2->Dir,pChanCap2->CapId));
  1079. }
  1080. ERRORMESSAGE((" -------- %s End --------\r\n",_fx_));
  1081. }
  1082. VOID DumpNonstdParameters(PCC_TERMCAP pChanCap1, PCC_TERMCAP pChanCap2)
  1083. {
  1084. FX_ENTRY("DumpNonstdParameters");
  1085. ERRORMESSAGE((" -------- %s Begin --------\r\n",_fx_));
  1086. DumpChannelParameters(pChanCap1, pChanCap2);
  1087. if(pChanCap1)
  1088. {
  1089. ERRORMESSAGE((" -------- Local Cap --------\r\n"));
  1090. if(pChanCap1->Cap.H245Aud_NONSTD.nonStandardIdentifier.choice == h221NonStandard_chosen)
  1091. {
  1092. ERRORMESSAGE(("t35CountryCode:%d(d), t35Extension:%d(d)\r\n",
  1093. pChanCap1->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.t35CountryCode,
  1094. pChanCap1->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.t35Extension));
  1095. ERRORMESSAGE(("MfrCode:%d(d), data length:%d(d)\r\n",
  1096. pChanCap1->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.manufacturerCode,
  1097. pChanCap1->Cap.H245Aud_NONSTD.data.length));
  1098. }
  1099. else
  1100. {
  1101. ERRORMESSAGE(("unrecognized nonStandardIdentifier.choice: %d(d)\r\n",
  1102. pChanCap1->Cap.H245Aud_NONSTD.nonStandardIdentifier.choice));
  1103. }
  1104. }
  1105. if(pChanCap2)
  1106. {
  1107. ERRORMESSAGE((" -------- Remote Cap --------\r\n"));
  1108. if(pChanCap2->Cap.H245Aud_NONSTD.nonStandardIdentifier.choice == h221NonStandard_chosen)
  1109. {
  1110. ERRORMESSAGE(("t35CountryCode:%d(d), t35Extension:%d(d)\r\n",
  1111. pChanCap2->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.t35CountryCode,
  1112. pChanCap2->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.t35Extension));
  1113. ERRORMESSAGE(("MfrCode:%d(d), data length:%d(d)\r\n",
  1114. pChanCap2->Cap.H245Aud_NONSTD.nonStandardIdentifier.u.h221NonStandard.manufacturerCode,
  1115. pChanCap2->Cap.H245Aud_NONSTD.data.length));
  1116. }
  1117. else
  1118. {
  1119. ERRORMESSAGE(("nonStandardIdentifier.choice: %d(d)\r\n",
  1120. pChanCap2->Cap.H245Aud_NONSTD.nonStandardIdentifier.choice));
  1121. }
  1122. }
  1123. ERRORMESSAGE((" -------- %s End --------\r\n",_fx_));
  1124. }
  1125. #endif
  1126.