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.

2726 lines
88 KiB

  1. /*
  2. * File: msivcaps.cpp
  3. *
  4. * VCM implementation of Microsoft Network Video capability object.
  5. *
  6. * Revision History:
  7. *
  8. * 06/06/96 mikev created msiacaps.cpp
  9. * 07/28/96 philf created (added support for video)
  10. */
  11. #define _MSIAV_ TRUE
  12. #include "precomp.h"
  13. BOOL GetFormatBuffer();
  14. extern PVCMFORMATDETAILS pvfd_g;
  15. #define PREF_ORDER_UNASSIGNED 0xffff
  16. //External function (in msiacaps.cpp) to read reg info in one shot
  17. #ifdef DEBUG
  18. extern ULONG ReadRegistryFormats (LPCSTR lpszKeyName,CHAR ***pppName,BYTE ***pppData,PUINT pnFormats,DWORD dwDebugSize);
  19. #else
  20. extern ULONG ReadRegistryFormats (LPCSTR lpszKeyName,CHAR ***pppName,BYTE ***pppData,PUINT pnFormats);
  21. #endif
  22. //This can be used as an export, so give it a unique name!
  23. #ifndef _ALPHA_
  24. VIDCAP_DETAILS default_vid_table[] =
  25. {
  26. #ifdef USE_BILINEAR_MSH26X
  27. {VIDEO_FORMAT_MSH263,STD_VID_TERMCAP(H245_CLIENT_VID_H263),STD_VID_PARAMS,{RTP_PAYLOAD_H263,0,30, 24, Small, 128, 96},0,TRUE,TRUE,1,245760*8,245760*8,10,10,5,0,NULL,0,NULL,"Microsoft H.263 Video Codec, vidc.M263, 24bit, 30fps, 128x096"},
  28. {VIDEO_FORMAT_MSH263,STD_VID_TERMCAP(H245_CLIENT_VID_H263),STD_VID_PARAMS,{RTP_PAYLOAD_H263,0,30, 24, Medium, 176, 144},0,TRUE,TRUE,1,245760*8,245760*8,10,10,4,0,NULL,0,NULL,"Microsoft H.263 Video Codec, vidc.M263, 24bit, 30fps, 176x144"},
  29. {VIDEO_FORMAT_MSH263,STD_VID_TERMCAP(H245_CLIENT_VID_H263),STD_VID_PARAMS,{RTP_PAYLOAD_H263,0,30, 24, Large, 352, 288},0,TRUE,TRUE,1,245760*8*4,245760*8*4,10,10,6,0,NULL,0,NULL,"Microsoft H.263 Video Codec, vidc.M263, 24bit, 30fps, 352x288"},
  30. {VIDEO_FORMAT_MSH261,STD_VID_TERMCAP(H245_CLIENT_VID_H261),STD_VID_PARAMS,{RTP_PAYLOAD_H261,0,30, 24, Medium, 176, 144},0,TRUE,TRUE,1,245760*8,245760*8,10,10,7,0,NULL,0,NULL,"Microsoft H.261 Video Codec, vidc.M261, 24bit, 30fps, 176x144"},
  31. {VIDEO_FORMAT_MSH261,STD_VID_TERMCAP(H245_CLIENT_VID_H261),STD_VID_PARAMS,{RTP_PAYLOAD_H261,0,30, 24, Large, 352, 288},0,TRUE,TRUE,1,245760*8*4,245760*8*4,10,10,8,0,NULL,0,NULL,"Microsoft H.261 Video Codec, vidc.M261, 24bit, 30fps, 352x288"},
  32. {VIDEO_FORMAT_MSH26X,NONSTD_VID_TERMCAP,STD_VID_PARAMS,{RTP_DYNAMIC_MIN+1,0,24, Small, 80, 64},0,TRUE,TRUE,1,245760*8,245760*8,10,10,2,0,NULL,0,NULL,"Microsoft H.263 Video Codec, vidc.M26X, 24bit, 30fps, 080x064"},
  33. {VIDEO_FORMAT_MSH26X,NONSTD_VID_TERMCAP,STD_VID_PARAMS,{RTP_DYNAMIC_MIN+1,0,30, 24, Medium, 128, 96},0,TRUE,TRUE,1,245760*8,245760*8,10,10,1,0,NULL,0,NULL,"Microsoft H.263 Video Codec, vidc.M26X, 24bit, 30fps, 128x096"},
  34. {VIDEO_FORMAT_MSH26X,NONSTD_VID_TERMCAP,STD_VID_PARAMS,{RTP_DYNAMIC_MIN+1,0,24, Large, 176, 144},0,TRUE,TRUE,1,245760*8,245760*8,10,10,3,0,NULL,0,NULL,"Microsoft H.263 Video Codec, vidc.M26X, 24bit, 30fps, 176x144"}
  35. #else
  36. {VIDEO_FORMAT_MSH263,STD_VID_TERMCAP(H245_CLIENT_VID_H263),STD_VID_PARAMS,{RTP_PAYLOAD_H263,0,30, 24, Small, 128, 96},0,TRUE,TRUE,1,245760*8,245760*8,10,10,5,0,NULL,0,NULL,"Microsoft H.263 Video Codec, vidc.M263, 24bit, 30fps, 128x096"},
  37. {VIDEO_FORMAT_MSH263,STD_VID_TERMCAP(H245_CLIENT_VID_H263),STD_VID_PARAMS,{RTP_PAYLOAD_H263,0,30, 24, Medium, 176, 144},0,TRUE,TRUE,1,245760*8,245760*8,10,10,2,0,NULL,0,NULL,"Microsoft H.263 Video Codec, vidc.M263, 24bit, 30fps, 176x144"},
  38. {VIDEO_FORMAT_MSH263,STD_VID_TERMCAP(H245_CLIENT_VID_H263),STD_VID_PARAMS,{RTP_PAYLOAD_H263,0,30, 24, Large, 352, 288},0,TRUE,TRUE,1,245760*8*4,245760*8*4,10,10,14,0,NULL,0,NULL,"Microsoft H.263 Video Codec, vidc.M263, 24bit, 30fps, 352x288"},
  39. {VIDEO_FORMAT_MSH261,STD_VID_TERMCAP(H245_CLIENT_VID_H261),STD_VID_PARAMS,{RTP_PAYLOAD_H261,0,30, 24, Medium, 176, 144},0,TRUE,TRUE,1,245760*8,245760*8,10,10,9,0,NULL,0,NULL,"Microsoft H.261 Video Codec, vidc.M261, 24bit, 30fps, 176x144"},
  40. {VIDEO_FORMAT_MSH261,STD_VID_TERMCAP(H245_CLIENT_VID_H261),STD_VID_PARAMS,{RTP_PAYLOAD_H261,0,30, 24, Large, 352, 288},0,TRUE,TRUE,1,245760*8*4,245760*8*4,10,10,20,0,NULL,0,NULL,"Microsoft H.261 Video Codec, vidc.M261, 24bit, 30fps, 352x288"},
  41. #endif
  42. };
  43. #else
  44. VIDCAP_DETAILS default_vid_table[] =
  45. {
  46. {VIDEO_FORMAT_DECH263,STD_VID_TERMCAP(H245_CLIENT_VID_H263),STD_VID_PARAMS,{RTP_PAYLOAD_H263,0,30, 24, Small,128, 96},0,TRUE,TRUE,1,53760,53760,10,10,10,0,0,5,0,NULL,0,NULL, "Digital H263 Video CODEC, vidc.D263, 24bit, 30fps, 128x096"},
  47. {VIDEO_FORMAT_DECH263,STD_VID_TERMCAP(H245_CLIENT_VID_H263),STD_VID_PARAMS,{RTP_PAYLOAD_H263,0,30, 24, Medium,176, 144},0,TRUE,TRUE,1,53760,53760,10,10,10,0,0,2,0,NULL,0,NULL,"Digital H263 Video Codec, vidc.D263, 24bit, 30fps, 176x144"},
  48. {VIDEO_FORMAT_DECH263,STD_VID_TERMCAP(H245_CLIENT_VID_H263),STD_VID_PARAMS,{RTP_PAYLOAD_H263,0,30, 24, Large,352, 288},0,TRUE,TRUE,1,53760,53760,10,10,10,0,0,14,0,NULL,0,NULL,"Digital H263 Video Codec, vidc.D263, 24bit, 30fps, 352x288"},
  49. {VIDEO_FORMAT_DECH261,STD_VID_TERMCAP(H245_CLIENT_VID_H261),STD_VID_PARAMS,{RTP_PAYLOAD_H261,0,30, 24, Medium,176, 144},0,TRUE,TRUE,1,53760,53760,10,10,10,0,0,9,0,NULL,0,NULL,"Digital H261 Video Codec, vidc.D261, 24bit, 30fps, 176x144"},
  50. {VIDEO_FORMAT_DECH261,STD_VID_TERMCAP(H245_CLIENT_VID_H261),STD_VID_PARAMS,{RTP_PAYLOAD_H261,0,30, 24, Large,352, 288},0,TRUE,TRUE,1,53760,53760,10,10,10,0,0,20,0,NULL,0,NULL,"Digital H261 Video Codec, vidc.D261, 24bit, 30fps, 352x288"},
  51. };
  52. #endif
  53. static UINT uDefVidTableEntries = sizeof(default_vid_table) /sizeof(VIDCAP_DETAILS);
  54. static BOOL bCreateDefTable = FALSE;
  55. //
  56. // static members of CMsivCapability
  57. //
  58. MEDIA_FORMAT_ID CMsivCapability::IDsByRank[MAX_CAPS_PRESORT];
  59. UINT CMsivCapability::uNumLocalFormats = 0; // # of active entries in pLocalFormats
  60. UINT CMsivCapability::uStaticRef = 0; // global ref count
  61. UINT CMsivCapability::uCapIDBase = 0; // rebase capability ID to index into IDsByRank
  62. UINT CMsivCapability::uLocalFormatCapacity = 0; // size of pLocalFormats (in multiples of AUDCAP_DETAILS)
  63. VIDCAP_DETAILS * CMsivCapability::pLocalFormats = NULL;
  64. CMsivCapability::CMsivCapability()
  65. :uRef(1),
  66. wMaxCPU(95),
  67. uNumRemoteDecodeFormats(0),
  68. uRemoteDecodeFormatCapacity(0),
  69. pRemoteDecodeFormats(NULL),
  70. bPublicizeTXCaps(FALSE),
  71. bPublicizeTSTradeoff(TRUE)
  72. {
  73. m_IAppVidCap.Init(this);
  74. }
  75. CMsivCapability::~CMsivCapability()
  76. {
  77. UINT u;
  78. VIDCAP_DETAILS *pDetails;
  79. // release global static memory (the local capabilities) if this is the last delete
  80. if(uStaticRef <= 1)
  81. {
  82. if (pLocalFormats)
  83. {
  84. pDetails = pLocalFormats;
  85. for(u=0; u <uNumLocalFormats; u++)
  86. {
  87. if(pDetails->lpLocalFormatDetails)
  88. {
  89. MEMFREE(pDetails->lpLocalFormatDetails);
  90. }
  91. // there really should never be remote details associated with the local
  92. // formats........
  93. if(pDetails->lpRemoteFormatDetails)
  94. {
  95. MEMFREE(pDetails->lpRemoteFormatDetails);
  96. }
  97. pDetails++;
  98. }
  99. MEMFREE(pLocalFormats);
  100. pLocalFormats=NULL;
  101. uLocalFormatCapacity = 0;
  102. }
  103. uStaticRef--;
  104. }
  105. else
  106. {
  107. uStaticRef--;
  108. }
  109. if (pRemoteDecodeFormats)
  110. {
  111. pDetails = pRemoteDecodeFormats;
  112. for(u=0; u <uNumRemoteDecodeFormats; u++)
  113. {
  114. if(pDetails->lpLocalFormatDetails)
  115. {
  116. MEMFREE(pDetails->lpLocalFormatDetails);
  117. }
  118. // there really should never be remote details associated with the local
  119. // formats........
  120. if(pDetails->lpRemoteFormatDetails)
  121. {
  122. MEMFREE(pDetails->lpRemoteFormatDetails);
  123. }
  124. pDetails++;
  125. }
  126. MEMFREE(pRemoteDecodeFormats);
  127. pRemoteDecodeFormats=NULL;
  128. uRemoteDecodeFormatCapacity = 0;
  129. }
  130. }
  131. UINT CMsivCapability::GetNumCaps(BOOL bRXCaps)
  132. {
  133. UINT u, uOut=0;
  134. VIDCAP_DETAILS *pDecodeDetails = pLocalFormats;
  135. if(bRXCaps)
  136. {
  137. for(u=0; u <uNumLocalFormats; u++)
  138. {
  139. if(pDecodeDetails->bRecvEnabled)
  140. uOut++;
  141. pDecodeDetails++;
  142. }
  143. return uOut;
  144. }
  145. else
  146. {
  147. for(u=0; u <uNumLocalFormats; u++)
  148. {
  149. if(pDecodeDetails->bSendEnabled)
  150. uOut++;
  151. pDecodeDetails++;
  152. }
  153. return uOut;
  154. }
  155. }
  156. STDMETHODIMP CMsivCapability::QueryInterface( REFIID iid, void ** ppvObject)
  157. {
  158. HRESULT hr = E_NOINTERFACE;
  159. if(!ppvObject)
  160. return hr;
  161. *ppvObject = 0;
  162. if(iid == IID_IAppVidCap )
  163. {
  164. *ppvObject = (LPAPPVIDCAPPIF)&m_IAppVidCap;
  165. AddRef();
  166. hr = hrSuccess;
  167. }
  168. else if(iid == IID_IH323MediaCap)
  169. {
  170. *ppvObject = (IH323MediaCap *)this;
  171. AddRef();
  172. hr = hrSuccess;
  173. }
  174. else if (iid == IID_IUnknown)
  175. {
  176. *ppvObject = this;
  177. AddRef();
  178. hr = hrSuccess;
  179. }
  180. return hr;
  181. }
  182. ULONG CMsivCapability::AddRef()
  183. {
  184. uRef++;
  185. return uRef;
  186. }
  187. ULONG CMsivCapability::Release()
  188. {
  189. uRef--;
  190. if(uRef == 0)
  191. {
  192. delete this;
  193. return 0;
  194. }
  195. return uRef;
  196. }
  197. HRESULT CMsivCapability::GetNumFormats(UINT *puNumFmtOut)
  198. {
  199. *puNumFmtOut = uNumLocalFormats;
  200. return hrSuccess;
  201. }
  202. VOID CMsivCapability::FreeRegistryKeyName(LPTSTR lpszKeyName)
  203. {
  204. if (lpszKeyName)
  205. {
  206. LocalFree(lpszKeyName);
  207. }
  208. }
  209. LPTSTR CMsivCapability::AllocRegistryKeyName(LPTSTR lpDriverName,
  210. UINT uSampleRate, UINT uBitsPerSample, UINT uBitsPerSec,UINT uWidth,UINT uHeight)
  211. {
  212. FX_ENTRY(("AllocRegistryKeyName"));
  213. BOOL bRet = FALSE;
  214. LPTSTR lpszKeyName = NULL;
  215. if(!lpDriverName)
  216. {
  217. return NULL;
  218. }
  219. // build a subkey name (drivername_samplerate_bitspersample)
  220. // allow room for THREE underscore chars + 2x17 bytes of string returned
  221. // from _itoa
  222. // NOTE: use wsprintf instead of itoa - because of dependency on runtime lib
  223. //Added 2 UINTs for video...
  224. lpszKeyName = (LPTSTR)LocalAlloc (LPTR, lstrlen(lpDriverName) * sizeof(*lpDriverName) +5*20);
  225. if (!lpszKeyName)
  226. {
  227. ERRORMESSAGE(("%s: LocalAlloc failed\r\n",_fx_));
  228. return(NULL);
  229. }
  230. // build a subkey name ("drivername_samplerate_bitspersample")
  231. wsprintf(lpszKeyName,
  232. "%s_%u_%u_%u_%u_%u",
  233. lpDriverName,
  234. uSampleRate,
  235. uBitsPerSample,
  236. uBitsPerSec,
  237. uWidth,
  238. uHeight);
  239. return (lpszKeyName);
  240. }
  241. VOID CMsivCapability::SortEncodeCaps(SortMode sortmode)
  242. {
  243. UINT iSorted=0;
  244. UINT iInsert = 0;
  245. UINT iCache=0;
  246. UINT iTemp =0;
  247. BOOL bInsert;
  248. VIDCAP_DETAILS *pDetails1, *pDetails2;
  249. if(!uNumLocalFormats)
  250. return;
  251. if(uNumLocalFormats ==1)
  252. {
  253. IDsByRank[0]=0;
  254. return;
  255. }
  256. // look at every cached format, build index array
  257. for(iCache=0;iCache<uNumLocalFormats;iCache++)
  258. {
  259. pDetails1 = pLocalFormats+iCache;
  260. for(iInsert=0;iInsert < iSorted; iInsert++)
  261. {
  262. pDetails2 = pLocalFormats+IDsByRank[iInsert];
  263. // if existing stuff is less than new stuff....
  264. bInsert = FALSE;
  265. switch(sortmode)
  266. {
  267. case SortByAppPref:
  268. if(pDetails2->wApplicationPrefOrder > pDetails1->wApplicationPrefOrder)
  269. bInsert = TRUE;
  270. break;
  271. default:
  272. break;
  273. }
  274. if(bInsert)
  275. {
  276. if(iSorted < MAX_CAPS_PRESORT)
  277. {
  278. iSorted++;
  279. }
  280. // make room, if there is something in the last element,
  281. // it gets overwritten
  282. for(iTemp = iSorted-1; iTemp > iInsert; iTemp--)
  283. {
  284. IDsByRank[iTemp] = IDsByRank[iTemp-1];
  285. }
  286. // insert at iInsert
  287. IDsByRank[iInsert] = iCache;
  288. break;
  289. }
  290. }
  291. // check end boundary
  292. if((iInsert == iSorted) && (iInsert < MAX_CAPS_PRESORT))
  293. {
  294. IDsByRank[iInsert] = iCache;
  295. iSorted++;
  296. }
  297. }
  298. }
  299. BOOL CMsivCapability::Init()
  300. {
  301. BOOL bRet;
  302. if(uStaticRef == 0)
  303. {
  304. if(bRet = ReInit())
  305. {
  306. uStaticRef++;
  307. }
  308. }
  309. else
  310. {
  311. uStaticRef++;
  312. bRet = TRUE;
  313. }
  314. return bRet;
  315. }
  316. BOOL CMsivCapability::ReInit()
  317. {
  318. DWORD dwDisposition;
  319. BOOL bRet = TRUE;
  320. //CVcmCapability::ReInit(); // base class ReInit MUST ALWAYS BE CALLED
  321. SYSTEM_INFO si;
  322. ZeroMemory(&IDsByRank, sizeof(IDsByRank));
  323. // LOOKLOOK - this supports a hack to disable CPU intensive codecs if not running on a pentium
  324. GetSystemInfo(&si);
  325. wMaxCPU = (si.dwProcessorType == PROCESSOR_INTEL_PENTIUM )? 100 : 95;
  326. UINT uNumRemoteDecodeFormats; // # of entries for remote decode capabilities
  327. UINT uRemoteDecodeFormatCapacity; // size of pRemoteDecodeFormats (in multiples of VIDCAP_DETAILS)
  328. if (pLocalFormats)
  329. {
  330. UINT u;
  331. VIDCAP_DETAILS *pDetails = pLocalFormats;
  332. for(u=0; u <uNumLocalFormats; u++)
  333. {
  334. if(pDetails->lpLocalFormatDetails)
  335. {
  336. MEMFREE(pDetails->lpLocalFormatDetails);
  337. }
  338. // there really should never be remote details associated with the local
  339. // formats........
  340. if(pDetails->lpRemoteFormatDetails)
  341. {
  342. MEMFREE(pDetails->lpRemoteFormatDetails);
  343. }
  344. pDetails++;
  345. }
  346. MEMFREE(pLocalFormats);
  347. pLocalFormats = NULL;
  348. uLocalFormatCapacity = 0;
  349. }
  350. uNumLocalFormats = 0;
  351. uCapIDBase = 0;
  352. uLocalFormatCapacity =0;
  353. // m_pAppParam should be non-NULL only if we want to add a VCM format
  354. // and not for standard enumeration
  355. m_pAppParam = NULL;
  356. if(!FormatEnum(this, VCM_FORMATENUMF_APP))
  357. {
  358. bRet = FALSE;
  359. goto RELEASE_AND_EXIT;
  360. }
  361. SortEncodeCaps(SortByAppPref);
  362. RELEASE_AND_EXIT:
  363. return bRet;
  364. }
  365. STDMETHODIMP CMsivCapability::GetDecodeFormatDetails(MEDIA_FORMAT_ID FormatID, VOID **ppFormat, UINT *puSize)
  366. {
  367. // validate input
  368. UINT uIndex = IDToIndex(FormatID);
  369. if(uIndex >= (UINT)uNumLocalFormats)
  370. {
  371. *puSize = 0;
  372. *ppFormat = NULL;
  373. return E_INVALIDARG;
  374. }
  375. *ppFormat = (pLocalFormats + uIndex)->lpLocalFormatDetails;
  376. *puSize = sizeof(VIDEOFORMATEX);
  377. return S_OK;
  378. }
  379. STDMETHODIMP CMsivCapability::GetEncodeFormatDetails(MEDIA_FORMAT_ID FormatID, VOID **ppFormat, UINT *puSize)
  380. {
  381. // same as GetDecodeFormatDetails
  382. return GetDecodeFormatDetails(FormatID, ppFormat, puSize);
  383. }
  384. VOID CMsivCapability::CalculateFormatProperties(VIDCAP_DETAILS *pFmtBuf, PVIDEOFORMATEX lpvfx)
  385. {
  386. if(!pFmtBuf)
  387. {
  388. return;
  389. }
  390. // Estimate input bit rate
  391. UINT uBitrateIn = lpvfx->nSamplesPerSec * WIDTHBYTES(lpvfx->bih.biWidth * lpvfx->bih.biBitCount) * lpvfx->bih.biHeight * 8;
  392. // set the maximum bitrate (uMaxBitrate). we're not setting the average bitrate (uAvgBitrate),
  393. // since the nAvgBytesPerSec reported by VCM is really worst case. uAvgBitrate will be set
  394. // from the hardcoded numbers for our known codecs and from the provided VIDCAP_INFO for
  395. // installable codecs
  396. pFmtBuf->uMaxBitrate = (lpvfx->nAvgBytesPerSec)? lpvfx->nAvgBytesPerSec*8:uBitrateIn;
  397. }
  398. VIDEO_FORMAT_ID CMsivCapability::AddFormat(VIDCAP_DETAILS *pFmtBuf,
  399. LPVOID lpvMappingData, UINT uSize)
  400. {
  401. VIDCAP_DETAILS *pTemp;
  402. VIDEO_PARAMS *pVidCapInfo;
  403. UINT format;
  404. if(!pFmtBuf)
  405. {
  406. return INVALID_VIDEO_FORMAT;
  407. }
  408. // check room
  409. if(uLocalFormatCapacity <= uNumLocalFormats)
  410. {
  411. // get more mem, realloc memory by CAP_CHUNK_SIZE for pLocalFormats
  412. pTemp = (VIDCAP_DETAILS *)MEMALLOC((uNumLocalFormats + CAP_CHUNK_SIZE)*sizeof(VIDCAP_DETAILS));
  413. if(!pTemp)
  414. goto ERROR_EXIT;
  415. // remember how much capacity we now have
  416. uLocalFormatCapacity = uNumLocalFormats + CAP_CHUNK_SIZE;
  417. #ifdef DEBUG
  418. if((uNumLocalFormats && !pLocalFormats) || (!uNumLocalFormats && pLocalFormats))
  419. {
  420. ERRORMESSAGE(("AddFormat:leak! uNumLocalFormats:0x%08lX, pLocalFormats:0x%08lX\r\n", uNumLocalFormats,pLocalFormats));
  421. }
  422. #endif
  423. // copy old stuff, discard old mem
  424. if(uNumLocalFormats && pLocalFormats)
  425. {
  426. memcpy(pTemp, pLocalFormats, uNumLocalFormats*sizeof(VIDCAP_DETAILS));
  427. MEMFREE(pLocalFormats);
  428. }
  429. pLocalFormats = pTemp;
  430. }
  431. // pTemp is where the stuff is cached
  432. pTemp = pLocalFormats+uNumLocalFormats;
  433. memcpy(pTemp, pFmtBuf, sizeof(VIDCAP_DETAILS));
  434. pTemp->uLocalDetailsSize = 0; // clear this now
  435. if(uSize && lpvMappingData)
  436. {
  437. pTemp->lpLocalFormatDetails = MEMALLOC(uSize);
  438. if(pTemp->lpLocalFormatDetails)
  439. {
  440. memcpy(pTemp->lpLocalFormatDetails, lpvMappingData, uSize);
  441. pTemp->uLocalDetailsSize = uSize;
  442. }
  443. #ifdef DEBUG
  444. else
  445. {
  446. ERRORMESSAGE(("AddFormat:allocation failed!\r\n"));
  447. }
  448. #endif
  449. }
  450. else
  451. {
  452. }
  453. // LOOKLOOK NEED TO FIXUP channel parameters
  454. // pTemp->dwDefaultSamples
  455. // pTemp->nonstd_params.wFramesPerPkt
  456. // pTemp->nonstd_params.wFramesPerPktMax
  457. // pTemp->nonstd_params.wFramesPerPktMin
  458. // pTemp->nonstd_params.wDataRate
  459. // pTemp->nonstd_params.wFrameSize
  460. // fixup the H245 parameters. Use the index of the cap entry as the cap ID
  461. pTemp->H245Cap.CapId = (USHORT)IndexToId(uNumLocalFormats);
  462. if(pTemp->H245Cap.ClientType ==0
  463. || pTemp->H245Cap.ClientType ==H245_CLIENT_VID_NONSTD)
  464. {
  465. pTemp->H245Cap.Cap.H245Vid_NONSTD.nonStandardIdentifier.choice = h221NonStandard_chosen;
  466. // NOTE: there is some question about the correct byte order
  467. // of the codes in the h221NonStandard structure
  468. pTemp->H245Cap.Cap.H245Vid_NONSTD.nonStandardIdentifier.u.h221NonStandard.t35CountryCode = USA_H221_COUNTRY_CODE;
  469. pTemp->H245Cap.Cap.H245Vid_NONSTD.nonStandardIdentifier.u.h221NonStandard.t35Extension = USA_H221_COUNTRY_EXTENSION;
  470. pTemp->H245Cap.Cap.H245Vid_NONSTD.nonStandardIdentifier.u.h221NonStandard.manufacturerCode = MICROSOFT_H_221_MFG_CODE;
  471. // Set the nonstandard data fields to null for now. The nonstandard cap data will be
  472. // created when capabilities are serialized.
  473. pTemp->H245Cap.Cap.H245Vid_NONSTD.data.length = 0;
  474. pTemp->H245Cap.Cap.H245Vid_NONSTD.data.value = NULL;
  475. }
  476. else
  477. {
  478. switch (pTemp->H245Cap.ClientType )
  479. {
  480. case H245_CLIENT_VID_H263: {
  481. pVidCapInfo=&pTemp->video_params;
  482. format=get_format (pVidCapInfo->biWidth,pVidCapInfo->biHeight);
  483. switch (format) {
  484. case SQCIF: {
  485. pTemp->H245Cap.Cap.H245Vid_H263.bit_mask =H263VideoCapability_sqcifMPI_present;
  486. //MPI minimum interval in units of 1/29.97sec so 30/ (frames/sec) is reasonable
  487. pTemp->H245Cap.Cap.H245Vid_H263.sqcifMPI = 30/pVidCapInfo->uSamplesPerSec;
  488. pTemp->H245Cap.Cap.H245Vid_H263.H263VdCpblty_qcifMPI =0;
  489. pTemp->H245Cap.Cap.H245Vid_H263.H263VdCpblty_cifMPI =0;
  490. break;
  491. }
  492. case QCIF: {
  493. pTemp->H245Cap.Cap.H245Vid_H263.bit_mask =H263VideoCapability_qcifMPI_present;
  494. pTemp->H245Cap.Cap.H245Vid_H263.sqcifMPI = 0;
  495. pTemp->H245Cap.Cap.H245Vid_H263.H263VdCpblty_qcifMPI =30/pVidCapInfo->uSamplesPerSec;
  496. pTemp->H245Cap.Cap.H245Vid_H263.H263VdCpblty_cifMPI =0;
  497. break;
  498. }
  499. case CIF: {
  500. pTemp->H245Cap.Cap.H245Vid_H263.bit_mask =H263VideoCapability_cifMPI_present;
  501. pTemp->H245Cap.Cap.H245Vid_H263.sqcifMPI = 0;
  502. pTemp->H245Cap.Cap.H245Vid_H263.H263VdCpblty_qcifMPI =0;
  503. pTemp->H245Cap.Cap.H245Vid_H263.H263VdCpblty_cifMPI =30/pVidCapInfo->uSamplesPerSec;
  504. break;
  505. }
  506. default:
  507. break;
  508. }
  509. pTemp->H245Cap.Cap.H245Vid_H263.cif4MPI =0;
  510. pTemp->H245Cap.Cap.H245Vid_H263.cif16MPI =0;
  511. pTemp->H245Cap.Cap.H245Vid_H263.maxBitRate = pFmtBuf->uMaxBitrate / 100; // in units of 100 bits/s
  512. pTemp->H245Cap.Cap.H245Vid_H263.unrestrictedVector = FALSE;
  513. pTemp->H245Cap.Cap.H245Vid_H263.arithmeticCoding = FALSE;
  514. pTemp->H245Cap.Cap.H245Vid_H263.advancedPrediction = FALSE;
  515. pTemp->H245Cap.Cap.H245Vid_H263.pbFrames = FALSE;
  516. pTemp->H245Cap.Cap.H245Vid_H263.tmprlSptlTrdOffCpblty = FALSE;
  517. pTemp->H245Cap.Cap.H245Vid_H263.hrd_B = 0;
  518. pTemp->H245Cap.Cap.H245Vid_H263.bppMaxKb = 0;
  519. /* Optional, and not supported pTemp->H245Cap.Cap.H245Vid_H263.slowQcifMPI =0;
  520. pTemp->H245Cap.Cap.H245Vid_H263.slowSqcifMPI =0;
  521. pTemp->H245Cap.Cap.H245Vid_H263.slowCifMPI =0;
  522. pTemp->H245Cap.Cap.H245Vid_H263.slowCif4MPI =0;
  523. pTemp->H245Cap.Cap.H245Vid_H263.slowCif16MPI =0;
  524. */
  525. pTemp->H245Cap.Cap.H245Vid_H263.H263VCy_errrCmpnstn = TRUE;
  526. break;
  527. }
  528. case H245_CLIENT_VID_H261:
  529. pVidCapInfo=&pTemp->video_params;
  530. format=get_format (pVidCapInfo->biWidth,pVidCapInfo->biHeight);
  531. switch (format) {
  532. case QCIF: {
  533. pTemp->H245Cap.Cap.H245Vid_H261.bit_mask =H261VdCpblty_qcifMPI_present;
  534. pTemp->H245Cap.Cap.H245Vid_H261.H261VdCpblty_qcifMPI =max (1,min (4,30/pVidCapInfo->uSamplesPerSec));
  535. pTemp->H245Cap.Cap.H245Vid_H261.H261VdCpblty_cifMPI =0;
  536. break;
  537. }
  538. case CIF: {
  539. pTemp->H245Cap.Cap.H245Vid_H261.bit_mask =H261VdCpblty_cifMPI_present;
  540. pTemp->H245Cap.Cap.H245Vid_H261.H261VdCpblty_qcifMPI =0;
  541. pTemp->H245Cap.Cap.H245Vid_H261.H261VdCpblty_cifMPI =max (1,min(4,30/pVidCapInfo->uSamplesPerSec));
  542. break;
  543. }
  544. default:
  545. break;
  546. }
  547. pTemp->H245Cap.Cap.H245Vid_H261.maxBitRate = pFmtBuf->uMaxBitrate / 100; // in units of 100 bits/s
  548. pTemp->H245Cap.Cap.H245Vid_H261.tmprlSptlTrdOffCpblty = FALSE;
  549. pTemp->H245Cap.Cap.H245Vid_H261.stillImageTransmission = FALSE;
  550. break;
  551. }
  552. }
  553. uNumLocalFormats++;
  554. return pTemp->H245Cap.CapId;
  555. ERROR_EXIT:
  556. return INVALID_VIDEO_FORMAT;
  557. }
  558. /***************************************************************************
  559. Name : CMsivCapability::BuildFormatName
  560. Purpose : Builds a format name for a format, from the format name and
  561. the tag name
  562. Parameters: pVidcapDetails [out] - pointer to an VIDCAP_DETAILS structure, where the
  563. created value name will be stored
  564. pszDriverName [in] - pointer to the name of the driver
  565. pszFormatName [in] - pointer to name of the format
  566. Returns : BOOL
  567. Comment :
  568. ***************************************************************************/
  569. BOOL CMsivCapability::BuildFormatName( PVIDCAP_DETAILS pVidcapDetails,
  570. WCHAR *pszDriverName,
  571. WCHAR *pszFormatName)
  572. {
  573. int iLen, iLen2;
  574. BOOL bRet=TRUE;
  575. char szTemp[260];
  576. if (!pVidcapDetails ||
  577. !pszDriverName ||
  578. !pszFormatName)
  579. {
  580. bRet = FALSE;
  581. goto out;
  582. }
  583. // concatenate VCM strings to form the first part of the registry key - the
  584. // format is szFormatTag (actually pVidcapDetails->szFormat)
  585. // (the string which describes the format tag followed by szFormatDetails
  586. // (the string which describes parameters, e.g. sample rate)
  587. iLen2 = WideCharToMultiByte(GetACP(), 0, pszDriverName, -1, NULL, 0, NULL, NULL);
  588. WideCharToMultiByte(GetACP(), 0, pszDriverName, iLen2, szTemp, iLen2, NULL, NULL);
  589. lstrcpyn(pVidcapDetails->szFormat, szTemp, sizeof(pVidcapDetails->szFormat));
  590. iLen = lstrlen(pVidcapDetails->szFormat);
  591. // if the format tag description string takes up all the space, don't
  592. // bother with the format details (need space for ", " also).
  593. // we're going to say that if we don't have room for 4 characters
  594. // of the format details string + " ,", then it's not worth it if the
  595. // point is generating a unique string -if it is not unique by now, it
  596. // will be because some VCM driver writer was misinformed
  597. if(iLen < (sizeof(pVidcapDetails->szFormat) + 8*sizeof(TCHAR)))
  598. {
  599. // ok to concatenate
  600. lstrcat(pVidcapDetails->szFormat,", ");
  601. // must check for truncation. so do the final concatenation via lstrcpyn
  602. // lstrcat(pFormatPrefsBuf->szFormat, pvfd->szFormat);
  603. iLen2 = WideCharToMultiByte(GetACP(), 0, pszFormatName, -1, NULL, 0, NULL, NULL);
  604. WideCharToMultiByte(GetACP(), 0, pszFormatName, iLen2, szTemp, iLen2, NULL, NULL);
  605. iLen = lstrlen(pVidcapDetails->szFormat);
  606. lstrcpyn(pVidcapDetails->szFormat+iLen, szTemp,
  607. sizeof(pVidcapDetails->szFormat) - iLen - sizeof(TCHAR));
  608. }
  609. out:
  610. return bRet;
  611. }
  612. /***************************************************************************
  613. Name : CMsivCapability::GetFormatName
  614. Purpose : Gets a driver and format info from VCM and builds a format name
  615. Parameters: pVidcapDetails [out] - pointer to an VIDCAP_DETAILS structure, where the
  616. created value name will be stored
  617. pvfx [in] - pointer to the VIDEOFORMATEX structure for which we
  618. need the driver name and the format name
  619. Returns : HRESULT
  620. Comment :
  621. ***************************************************************************/
  622. HRESULT CMsivCapability::GetFormatName( PVIDCAP_DETAILS pVidcapDetails,
  623. PVIDEOFORMATEX pvfx)
  624. {
  625. VCMDRIVERDETAILS vdd;
  626. VCMFORMATDETAILS vfd;
  627. HRESULT hr=NOERROR;
  628. // get the driver details info in order to build correct format name
  629. vdd.fccHandler = pvfx->dwFormatTag;
  630. if (vcmDriverDetails(&vdd) != MMSYSERR_NOERROR)
  631. {
  632. ERRORMESSAGE(("CMsivCapability::GetFormatName: can't get the driver details\r\n"));
  633. hr = CAPS_E_NOMATCH;
  634. goto out;
  635. }
  636. // have the driver details. get the format details
  637. vfd.pvfx = pvfx;
  638. if (vcmFormatDetails(&vfd) != MMSYSERR_NOERROR)
  639. {
  640. ERRORMESSAGE(("CMsivCapability::GetFormatName: can't get the format details\r\n"));
  641. hr = CAPS_E_NOMATCH;
  642. goto out;
  643. }
  644. // have the format details too. build the name to store in the registry
  645. if (!BuildFormatName(pVidcapDetails, vdd.szDescription, vfd.szFormat))
  646. {
  647. ERRORMESSAGE(("CMsivCapability::GetFormatName: can't build format name\r\n"));
  648. hr = CAPS_E_SYSTEM_ERROR;
  649. goto out;
  650. }
  651. out:
  652. return hr;
  653. }
  654. BOOL CMsivCapability::FormatEnumHandler(HVCMDRIVERID hvdid,
  655. PVCMFORMATDETAILS pvfd, VCMDRIVERDETAILS *pvdd, DWORD_PTR dwInstance)
  656. {
  657. CMsivCapability *pCapObject = (CMsivCapability *)dwInstance;
  658. VIDCAP_DETAILS vidcap_entry;
  659. UINT i;
  660. // evaluate the details
  661. if(IsFormatSpecified(pvfd->pvfx, pvfd, pvdd, &vidcap_entry))
  662. {
  663. DEBUGMSG(ZONE_VCM,("FormatEnumHandler: tag 0x%08X\r\n",
  664. pvfd->pvfx->dwFormatTag));
  665. DEBUGMSG(ZONE_VCM,("FormatEnumHandler: nSamplesPerSec 0x%08lX, nAvgBytesPerSec 0x%08lX,\r\n",
  666. pvfd->pvfx->nSamplesPerSec, pvfd->pvfx->nAvgBytesPerSec));
  667. DEBUGMSG(ZONE_VCM,("FormatEnumHandler: nBlockAlign 0x%08X, wBitsPerSample 0x%04X\r\n",
  668. pvfd->pvfx->nBlockAlign, pvfd->pvfx->wBitsPerSample));
  669. DEBUGMSG(ZONE_VCM,("FormatEnumHandler: szFormat %s,\r\n",
  670. pvfd->szFormat));
  671. // done inside IsFormatSpecified and/or whatever it calls
  672. // CalculateFormatProperties(&audcap_details, pvfd->pvfx);
  673. i=AddFormat(&vidcap_entry, (LPVOID)pvfd->pvfx,
  674. (pvfd->pvfx) ? sizeof(VIDEOFORMATEX):0);
  675. if (i != INVALID_VIDEO_FORMAT) {
  676. //Set the Send/Recv Flags...
  677. //This now needs to set bSendEnabled, and bRecvEnabled, according to pvfd->dwFlags
  678. //So, we need to find the format, and update the flags accordingly.
  679. //OUTPUT IS RECV!!!!
  680. if (pvfd->dwFlags == VCM_FORMATENUMF_BOTH) {
  681. pLocalFormats[i].bSendEnabled=TRUE;
  682. pLocalFormats[i].bRecvEnabled=TRUE;
  683. }else {
  684. if(pvfd->dwFlags == VCM_FORMATENUMF_OUTPUT) {
  685. pLocalFormats[i].bSendEnabled=FALSE;
  686. pLocalFormats[i].bRecvEnabled=TRUE;
  687. } else {
  688. pLocalFormats[i].bSendEnabled=TRUE;
  689. pLocalFormats[i].bRecvEnabled=FALSE;
  690. }
  691. }
  692. }
  693. }
  694. return TRUE;
  695. }
  696. BOOL CMsivCapability::IsFormatSpecified(PVIDEOFORMATEX lpFormat, PVCMFORMATDETAILS pvfd,
  697. VCMDRIVERDETAILS *pvdd, VIDCAP_DETAILS *pVidcapDetails)
  698. {
  699. VIDCAP_DETAILS *pcap_entry;
  700. BOOL bRet = FALSE;
  701. LPTSTR lpszKeyName = NULL;
  702. DWORD dwRes;
  703. UINT i;
  704. if(!lpFormat || !pVidcapDetails)
  705. {
  706. return FALSE;
  707. }
  708. RtlZeroMemory((PVOID) pVidcapDetails, sizeof(VIDCAP_DETAILS));
  709. // fixup the VIDEOFORMAT fields of video_params so that the key name can be built
  710. pVidcapDetails->video_params.uSamplesPerSec = lpFormat->nSamplesPerSec;
  711. pVidcapDetails->video_params.uBitsPerSample = MAKELONG(lpFormat->bih.biBitCount,0);
  712. pVidcapDetails->video_params.biWidth=lpFormat->bih.biWidth;
  713. pVidcapDetails->video_params.biHeight=lpFormat->bih.biHeight;
  714. pVidcapDetails->uMaxBitrate=lpFormat->nAvgBytesPerSec * 8;
  715. // build the name of the format out of the driver and the VCM format name
  716. if ((!pvdd) ||
  717. !BuildFormatName(pVidcapDetails, pvdd->szDescription, pvfd->szFormat))
  718. {
  719. ERRORMESSAGE(("IsFormatSpecified: Coludn't build format name\r\n"));
  720. return(FALSE);
  721. }
  722. lpszKeyName = AllocRegistryKeyName( pVidcapDetails->szFormat,
  723. pVidcapDetails->video_params.uSamplesPerSec,
  724. pVidcapDetails->video_params.uBitsPerSample,
  725. pVidcapDetails->uMaxBitrate,
  726. pVidcapDetails->video_params.biWidth,
  727. pVidcapDetails->video_params.biHeight);
  728. if (!lpszKeyName)
  729. {
  730. ERRORMESSAGE(("IsFormatSpecified: Alloc failed\r\n"));
  731. return(FALSE);
  732. }
  733. RegEntry reVidCaps(szRegInternetPhone TEXT("\\") szRegInternetPhoneVCMEncodings,
  734. HKEY_LOCAL_MACHINE,
  735. FALSE,
  736. KEY_READ);
  737. dwRes = reVidCaps.GetBinary(lpszKeyName, (PVOID *) &pcap_entry);
  738. // use current registry setting if it exists
  739. if(dwRes && (dwRes == sizeof(VIDCAP_DETAILS)))
  740. {
  741. // do a quick sanity check on the contents
  742. if((lpFormat->dwFormatTag == pcap_entry->dwFormatTag)
  743. && (lpFormat->nSamplesPerSec == (DWORD)pcap_entry->video_params.uSamplesPerSec)
  744. && (lpFormat->wBitsPerSample == LOWORD(pcap_entry->video_params.uBitsPerSample))
  745. && (lpFormat->bih.biWidth == (LONG) pcap_entry->video_params.biWidth)
  746. && (lpFormat->bih.biHeight == (LONG) pcap_entry->video_params.biHeight))
  747. {
  748. CopyMemory(pVidcapDetails, pcap_entry, sizeof(VIDCAP_DETAILS));
  749. bRet = TRUE;
  750. }
  751. }
  752. else // check the static default table, and recreate the default entries
  753. {
  754. for(i=0;i< uDefVidTableEntries; i++)
  755. {
  756. if((lpFormat->dwFormatTag == default_vid_table[i].dwFormatTag)
  757. && (lpFormat->nSamplesPerSec == (DWORD)default_vid_table[i].video_params.uSamplesPerSec)
  758. && (lpFormat->wBitsPerSample == LOWORD(default_vid_table[i].video_params.uBitsPerSample))
  759. && (lpFormat->bih.biWidth == (LONG) default_vid_table[i].video_params.biWidth)
  760. && (lpFormat->bih.biHeight == (LONG) default_vid_table[i].video_params.biHeight))
  761. {
  762. // found matching default entry - copy stuff from table
  763. // (but don't overwrite the string)
  764. memcpy(pVidcapDetails, &default_vid_table[i],
  765. sizeof(VIDCAP_DETAILS) - sizeof(pVidcapDetails->szFormat));
  766. // LOOKLOOK - test against CPU limitations.
  767. // this supports a hack to disable CPU intensive codecs if not running
  768. //on a pentium
  769. if(default_vid_table[i].wCPUUtilizationEncode > wMaxCPU)
  770. {
  771. pVidcapDetails->bSendEnabled = FALSE;
  772. pVidcapDetails->bRecvEnabled = FALSE;
  773. }
  774. // add this to the registry
  775. CalculateFormatProperties(pVidcapDetails, lpFormat);
  776. bRet = UpdateFormatInRegistry(pVidcapDetails);
  777. break;
  778. }
  779. }
  780. }
  781. if (lpszKeyName)
  782. {
  783. FreeRegistryKeyName(lpszKeyName);
  784. }
  785. return(bRet);
  786. }
  787. /***************************************************************************
  788. Name : CMsivCapability::CopyVidcapInfo
  789. Purpose : Copies basic video info from an VIDCAP_INFO structure to an
  790. VIDCAP_DETAILS structure, or vice versa. VIDCAP_INFO is external
  791. representation. VIDCAP_DETAILS is internal one.
  792. Parameters: pDetails - pointer to an VIDCAP_DETAILS structure
  793. pInfo - pointer to an VIDCAP_INFO structure
  794. bDirection - 0 = ->, 1 = <-
  795. Returns : HRESULT
  796. Comment :
  797. ***************************************************************************/
  798. HRESULT CMsivCapability::CopyVidcapInfo(PVIDCAP_DETAILS pDetails,
  799. PVIDCAP_INFO pInfo,
  800. BOOL bDirection)
  801. {
  802. WORD wSortIndex;
  803. VIDEO_FORMAT_ID Id;
  804. UINT uIndex;
  805. HRESULT hr=NOERROR;
  806. if(!pInfo || !pDetails)
  807. {
  808. hr = CAPS_E_INVALID_PARAM;
  809. goto out;
  810. }
  811. if (bDirection)
  812. {
  813. // VIDCAP_INFO -> VIDCAP_DETAILS
  814. // the caller cannot modify szFormat, Id, wSortIndex and uMaxBitrate, all calculated fields
  815. // nAvgBitrate can be provided, but will be overriden if the codec provided a non-zero
  816. // value in the VIDEOFORMATEX structure
  817. pDetails->dwFormatTag = pInfo->dwFormatTag;
  818. pDetails->uAvgBitrate = pInfo->uAvgBitrate;
  819. pDetails->wCPUUtilizationEncode = pInfo->wCPUUtilizationEncode;
  820. pDetails->wCPUUtilizationDecode = pInfo->wCPUUtilizationDecode;
  821. pDetails->bSendEnabled = pInfo->bSendEnabled;
  822. pDetails->bRecvEnabled = pInfo->bRecvEnabled;
  823. pDetails->video_params.enumVideoSize = pInfo->enumVideoSize;
  824. pDetails->video_params.biHeight = pInfo->bih.biHeight;
  825. pDetails->video_params.biWidth = pInfo->bih.biWidth;
  826. // lpLocalFormatDetails is updated in AddFormat
  827. // DO NOT overwrite any of the fields used to construct the regkey name
  828. // pDetails->video_params.uSamplesPerSec = pInfo->uFrameRate;
  829. pDetails->video_params.uBitsPerSample = pInfo->dwBitsPerSample;
  830. //Re-adjust to frame rate. MPI is Interval in units of 1/29.97 seconds
  831. //No div by zero error
  832. pInfo->uFrameRate= max(1,pInfo->uFrameRate);
  833. pDetails->nonstd_params.MPI = 30/pInfo->uFrameRate;
  834. }
  835. else
  836. {
  837. // VIDCAP_DETAILS -> VIDCAP_INFO
  838. PVIDEOFORMATEX pvfx = (PVIDEOFORMATEX) pDetails->lpLocalFormatDetails;
  839. // find the sort index.
  840. uIndex = (UINT)(pDetails - pLocalFormats);
  841. Id = IndexToId(uIndex);
  842. for(wSortIndex=0; wSortIndex<uNumLocalFormats && wSortIndex < MAX_CAPS_PRESORT; wSortIndex++)
  843. {
  844. if (uIndex == IDsByRank[wSortIndex])
  845. break; // found it
  846. }
  847. // note: recall that only MAX_CAPS_PRESORT are sorted and the rest are in random order.
  848. // the rest all have a value of MAX_CAPS_PRESORT for the sort index
  849. pInfo->dwFormatTag = pDetails->dwFormatTag;
  850. pInfo->Id = Id;
  851. memcpy(pInfo->szFormat, pDetails->szFormat, sizeof(pInfo->szFormat));
  852. pInfo->wCPUUtilizationEncode = pDetails->wCPUUtilizationEncode;
  853. pInfo->wCPUUtilizationDecode = pDetails->wCPUUtilizationDecode;
  854. pInfo->bSendEnabled = pDetails->bSendEnabled;
  855. pInfo->bRecvEnabled = pDetails->bRecvEnabled;
  856. pInfo->wSortIndex = wSortIndex;
  857. pInfo->enumVideoSize = pDetails->video_params.enumVideoSize;
  858. if (pvfx)
  859. RtlCopyMemory(&pInfo->bih, &pvfx->bih, sizeof(BITMAPINFOHEADER));
  860. //The h.323 nonstd params for bitrate is in units of 100 bits/sec
  861. pInfo->dwBitsPerSample = pDetails->video_params.uBitsPerSample;
  862. pInfo->uAvgBitrate = pDetails->uAvgBitrate;
  863. pInfo->uMaxBitrate = pDetails->nonstd_params.maxBitRate*100;
  864. //Re-adjust to frame rate. MPI is Interval in units of 1/29.97 seconds
  865. //No div by zero error
  866. pDetails->nonstd_params.MPI= max(1,pDetails->nonstd_params.MPI);
  867. pInfo->uFrameRate = min(30,30/pDetails->nonstd_params.MPI);
  868. }
  869. out:
  870. return hr;
  871. }
  872. HRESULT CMsivCapability::EnumCommonFormats(PBASIC_VIDCAP_INFO pFmtBuf, UINT uBufsize,
  873. UINT *uNumFmtOut, BOOL bTXCaps)
  874. {
  875. UINT u, uNumOut = 0;;
  876. HRESULT hr = hrSuccess;
  877. VIDCAP_DETAILS *pDetails = pLocalFormats;
  878. MEDIA_FORMAT_ID FormatIDRemote;
  879. HRESULT hrIsCommon;
  880. // validate input
  881. if(!pFmtBuf || !uNumFmtOut || (uBufsize < (sizeof(BASIC_VIDCAP_INFO)*uNumLocalFormats)))
  882. {
  883. return CAPS_E_INVALID_PARAM;
  884. }
  885. if(!uNumLocalFormats || !pDetails)
  886. {
  887. return CAPS_E_NOCAPS;
  888. }
  889. // temporary - enumerating requestable receive formats is not yet supported
  890. if(!bTXCaps)
  891. return CAPS_E_NOT_SUPPORTED;
  892. for(u=0; (u <uNumLocalFormats) && (u <MAX_CAPS_PRESORT); u++)
  893. {
  894. pDetails = pLocalFormats + IDsByRank[u];
  895. // if there is a session, then return formats that are common to local and remote.
  896. if(uNumRemoteDecodeFormats)
  897. {
  898. hrIsCommon = ResolveToLocalFormat(IndexToId(IDsByRank[u]), &FormatIDRemote);
  899. if(HR_SUCCEEDED(hrIsCommon))
  900. {
  901. hr = CopyVidcapInfo (pDetails, pFmtBuf, 0);
  902. if(!HR_SUCCEEDED(hr))
  903. goto EXIT;
  904. uNumOut++;
  905. pFmtBuf++;
  906. }
  907. }
  908. else // no remote capabilities exist because there is no current session
  909. {
  910. hr = CAPS_E_NOCAPS;
  911. }
  912. }
  913. *uNumFmtOut = uNumOut;
  914. EXIT:
  915. return hr;
  916. }
  917. HRESULT CMsivCapability::EnumFormats(PBASIC_VIDCAP_INFO pFmtBuf, UINT uBufsize,
  918. UINT *uNumFmtOut)
  919. {
  920. UINT u;
  921. HRESULT hr = hrSuccess;
  922. VIDCAP_DETAILS *pDetails = pLocalFormats;
  923. // validate input
  924. if(!pFmtBuf || !uNumFmtOut || (uBufsize < (sizeof(BASIC_VIDCAP_INFO)*uNumLocalFormats)))
  925. {
  926. return CAPS_E_INVALID_PARAM;
  927. }
  928. if(!uNumLocalFormats || !pDetails)
  929. {
  930. return CAPS_E_NOCAPS;
  931. }
  932. for(u=0; (u <uNumLocalFormats) && (u <MAX_CAPS_PRESORT); u++)
  933. {
  934. pDetails = pLocalFormats + IDsByRank[u];
  935. hr = CopyVidcapInfo (pDetails, pFmtBuf, 0);
  936. if(!HR_SUCCEEDED(hr))
  937. goto EXIT;
  938. pFmtBuf++;
  939. }
  940. *uNumFmtOut = min(uNumLocalFormats, MAX_CAPS_PRESORT);
  941. EXIT:
  942. return hr;
  943. }
  944. HRESULT CMsivCapability::GetBasicVidcapInfo (VIDEO_FORMAT_ID Id, PBASIC_VIDCAP_INFO pFormatPrefsBuf)
  945. {
  946. VIDCAP_DETAILS *pFmt;
  947. UINT uIndex = IDToIndex(Id);
  948. if(!pFormatPrefsBuf || (uNumLocalFormats <= uIndex))
  949. {
  950. return CAPS_E_INVALID_PARAM;
  951. }
  952. pFmt = pLocalFormats + uIndex;
  953. return (CopyVidcapInfo(pFmt,pFormatPrefsBuf,0));
  954. }
  955. HRESULT CMsivCapability::ApplyAppFormatPrefs (PBASIC_VIDCAP_INFO pFormatPrefsBuf,
  956. UINT uNumFormatPrefs)
  957. {
  958. FX_ENTRY ("CMsivCapability::ApplyAppFormatPrefs");
  959. UINT u, v;
  960. PBASIC_VIDCAP_INFO pTemp;
  961. VIDCAP_DETAILS *pFmt;
  962. if(!pFormatPrefsBuf || (uNumLocalFormats != uNumFormatPrefs))
  963. {
  964. ERRORMESSAGE(("%s invalid param: pFbuf:0x%08lx, uNumIN:%d, uNum:%d\r\n",
  965. _fx_, pFormatPrefsBuf, uNumFormatPrefs, uNumLocalFormats));
  966. return CAPS_E_INVALID_PARAM;
  967. }
  968. // validate
  969. for(u=0; u <uNumLocalFormats; u++)
  970. {
  971. pTemp = pFormatPrefsBuf+u;
  972. // make sure that the format ID is real
  973. if(IDToIndex(pTemp->Id) >= uNumLocalFormats)
  974. {
  975. return CAPS_E_INVALID_PARAM;
  976. }
  977. // look for bad sort indices, duplicate sort indices and duplicate format IDs
  978. if(pTemp->wSortIndex >= uNumLocalFormats)
  979. return CAPS_E_INVALID_PARAM;
  980. for(v=u+1; v <uNumLocalFormats; v++)
  981. {
  982. if((pTemp->wSortIndex == pFormatPrefsBuf[v].wSortIndex)
  983. || (pTemp->Id == pFormatPrefsBuf[v].Id))
  984. {
  985. ERRORMESSAGE(("%s invalid param: wSI1:0x%04x, wSI2:0x%04x, ID1:%d, ID2:%d\r\n",
  986. _fx_, pTemp->wSortIndex, pFormatPrefsBuf[v].wSortIndex, pTemp->Id,
  987. pFormatPrefsBuf[v].Id));
  988. return CAPS_E_INVALID_PARAM;
  989. }
  990. }
  991. }
  992. // all seems well
  993. for(u=0; u <uNumLocalFormats; u++)
  994. {
  995. pTemp = pFormatPrefsBuf+u; // next entry of the input
  996. pFmt = pLocalFormats + IDToIndex(pTemp->Id); // identifies this local format
  997. // apply the new sort order
  998. pFmt->wApplicationPrefOrder = pTemp->wSortIndex;
  999. // update the updatable parameters (CPU utilization, bitrate)
  1000. pFmt->bSendEnabled = pTemp->bSendEnabled;
  1001. pFmt->bRecvEnabled = pTemp->bRecvEnabled;
  1002. // DO NOT overwrite any of the fields used to construct the regkey name
  1003. // pFmt->video_params.uSamplesPerSec = pTemp->uFrameRate;
  1004. //Units of 100 bits/sec
  1005. pFmt->nonstd_params.maxBitRate= (pTemp->uMaxBitrate/100);
  1006. // pFmt->nonstd_params.maxBPP= 0;
  1007. pFmt->nonstd_params.MPI= 30/max(pTemp->uFrameRate, 1);
  1008. // only the tuning wizard or other profiling app can write wCPUUtilizationEncode,
  1009. // wCPUUtilizationDecode, uAvgBitrate
  1010. // update the registry
  1011. UpdateFormatInRegistry(pFmt);
  1012. // now update the sort order contained in VIDsByRank
  1013. // note: recall that only MAX_CAPS_PRESORT are sorted and the rest are in random order.
  1014. // LOOKLOOK - maybe need a separate sort order array? - the order in VIDsByRank
  1015. // is being overriden here
  1016. // the array holds the sorted indices into the array of formats in pLocalFormats
  1017. if(pTemp->wSortIndex < MAX_CAPS_PRESORT)
  1018. {
  1019. // insert the format at the position indicated by the input
  1020. IDsByRank[pTemp->wSortIndex] = (MEDIA_FORMAT_ID)(pFmt - pLocalFormats);
  1021. }
  1022. }
  1023. return hrSuccess;
  1024. }
  1025. // update the registry
  1026. BOOL CMsivCapability::UpdateFormatInRegistry(VIDCAP_DETAILS *pVidcapDetails)
  1027. {
  1028. FX_ENTRY(("CMsivCapability::UpdateFormatInRegistry"));
  1029. LPTSTR lpszKeyName = NULL;
  1030. BOOL bRet;
  1031. if(!pVidcapDetails)
  1032. {
  1033. return FALSE;
  1034. }
  1035. lpszKeyName = AllocRegistryKeyName( pVidcapDetails->szFormat,
  1036. pVidcapDetails->video_params.uSamplesPerSec,
  1037. pVidcapDetails->video_params.uBitsPerSample,
  1038. pVidcapDetails->uMaxBitrate,
  1039. pVidcapDetails->video_params.biWidth,
  1040. pVidcapDetails->video_params.biHeight);
  1041. if (!lpszKeyName)
  1042. {
  1043. ERRORMESSAGE(("%s:Alloc failed\r\n",_fx_));
  1044. return(FALSE);
  1045. }
  1046. DEBUGMSG(ZONE_VCM,("%s:updating %s, wPref:0x%04x, bS:%d, bR:%d\r\n",
  1047. _fx_, lpszKeyName, pVidcapDetails->wApplicationPrefOrder,
  1048. pVidcapDetails->bSendEnabled, pVidcapDetails->bRecvEnabled));
  1049. // add this to the registry
  1050. RegEntry reVidCaps(szRegInternetPhone TEXT("\\") szRegInternetPhoneVCMEncodings,
  1051. HKEY_LOCAL_MACHINE);
  1052. bRet = (ERROR_SUCCESS == reVidCaps.SetValue(lpszKeyName,
  1053. pVidcapDetails,
  1054. sizeof(VIDCAP_DETAILS)));
  1055. FreeRegistryKeyName(lpszKeyName);
  1056. return(bRet);
  1057. }
  1058. /***************************************************************************
  1059. Name : CMsivCapability::AddVCMFormat
  1060. Purpose : Adds an VCM format to the list of formats we support
  1061. Parameters: pvfx - pointer to the videoformat structure for the added codec
  1062. pVidcapInfo - additional format info that is not in the videoformat
  1063. structure
  1064. Returns : HRESULT
  1065. Comment :
  1066. ***************************************************************************/
  1067. HRESULT CMsivCapability::AddVCMFormat (PVIDEOFORMATEX pvfx, PVIDCAP_INFO pVidcapInfo)
  1068. {
  1069. HRESULT hr = hrSuccess;
  1070. // initialize cap entry with default values
  1071. VIDCAP_DETAILS cap_entry =
  1072. {VIDEO_FORMAT_UNKNOWN, NONSTD_VID_TERMCAP,STD_VID_PARAMS,
  1073. {RTP_DYNAMIC_MIN+1, 0, 30, 7680, Small, 0, 0},0,
  1074. TRUE, TRUE,
  1075. 1, // default number of samples per packet
  1076. 245760*8, // default to 16kbs bitrate
  1077. 245760*8, // unknown average bitrate
  1078. 10, 10, // default CPU utilization
  1079. PREF_ORDER_UNASSIGNED, // unassigned sort order
  1080. 0,NULL,0,NULL,
  1081. ""};
  1082. if(!pvfx || !pVidcapInfo)
  1083. {
  1084. hr = CAPS_E_INVALID_PARAM;
  1085. goto out;
  1086. }
  1087. /*
  1088. * Build the VIDCAP_DETAILS structure for this format
  1089. */
  1090. // now add VIDCAP_INFO information
  1091. CopyVidcapInfo(&cap_entry, pVidcapInfo, 1);
  1092. // calculate whatever parameters can be calculated
  1093. // use actual bits per sample unless the bps field is zero, in which case
  1094. // assume 16 bits (worst case).
  1095. CalculateFormatProperties(&cap_entry, pvfx);
  1096. // Make sure it's an upper case FourCC
  1097. if (cap_entry.dwFormatTag > 256)
  1098. CharUpperBuff((LPTSTR)&cap_entry.dwFormatTag, sizeof(DWORD));
  1099. // set the RTP payload number. We are using a random number from the dynamic range
  1100. // for the installable codecs
  1101. cap_entry.video_params.RTPPayload = RTP_DYNAMIC_MIN+1;
  1102. // get the format name and driver name for this format from VCM and
  1103. // build a format name to add to the registry
  1104. hr = GetFormatName(&cap_entry, pvfx);
  1105. if (FAILED(hr))
  1106. goto out;
  1107. // add this to the registry
  1108. if(!UpdateFormatInRegistry(&cap_entry))
  1109. {
  1110. ERRORMESSAGE(("CMsivCapability::AddVCMFormat: can't update registry\r\n"));
  1111. hr = CAPS_E_SYSTEM_ERROR;
  1112. goto out;
  1113. }
  1114. // reinit to update the list of local formats
  1115. if (!ReInit())
  1116. {
  1117. hr = CAPS_E_SYSTEM_ERROR;
  1118. goto out;
  1119. }
  1120. out:
  1121. return hr;
  1122. }
  1123. /***************************************************************************
  1124. Name : CMsivCapability::RemoveVCMFormat
  1125. Purpose : Removes an VCM format to the list of formats we support
  1126. Parameters: pvfx - pointer to the videoformat structure for the added codec
  1127. Returns : HRESULT
  1128. Comment :
  1129. ***************************************************************************/
  1130. HRESULT CMsivCapability::RemoveVCMFormat (PVIDEOFORMATEX pvfx)
  1131. {
  1132. HRESULT hr = hrSuccess;
  1133. HKEY hKey = NULL;
  1134. LPTSTR lpszValueName = NULL;
  1135. DWORD dwErr;
  1136. VIDCAP_DETAILS cap_entry;
  1137. if(!pvfx)
  1138. {
  1139. return CAPS_E_INVALID_PARAM;
  1140. }
  1141. // get the format name and driver name for this format from VCM and
  1142. // build a format name to add to the registry
  1143. hr = GetFormatName(&cap_entry, pvfx);
  1144. if (FAILED(hr))
  1145. goto out;
  1146. lpszValueName = AllocRegistryKeyName(cap_entry.szFormat,
  1147. pvfx->nSamplesPerSec,
  1148. MAKELONG(pvfx->wBitsPerSample,0),
  1149. pvfx->nAvgBytesPerSec*8,
  1150. pvfx->bih.biWidth,
  1151. pvfx->bih.biHeight);
  1152. if (!lpszValueName)
  1153. {
  1154. ERRORMESSAGE(("CMsivCapability::RemoveVCMFormat: Alloc failed\r\n"));
  1155. hr = CAPS_E_SYSTEM_ERROR;
  1156. goto out;
  1157. }
  1158. // Get the key handle
  1159. if (dwErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1160. szRegInternetPhone TEXT("\\") szRegInternetPhoneVCMEncodings,
  1161. 0, KEY_ALL_ACCESS, &hKey))
  1162. {
  1163. ERRORMESSAGE(("CMsivCapability::RemoveVCMFormat: can't open key to delete\r\n"));
  1164. hr = CAPS_E_SYSTEM_ERROR;
  1165. goto out;
  1166. }
  1167. dwErr = RegDeleteValue(hKey, lpszValueName );
  1168. if(dwErr != ERROR_SUCCESS)
  1169. {
  1170. hr = CAPS_E_SYSTEM_ERROR;
  1171. goto out;
  1172. }
  1173. // reinit to update the list of local formats
  1174. if (!ReInit())
  1175. {
  1176. hr = CAPS_E_SYSTEM_ERROR;
  1177. goto out;
  1178. }
  1179. out:
  1180. if (hKey)
  1181. RegCloseKey(hKey);
  1182. if(lpszValueName)
  1183. MEMFREE(lpszValueName);
  1184. return hr;
  1185. }
  1186. UINT CMsivCapability::GetLocalSendParamSize(MEDIA_FORMAT_ID dwID)
  1187. {
  1188. return (sizeof(VIDEO_CHANNEL_PARAMETERS));
  1189. }
  1190. UINT CMsivCapability::GetLocalRecvParamSize(PCC_TERMCAP pCapability)
  1191. {
  1192. return (sizeof(VIDEO_CHANNEL_PARAMETERS));
  1193. }
  1194. HRESULT CMsivCapability::CreateCapList(LPVOID *ppCapBuf)
  1195. {
  1196. HRESULT hr = hrSuccess;
  1197. UINT u;
  1198. VIDCAP_DETAILS *pDecodeDetails = pLocalFormats;
  1199. PCC_TERMCAPLIST pTermCapList = NULL;
  1200. PPCC_TERMCAP ppCCThisTermCap = NULL;
  1201. PCC_TERMCAP pCCThisCap = NULL;
  1202. PNSC_VIDEO_CAPABILITY pNSCapNext = NULL;
  1203. PVIDEOFORMATEX lpvcd;
  1204. VIDEO_PARAMS *pVidCapInfo;
  1205. UINT format;
  1206. FX_ENTRY ("CreateCapList");
  1207. // validate input
  1208. if(!ppCapBuf)
  1209. {
  1210. hr = CAPS_E_INVALID_PARAM;
  1211. goto ERROR_OUT;
  1212. }
  1213. *ppCapBuf = NULL;
  1214. if(!uNumLocalFormats || !pDecodeDetails)
  1215. {
  1216. hr = CAPS_E_NOCAPS;
  1217. goto ERROR_OUT;
  1218. }
  1219. pTermCapList = (PCC_TERMCAPLIST)MemAlloc(sizeof(CC_TERMCAPLIST));
  1220. if(!pTermCapList)
  1221. {
  1222. hr = CAPS_E_NOMEM;
  1223. goto ERROR_OUT;
  1224. }
  1225. ppCCThisTermCap = (PPCC_TERMCAP)MemAlloc(uNumLocalFormats * sizeof(PCC_TERMCAP));
  1226. if(!ppCCThisTermCap)
  1227. {
  1228. hr = CAPS_E_NOMEM;
  1229. goto ERROR_OUT;
  1230. }
  1231. pTermCapList->wLength = 0;
  1232. // point the CC_TERMCAPLIST pTermCapArray at the array of PCC_TERMCAP
  1233. pTermCapList->pTermCapArray = ppCCThisTermCap;
  1234. /*
  1235. CC_TERMCAPLIST PCC_TERMCAP CC_TERMCAP
  1236. pTermCapList-> {
  1237. wLength
  1238. pTermCapArray--->pTermCap----------->{single capability.....}
  1239. }
  1240. pTermCap----------->{single capability.}
  1241. pTermCap----------->{single capability...}
  1242. */
  1243. for(u=0; u <uNumLocalFormats; u++)
  1244. {
  1245. // check if enabled for receive, skip if false
  1246. // also skip if public version of capabilities is to be advertised via a
  1247. // separate local capability entry
  1248. if((!pDecodeDetails->bRecvEnabled ) || (pDecodeDetails->dwPublicRefIndex))
  1249. {
  1250. pDecodeDetails++;
  1251. continue;
  1252. }
  1253. if(pDecodeDetails->H245Cap.ClientType ==0
  1254. || pDecodeDetails->H245Cap.ClientType ==H245_CLIENT_VID_NONSTD)
  1255. {
  1256. lpvcd = (PVIDEOFORMATEX)pDecodeDetails->lpLocalFormatDetails;
  1257. if(!lpvcd)
  1258. {
  1259. pDecodeDetails++;
  1260. continue;
  1261. }
  1262. // allocate for this one capability
  1263. pCCThisCap = (PCC_TERMCAP)MemAlloc(sizeof(CC_TERMCAP));
  1264. pNSCapNext = (PNSC_VIDEO_CAPABILITY)MemAlloc(sizeof(NSC_VIDEO_CAPABILITY));
  1265. if((!pCCThisCap)|| (!pNSCapNext))
  1266. {
  1267. hr = CAPS_E_NOMEM;
  1268. goto ERROR_OUT;
  1269. }
  1270. // set type of nonstandard capability
  1271. pNSCapNext->cvp_type = NSC_VCM_VIDEOFORMATEX;
  1272. // stuff both chunks of nonstandard capability info into buffer
  1273. // first stuff the "channel parameters" (the format independent communication options)
  1274. memcpy(&pNSCapNext->cvp_params, &pDecodeDetails->nonstd_params, sizeof(NSC_CHANNEL_VIDEO_PARAMETERS));
  1275. // then the VCM stuff
  1276. memcpy(&pNSCapNext->cvp_data.vfx, lpvcd, sizeof(VIDEOFORMATEX));
  1277. pCCThisCap->ClientType = H245_CLIENT_VID_NONSTD;
  1278. pCCThisCap->DataType = H245_DATA_VIDEO;
  1279. pCCThisCap->Dir = (pDecodeDetails->bSendEnabled && bPublicizeTXCaps)
  1280. ? H245_CAPDIR_LCLRXTX :H245_CAPDIR_LCLRX;
  1281. // LOOKLOOK use the index of the cap entry as the ID
  1282. // The ID is already preset in local formats by AddCapabilityBase()
  1283. // pCCThisCap->CapId = (USHORT)IndexToId(u);
  1284. pCCThisCap->CapId = pDecodeDetails->H245Cap.CapId;
  1285. // all nonstandard identifier fields are unsigned short
  1286. // two possibilities for choice are "h221NonStandard_chosen" and "object_chosen"
  1287. pCCThisCap->Cap.H245Vid_NONSTD.nonStandardIdentifier.choice = h221NonStandard_chosen;
  1288. // NOTE: there is some question about the correct byte order
  1289. // of the codes in the h221NonStandard structure
  1290. pCCThisCap->Cap.H245Vid_NONSTD.nonStandardIdentifier.u.h221NonStandard.t35CountryCode = USA_H221_COUNTRY_CODE;
  1291. pCCThisCap->Cap.H245Vid_NONSTD.nonStandardIdentifier.u.h221NonStandard.t35Extension = USA_H221_COUNTRY_EXTENSION;
  1292. pCCThisCap->Cap.H245Vid_NONSTD.nonStandardIdentifier.u.h221NonStandard.manufacturerCode = MICROSOFT_H_221_MFG_CODE;
  1293. // set size of buffer
  1294. pCCThisCap->Cap.H245Vid_NONSTD.data.length = sizeof(NSC_VIDEO_CAPABILITY) - BMIH_SLOP_BYTES;
  1295. pCCThisCap->Cap.H245Vid_NONSTD.data.value = (BYTE *)pNSCapNext; // point to nonstandard stuff
  1296. // pNSCapNext is now referenced by the pTermCapList and will
  1297. // be cleaned up via DeleteCapList(). Null the ptr so that error cleanup
  1298. // won't try redundant cleanup.
  1299. pNSCapNext = NULL;
  1300. }
  1301. else
  1302. {
  1303. // allocate for this one capability
  1304. pCCThisCap = (PCC_TERMCAP)MemAlloc(sizeof(CC_TERMCAP));
  1305. if(!pCCThisCap)
  1306. {
  1307. hr = CAPS_E_NOMEM;
  1308. goto ERROR_OUT;
  1309. }
  1310. pCCThisCap->ClientType = (H245_CLIENT_T)pDecodeDetails->H245Cap.ClientType;
  1311. pCCThisCap->DataType = H245_DATA_VIDEO;
  1312. pCCThisCap->Dir = H245_CAPDIR_LCLRX; // should this be H245_CAPDIR_LCLRX for receive caps?
  1313. pCCThisCap->CapId = pDecodeDetails->H245Cap.CapId;
  1314. pVidCapInfo=&pDecodeDetails->video_params;
  1315. switch (pCCThisCap->ClientType )
  1316. {
  1317. case H245_CLIENT_VID_H263:
  1318. #pragma message ("Collapse H.263 formats")
  1319. // refer to the hack that sets H245Vid_H263 parameters
  1320. // when formats are enumerated. if that was always done right, then
  1321. // all that needs to happen here is collapsing
  1322. // This is where the formats need to collapse. H.263 probably
  1323. // should not be collapsed into 1 format. Given M specific local
  1324. // formats, collapse into N.
  1325. format=get_format (pVidCapInfo->biWidth,pVidCapInfo->biHeight);
  1326. switch (format) {
  1327. case SQCIF: {
  1328. pCCThisCap->Cap.H245Vid_H263.bit_mask =H263VideoCapability_sqcifMPI_present;
  1329. //MPI minimum interval in units of 1/29.97sec so 30/ (frames/sec) is reasonable
  1330. pCCThisCap->Cap.H245Vid_H263.sqcifMPI = max (1,pDecodeDetails->nonstd_params.MPI); //30/pVidCapInfo->uSamplesPerSec;
  1331. pCCThisCap->Cap.H245Vid_H263.H263VdCpblty_qcifMPI =0;
  1332. pCCThisCap->Cap.H245Vid_H263.H263VdCpblty_cifMPI =0;
  1333. break;
  1334. }
  1335. case QCIF: {
  1336. pCCThisCap->Cap.H245Vid_H263.bit_mask =H263VideoCapability_qcifMPI_present;
  1337. pCCThisCap->Cap.H245Vid_H263.sqcifMPI = 0;
  1338. pCCThisCap->Cap.H245Vid_H263.H263VdCpblty_qcifMPI =max (1,pDecodeDetails->nonstd_params.MPI);//30/pVidCapInfo->uSamplesPerSec; ;;
  1339. pCCThisCap->Cap.H245Vid_H263.H263VdCpblty_cifMPI =0;
  1340. break;
  1341. }
  1342. case CIF: {
  1343. pCCThisCap->Cap.H245Vid_H263.bit_mask =H263VideoCapability_cifMPI_present;
  1344. pCCThisCap->Cap.H245Vid_H263.sqcifMPI = 0;
  1345. pCCThisCap->Cap.H245Vid_H263.H263VdCpblty_qcifMPI =0;
  1346. pCCThisCap->Cap.H245Vid_H263.H263VdCpblty_cifMPI = max (1,pDecodeDetails->nonstd_params.MPI);//30/pVidCapInfo->uSamplesPerSec;
  1347. break;
  1348. }
  1349. default:
  1350. break;
  1351. }
  1352. pCCThisCap->Cap.H245Vid_H263.cif4MPI =0;
  1353. pCCThisCap->Cap.H245Vid_H263.cif16MPI =0;
  1354. pCCThisCap->Cap.H245Vid_H263.maxBitRate =
  1355. pDecodeDetails->nonstd_params.maxBitRate;
  1356. pCCThisCap->Cap.H245Vid_H263.unrestrictedVector = FALSE;
  1357. pCCThisCap->Cap.H245Vid_H263.arithmeticCoding = FALSE;
  1358. pCCThisCap->Cap.H245Vid_H263.advancedPrediction = FALSE;
  1359. pCCThisCap->Cap.H245Vid_H263.pbFrames = FALSE;
  1360. pCCThisCap->Cap.H245Vid_H263.tmprlSptlTrdOffCpblty = (ASN1bool_t)bPublicizeTSTradeoff;
  1361. pCCThisCap->Cap.H245Vid_H263.hrd_B = 0;
  1362. pCCThisCap->Cap.H245Vid_H263.bppMaxKb =
  1363. pDecodeDetails->nonstd_params.maxBPP;
  1364. /* Optional, and not supported pCCThisCap->Cap.H245Vid_H263.slowQcifMPI =0;
  1365. pCCThisCap->Cap.H245Vid_H263.slowSqcifMPI =0;
  1366. pCCThisCap->Cap.H245Vid_H263.slowCifMPI =0;
  1367. pCCThisCap->Cap.H245Vid_H263.slowCif4MPI =0;
  1368. pCCThisCap->Cap.H245Vid_H263.slowCif16MPI =0;
  1369. */
  1370. pCCThisCap->Cap.H245Vid_H263.H263VCy_errrCmpnstn = TRUE;
  1371. break;
  1372. case H245_CLIENT_VID_H261:
  1373. #pragma message ("Collapse H.261 formats")
  1374. // refer to the hack that sets H245Vid_H261 parameters
  1375. // when formats are enumerated. if that was always done right, then
  1376. // all that needs to happen here is collapsing
  1377. // This is where the formats need to collapse. H.261 probably
  1378. // should not be collapsed into 1 format. Given M specific local
  1379. // formats, collapse into N.
  1380. format=get_format (pVidCapInfo->biWidth,pVidCapInfo->biHeight);
  1381. switch (format) {
  1382. case QCIF: {
  1383. pCCThisCap->Cap.H245Vid_H261.bit_mask =H261VdCpblty_qcifMPI_present;
  1384. pCCThisCap->Cap.H245Vid_H261.H261VdCpblty_qcifMPI =max (1,min(4,pDecodeDetails->nonstd_params.MPI));//30/pVidCapInfo->uSamplesPerSec; ;;
  1385. pCCThisCap->Cap.H245Vid_H261.H261VdCpblty_cifMPI =0;
  1386. break;
  1387. }
  1388. case CIF: {
  1389. pCCThisCap->Cap.H245Vid_H261.bit_mask =H261VdCpblty_cifMPI_present;
  1390. pCCThisCap->Cap.H245Vid_H261.H261VdCpblty_qcifMPI =0;
  1391. pCCThisCap->Cap.H245Vid_H261.H261VdCpblty_cifMPI =max (1,min(4,pDecodeDetails->nonstd_params.MPI));//30/pVidCapInfo->uSamplesPerSec;
  1392. break;
  1393. }
  1394. default:
  1395. break;
  1396. }
  1397. pCCThisCap->Cap.H245Vid_H261.maxBitRate = (ASN1uint16_t)pDecodeDetails->nonstd_params.maxBitRate;
  1398. pCCThisCap->Cap.H245Vid_H261.tmprlSptlTrdOffCpblty = (ASN1bool_t)bPublicizeTSTradeoff;
  1399. pCCThisCap->Cap.H245Vid_H261.stillImageTransmission = FALSE;
  1400. break;
  1401. default:
  1402. case H245_CLIENT_VID_NONSTD:
  1403. break;
  1404. }
  1405. }
  1406. pDecodeDetails++;
  1407. *ppCCThisTermCap++ = pCCThisCap;// add ptr to this capability to the array
  1408. pTermCapList->wLength++; // count this entry
  1409. // pCCThisCap is now referenced by the pTermCapList and will
  1410. // be cleaned up via DeleteCapList(). Null the ptr so that error cleanup
  1411. // won't try redundant cleanup.
  1412. pCCThisCap = NULL;
  1413. }
  1414. *ppCapBuf = pTermCapList;
  1415. return hr;
  1416. ERROR_OUT:
  1417. if(pTermCapList)
  1418. {
  1419. DeleteCapList(pTermCapList);
  1420. }
  1421. if(pCCThisCap)
  1422. MemFree(pCCThisCap);
  1423. if(pNSCapNext)
  1424. MemFree(pNSCapNext);
  1425. return hr;
  1426. }
  1427. HRESULT CMsivCapability::DeleteCapList(LPVOID pCapBuf)
  1428. {
  1429. UINT u;
  1430. PCC_TERMCAPLIST pTermCapList = (PCC_TERMCAPLIST)pCapBuf;
  1431. PCC_TERMCAP pCCThisCap;
  1432. PNSC_VIDEO_CAPABILITY pNSCap;
  1433. if(!pTermCapList)
  1434. {
  1435. return CAPS_E_INVALID_PARAM;
  1436. }
  1437. if(pTermCapList->pTermCapArray)
  1438. {
  1439. while(pTermCapList->wLength--)
  1440. {
  1441. pCCThisCap = *(pTermCapList->pTermCapArray + pTermCapList->wLength);
  1442. if(pCCThisCap)
  1443. {
  1444. if(pCCThisCap->ClientType == H245_CLIENT_VID_NONSTD)
  1445. {
  1446. if(pCCThisCap->Cap.H245Vid_NONSTD.data.value)
  1447. {
  1448. MemFree(pCCThisCap->Cap.H245Vid_NONSTD.data.value);
  1449. }
  1450. }
  1451. MemFree(pCCThisCap);
  1452. }
  1453. }
  1454. MemFree(pTermCapList->pTermCapArray);
  1455. }
  1456. MemFree(pTermCapList);
  1457. return hrSuccess;
  1458. }
  1459. BOOL CMsivCapability::IsCapabilityRecognized(PCC_TERMCAP pCCThisCap)
  1460. {
  1461. FX_ENTRY ("CMsivCapability::IsCapabilityRecognized");
  1462. if(pCCThisCap->DataType != H245_DATA_VIDEO)
  1463. return FALSE;
  1464. if(pCCThisCap->ClientType == H245_CLIENT_VID_NONSTD)
  1465. {
  1466. // do we recognize this?
  1467. if(pCCThisCap->Cap.H245Vid_NONSTD.nonStandardIdentifier.choice == h221NonStandard_chosen)
  1468. {
  1469. if((pCCThisCap->Cap.H245Vid_NONSTD.nonStandardIdentifier.u.h221NonStandard.t35CountryCode == USA_H221_COUNTRY_CODE)
  1470. && (pCCThisCap->Cap.H245Vid_NONSTD.nonStandardIdentifier.u.h221NonStandard.t35Extension == USA_H221_COUNTRY_EXTENSION)
  1471. && (pCCThisCap->Cap.H245Vid_NONSTD.nonStandardIdentifier.u.h221NonStandard.manufacturerCode == MICROSOFT_H_221_MFG_CODE))
  1472. {
  1473. // ok, this is ours so far. Now what data type is contained therein?
  1474. // welllll, lets keep a copy of this regardless ????. If we can't understand
  1475. // future versions of ourselves, then what???
  1476. return TRUE;
  1477. }
  1478. else
  1479. {
  1480. // unrecognized nonstandard capability
  1481. ERRORMESSAGE(("%s:unrecognized nonstd capability\r\n",_fx_));
  1482. #ifdef DEBUG
  1483. VOID DumpNonstdParameters(PCC_TERMCAP , PCC_TERMCAP );
  1484. DumpNonstdParameters(NULL, pCCThisCap);
  1485. #endif
  1486. return FALSE;
  1487. }
  1488. }
  1489. }
  1490. return TRUE;
  1491. }
  1492. // the intent is to keep a copy of the channel parameters used to open a send channel
  1493. // that the remote end can decode.
  1494. VIDEO_FORMAT_ID CMsivCapability::AddRemoteDecodeFormat(PCC_TERMCAP pCCThisCap)
  1495. {
  1496. FX_ENTRY ("CMsivCapability::AddRemoteDecodeFormat");
  1497. VIDCAP_DETAILS vidcapdetails =
  1498. {VIDEO_FORMAT_UNKNOWN,NONSTD_VID_TERMCAP, STD_VID_PARAMS,
  1499. {RTP_DYNAMIC_MIN+1, 0, 30, 7680, Small, 0, 0},0,
  1500. TRUE, TRUE, 1, 245760*8,245760*8,10,10,0,0,NULL,0,NULL,""};
  1501. VIDCAP_DETAILS *pTemp;
  1502. LPVOID lpData = NULL;
  1503. UINT uSize = 0;
  1504. if(!pCCThisCap)
  1505. {
  1506. return INVALID_VIDEO_FORMAT;
  1507. }
  1508. // check room
  1509. if(uRemoteDecodeFormatCapacity <= uNumRemoteDecodeFormats)
  1510. {
  1511. // get more mem, realloc memory by CAP_CHUNK_SIZE for pRemoteDecodeFormats
  1512. pTemp = (VIDCAP_DETAILS *)MEMALLOC((uNumRemoteDecodeFormats + CAP_CHUNK_SIZE)*sizeof(VIDCAP_DETAILS));
  1513. if(!pTemp)
  1514. goto ERROR_EXIT;
  1515. // remember how much capacity we now have
  1516. uRemoteDecodeFormatCapacity = uNumRemoteDecodeFormats + CAP_CHUNK_SIZE;
  1517. #ifdef DEBUG
  1518. if((uNumRemoteDecodeFormats && !pRemoteDecodeFormats) || (!uNumRemoteDecodeFormats && pRemoteDecodeFormats))
  1519. {
  1520. ERRORMESSAGE(("%s:leak! uNumRemoteDecodeFormats:0x%08lX, pRemoteDecodeFormats:0x%08lX\r\n",
  1521. _fx_, uNumRemoteDecodeFormats,pRemoteDecodeFormats));
  1522. }
  1523. #endif
  1524. // copy old stuff, discard old mem
  1525. if(uNumRemoteDecodeFormats && pRemoteDecodeFormats)
  1526. {
  1527. memcpy(pTemp, pRemoteDecodeFormats, uNumRemoteDecodeFormats*sizeof(AUDCAP_DETAILS));
  1528. MEMFREE(pRemoteDecodeFormats);
  1529. }
  1530. pRemoteDecodeFormats = pTemp;
  1531. }
  1532. // pTemp is where the stuff is cached
  1533. pTemp = pRemoteDecodeFormats+uNumRemoteDecodeFormats;
  1534. // fixup the capability structure being added. First thing: initialize defaults
  1535. memcpy(pTemp, &vidcapdetails, sizeof(VIDCAP_DETAILS));
  1536. // next, the H245 parameters
  1537. memcpy(&pTemp->H245Cap, pCCThisCap, sizeof(pTemp->H245Cap));
  1538. // Note: if nonstandard data exists, the nonstd pointers need to be fixed up
  1539. if(pCCThisCap->ClientType == H245_CLIENT_VID_NONSTD)
  1540. {
  1541. // do we recognize this?
  1542. if(pCCThisCap->Cap.H245Vid_NONSTD.nonStandardIdentifier.choice == h221NonStandard_chosen)
  1543. {
  1544. if((pCCThisCap->Cap.H245Vid_NONSTD.nonStandardIdentifier.u.h221NonStandard.t35CountryCode == USA_H221_COUNTRY_CODE)
  1545. && (pCCThisCap->Cap.H245Vid_NONSTD.nonStandardIdentifier.u.h221NonStandard.t35Extension == USA_H221_COUNTRY_EXTENSION)
  1546. && (pCCThisCap->Cap.H245Vid_NONSTD.nonStandardIdentifier.u.h221NonStandard.manufacturerCode == MICROSOFT_H_221_MFG_CODE))
  1547. {
  1548. // ok, this is ours so far. Now what data type is contained therein?
  1549. // welllll, lets keep a copy of this regardless ????. If we can't understand
  1550. // future versions of ourselves, then what???
  1551. uSize = pCCThisCap->Cap.H245Vid_NONSTD.data.length;
  1552. lpData = pCCThisCap->Cap.H245Vid_NONSTD.data.value;
  1553. }
  1554. }
  1555. }
  1556. // this is not really necessary to set RTP payload type of what is received - it should
  1557. // be obvious.
  1558. else if (pCCThisCap->ClientType == H245_CLIENT_VID_H263 )
  1559. {
  1560. pTemp->video_params.RTPPayload = RTP_PAYLOAD_H263;
  1561. }
  1562. else if(pCCThisCap->ClientType == H245_CLIENT_VID_H261)
  1563. {
  1564. pTemp->video_params.RTPPayload = RTP_PAYLOAD_H261;
  1565. }
  1566. pTemp->uLocalDetailsSize = 0; // we're not keeping another copy of local encode details
  1567. pTemp->lpLocalFormatDetails =0; // we're not keeping another copy of local encode details
  1568. pTemp->uRemoteDetailsSize = 0; // clear this now
  1569. if(uSize && lpData)
  1570. {
  1571. pTemp->H245Cap.Cap.H245Vid_NONSTD.data.length = uSize;
  1572. pTemp->H245Cap.Cap.H245Vid_NONSTD.data.value = (unsigned char *)lpData;
  1573. pTemp->lpRemoteFormatDetails = MEMALLOC(uSize);
  1574. if(pTemp->lpRemoteFormatDetails)
  1575. {
  1576. memcpy(pTemp->lpRemoteFormatDetails, lpData, uSize);
  1577. pTemp->uRemoteDetailsSize = uSize;
  1578. }
  1579. #ifdef DEBUG
  1580. else
  1581. {
  1582. ERRORMESSAGE(("%s:allocation failed!\r\n",_fx_));
  1583. }
  1584. #endif
  1585. }
  1586. else
  1587. {
  1588. pTemp->lpRemoteFormatDetails = NULL;
  1589. pTemp->uRemoteDetailsSize =0;
  1590. }
  1591. uNumRemoteDecodeFormats++;
  1592. // use the index as the ID
  1593. return (uNumRemoteDecodeFormats-1);
  1594. ERROR_EXIT:
  1595. return INVALID_VIDEO_FORMAT;
  1596. }
  1597. VOID CMsivCapability::FlushRemoteCaps()
  1598. {
  1599. if(pRemoteDecodeFormats)
  1600. {
  1601. MEMFREE(pRemoteDecodeFormats);
  1602. pRemoteDecodeFormats = NULL;
  1603. uNumRemoteDecodeFormats = 0;
  1604. uRemoteDecodeFormatCapacity = 0;
  1605. }
  1606. }
  1607. HRESULT CMsivCapability::AddRemoteDecodeCaps(PCC_TERMCAPLIST pTermCapList)
  1608. {
  1609. FX_ENTRY ("CMsivCapability::AddRemoteDecodeCaps");
  1610. HRESULT hr = hrSuccess;
  1611. PPCC_TERMCAP ppCCThisCap;
  1612. PCC_TERMCAP pCCThisCap;
  1613. WORD wNumCaps;
  1614. //ERRORMESSAGE(("%s,\r\n", _fx_));
  1615. if(!pTermCapList) // additional capability descriptors may be added
  1616. { // at any time
  1617. return CAPS_E_INVALID_PARAM;
  1618. }
  1619. // cleanup old term caps if term caps are being addded and old caps exist
  1620. FlushRemoteCaps();
  1621. wNumCaps = pTermCapList->wLength;
  1622. ppCCThisCap = pTermCapList->pTermCapArray;
  1623. /*
  1624. CC_TERMCAPLIST TERMCAPINFO CC_TERMCAP
  1625. pTermCapList-> {
  1626. wLength
  1627. pTermCapInfo--->pTermCap----------->{single capability.....}
  1628. }
  1629. pTermCap----------->{single capability.}
  1630. pTermCap----------->{single capability...}
  1631. */
  1632. while(wNumCaps--)
  1633. {
  1634. if(!(pCCThisCap = *ppCCThisCap++))
  1635. {
  1636. ERRORMESSAGE(("%s:null pTermCap, 0x%04x of 0x%04x\r\n",
  1637. _fx_, pTermCapList->wLength - wNumCaps, pTermCapList->wLength));
  1638. continue;
  1639. }
  1640. if(!IsCapabilityRecognized(pCCThisCap))
  1641. {
  1642. continue;
  1643. }
  1644. AddRemoteDecodeFormat(pCCThisCap);
  1645. }
  1646. return hr;
  1647. }
  1648. // Given the ID of a local format, gets the channel parameters that are sent to the
  1649. // remote end as part of the capability exchange. This function is not used by the
  1650. // capability exchange code (because it sends more than just these parameters).
  1651. // However, this is useful information by itself - it can be used for validating the
  1652. // parameters of channel open requests against the expected parameters
  1653. HRESULT CMsivCapability::GetPublicDecodeParams(LPVOID pBufOut, UINT uBufSize, VIDEO_FORMAT_ID id)
  1654. {
  1655. UINT uIndex = IDToIndex(id);
  1656. // validate input
  1657. if(!pBufOut|| (uIndex >= (UINT)uNumLocalFormats))
  1658. {
  1659. return CAPS_E_INVALID_PARAM;
  1660. }
  1661. if(uBufSize < sizeof(CC_TERMCAP))
  1662. {
  1663. return CAPS_E_BUFFER_TOO_SMALL;
  1664. }
  1665. memcpy(pBufOut, &((pLocalFormats + uIndex)->H245Cap), sizeof(CC_TERMCAP));
  1666. return hrSuccess;
  1667. }
  1668. HRESULT CMsivCapability::SetAudioPacketDuration(UINT uPacketDuration)
  1669. {
  1670. return CAPS_E_INVALID_PARAM;
  1671. }
  1672. // Given the IDs of "matching" local and remote formats, gets the preferred channel parameters
  1673. // that will be used in requests to open a channel for sending to the remote.
  1674. HRESULT CMsivCapability::GetEncodeParams(LPVOID pBufOut, UINT uBufSize,LPVOID pLocalParams, UINT uSizeLocal,
  1675. VIDEO_FORMAT_ID idRemote, VIDEO_FORMAT_ID idLocal)
  1676. {
  1677. UINT uLocalIndex = IDToIndex(idLocal);
  1678. VIDCAP_DETAILS *pLocalDetails = pLocalFormats + uLocalIndex;
  1679. VIDCAP_DETAILS *pFmtTheirs;
  1680. VIDEO_CHANNEL_PARAMETERS local_params;
  1681. UINT u;
  1682. PCC_TERMCAP pTermCap = (PCC_TERMCAP)pBufOut;
  1683. // validate input
  1684. // AddCapabilityBase adds to the ID below. Make sure we're checking Video Formats
  1685. if(!pBufOut)
  1686. {
  1687. return CAPS_E_INVALID_PARAM;
  1688. }
  1689. if(uBufSize < sizeof(CC_TERMCAP))
  1690. {
  1691. return CAPS_E_BUFFER_TOO_SMALL;
  1692. }
  1693. if(!pLocalParams|| uSizeLocal < sizeof(VIDEO_CHANNEL_PARAMETERS)
  1694. ||(uLocalIndex >= (UINT)uNumLocalFormats))
  1695. {
  1696. return CAPS_E_INVALID_PARAM;
  1697. }
  1698. pFmtTheirs = pRemoteDecodeFormats; // start at the beginning of the remote formats
  1699. for(u=0; u<uNumRemoteDecodeFormats; u++)
  1700. {
  1701. if(pFmtTheirs->H245Cap.CapId == idRemote)
  1702. {
  1703. // copy CC_TERMCAP struct. Any data referenced by CC_TERMCAP now has
  1704. // two references to it. i.e. pTermCap->extrablah is the same
  1705. // location as pFmtTheirs->extrablah
  1706. memcpy(pBufOut, &(pFmtTheirs->H245Cap), sizeof(CC_TERMCAP));
  1707. break;
  1708. }
  1709. pFmtTheirs++; // next entry in receiver's caps
  1710. }
  1711. // check for an unfound format
  1712. if(u >= uNumRemoteDecodeFormats)
  1713. goto ERROR_EXIT;
  1714. // select channel parameters if appropriate. The audio formats that have variable parameters
  1715. // are :
  1716. #pragma message ("Are H.26? variable parameter formats?")
  1717. // H245_CAP_H261 H245Vid_H261;
  1718. // H245_CAP_H263 H245Vid_H263;
  1719. // and of course all nonstandard formats
  1720. // Select parameters based on local capability info
  1721. if(pTermCap->ClientType == H245_CLIENT_VID_H263)
  1722. {
  1723. unsigned short bit_mask;
  1724. // select frames per packet based on minimum latency value that is acceptable
  1725. #define H263_QCIF 0x4000
  1726. #define H263_MAXBP 0x0200
  1727. //H263_QCIF | H263_MAXBP;
  1728. pTermCap->Cap.H245Vid_H263.bit_mask= H263_MAXBP | pLocalDetails->H245Cap.Cap.H245Vid_H263.bit_mask;
  1729. local_params.ns_params.maxBitRate = pTermCap->Cap.H245Vid_H263.maxBitRate
  1730. = min (pLocalDetails->nonstd_params.maxBitRate , pFmtTheirs->H245Cap.Cap.H245Vid_H263.maxBitRate);
  1731. local_params.ns_params.maxBPP = pTermCap->Cap.H245Vid_H263.bppMaxKb
  1732. = min (pLocalDetails->nonstd_params.maxBPP, pFmtTheirs->H245Cap.Cap.H245Vid_H263.bppMaxKb);
  1733. // we (the local end) need to know that actual MPI is going to be used!
  1734. // like everywhere else in this module, the assumption is that local H.263 capabilities are
  1735. // fanned out with one local cap entry per frame size.
  1736. // MPI minimum interval in units of 1/29.97sec so take the longest interval
  1737. // there is no pretty way to do this
  1738. bit_mask = pLocalDetails->H245Cap.Cap.H245Vid_H263.bit_mask;
  1739. if(bit_mask & H263VideoCapability_sqcifMPI_present)
  1740. {
  1741. local_params.ns_params.MPI = pTermCap->Cap.H245Vid_H263.sqcifMPI =
  1742. max(pLocalDetails->nonstd_params.MPI,
  1743. pTermCap->Cap.H245Vid_H263.sqcifMPI);
  1744. }
  1745. else if (bit_mask & H263VideoCapability_qcifMPI_present)
  1746. {
  1747. local_params.ns_params.MPI = pTermCap->Cap.H245Vid_H263.H263VdCpblty_qcifMPI =
  1748. max(pLocalDetails->nonstd_params.MPI,
  1749. pTermCap->Cap.H245Vid_H263.H263VdCpblty_qcifMPI);
  1750. }
  1751. else if (bit_mask & H263VideoCapability_cifMPI_present)
  1752. {
  1753. local_params.ns_params.MPI = pTermCap->Cap.H245Vid_H263.H263VdCpblty_cifMPI =
  1754. max(pLocalDetails->nonstd_params.MPI,
  1755. pTermCap->Cap.H245Vid_H263.H263VdCpblty_cifMPI);
  1756. }
  1757. else if (bit_mask & H263VideoCapability_cif4MPI_present)
  1758. {
  1759. local_params.ns_params.MPI = pTermCap->Cap.H245Vid_H263.cif4MPI =
  1760. max(pLocalDetails->H245Cap.Cap.H245Vid_H263.cif4MPI,
  1761. pTermCap->Cap.H245Vid_H263.cif4MPI);
  1762. }
  1763. else if (bit_mask & H263VideoCapability_cif16MPI_present)
  1764. {
  1765. local_params.ns_params.MPI = pTermCap->Cap.H245Vid_H263.cif16MPI =
  1766. max(pLocalDetails->nonstd_params.MPI,
  1767. pTermCap->Cap.H245Vid_H263.cif16MPI);
  1768. }
  1769. // else // impossible. Doom, as MikeG and JonT would say
  1770. }
  1771. else if(pTermCap->ClientType == H245_CLIENT_VID_H261)
  1772. {
  1773. unsigned short bit_mask;
  1774. // select frames per packet based on minimum latency value that is acceptable
  1775. pTermCap->Cap.H245Vid_H261.bit_mask= pLocalDetails->H245Cap.Cap.H245Vid_H261.bit_mask;
  1776. local_params.ns_params.maxBitRate = pTermCap->Cap.H245Vid_H261.maxBitRate
  1777. = min (pLocalDetails->nonstd_params.maxBitRate , pFmtTheirs->H245Cap.Cap.H245Vid_H261.maxBitRate);
  1778. // we (the local end) need to know that actual MPI is going to be used!
  1779. // like everywhere else in this module, the assumption is that local H.261 capabilities are
  1780. // fanned out with one local cap entry per frame size.
  1781. // MPI minimum interval in units of 1/29.97sec so take the longest interval
  1782. // there is no pretty way to do this
  1783. bit_mask = pLocalDetails->H245Cap.Cap.H245Vid_H261.bit_mask;
  1784. if (bit_mask & H261VdCpblty_qcifMPI_present)
  1785. {
  1786. local_params.ns_params.MPI = pTermCap->Cap.H245Vid_H261.H261VdCpblty_qcifMPI =
  1787. max(pLocalDetails->nonstd_params.MPI,
  1788. pTermCap->Cap.H245Vid_H261.H261VdCpblty_qcifMPI);
  1789. }
  1790. else if (bit_mask & H261VdCpblty_cifMPI_present)
  1791. {
  1792. local_params.ns_params.MPI = pTermCap->Cap.H245Vid_H261.H261VdCpblty_cifMPI =
  1793. max(pLocalDetails->nonstd_params.MPI,
  1794. pTermCap->Cap.H245Vid_H261.H261VdCpblty_cifMPI);
  1795. }
  1796. // else // impossible. Doom, as MikeG and JonT would say
  1797. }
  1798. else if (pTermCap->ClientType == H245_CLIENT_VID_NONSTD)
  1799. {
  1800. // NOT YET IMPLEMENTED!!!!. even the nonstandard parameters need to be fixed
  1801. // up here based on mutual maxes and mins
  1802. memcpy(&local_params.ns_params, &pLocalDetails->nonstd_params,
  1803. sizeof(NSC_CHANNEL_VIDEO_PARAMETERS));
  1804. }
  1805. local_params.RTP_Payload = pLocalDetails->video_params.RTPPayload;
  1806. //Fixup local
  1807. memcpy(pLocalParams, &local_params, sizeof(VIDEO_CHANNEL_PARAMETERS));
  1808. return hrSuccess;
  1809. ERROR_EXIT:
  1810. return CAPS_E_INVALID_PARAM;
  1811. }
  1812. BOOL NonStandardCapsCompareV(VIDCAP_DETAILS *pFmtMine, PNSC_VIDEO_CAPABILITY pCap2,
  1813. UINT uSize2)
  1814. {
  1815. PVIDEOFORMATEX lpvcd;
  1816. if(!pFmtMine || !pCap2)
  1817. return FALSE;
  1818. if(!(lpvcd = (PVIDEOFORMATEX)pFmtMine->lpLocalFormatDetails))
  1819. return FALSE;
  1820. if(pCap2->cvp_type == NSC_VCM_VIDEOFORMATEX)
  1821. {
  1822. // check sizes first
  1823. if(lpvcd->bih.biSize != pCap2->cvp_data.vfx.bih.biSize)
  1824. {
  1825. return FALSE;
  1826. }
  1827. // compare structures, including extra bytes
  1828. if(memcmp(lpvcd, &pCap2->cvp_data.vfx,
  1829. sizeof(VIDEOFORMATEX) - BMIH_SLOP_BYTES)==0)
  1830. {
  1831. return TRUE;
  1832. }
  1833. }
  1834. else if(pCap2->cvp_type == NSC_VCMABBREV)
  1835. {
  1836. if((LOWORD(pCap2->cvp_data.vcm_brief.dwFormatTag) == lpvcd->dwFormatTag)
  1837. && (pCap2->cvp_data.vcm_brief.dwSamplesPerSec == lpvcd->nSamplesPerSec)
  1838. && (LOWORD(pCap2->cvp_data.vcm_brief.dwBitsPerSample) == lpvcd->wBitsPerSample))
  1839. {
  1840. return TRUE;
  1841. }
  1842. }
  1843. return FALSE;
  1844. }
  1845. BOOL HasNonStandardCapsTS(VIDCAP_DETAILS *pFmtMine, PNSC_VIDEO_CAPABILITY pCap2)
  1846. {
  1847. PVIDEOFORMATEX lpvcd;
  1848. if(!pFmtMine || !pCap2)
  1849. return FALSE;
  1850. if(!(lpvcd = (PVIDEOFORMATEX)pFmtMine->lpLocalFormatDetails))
  1851. return FALSE;
  1852. if(pCap2->cvp_type == NSC_VCM_VIDEOFORMATEX)
  1853. if(lpvcd->dwSupportTSTradeOff && pCap2->cvp_data.vfx.dwSupportTSTradeOff)
  1854. return TRUE;
  1855. return FALSE;
  1856. }
  1857. HRESULT CMsivCapability::ResolveToLocalFormat(MEDIA_FORMAT_ID FormatIDLocal,
  1858. MEDIA_FORMAT_ID * pFormatIDRemote)
  1859. {
  1860. VIDCAP_DETAILS *pFmtLocal;
  1861. VIDCAP_DETAILS *pFmtRemote;
  1862. UINT format_mask;
  1863. UINT uIndex = IDToIndex(FormatIDLocal);
  1864. UINT i;
  1865. if(!pFormatIDRemote || (FormatIDLocal == INVALID_MEDIA_FORMAT)
  1866. || (uIndex >= (UINT)uNumLocalFormats))
  1867. {
  1868. return CAPS_E_INVALID_PARAM;
  1869. }
  1870. pFmtLocal = pLocalFormats + uIndex;
  1871. pFmtRemote = pRemoteDecodeFormats; // start at the beginning of the remote formats
  1872. for(i=0; i<uNumRemoteDecodeFormats; i++)
  1873. {
  1874. if(!pFmtLocal->bSendEnabled)
  1875. continue;
  1876. // compare capabilities - start by comparing the format tag. a.k.a. "ClientType" in H.245 land
  1877. if(pFmtLocal->H245Cap.ClientType == pFmtRemote->H245Cap.ClientType)
  1878. {
  1879. // if this is a nonstandard cap, compare nonstandard parameters
  1880. if(pFmtLocal->H245Cap.ClientType == H245_CLIENT_VID_NONSTD)
  1881. {
  1882. if(NonStandardCapsCompareV(pFmtLocal,
  1883. (PNSC_VIDEO_CAPABILITY)pFmtRemote->H245Cap.Cap.H245Vid_NONSTD.data.value,
  1884. pFmtRemote->H245Cap.Cap.H245Vid_NONSTD.data.length))
  1885. {
  1886. goto RESOLVED_EXIT;
  1887. }
  1888. }
  1889. else // compare standard parameters, if any
  1890. {
  1891. // well, so far, there aren't any parameters that are significant enough
  1892. // to affect the match/no match decision
  1893. if (pFmtLocal->H245Cap.ClientType == H245_CLIENT_VID_H263)
  1894. {
  1895. format_mask= H263VideoCapability_sqcifMPI_present
  1896. | H263VideoCapability_qcifMPI_present | H263VideoCapability_cifMPI_present
  1897. | H263VideoCapability_cif4MPI_present | H263VideoCapability_cif16MPI_present;
  1898. if ((pFmtRemote->H245Cap.Cap.H245Vid_H263.bit_mask & format_mask) & (pFmtLocal->H245Cap.Cap.H245Vid_H263.bit_mask & format_mask))
  1899. {
  1900. // compatible basic format
  1901. goto RESOLVED_EXIT;
  1902. }
  1903. }
  1904. else if (pFmtLocal->H245Cap.ClientType == H245_CLIENT_VID_H261)
  1905. {
  1906. format_mask= H261VdCpblty_qcifMPI_present | H261VdCpblty_cifMPI_present;
  1907. if ((pFmtRemote->H245Cap.Cap.H245Vid_H261.bit_mask & format_mask) & (pFmtLocal->H245Cap.Cap.H245Vid_H261.bit_mask & format_mask))
  1908. {
  1909. // compatible basic format
  1910. goto RESOLVED_EXIT;
  1911. }
  1912. }
  1913. else
  1914. {
  1915. //Some other standard format
  1916. goto RESOLVED_EXIT;
  1917. }
  1918. }
  1919. }
  1920. pFmtRemote++; // next entry in remote caps
  1921. }
  1922. return CAPS_E_NOMATCH;
  1923. RESOLVED_EXIT:
  1924. // Match!
  1925. // return ID of remote decoding (receive fmt) caps that match our
  1926. // send caps
  1927. *pFormatIDRemote = pFmtRemote->H245Cap.CapId;
  1928. return hrSuccess;
  1929. }
  1930. // resolve using currently cached local and remote formats
  1931. HRESULT CMsivCapability::ResolveEncodeFormat(
  1932. VIDEO_FORMAT_ID *pIDEncodeOut,
  1933. VIDEO_FORMAT_ID *pIDRemoteDecode)
  1934. {
  1935. UINT i,j=0,format_mask;
  1936. VIDCAP_DETAILS *pFmtMine = pLocalFormats;
  1937. VIDCAP_DETAILS *pFmtTheirs;
  1938. if(!pIDEncodeOut || !pIDRemoteDecode)
  1939. {
  1940. return CAPS_E_INVALID_PARAM;
  1941. }
  1942. if(!uNumLocalFormats || !pLocalFormats)
  1943. {
  1944. *pIDEncodeOut = *pIDRemoteDecode = INVALID_VIDEO_FORMAT;
  1945. return CAPS_E_NOCAPS;
  1946. }
  1947. if(!pRemoteDecodeFormats || !uNumRemoteDecodeFormats)
  1948. {
  1949. *pIDEncodeOut = *pIDRemoteDecode = INVALID_VIDEO_FORMAT;
  1950. return CAPS_E_NOMATCH;
  1951. }
  1952. // decide how to encode. my caps are ordered by my preference according to
  1953. // the contents of IDsByRank[]
  1954. //If given a salt, find the position and add it
  1955. if (*pIDEncodeOut != INVALID_MEDIA_FORMAT)
  1956. {
  1957. UINT uIndex = IDToIndex(*pIDEncodeOut);
  1958. if (uIndex > uNumLocalFormats)
  1959. {
  1960. return CAPS_W_NO_MORE_FORMATS;
  1961. }
  1962. for(i=0; i<uNumLocalFormats; i++)
  1963. {
  1964. if (pLocalFormats[IDsByRank[i]].H245Cap.CapId == *pIDEncodeOut)
  1965. {
  1966. j=i+1;
  1967. break;
  1968. }
  1969. }
  1970. }
  1971. // start at index j
  1972. for(i=j; i<uNumLocalFormats; i++)
  1973. {
  1974. pFmtMine = pLocalFormats + IDsByRank[i];
  1975. // check to see if this format is enabled for encoding
  1976. if(!pFmtMine->bSendEnabled)
  1977. continue;
  1978. pFmtTheirs = pRemoteDecodeFormats; // start at the beginning of the remote formats
  1979. for(j=0; j<uNumRemoteDecodeFormats; j++)
  1980. {
  1981. // compare capabilities - start by comparing the format tag. a.k.a. "ClientType" in H.245 land
  1982. if(pFmtMine->H245Cap.ClientType == pFmtTheirs->H245Cap.ClientType)
  1983. {
  1984. // if this is a nonstandard cap, compare nonstandard parameters
  1985. if(pFmtMine->H245Cap.ClientType == H245_CLIENT_VID_NONSTD)
  1986. {
  1987. if(NonStandardCapsCompareV(pFmtMine,
  1988. (PNSC_VIDEO_CAPABILITY)pFmtTheirs->H245Cap.Cap.H245Vid_NONSTD.data.value,
  1989. pFmtTheirs->H245Cap.Cap.H245Vid_NONSTD.data.length))
  1990. {
  1991. goto RESOLVED_EXIT;
  1992. }
  1993. }
  1994. else // compare standard parameters, if any
  1995. {
  1996. // well, so far, there aren't any parameters that are significant enough
  1997. // to affect the match/no match decision
  1998. if (pFmtMine->H245Cap.ClientType == H245_CLIENT_VID_H263)
  1999. {
  2000. format_mask= H263VideoCapability_sqcifMPI_present| H263VideoCapability_qcifMPI_present
  2001. |H263VdCpblty_cifMPI_present
  2002. |H263VideoCapability_cif4MPI_present
  2003. |H263VideoCapability_cif16MPI_present;
  2004. if ((pFmtTheirs->H245Cap.Cap.H245Vid_H263.bit_mask & format_mask) & (pFmtMine->H245Cap.Cap.H245Vid_H263.bit_mask & format_mask))
  2005. {
  2006. // compatible basic format
  2007. goto RESOLVED_EXIT;
  2008. }
  2009. }
  2010. else if (pFmtMine->H245Cap.ClientType == H245_CLIENT_VID_H261)
  2011. {
  2012. format_mask= H261VdCpblty_qcifMPI_present | H261VdCpblty_cifMPI_present;
  2013. if ((pFmtTheirs->H245Cap.Cap.H245Vid_H261.bit_mask & format_mask) & (pFmtMine->H245Cap.Cap.H245Vid_H261.bit_mask & format_mask))
  2014. {
  2015. // compatible basic format
  2016. goto RESOLVED_EXIT;
  2017. }
  2018. } else {
  2019. //Some other standard format
  2020. goto RESOLVED_EXIT;
  2021. }
  2022. }
  2023. }
  2024. pFmtTheirs++; // next entry in receiver's caps
  2025. }
  2026. }
  2027. return CAPS_E_NOMATCH;
  2028. RESOLVED_EXIT:
  2029. // Match!
  2030. // return ID of our encoding (sending fmt) caps that match
  2031. *pIDEncodeOut = pFmtMine->H245Cap.CapId;
  2032. // return ID of remote decoding (receive fmt) caps that match our
  2033. // send caps
  2034. *pIDRemoteDecode = pFmtTheirs->H245Cap.CapId;
  2035. return hrSuccess;
  2036. }
  2037. HRESULT CMsivCapability::GetDecodeParams(PCC_RX_CHANNEL_REQUEST_CALLBACK_PARAMS pChannelParams,
  2038. VIDEO_FORMAT_ID * pFormatID, LPVOID lpvBuf, UINT uBufSize)
  2039. {
  2040. UINT i,j=0;
  2041. VIDCAP_DETAILS *pFmtMine = pLocalFormats;
  2042. VIDCAP_DETAILS *pFmtTheirs = pRemoteDecodeFormats;
  2043. VIDEO_CHANNEL_PARAMETERS local_params;
  2044. PNSC_CHANNEL_VIDEO_PARAMETERS pNSCap = &local_params.ns_params;
  2045. PCC_TERMCAP pCapability;
  2046. if(!pChannelParams || !(pCapability = pChannelParams->pChannelCapability) || !pFormatID || !lpvBuf ||
  2047. (uBufSize < sizeof(VIDEO_CHANNEL_PARAMETERS)))
  2048. {
  2049. return CAPS_E_INVALID_PARAM;
  2050. }
  2051. if(!uNumLocalFormats || !pLocalFormats)
  2052. {
  2053. return CAPS_E_NOCAPS;
  2054. }
  2055. local_params.TS_Tradeoff = FALSE; // initialize TS tradeoff
  2056. for(i=0; i<uNumLocalFormats; i++)
  2057. {
  2058. pFmtMine = pLocalFormats + IDsByRank[i];
  2059. // compare capabilities - start by comparing the format tag. a.k.a. "ClientType" in H.245 land
  2060. if(pFmtMine->H245Cap.ClientType == pCapability->ClientType)
  2061. {
  2062. // if this is a nonstandard cap, compare nonstandard parameters
  2063. if(pFmtMine->H245Cap.ClientType == H245_CLIENT_VID_NONSTD)
  2064. {
  2065. if(NonStandardCapsCompareV(pFmtMine, (PNSC_VIDEO_CAPABILITY)pCapability->Cap.H245Vid_NONSTD.data.value,
  2066. pCapability->Cap.H245Vid_NONSTD.data.length))
  2067. {
  2068. #pragma message ("someday may need need fixup of nonstd params")
  2069. // for now, the remote & local nonstandard params are what we want
  2070. // and the remote's version of NSC_CHANNEL_VIDEO_PARAMETERS will
  2071. // be copied out
  2072. pNSCap = (PNSC_CHANNEL_VIDEO_PARAMETERS)
  2073. &((PNSC_VIDEO_CAPABILITY)pCapability->Cap.H245Vid_NONSTD.data.value)->cvp_params;
  2074. // Does this format support temporal/spatial tradeoff
  2075. if(HasNonStandardCapsTS(pFmtMine, (PNSC_VIDEO_CAPABILITY)pCapability->Cap.H245Vid_NONSTD.data.value))
  2076. local_params.TS_Tradeoff = TRUE;
  2077. else
  2078. local_params.TS_Tradeoff = FALSE;
  2079. goto RESOLVED_EXIT;
  2080. }
  2081. }
  2082. else // compare standard parameters, if any
  2083. {
  2084. switch (pFmtMine->H245Cap.ClientType)
  2085. {
  2086. unsigned short bit_mask, format_mask, usMyMPI, usTheirMPI;
  2087. case H245_CLIENT_VID_H263:
  2088. // like everywhere else in this module, the assumption is that
  2089. // local H.263 capabilities are fanned out with one local cap entry
  2090. // per frame size.
  2091. format_mask= H263VideoCapability_sqcifMPI_present
  2092. | H263VideoCapability_qcifMPI_present
  2093. | H263VideoCapability_cifMPI_present
  2094. | H263VideoCapability_cif4MPI_present
  2095. | H263VideoCapability_cif16MPI_present;
  2096. // bail out if no match or nonexistent frame size
  2097. if (!((pCapability->Cap.H245Vid_H263.bit_mask & format_mask) & (pFmtMine->H245Cap.Cap.H245Vid_H263.bit_mask & format_mask)))
  2098. continue;
  2099. // get the maximum bitrate
  2100. local_params.ns_params.maxBitRate = min(pFmtMine->H245Cap.Cap.H245Vid_H263.maxBitRate,
  2101. pCapability->Cap.H245Vid_H263.maxBitRate);
  2102. local_params.ns_params.maxBPP = min (pFmtMine->H245Cap.Cap.H245Vid_H263.bppMaxKb ,
  2103. pCapability->Cap.H245Vid_H263.bppMaxKb);
  2104. // FIND THE MAXIMUM MPI!!!!. (minimum frame rate)
  2105. // there is no pretty way to do this
  2106. bit_mask = pFmtMine->H245Cap.Cap.H245Vid_H263.bit_mask;
  2107. if(bit_mask & H263VideoCapability_sqcifMPI_present)
  2108. {
  2109. local_params.ns_params.MPI =
  2110. max(pFmtMine->H245Cap.Cap.H245Vid_H263.sqcifMPI,
  2111. pCapability->Cap.H245Vid_H263.sqcifMPI);
  2112. }
  2113. else if (bit_mask & H263VideoCapability_qcifMPI_present)
  2114. {
  2115. local_params.ns_params.MPI =
  2116. max(pFmtMine->H245Cap.Cap.H245Vid_H263.H263VdCpblty_qcifMPI,
  2117. pCapability->Cap.H245Vid_H263.H263VdCpblty_qcifMPI);
  2118. }
  2119. else if (bit_mask & H263VideoCapability_cifMPI_present)
  2120. {
  2121. local_params.ns_params.MPI =
  2122. max(pFmtMine->H245Cap.Cap.H245Vid_H263.H263VdCpblty_cifMPI,
  2123. pCapability->Cap.H245Vid_H263.H263VdCpblty_cifMPI);
  2124. }
  2125. else if (bit_mask & H263VideoCapability_cif4MPI_present)
  2126. {
  2127. local_params.ns_params.MPI =
  2128. max(pFmtMine->H245Cap.Cap.H245Vid_H263.cif4MPI,
  2129. pCapability->Cap.H245Vid_H263.cif4MPI);
  2130. }
  2131. else if (bit_mask & H263VideoCapability_cif16MPI_present)
  2132. {
  2133. local_params.ns_params.MPI =
  2134. max(pFmtMine->H245Cap.Cap.H245Vid_H263.cif16MPI,
  2135. pCapability->Cap.H245Vid_H263.cif16MPI);
  2136. }
  2137. else // impossible. Doom, as MikeG and JonT would say
  2138. continue;
  2139. // Fallout (And the format is found!)
  2140. // And one more special thing: find out if the other end
  2141. // advertised Temporal/Spatial tradeoff in it's send capabilities.
  2142. // First try the obvious. Technically, it only makes sense for
  2143. // transmit capabilities, but if the channel params have it, then
  2144. // the other end must have the capability
  2145. if(pCapability->Cap.H245Vid_H263.tmprlSptlTrdOffCpblty)
  2146. {
  2147. local_params.TS_Tradeoff = TRUE;
  2148. }
  2149. else
  2150. {
  2151. // Search for a H.263 SEND capability that has the T/S tradoff set
  2152. for(j=0; j<uNumRemoteDecodeFormats; j++)
  2153. {
  2154. if((pFmtTheirs->H245Cap.ClientType == H245_CLIENT_VID_H263)
  2155. // exclude RX capabilities
  2156. && (pFmtTheirs->H245Cap.Dir != H245_CAPDIR_LCLRX)
  2157. && (pFmtTheirs->H245Cap.Dir != H245_CAPDIR_RMTRX))
  2158. {
  2159. if ((pFmtTheirs->H245Cap.Cap.H245Vid_H263.bit_mask & format_mask) & (pFmtMine->H245Cap.Cap.H245Vid_H263.bit_mask & format_mask))
  2160. {
  2161. local_params.TS_Tradeoff = TRUE;
  2162. break;
  2163. }
  2164. }
  2165. pFmtTheirs++; // next entry in receiver's caps
  2166. }
  2167. }
  2168. goto RESOLVED_EXIT;
  2169. break;
  2170. case H245_CLIENT_VID_H261:
  2171. // like everywhere else in this module, the assumption is that
  2172. // local H.261 capabilities are fanned out with one local cap entry
  2173. // per frame size.
  2174. format_mask= H261VdCpblty_qcifMPI_present |H261VdCpblty_cifMPI_present;
  2175. // bail out if no match or nonexistent frame size
  2176. if (!((pCapability->Cap.H245Vid_H261.bit_mask & format_mask) & (pFmtMine->H245Cap.Cap.H245Vid_H261.bit_mask & format_mask)))
  2177. continue;
  2178. // get the maximum bitrate
  2179. local_params.ns_params.maxBitRate = min(pFmtMine->H245Cap.Cap.H245Vid_H261.maxBitRate,
  2180. pCapability->Cap.H245Vid_H261.maxBitRate);
  2181. // FIND THE MAXIMUM MPI!!!!. (minimum frame rate)
  2182. // there is no pretty way to do this
  2183. bit_mask = pFmtMine->H245Cap.Cap.H245Vid_H261.bit_mask;
  2184. if (bit_mask & H261VdCpblty_qcifMPI_present)
  2185. {
  2186. local_params.ns_params.MPI =
  2187. max(pFmtMine->H245Cap.Cap.H245Vid_H261.H261VdCpblty_qcifMPI,
  2188. pCapability->Cap.H245Vid_H261.H261VdCpblty_qcifMPI);
  2189. }
  2190. else if (bit_mask & H261VdCpblty_cifMPI_present)
  2191. {
  2192. local_params.ns_params.MPI =
  2193. max(pFmtMine->H245Cap.Cap.H245Vid_H261.H261VdCpblty_cifMPI,
  2194. pCapability->Cap.H245Vid_H261.H261VdCpblty_cifMPI);
  2195. }
  2196. else // impossible. Doom, as MikeG and JonT would say
  2197. continue;
  2198. // Fallout (And the format is found!)
  2199. // And one more special thing: find out if the other end
  2200. // advertised Temporal/Spatial tradeoff in it's send capabilities.
  2201. // First try the obvious. Technically, it only makes sense for
  2202. // transmit capabilities, but if the channel params have it, then
  2203. // the other end must have the capability
  2204. if(pCapability->Cap.H245Vid_H261.tmprlSptlTrdOffCpblty)
  2205. {
  2206. local_params.TS_Tradeoff = TRUE;
  2207. }
  2208. else
  2209. {
  2210. // Search for a H.261 SEND capability that has the T/S tradoff set
  2211. for(j=0; j<uNumRemoteDecodeFormats; j++)
  2212. {
  2213. if((pFmtTheirs->H245Cap.ClientType == H245_CLIENT_VID_H261)
  2214. // exclude RX capabilities
  2215. && (pFmtTheirs->H245Cap.Dir != H245_CAPDIR_LCLRX)
  2216. && (pFmtTheirs->H245Cap.Dir != H245_CAPDIR_RMTRX))
  2217. {
  2218. if ((pFmtTheirs->H245Cap.Cap.H245Vid_H261.bit_mask
  2219. & format_mask)
  2220. & (pFmtMine->H245Cap.Cap.H245Vid_H261.bit_mask
  2221. & format_mask))
  2222. {
  2223. local_params.TS_Tradeoff = TRUE;
  2224. break;
  2225. }
  2226. }
  2227. pFmtTheirs++; // next entry in receiver's caps
  2228. }
  2229. }
  2230. goto RESOLVED_EXIT;
  2231. break;
  2232. default:
  2233. goto RESOLVED_EXIT;
  2234. break;
  2235. }
  2236. }// end else compare standard parameters, if any
  2237. }// end if(pFmtMine->H245Cap.ClientType == pCapability->ClientType)
  2238. }
  2239. return CAPS_E_NOMATCH;
  2240. RESOLVED_EXIT:
  2241. // Match!
  2242. // return ID of the decoding caps that match
  2243. *pFormatID = pFmtMine->H245Cap.CapId;
  2244. local_params.RTP_Payload = pChannelParams->bRTPPayloadType;;
  2245. memcpy(lpvBuf, &local_params, sizeof(VIDEO_CHANNEL_PARAMETERS));
  2246. return hrSuccess;
  2247. }
  2248. HRESULT CMsivCapability::SetCapIDBase (UINT uNewBase)
  2249. {
  2250. uCapIDBase = uNewBase;
  2251. UINT u;
  2252. for (u=0;u<uNumLocalFormats;u++)
  2253. {
  2254. pLocalFormats[u].H245Cap.CapId = u + uCapIDBase;
  2255. }
  2256. return hrSuccess;
  2257. }
  2258. BOOL CMsivCapability::IsHostForCapID(MEDIA_FORMAT_ID CapID)
  2259. {
  2260. if((CapID >= uCapIDBase) && ((CapID - uCapIDBase) < uNumLocalFormats))
  2261. return TRUE;
  2262. else
  2263. return FALSE;
  2264. }
  2265. HRESULT CMsivCapability::IsFormatEnabled (MEDIA_FORMAT_ID FormatID, PBOOL bRecv, PBOOL bSend)
  2266. {
  2267. UINT uIndex = IDToIndex(FormatID);
  2268. // validate input
  2269. if(uIndex >= (UINT)uNumLocalFormats)
  2270. {
  2271. return CAPS_E_INVALID_PARAM;
  2272. }
  2273. *bSend=((pLocalFormats + uIndex)->bSendEnabled);
  2274. *bRecv=((pLocalFormats + uIndex)->bRecvEnabled);
  2275. return hrSuccess;
  2276. }
  2277. BOOL CMsivCapability::IsFormatPublic (MEDIA_FORMAT_ID FormatID)
  2278. {
  2279. UINT uIndex = IDToIndex(FormatID);
  2280. // validate input
  2281. if(uIndex >= (UINT)uNumLocalFormats)
  2282. return FALSE;
  2283. // test if this is format is a duplicate of a public format
  2284. if((pLocalFormats + uIndex)->dwPublicRefIndex)
  2285. return FALSE; // then we keep this format to ourselves
  2286. else
  2287. return TRUE;
  2288. }
  2289. MEDIA_FORMAT_ID CMsivCapability::GetPublicID(MEDIA_FORMAT_ID FormatID)
  2290. {
  2291. UINT uIndex = IDToIndex(FormatID);
  2292. // validate input
  2293. if(uIndex >= (UINT)uNumLocalFormats)
  2294. return INVALID_MEDIA_FORMAT;
  2295. if((pLocalFormats + uIndex)->dwPublicRefIndex)
  2296. {
  2297. return (pLocalFormats + ((pLocalFormats + uIndex)->dwPublicRefIndex))->H245Cap.CapId;
  2298. }
  2299. else
  2300. {
  2301. return FormatID;
  2302. }
  2303. }
  2304. // Returns the Id of the format with the smallest wSortIndex - preferred format.
  2305. HRESULT CMsivCapability::GetPreferredFormatId (VIDEO_FORMAT_ID *pId)
  2306. {
  2307. HRESULT hr = hrSuccess;
  2308. VIDCAP_DETAILS *pDetails = pLocalFormats;
  2309. UINT u, uIndex;
  2310. WORD wSortIndex, wMinSortIndex = SHRT_MAX;
  2311. // Validate input param
  2312. if (!pId)
  2313. return((HRESULT)CAPS_E_INVALID_PARAM);
  2314. // Validate state
  2315. if(!uNumLocalFormats || !pDetails)
  2316. return((HRESULT)CAPS_E_NOCAPS);
  2317. // Look for the format with the smallest wSortIndex
  2318. for (u = 0; (u < uNumLocalFormats) && (u < MAX_CAPS_PRESORT); u++)
  2319. {
  2320. pDetails = pLocalFormats + IDsByRank[u];
  2321. // Find the sort index.
  2322. uIndex = (UINT)(pDetails - pLocalFormats);
  2323. for (wSortIndex = 0; (wSortIndex < uNumLocalFormats) && (wSortIndex < MAX_CAPS_PRESORT); wSortIndex++)
  2324. {
  2325. if (uIndex == IDsByRank[wSortIndex])
  2326. break; // Found it
  2327. }
  2328. if (wSortIndex <= wMinSortIndex)
  2329. {
  2330. *pId = IndexToId(uIndex);
  2331. wMinSortIndex = wSortIndex;
  2332. }
  2333. }
  2334. return(hr);
  2335. }
  2336.