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.

426 lines
11 KiB

  1. /*******************************************************************************
  2. Module: bgcall.cpp
  3. Author: Qianbo Huai
  4. Abstract:
  5. implements bridge call object
  6. *******************************************************************************/
  7. #include "stdafx.h"
  8. #include "work.h"
  9. #include <bridge.h>
  10. // to change
  11. const BSTR CLSID_String_BridgeTerminal = L"{581d09e5-0b45-11d3-a565-00c04f8ef6e3}";
  12. /*//////////////////////////////////////////////////////////////////////////////
  13. constructor
  14. ////*/
  15. CBridgeCall::CBridgeCall (CBridge *pBridge)
  16. {
  17. m_pBridge = pBridge;
  18. m_pH323Call = NULL;
  19. m_pSDPCall = NULL;
  20. }
  21. /*//////////////////////////////////////////////////////////////////////////////
  22. ////*/
  23. CBridgeCall::~CBridgeCall ()
  24. {
  25. Clear ();
  26. m_pBridge = NULL;
  27. }
  28. /*//////////////////////////////////////////////////////////////////////////////
  29. select terminals and connect the call
  30. ////*/
  31. HRESULT
  32. CBridgeCall::BridgeCalls ()
  33. {
  34. HRESULT hr;
  35. hr = SelectBridgeTerminals ();
  36. if (FAILED(hr))
  37. return hr;
  38. hr = SetupParticipantInfo ();
  39. if (FAILED(hr))
  40. return hr;
  41. hr = SetMulticastMode ();
  42. if (FAILED(hr))
  43. return hr;
  44. // connect h323 call
  45. hr = m_pH323Call->Answer ();
  46. if (FAILED(hr))
  47. return hr;
  48. // connect sdp call
  49. hr = m_pSDPCall->Connect (VARIANT_TRUE);
  50. if (FAILED(hr))
  51. {
  52. m_pH323Call->Disconnect (DC_NORMAL);
  53. return hr;
  54. }
  55. return S_OK;
  56. }
  57. /*//////////////////////////////////////////////////////////////////////////////
  58. ////*/
  59. HRESULT
  60. CBridgeCall::SelectBridgeTerminals ()
  61. {
  62. HRESULT hr;
  63. ITAddress *pAddress = NULL;
  64. ITMSPAddress *pMSPAddress = NULL;
  65. ITTerminal *pH323ToSDPVideoBT = NULL;
  66. ITTerminal *pH323ToSDPAudioBT = NULL;
  67. ITTerminal *pSDPToH323VideoBT = NULL;
  68. ITTerminal *pSDPToH323AudioBT = NULL;
  69. ITStreamControl *pStreamControl = NULL;
  70. IEnumStream *pEnumStreams = NULL;
  71. ITStream *pStream = NULL;
  72. // get SDP address
  73. hr = m_pBridge->GetSDPAddress (&pAddress);
  74. if (FAILED(hr))
  75. return hr;
  76. // get MSP address
  77. hr = pAddress->QueryInterface (IID_ITMSPAddress, (void**)&pMSPAddress);
  78. if (FAILED(hr))
  79. return hr;
  80. IConfBridge *pBridge = NULL;
  81. // create CConfBridge
  82. hr = CoCreateInstance (
  83. __uuidof(ConfBridge),
  84. NULL,
  85. CLSCTX_INPROC_SERVER,
  86. IID_IConfBridge,
  87. (LPVOID *)&pBridge
  88. );
  89. if (FAILED(hr))
  90. return hr;
  91. // create terminal: video H323->SDP
  92. hr = pBridge->CreateBridgeTerminal (
  93. // (MSP_HANDLE)pMSPAddress,
  94. // CLSID_String_BridgeTerminal,
  95. TAPIMEDIATYPE_VIDEO,
  96. // TD_RENDER, // not used
  97. &pH323ToSDPVideoBT
  98. );
  99. if (FAILED(hr))
  100. goto Error;
  101. // create terminal: audio H323->SDP
  102. hr = pBridge->CreateBridgeTerminal (
  103. // (MSP_HANDLE)pMSPAddress,
  104. // CLSID_String_BridgeTerminal,
  105. TAPIMEDIATYPE_AUDIO,
  106. // TD_RENDER, // not used
  107. &pH323ToSDPAudioBT
  108. );
  109. if (FAILED(hr))
  110. goto Error;
  111. // create terminal: video SDP->H323
  112. hr = pBridge->CreateBridgeTerminal (
  113. // (MSP_HANDLE)pMSPAddress,
  114. // CLSID_String_BridgeTerminal,
  115. TAPIMEDIATYPE_VIDEO,
  116. // TD_RENDER, // not used
  117. &pSDPToH323VideoBT
  118. );
  119. if (FAILED(hr))
  120. goto Error;
  121. // create terminal: audio SDP->H323
  122. hr = pBridge->CreateBridgeTerminal (
  123. // (MSP_HANDLE)pMSPAddress,
  124. // CLSID_String_BridgeTerminal,
  125. TAPIMEDIATYPE_AUDIO,
  126. // TD_RENDER, // not used
  127. &pSDPToH323AudioBT
  128. );
  129. if (FAILED(hr))
  130. goto Error;
  131. pMSPAddress->Release ();
  132. pMSPAddress = NULL;
  133. pAddress->Release ();
  134. pAddress = NULL;
  135. pBridge->Release ();
  136. pBridge = NULL;
  137. // get stream control on H323
  138. hr = m_pH323Call->QueryInterface (
  139. IID_ITStreamControl,
  140. (void **)&pStreamControl
  141. );
  142. if (FAILED(hr))
  143. goto Error;
  144. // get enum stream on H323
  145. hr = pStreamControl->EnumerateStreams (&pEnumStreams);
  146. if (FAILED(hr))
  147. goto Error;
  148. pStreamControl->Release ();
  149. pStreamControl = NULL;
  150. // iterate each stream on H323, select terminals
  151. while (S_OK == pEnumStreams->Next (1, &pStream, NULL))
  152. {
  153. if (IsStream (pStream, TAPIMEDIATYPE_VIDEO, TD_CAPTURE))
  154. {
  155. // video: h323 to sdp
  156. hr = pStream->SelectTerminal (pH323ToSDPVideoBT);
  157. if (FAILED(hr))
  158. goto Error;
  159. }
  160. else if (IsStream (pStream, TAPIMEDIATYPE_VIDEO, TD_RENDER))
  161. {
  162. // video: sdp to h323
  163. hr = pStream->SelectTerminal (pSDPToH323VideoBT);
  164. if (FAILED(hr))
  165. goto Error;
  166. IKeyFrameControl* pIKeyFrameControl;
  167. hr = pStream->QueryInterface(&pIKeyFrameControl);
  168. if (SUCCEEDED(hr))
  169. {
  170. hr = pIKeyFrameControl->PeriodicUpdatePicture(TRUE, 5);
  171. pIKeyFrameControl->Release();
  172. }
  173. }
  174. else if (IsStream (pStream, TAPIMEDIATYPE_AUDIO, TD_CAPTURE))
  175. {
  176. // audio: h323 to sdp
  177. hr = pStream->SelectTerminal (pH323ToSDPAudioBT);
  178. if (FAILED(hr))
  179. goto Error;
  180. }
  181. else if (IsStream (pStream, TAPIMEDIATYPE_AUDIO, TD_RENDER))
  182. {
  183. // video: sdp to h323
  184. hr = pStream->SelectTerminal (pSDPToH323AudioBT);
  185. if (FAILED(hr))
  186. goto Error;
  187. }
  188. pStream->Release ();
  189. pStream = NULL;
  190. }
  191. if (pStream)
  192. {
  193. pStream->Release ();
  194. pStream = NULL;
  195. }
  196. pEnumStreams->Release ();
  197. pEnumStreams = NULL;
  198. // get stream control on SDP
  199. hr = m_pSDPCall->QueryInterface (
  200. IID_ITStreamControl,
  201. (void **)&pStreamControl
  202. );
  203. if (FAILED(hr))
  204. goto Error;
  205. // get enum stream on SDP
  206. hr = pStreamControl->EnumerateStreams (&pEnumStreams);
  207. if (FAILED(hr))
  208. goto Error;
  209. pStreamControl->Release ();
  210. pStreamControl = NULL;
  211. // iterate each stream on SDP, select terminals
  212. while (S_OK == pEnumStreams->Next (1, &pStream, NULL))
  213. {
  214. if (IsStream (pStream, TAPIMEDIATYPE_VIDEO, TD_CAPTURE))
  215. {
  216. // video: sdp to h323
  217. hr = pStream->SelectTerminal (pSDPToH323VideoBT);
  218. if (FAILED(hr))
  219. goto Error;
  220. }
  221. else if (IsStream (pStream, TAPIMEDIATYPE_VIDEO, TD_RENDER))
  222. {
  223. // video: h323 to sdp
  224. hr = pStream->SelectTerminal (pH323ToSDPVideoBT);
  225. if (FAILED(hr))
  226. goto Error;
  227. }
  228. else if (IsStream (pStream, TAPIMEDIATYPE_AUDIO, TD_CAPTURE))
  229. {
  230. // audio: sdp to h323
  231. hr = pStream->SelectTerminal (pSDPToH323AudioBT);
  232. if (FAILED(hr))
  233. goto Error;
  234. }
  235. else if (IsStream (pStream, TAPIMEDIATYPE_AUDIO, TD_RENDER))
  236. {
  237. // video: h323 to sdp
  238. hr = pStream->SelectTerminal (pH323ToSDPAudioBT);
  239. if (FAILED(hr))
  240. goto Error;
  241. }
  242. pStream->Release ();
  243. pStream = NULL;
  244. }
  245. Cleanup:
  246. // release streams
  247. if (pStream)
  248. pStream->Release ();
  249. if (pEnumStreams)
  250. pEnumStreams->Release ();
  251. if (pStreamControl)
  252. pStreamControl->Release ();
  253. // release terminals
  254. if (pH323ToSDPVideoBT)
  255. pH323ToSDPVideoBT->Release ();
  256. if (pH323ToSDPAudioBT)
  257. pH323ToSDPAudioBT->Release ();
  258. if (pSDPToH323VideoBT)
  259. pSDPToH323VideoBT->Release ();
  260. if (pSDPToH323AudioBT)
  261. pSDPToH323AudioBT->Release ();
  262. if (pBridge)
  263. pBridge->Release ();
  264. return hr;
  265. Error:
  266. goto Cleanup;
  267. }
  268. HRESULT
  269. CBridgeCall::SetupParticipantInfo ()
  270. {
  271. HRESULT hr = S_OK;
  272. ITCallInfo *pCallInfo = NULL;
  273. BSTR CallerIDName = NULL;
  274. BSTR CallerIDNumber = NULL;
  275. ITLocalParticipant *pLocalParticipant = NULL;
  276. BSTR CName = NULL;
  277. // get the caller info from the H323 side.
  278. hr = m_pH323Call->QueryInterface(&pCallInfo);
  279. if (FAILED(hr)) goto cleanup;
  280. hr = pCallInfo->get_CallInfoString(CIS_CALLERIDNAME, &CallerIDName);
  281. if (FAILED(hr)) goto cleanup;
  282. hr = pCallInfo->get_CallInfoString(CIS_CALLERIDNUMBER, &CallerIDNumber);
  283. if (FAILED(hr)) goto cleanup;
  284. // construct the CName for the SDP side.
  285. CName = SysAllocStringLen(NULL,
  286. SysStringLen(CallerIDName) + SysStringLen(CallerIDNumber) + 2);
  287. wsprintfW(CName, L"%ws@%ws", CallerIDName, CallerIDNumber);
  288. // set the CName on the SDP side.
  289. hr = m_pSDPCall->QueryInterface(&pLocalParticipant);
  290. if (FAILED(hr)) goto cleanup;
  291. hr = pLocalParticipant->put_LocalParticipantTypedInfo(
  292. PTI_CANONICALNAME, CName
  293. );
  294. if (FAILED(hr)) goto cleanup;
  295. hr = pLocalParticipant->put_LocalParticipantTypedInfo(
  296. PTI_NAME, CallerIDName
  297. );
  298. if (FAILED(hr)) goto cleanup;
  299. cleanup:
  300. if (pCallInfo) pCallInfo->Release();
  301. if (CallerIDName) SysFreeString(CallerIDName);
  302. if (CallerIDNumber) SysFreeString(CallerIDNumber);
  303. if (pLocalParticipant) pLocalParticipant->Release();
  304. if (CName) SysFreeString(CName);
  305. return hr;
  306. }
  307. HRESULT
  308. CBridgeCall::SetMulticastMode ()
  309. {
  310. IMulticastControl * pIMulticastControl = NULL;
  311. HRESULT hr = m_pSDPCall->QueryInterface(&pIMulticastControl);
  312. if (FAILED(hr)) return hr;
  313. hr = pIMulticastControl->put_LoopbackMode(MM_SELECTIVE_LOOPBACK);
  314. pIMulticastControl->Release();
  315. return hr;
  316. }
  317. /*//////////////////////////////////////////////////////////////////////////////
  318. clear calls, return to initial state
  319. ////*/
  320. void
  321. CBridgeCall::Clear ()
  322. {
  323. if (m_pH323Call)
  324. {
  325. m_pH323Call->Disconnect (DC_NORMAL);
  326. m_pH323Call->Release ();
  327. m_pH323Call = NULL;
  328. }
  329. if (m_pSDPCall)
  330. {
  331. m_pSDPCall->Disconnect (DC_NORMAL);
  332. m_pSDPCall->Release ();
  333. m_pSDPCall = NULL;
  334. }
  335. }
  336. /*//////////////////////////////////////////////////////////////////////////////
  337. ////*/
  338. BOOL CBridgeCall::IsStream (
  339. ITStream *pStream,
  340. long lMediaType,
  341. TERMINAL_DIRECTION tdDirection
  342. )
  343. {
  344. long mediatype;
  345. TERMINAL_DIRECTION direction;
  346. if (FAILED (pStream->get_Direction(&direction)))
  347. return false;
  348. if (FAILED (pStream->get_MediaType(&mediatype)))
  349. return false;
  350. return ((direction == tdDirection) &&
  351. (mediatype == lMediaType));
  352. }