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

1374 lines
35 KiB

  1. #include "precomp.h"
  2. #ifndef OLDSTUFF
  3. extern IRTP *g_pIRTP;
  4. #endif
  5. STDMETHODIMP ImpICommChan::StandbyInit(LPGUID lpMID, LPIH323PubCap pCapObject,
  6. IMediaChannel* pMediaStreamSend)
  7. {
  8. if((!lpMID) || (!pCapObject))
  9. return CHAN_E_INVALID_PARAM;
  10. m_MediaID = *lpMID;
  11. bIsSendDirection = TRUE;
  12. m_pMediaStream = pMediaStreamSend;
  13. m_pMediaStream->AddRef();
  14. // keeps a cap object ref
  15. pCapObject->AddRef();
  16. m_pCapObject = pCapObject;
  17. return hrSuccess;
  18. }
  19. STDMETHODIMP ImpICommChan::QueryInterface( REFIID iid, void ** ppvObject)
  20. {
  21. // this breaks the rules for the official COM QueryInterface because
  22. // the interfaces that are queried for are not necessarily real COM
  23. // interfaces. The reflexive property of QueryInterface would be broken in
  24. // that case.
  25. HRESULT hr = E_NOINTERFACE;
  26. if(!ppvObject)
  27. return hr;
  28. *ppvObject = 0;
  29. if(iid == IID_IUnknown)
  30. {
  31. *ppvObject = this;
  32. hr = hrSuccess;
  33. AddRef();
  34. }
  35. else if((iid == IID_ICommChannel))
  36. {
  37. *ppvObject = (ICommChannel *)this;
  38. hr = hrSuccess;
  39. AddRef();
  40. }
  41. else if((iid == IID_ICtrlCommChannel))
  42. {
  43. *ppvObject = (ICtrlCommChan *)this;
  44. hr = hrSuccess;
  45. AddRef();
  46. }
  47. else if((iid == IID_IStreamSignal))
  48. {
  49. *ppvObject = (IStreamSignal *)this;
  50. hr = hrSuccess;
  51. AddRef();
  52. }
  53. else if((iid == IID_IAppAudioCap ) && m_pCapObject)
  54. {
  55. hr = m_pCapObject->QueryInterface(iid, ppvObject);
  56. }
  57. else if((iid == IID_IAppVidCap ) && m_pCapObject)
  58. {
  59. hr = m_pCapObject->QueryInterface(iid, ppvObject);
  60. }
  61. else if((iid == IID_IDualPubCap) && m_pCapObject)
  62. {
  63. hr = m_pCapObject->QueryInterface(iid, ppvObject);
  64. }
  65. else if(iid == IID_IVideoRender)
  66. {
  67. hr=hrSuccess;
  68. if(!m_pMediaStream && m_pH323ConfAdvise)
  69. {
  70. hr = m_pH323ConfAdvise->GetMediaChannel(&m_MediaID,
  71. bIsSendDirection, &m_pMediaStream);
  72. }
  73. if(HR_SUCCEEDED(hr))
  74. {
  75. hr = m_pMediaStream->QueryInterface(iid, ppvObject);
  76. }
  77. }
  78. else if(iid == IID_IVideoChannel)
  79. {
  80. hr=hrSuccess;
  81. if(!m_pMediaStream && m_pH323ConfAdvise)
  82. {
  83. hr = m_pH323ConfAdvise->GetMediaChannel(&m_MediaID,
  84. bIsSendDirection, &m_pMediaStream);
  85. }
  86. if(HR_SUCCEEDED(hr))
  87. {
  88. hr = m_pMediaStream->QueryInterface(iid, ppvObject);
  89. }
  90. }
  91. return (hr);
  92. }
  93. ULONG ImpICommChan::AddRef()
  94. {
  95. m_uRef++;
  96. DEBUGMSG(ZONE_REFCOUNT,("ImpICommChan::AddRef:(0x%08lX)->AddRef() m_uRef = 0x%08lX\r\n",this, m_uRef ));
  97. return m_uRef;
  98. }
  99. ULONG ImpICommChan::Release()
  100. {
  101. m_uRef--;
  102. if(m_uRef == 0)
  103. {
  104. DEBUGMSG(ZONE_REFCOUNT,("ImpICommChan::Release:(0x%08lX)->Releasing\r\n", this));
  105. delete this;
  106. return 0;
  107. }
  108. else
  109. {
  110. DEBUGMSG(ZONE_REFCOUNT,("ImpICommChan::Release:(0x%08lX)->Release() m_uRef = 0x%08lX\r\n",this, m_uRef ));
  111. return m_uRef;
  112. }
  113. }
  114. HRESULT ImpICommChan::GetMediaType(LPGUID pGuid)
  115. {
  116. if(!pGuid)
  117. return CHAN_E_INVALID_PARAM;
  118. *pGuid = m_MediaID;
  119. return hrSuccess;
  120. }
  121. HRESULT ImpICommChan::IsChannelOpen(BOOL *pbOpen)
  122. {
  123. if(!pbOpen)
  124. return CHAN_E_INVALID_PARAM;
  125. *pbOpen = (IsComchOpen()) ? TRUE:FALSE;
  126. return hrSuccess;
  127. }
  128. STDMETHODIMP ImpICommChan::GetProperty(DWORD prop, PVOID pBuf, LPUINT pcbBuf)
  129. {
  130. #define CHECKSIZE(type) if(*pcbBuf != sizeof(type)) return CHAN_E_INVALID_PARAM;
  131. #define OUTPROP(type) *(type *)pBuf
  132. if(!pBuf || !pcbBuf)
  133. return CHAN_E_INVALID_PARAM;
  134. switch (prop)
  135. {
  136. case PROP_TS_TRADEOFF:
  137. CHECKSIZE(DWORD);
  138. OUTPROP(DWORD) = m_TemporalSpatialTradeoff;
  139. break;
  140. case PROP_REMOTE_TS_CAPABLE:
  141. CHECKSIZE(BOOL);
  142. OUTPROP(BOOL) = m_bPublicizeTSTradeoff;
  143. break;
  144. case PROP_CHANNEL_ENABLED:
  145. CHECKSIZE(BOOL);
  146. OUTPROP(BOOL) = (m_dwFlags && COMCH_ENABLED )? TRUE:FALSE;
  147. break;
  148. case PROP_LOCAL_FORMAT_ID:
  149. CHECKSIZE(MEDIA_FORMAT_ID);
  150. OUTPROP(MEDIA_FORMAT_ID) = m_LocalFmt;
  151. break;
  152. case PROP_REMOTE_FORMAT_ID:
  153. CHECKSIZE(MEDIA_FORMAT_ID);
  154. OUTPROP(MEDIA_FORMAT_ID) = m_RemoteFmt;
  155. break;
  156. case PROP_REMOTE_PAUSED:
  157. CHECKSIZE(BOOL);
  158. OUTPROP(BOOL) = (IsStreamingRemote())? FALSE:TRUE;
  159. break;
  160. case PROP_LOCAL_PAUSE_RECV:
  161. case PROP_LOCAL_PAUSE_SEND:
  162. CHECKSIZE(BOOL);
  163. OUTPROP(BOOL) = IsPausedLocal();
  164. break;
  165. case PROP_VIDEO_PREVIEW_ON:
  166. CHECKSIZE(BOOL);
  167. OUTPROP(BOOL) = IsStreamingStandby();
  168. break;
  169. case PROP_VIDEO_PREVIEW_STANDBY:
  170. CHECKSIZE(BOOL);
  171. OUTPROP(BOOL) = IsConfigStandby();
  172. break;
  173. default:
  174. if(m_pMediaStream)
  175. {
  176. // we don't recognize this property, pass to media control
  177. return m_pMediaStream->GetProperty(prop, pBuf, (LPUINT)pcbBuf);
  178. }
  179. else
  180. return CHAN_E_INVALID_PARAM;
  181. break;
  182. }
  183. return hrSuccess;
  184. }
  185. // Some properties are not writeable by client code. CtrlChanSetProperty allows setting of
  186. // those properties. This method is *not* exposed in ICommChannel
  187. STDMETHODIMP ImpICommChan::CtrlChanSetProperty(DWORD prop, PVOID pBuf, DWORD cbBuf)
  188. {
  189. FX_ENTRY("ImpICommChan::CtrlChanSetProperty");
  190. BOOL bTemp;
  191. HRESULT hr = hrSuccess;
  192. if(!pBuf || !pBuf || !cbBuf)
  193. return CHAN_E_INVALID_PARAM;
  194. #define CHECKSIZEIN(type) if(cbBuf != sizeof(type)) return CHAN_E_INVALID_PARAM;
  195. #define INPROP(type) *(type *)pBuf
  196. switch (prop)
  197. {
  198. case PROP_TS_TRADEOFF_IND: // remote sender changed T/S tradeoff of what it is
  199. if(bIsSendDirection) // sending (valid for receive channels only)
  200. return CHAN_E_INVALID_PARAM;
  201. m_TemporalSpatialTradeoff = INPROP(DWORD);
  202. if(m_pH323ConfAdvise && m_pCtlChan)
  203. {
  204. DEBUGMSG(ZONE_COMMCHAN,("%s:issuing notification 0x%08lX\r\n",_fx_, CHANNEL_VIDEO_TS_TRADEOFF));
  205. m_pH323ConfAdvise->ChannelEvent(this, m_pCtlChan->GetIConnIF(), CHANNEL_VIDEO_TS_TRADEOFF);
  206. }
  207. break;
  208. case PROP_REMOTE_FORMAT_ID:
  209. CHECKSIZEIN(DWORD);
  210. m_RemoteFmt = INPROP(DWORD);
  211. break;
  212. case PROP_REMOTE_TS_CAPABLE: // only valid for receive channels
  213. if(bIsSendDirection)
  214. return CHAN_E_INVALID_PARAM;
  215. else
  216. {
  217. CHECKSIZEIN(BOOL);
  218. m_bPublicizeTSTradeoff = INPROP(BOOL);
  219. DEBUGMSG (ZONE_COMMCHAN,("%s:remote TS tradeoff cap %d\r\n", _fx_, m_bPublicizeTSTradeoff));
  220. }
  221. break;
  222. default:
  223. return SetProperty(prop, pBuf, cbBuf);
  224. break;
  225. }
  226. return hr;
  227. }
  228. STDMETHODIMP ImpICommChan::Preview(MEDIA_FORMAT_ID idLocalFormat, IMediaChannel * pMediaStream)
  229. {
  230. HRESULT hr = hrSuccess;
  231. FX_ENTRY("ImpICommChan::Preview");
  232. SHOW_OBJ_ETIME("ImpICommChan::Preview");
  233. LPVOID lpvFormatDetails;
  234. UINT uFormatSize;
  235. if(!bIsSendDirection)
  236. {
  237. hr = CHAN_E_INVALID_PARAM;
  238. goto EXIT;
  239. }
  240. if(NULL == pMediaStream)
  241. {
  242. // preview off
  243. if(IsStreamingStandby())
  244. {
  245. DEBUGMSG(ZONE_COMMCHAN,("%s:(%s)transition to preview OFF\r\n",_fx_,
  246. (bIsSendDirection)?"send":"recv"));
  247. //turn preview off.
  248. // if network side is paused or closed, stop all streaming
  249. if(!IsComchOpen() || !IsStreamingNet())
  250. {
  251. DEBUGMSG(ZONE_COMMCHAN,("%s:(%s)stopping local stream\r\n",_fx_,
  252. (bIsSendDirection)?"send":"recv"));
  253. // Stop the stream, but DO NOT UNCONFIGURE becase we want to
  254. // be able to start later
  255. hr = m_pMediaStream->Stop();
  256. if(!HR_SUCCEEDED(hr))
  257. {
  258. DEBUGMSG(ZONE_COMMCHAN,("%s:(%s)Stop() returned 0x%08lx\r\n",_fx_,
  259. (bIsSendDirection)?"send":"recv", hr));
  260. }
  261. SHOW_OBJ_ETIME("ImpICommChan::Preview - stopped");
  262. LocalStreamFlagOff();
  263. }
  264. // else just need to turn off flag
  265. StandbyFlagOff();
  266. }
  267. else
  268. DEBUGMSG(ZONE_COMMCHAN,("%s:(%s) no change (%s)\r\n",_fx_,
  269. (bIsSendDirection)?"send":"recv", "OFF"));
  270. }
  271. else
  272. {
  273. // preview on
  274. ASSERT(m_pCapObject);
  275. if(idLocalFormat == INVALID_MEDIA_FORMAT)
  276. {
  277. hr = CHAN_E_INVALID_PARAM;
  278. goto EXIT;
  279. }
  280. ASSERT(!(m_pMediaStream && (m_pMediaStream != pMediaStream)));
  281. if (m_pMediaStream == NULL)
  282. {
  283. m_pMediaStream = pMediaStream;
  284. m_pMediaStream->AddRef();
  285. }
  286. if(!IsStreamingStandby())
  287. {
  288. DEBUGMSG(ZONE_COMMCHAN,("%s:(%s)transition to preview ON\r\n",_fx_,
  289. (bIsSendDirection)?"send":"recv"));
  290. // turn preview on.
  291. if(!IsStreamingLocal())
  292. {
  293. ASSERT(!IsStreamingNet());
  294. if(IsComchOpen())
  295. {
  296. // if the channel is open, local streaming should only be off
  297. // if the network side of the channel is paused.
  298. //ASSERT(!IsStreamingNet());
  299. }
  300. else
  301. {
  302. // ensure that the stream does not come up with network send enabled
  303. // (!!!!! override default stream behavior !!!!!)
  304. BOOL bPause = TRUE;
  305. hr = m_pMediaStream->SetProperty(
  306. (bIsSendDirection)? PROP_PAUSE_SEND:PROP_PAUSE_RECV,
  307. &bPause, sizeof(bPause));
  308. // get format info for the specified format
  309. m_pCapObject->GetEncodeFormatDetails(idLocalFormat, &lpvFormatDetails, &uFormatSize);
  310. // fire up the local stream
  311. // this is now a two step process
  312. hr = m_pMediaStream->Configure((BYTE*)lpvFormatDetails, uFormatSize,
  313. NULL, 0, (IUnknown*)(ImpICommChan *)this);
  314. if(!HR_SUCCEEDED(hr))
  315. {
  316. ERRORMESSAGE(("%s: m_pMediaStream->Configure returned 0x%08lX\r\n", _fx_, hr));
  317. goto EXIT;
  318. }
  319. m_pMediaStream->SetNetworkInterface(NULL);
  320. if(!HR_SUCCEEDED(hr))
  321. {
  322. ERRORMESSAGE(("%s: m_pMediaStream->SetNetworkInterface returned 0x%08lX\r\n", _fx_, hr));
  323. goto EXIT;
  324. }
  325. SHOW_OBJ_ETIME("ImpICommChan::Preview - config'd for preview");
  326. }
  327. // Start the stream
  328. hr = m_pMediaStream->Start();
  329. if(!HR_SUCCEEDED(hr))
  330. {
  331. ERRORMESSAGE(("%s: m_pMediaStream->Start returned 0x%08lX\r\n", _fx_, hr));
  332. goto EXIT;
  333. }
  334. SHOW_OBJ_ETIME("ImpICommChan::Preview - started preview");
  335. LocalStreamFlagOn();
  336. }
  337. // else // just need to set flag to make preview sticky
  338. StandbyFlagOn();
  339. }
  340. else
  341. DEBUGMSG(ZONE_COMMCHAN,("%s:(%s) no change (%s)\r\n",_fx_,
  342. (bIsSendDirection)?"send":"recv", "ON"));
  343. }
  344. EXIT:
  345. return hr;
  346. }
  347. STDMETHODIMP ImpICommChan::PauseNetworkStream(BOOL fPause)
  348. {
  349. if(fPause)
  350. LocalPauseFlagOn();
  351. else
  352. LocalPauseFlagOff();
  353. return PauseNet(fPause, FALSE);
  354. }
  355. BOOL ImpICommChan::IsNetworkStreamPaused(VOID)
  356. {
  357. return IsPausedLocal();
  358. }
  359. BOOL ImpICommChan::IsRemotePaused(VOID)
  360. {
  361. return (IsStreamingRemote())? FALSE:TRUE;
  362. }
  363. STDMETHODIMP ImpICommChan::PauseNet(BOOL bPause, BOOL bRemoteInitiated)
  364. {
  365. HRESULT hr = hrSuccess;
  366. FX_ENTRY("ImpICommChan::PauseNet");
  367. // issue notification
  368. if(bRemoteInitiated)
  369. {
  370. // keep track of remote state
  371. if(bPause)
  372. RemoteStreamFlagOff();
  373. else
  374. RemoteStreamFlagOn();
  375. if(!IsNotificationSupressed())
  376. {
  377. if(m_pH323ConfAdvise && m_pCtlChan)
  378. {
  379. DEBUGMSG(ZONE_COMMCHAN,("%s:issuing %s notification \r\n",_fx_,
  380. (bPause)?"pause":"un-pause"));
  381. m_pH323ConfAdvise->ChannelEvent(this, m_pCtlChan->GetIConnIF(),
  382. (bPause)? CHANNEL_REMOTE_PAUSE_ON: CHANNEL_REMOTE_PAUSE_OFF);
  383. }
  384. else
  385. DEBUGMSG(ZONE_COMMCHAN,("%s:not issuing %s notification: m_pH323ConfAdvise: 0x%08lX, m_pCtlChan:0x%08lX \r\n"
  386. ,_fx_, (bPause)?"pause":"un-pause", m_pH323ConfAdvise,m_pCtlChan));
  387. }
  388. }
  389. if(bPause && IsStreamingNet())
  390. {
  391. ASSERT(IsComchOpen());
  392. // deactivate the channel
  393. DEBUGMSG(ZONE_COMMCHAN,("%s:(%s)transition to pause\r\n",_fx_,
  394. (bIsSendDirection)?"send":"recv" ));
  395. if(!bRemoteInitiated)
  396. {
  397. // locally initiated, so signal remote
  398. if(bIsSendDirection)
  399. {
  400. DEBUGMSG (ZONE_COMMCHAN,("%s:signaling pause of %s channel\r\n",
  401. _fx_, (bIsSendDirection)?"send":"recv" ));
  402. // signal remote
  403. MiscellaneousIndication mi;
  404. mi.type.choice = logicalChannelInactive_chosen;
  405. hr = m_pCtlChan->MiscChannelIndication(this, &mi);
  406. if(!HR_SUCCEEDED(hr))
  407. {
  408. DEBUGMSG (ZONE_COMMCHAN,("%s:(%s) CC_Mute returned 0x%08lx\r\n",
  409. _fx_, (bIsSendDirection)?"send":"recv", hr));
  410. hr = hrSuccess; // don't care about signaling error, act normal
  411. }
  412. }
  413. }
  414. //
  415. hr = m_pMediaStream->SetProperty(
  416. (bIsSendDirection)? PROP_PAUSE_SEND:PROP_PAUSE_RECV,
  417. &bPause, sizeof(bPause));
  418. NetworkStreamFlagOff();
  419. // LOOKLOOK - can't stop receive streams because they can't be restarted
  420. // check this with GeorgeJ
  421. // if(!IsStreamingStandby()) // need local stream for anything?
  422. if(!IsStreamingStandby() && bIsSendDirection) // need local stream for anything?
  423. {
  424. DEBUGMSG(ZONE_COMMCHAN,("%s:(%s)stopping local stream\r\n",_fx_,
  425. (bIsSendDirection)?"send":"recv"));
  426. // can shut off local streaming now
  427. hr = m_pMediaStream->Stop();
  428. LocalStreamFlagOff();
  429. }
  430. }
  431. else if(!bPause && !IsStreamingNet())
  432. {
  433. DEBUGMSG(ZONE_COMMCHAN,("%s:(%s)transition to unpause\r\n",_fx_,
  434. (bIsSendDirection)?"send":"recv"));
  435. if(IsComchOpen())
  436. {
  437. // activate the channel
  438. if(!bRemoteInitiated)
  439. {
  440. // locally initiated, so signal remote
  441. if(bIsSendDirection)
  442. {
  443. DEBUGMSG (ZONE_COMMCHAN,("%s:signaling UNpause of %s channel\r\n",
  444. _fx_, (bIsSendDirection)?"send":"recv" ));
  445. // signal remote
  446. MiscellaneousIndication mi;
  447. mi.type.choice = logicalChannelActive_chosen;
  448. hr = m_pCtlChan->MiscChannelIndication(this, &mi);
  449. if(!HR_SUCCEEDED(hr))
  450. {
  451. DEBUGMSG (ZONE_COMMCHAN,("%s:(%s) CC_UnMute returned 0x%08lx\r\n",
  452. _fx_, (bIsSendDirection)?"send":"recv", hr));
  453. hr = hrSuccess; // don't care about signaling error, act normal
  454. }
  455. }
  456. }
  457. else
  458. {
  459. // remotely initiated OR special case first time channel is unpaused
  460. // after opening
  461. AllowNotifications(); // stop supressing notifications
  462. }
  463. if(!IsPausedLocal())
  464. {
  465. // MUST ensure unpaused state before starting stream ????
  466. hr = m_pMediaStream->SetProperty(
  467. (bIsSendDirection)? PROP_PAUSE_SEND:PROP_PAUSE_RECV,
  468. &bPause, sizeof(bPause));
  469. // check local streaming state, start it if needed
  470. if(!IsStreamingLocal())
  471. {
  472. DEBUGMSG(ZONE_COMMCHAN,("%s:(%s)starting local stream\r\n",_fx_,
  473. (bIsSendDirection)?"send":"recv"));
  474. // need to startup stream
  475. hr = m_pMediaStream->Start();
  476. LocalStreamFlagOn();
  477. }
  478. else
  479. {
  480. if(bIsSendDirection)
  481. {
  482. DEBUGMSG(ZONE_COMMCHAN,("%s:(%s)already streaming locally\r\n",_fx_,
  483. (bIsSendDirection)?"send":"recv" ));
  484. DEBUGMSG(ZONE_COMMCHAN,("%s:(%s)RESTARTING local stream\r\n",_fx_,
  485. (bIsSendDirection)?"send":"recv"));
  486. // This is temporary until it is possible to start the
  487. // network side of a running stream
  488. hr = m_pMediaStream->Stop();
  489. hr = m_pMediaStream->Start();
  490. }
  491. }
  492. NetworkStreamFlagOn();
  493. //
  494. // if this is a receive video channel, make the sender send an I-frame now
  495. //
  496. if(!bIsSendDirection && (GetTickCount() > (m_dwLastUpdateTick + MIN_IFRAME_REQ_TICKS)))
  497. {
  498. if((MEDIA_TYPE_H323VIDEO == m_MediaID))
  499. {
  500. MiscellaneousCommand mc;
  501. // mc.logicalChannelNumber = ?; ** call control fills this in **
  502. mc.type.choice = videoFastUpdatePicture_chosen;
  503. // do the control channel signaling for THIS channel
  504. hr = m_pCtlChan->MiscChannelCommand(this, &mc);
  505. }
  506. m_dwLastUpdateTick = GetTickCount();
  507. }
  508. }
  509. }
  510. else
  511. ERRORMESSAGE(("%s:(%s) Not open: bPause=%d, streaming=%d\r\n", _fx_,
  512. (bIsSendDirection)?"send":"recv", bPause, IsStreamingNet()));
  513. }
  514. else
  515. {
  516. ERRORMESSAGE(("%s:(%s) bPause=%d, streaming=%d\r\n", _fx_,
  517. (bIsSendDirection)?"send":"recv", bPause, IsStreamingNet()));
  518. }
  519. return hr;
  520. }
  521. STDMETHODIMP ImpICommChan::SetProperty(DWORD prop, PVOID pBuf, UINT cbBuf)
  522. {
  523. FX_ENTRY("ImpICommChan::SetProperty");
  524. BOOL bTemp;
  525. HRESULT hr = hrSuccess;
  526. if(!pBuf || !pBuf || !cbBuf)
  527. return CHAN_E_INVALID_PARAM;
  528. #define CHECKSIZEIN(type) if(cbBuf != sizeof(type)) return CHAN_E_INVALID_PARAM;
  529. #define INPROP(type) *(type *)pBuf
  530. #define SetMediaProperty() \
  531. if(m_pMediaStream) \
  532. {return m_pMediaStream->SetProperty(prop, pBuf, cbBuf); } \
  533. else hr = CHAN_E_INVALID_PARAM;
  534. switch (prop)
  535. {
  536. // (read only) case PROP_REMOTE_FORMAT_ID:
  537. // (read only) case PROP_LOCAL_FORMAT_ID:
  538. // (read only) case PROP_REMOTE_TS_CAPABLE:
  539. case PROP_TS_TRADEOFF:
  540. CHECKSIZEIN(DWORD);
  541. if(bIsSendDirection) // set local T/S tradeoff, then signal remote
  542. {
  543. // scale value - input is 0-31, (lower number = higher quality and lower frame rate)
  544. m_TemporalSpatialTradeoff = INPROP(DWORD);
  545. DEBUGMSG (ZONE_COMMCHAN,("%s:TS tradeoff (tx) %d\r\n", _fx_, m_TemporalSpatialTradeoff));
  546. // change our compression
  547. if (m_pMediaStream)
  548. {
  549. HRESULT hr;
  550. hr = m_pMediaStream->SetProperty(PROP_VIDEO_IMAGE_QUALITY,
  551. &m_TemporalSpatialTradeoff, sizeof (m_TemporalSpatialTradeoff));
  552. }
  553. if(m_bPublicizeTSTradeoff && m_pCtlChan) // check our own capability and if in a call
  554. {
  555. // we said we supported TS tradeoff, so we have to signal our
  556. // new value
  557. MiscellaneousIndication mi;
  558. // mi.logicalChannelNumber = ?; ** call control fills this in **
  559. mi.type.choice = MIn_tp_vdTmprlSptlTrdOff_chosen;
  560. mi.type.u.MIn_tp_vdTmprlSptlTrdOff = LOWORD(m_TemporalSpatialTradeoff);
  561. // do the control channel signaling for THIS channel
  562. hr = m_pCtlChan->MiscChannelIndication(this, &mi);
  563. }
  564. }
  565. else // signal remote to change its T/S tradoff of its send channel
  566. {
  567. m_TemporalSpatialTradeoff = INPROP(DWORD);
  568. DEBUGMSG (ZONE_COMMCHAN,("%s:TS tradeoff (rx) %d\r\n", _fx_, m_TemporalSpatialTradeoff));
  569. if(m_bPublicizeTSTradeoff && m_pCtlChan)// check remote's TS capability
  570. {
  571. MiscellaneousCommand mc;
  572. // mc.logicalChannelNumber = ?; ** call control fills this in **
  573. mc.type.choice = MCd_tp_vdTmprlSptlTrdOff_chosen;
  574. mc.type.u.MCd_tp_vdTmprlSptlTrdOff = LOWORD(m_TemporalSpatialTradeoff);
  575. hr = m_pCtlChan->MiscChannelCommand(this, &mc);
  576. }
  577. else // remote said it does not support TS tradeoff
  578. return CHAN_E_INVALID_PARAM;
  579. }
  580. break;
  581. case PROP_CHANNEL_ENABLED:
  582. CHECKSIZEIN(BOOL);
  583. if(INPROP(BOOL))
  584. {
  585. m_dwFlags |= COMCH_ENABLED;
  586. }
  587. else
  588. {
  589. m_dwFlags &= ~COMCH_ENABLED;
  590. }
  591. break;
  592. //
  593. // Media streaming properties
  594. //
  595. case PROP_LOCAL_PAUSE_RECV:
  596. case PROP_LOCAL_PAUSE_SEND:
  597. CHECKSIZEIN(BOOL);
  598. bTemp = INPROP(BOOL);
  599. if(bTemp)
  600. LocalPauseFlagOn();
  601. else
  602. LocalPauseFlagOff();
  603. hr = PauseNet(bTemp, FALSE);
  604. break;
  605. case PROP_PAUSE_RECV:
  606. case PROP_PAUSE_SEND:
  607. CHECKSIZEIN(BOOL);
  608. hr = PauseNet(INPROP(BOOL), FALSE);
  609. break;
  610. // case PROP_PAUSE_RECV:
  611. // SetMediaProperty();
  612. // break;
  613. case PROP_VIDEO_PREVIEW_ON:
  614. ASSERT(0);
  615. break;
  616. case PROP_VIDEO_PREVIEW_STANDBY:
  617. CHECKSIZEIN(BOOL);
  618. bTemp = INPROP(BOOL);
  619. if(bTemp)
  620. StandbyConfigFlagOn();
  621. else
  622. StandbyConfigFlagOff();
  623. break;
  624. default:
  625. // we don't recognize this property, pass to media control
  626. if(m_pMediaStream)
  627. {
  628. return m_pMediaStream->SetProperty(prop, pBuf, cbBuf);
  629. }
  630. else
  631. hr = CHAN_E_INVALID_PARAM;
  632. break;
  633. }
  634. return hr;
  635. }
  636. HRESULT ImpICommChan::EnableOpen(BOOL bEnable)
  637. {
  638. if(bEnable)
  639. {
  640. m_dwFlags |= COMCH_ENABLED;
  641. }
  642. else
  643. {
  644. m_dwFlags &= ~COMCH_ENABLED;
  645. }
  646. return hrSuccess;
  647. }
  648. HRESULT ImpICommChan::GetLocalParams(LPVOID lpvChannelParams, UINT uBufSize)
  649. {
  650. if(!lpvChannelParams || !pLocalParams || !uBufSize)
  651. return CHAN_E_INVALID_PARAM;
  652. if(uBufSize < uLocalParamSize)
  653. return CHAN_E_INVALID_PARAM;
  654. memcpy(lpvChannelParams, pLocalParams, uLocalParamSize);
  655. return hrSuccess;
  656. }
  657. HRESULT ImpICommChan::ConfigureStream(MEDIA_FORMAT_ID idLocalFormat)
  658. {
  659. FX_ENTRY("ImpICommChan::ConfigureStream");
  660. HRESULT hr;
  661. ASSERT(m_pRTPChan && m_pCapObject);
  662. LPVOID lpvFormatGoo;
  663. UINT uFormatGooSize;
  664. IUnknown *pUnknown=NULL;
  665. // get format info for Configure()
  666. if(bIsSendDirection)
  667. {
  668. m_pCapObject->GetEncodeFormatDetails(idLocalFormat, &lpvFormatGoo, &uFormatGooSize);
  669. }
  670. else
  671. {
  672. m_pCapObject->GetDecodeFormatDetails(idLocalFormat, &lpvFormatGoo, &uFormatGooSize);
  673. }
  674. hr = m_pMediaStream->Configure((BYTE*)lpvFormatGoo, uFormatGooSize,
  675. (BYTE*)pLocalParams, uLocalParamSize,
  676. (IUnknown*)(ImpICommChan *)this);
  677. if(!HR_SUCCEEDED(hr))
  678. {
  679. ERRORMESSAGE(("%s: Configure returned 0x%08lX\r\n", _fx_, hr));
  680. }
  681. // SetNetworkInterface expects an IUnknown pointer
  682. // the IUnknown wil be QI'd for either an IRTPSend or an IRTPRecv
  683. // interface. The IUnknown should be free'd by the caller.
  684. if (m_pRTPChan)
  685. {
  686. m_pRTPChan->QueryInterface(IID_IUnknown, (void**)&pUnknown);
  687. ASSERT(pUnknown);
  688. }
  689. hr = m_pMediaStream->SetNetworkInterface(pUnknown);
  690. if(!HR_SUCCEEDED(hr))
  691. {
  692. ERRORMESSAGE(("%s: SetNetworkInterface returned 0x%08lX\r\n", _fx_, hr));
  693. }
  694. if (pUnknown)
  695. {
  696. pUnknown->Release();
  697. }
  698. return hr;
  699. }
  700. HRESULT ImpICommChan::ConfigureCapability(LPVOID lpvRemoteChannelParams, UINT uRemoteParamSize,
  701. LPVOID lpvLocalParams, UINT uGivenLocalParamSize)
  702. {
  703. HRESULT hr= hrSuccess;
  704. if(!lpvRemoteChannelParams)
  705. return CHAN_E_INVALID_PARAM;
  706. if(pRemoteParams)
  707. {
  708. MemFree(pRemoteParams);
  709. pRemoteParams = NULL;
  710. }
  711. // if uParamSize ==0, it means that the memory that lpvRemoteChannelParams points to
  712. // is being supplied
  713. if(uRemoteParamSize)
  714. {
  715. pRemoteParams = MemAlloc(uRemoteParamSize);
  716. if(pRemoteParams)
  717. {
  718. memcpy(pRemoteParams, lpvRemoteChannelParams, uRemoteParamSize);
  719. }
  720. }
  721. else
  722. pRemoteParams = lpvRemoteChannelParams;
  723. if(lpvLocalParams)
  724. {
  725. // memory for local parameters is always supplied by the caller
  726. if (!uGivenLocalParamSize)
  727. {
  728. hr = CHAN_E_INVALID_PARAM;
  729. goto EXIT;
  730. }
  731. if(pLocalParams)
  732. {
  733. MemFree(pLocalParams);
  734. // not needed pLocalParams= NULL;
  735. }
  736. uLocalParamSize = uGivenLocalParamSize;
  737. pLocalParams = lpvLocalParams;
  738. }
  739. EXIT:
  740. return hr;
  741. }
  742. HRESULT ImpICommChan::OnChannelClose(DWORD dwStatus)
  743. {
  744. HRESULT hr = hrSuccess;
  745. FX_ENTRY("ImpICommChan::OnChannelClose");
  746. BOOL fCloseAction = FALSE;
  747. SHOW_OBJ_ETIME("ImpICommChan::OnChannelClose");
  748. m_dwFlags &= ~COMCH_OPEN_PENDING;
  749. switch(dwStatus)
  750. {
  751. case CHANNEL_CLOSED:
  752. DEBUGMSG(ZONE_COMMCHAN,("%s:closing (%s)\r\n"
  753. ,_fx_, (bIsSendDirection)?"send":"recv"));
  754. if(IsComchOpen())
  755. {
  756. fCloseAction = TRUE;
  757. m_dwFlags &= ~COMCH_OPEN;
  758. }
  759. else
  760. {
  761. ERRORMESSAGE(("%s: %d notification when not open (%s)\r\n", _fx_,
  762. dwStatus,(bIsSendDirection)?"send":"recv"));
  763. }
  764. break;
  765. //case CHANNEL_REJECTED:
  766. //case CHANNEL_NO_CAPABILITY:
  767. default:
  768. break;
  769. }
  770. // clear general purpose channel handle
  771. dwhChannel = 0;
  772. // LOOKLOOK **** RIGHT HERE ***
  773. // ** need to notify the UI of the channel event ON_CLOSING so that the last
  774. // frame can be grabbed for rendering (a still picture is better than a black window)
  775. // LOOKLOOK **** RIGHT HERE ***
  776. // Now check preview state
  777. if(IsStreamingStandby() && bIsSendDirection )
  778. {
  779. if (m_pMediaStream != NULL)
  780. {
  781. DEBUGMSG(ZONE_COMMCHAN,("%s:transition back to preview\r\n" ,_fx_));
  782. // need to stop sending and reconfigure for preview
  783. // make sure send is paused
  784. DWORD dwProp = TRUE;
  785. hr = m_pMediaStream->SetProperty (PROP_PAUSE_SEND,&dwProp, sizeof(dwProp));
  786. if(!HR_SUCCEEDED(hr))
  787. {
  788. ERRORMESSAGE(("%s: m_pMediaStream->SetProperty returned 0x%08lX\r\n", _fx_, hr));
  789. // do what now?
  790. }
  791. NetworkStreamFlagOff();
  792. hr = m_pMediaStream->Stop();
  793. LocalStreamFlagOff();
  794. StandbyFlagOff();
  795. ASSERT(hr == S_OK);
  796. }
  797. else
  798. {
  799. NetworkStreamFlagOff();
  800. LocalStreamFlagOff();
  801. }
  802. if(fCloseAction)
  803. {
  804. // Cleanup RTP session. This is a NOP if the opposite direction is still open.
  805. if (m_pRTPChan)
  806. {
  807. m_pRTPChan->Release();
  808. m_pRTPChan = NULL;
  809. }
  810. }
  811. }
  812. else // not previewing
  813. {
  814. //
  815. // Stop the media stream
  816. //
  817. if (m_pMediaStream)
  818. {
  819. hr = m_pMediaStream->Stop(); // probably not necessary
  820. ASSERT(hr == S_OK);
  821. // implement "capture device standby": don't unconfigure if
  822. // the standby flag is set and it is a send stream.
  823. if(!IsConfigStandby() || !bIsSendDirection)
  824. {
  825. if(!bIsSendDirection) // keep send stream reference until *this* object is released
  826. {
  827. m_pMediaStream->Release();
  828. m_pMediaStream = NULL;
  829. }
  830. }
  831. }
  832. SHOW_OBJ_ETIME("ImpICommChan::OnChannelClose - stream stopped");
  833. if(fCloseAction)
  834. {
  835. // Cleanup RTP session. This is a NOP if the opposite direction is still open.
  836. if (m_pRTPChan)
  837. {
  838. m_pRTPChan->Release();
  839. m_pRTPChan = NULL;
  840. }
  841. }
  842. StreamFlagsOff();
  843. }// end if not previewing
  844. if(m_pH323ConfAdvise && m_pCtlChan)
  845. {
  846. DEBUGMSG(ZONE_COMMCHAN,("%s:issuing notification 0x%08lX\r\n",_fx_, dwStatus));
  847. m_pH323ConfAdvise->ChannelEvent(this, m_pCtlChan->GetIConnIF(), dwStatus);
  848. }
  849. return hr;
  850. }
  851. HRESULT ImpICommChan::OnChannelOpening()
  852. {
  853. ASSERT((m_dwFlags & COMCH_OPEN_PENDING) ==0);
  854. m_dwFlags |= COMCH_OPEN_PENDING;
  855. return hrSuccess;
  856. }
  857. HRESULT ImpICommChan::OnChannelOpen(DWORD dwStatus)
  858. {
  859. HRESULT hr;
  860. BOOL bConfigured = FALSE, bNewStream = FALSE; // these bools make error cleanup cleaner
  861. FX_ENTRY("ImpICommChan::OnChannelOpen");
  862. SHOW_OBJ_ETIME("ImpICommChan::OnChannelOpen");
  863. // the open is no longer pending, regardless of success or failure
  864. m_dwFlags &= ~COMCH_OPEN_PENDING;
  865. m_dwLastUpdateTick = 0; // reset tick count of last I-frame request so that one
  866. // will be requested
  867. if(IsComchOpen())
  868. {
  869. ERRORMESSAGE(("%s: %d notification when open (%s)\r\n", _fx_,
  870. dwStatus, (bIsSendDirection)?"send":"recv"));
  871. }
  872. switch(dwStatus)
  873. {
  874. case CHANNEL_OPEN:
  875. m_dwFlags |= (COMCH_OPEN | COMCH_SUPPRESS_NOTIFICATION);
  876. break;
  877. default:
  878. dwStatus = CHANNEL_OPEN_ERROR;
  879. // fall through to notification
  880. case CHANNEL_REJECTED:
  881. case CHANNEL_NO_CAPABILITY:
  882. goto NOTIFICATION;
  883. break;
  884. }
  885. // The channel is open as far as call control is concerned.
  886. // if previewing, the stream already exists. We don't want another, nor do we
  887. // want to tear it down at channel close time or in error cases
  888. if(!m_pMediaStream)
  889. {
  890. ASSERT(!IsStreamingLocal() &&m_pH323ConfAdvise); // can't be streaming without a stream
  891. bNewStream = TRUE;
  892. // Associate the media streaming endpoint with this channel
  893. // see above
  894. hr = m_pH323ConfAdvise->GetMediaChannel(&m_MediaID,
  895. bIsSendDirection, &m_pMediaStream);
  896. if(!HR_SUCCEEDED(hr))
  897. {
  898. ERRORMESSAGE(("%s: m_pH323ConfAdvise->GetMediaChannel returned 0x%08lX\r\n", _fx_, hr));
  899. goto ERROR_NOTIFICATION;
  900. }
  901. }
  902. if(IsStreamingLocal())
  903. {
  904. DEBUGMSG(ZONE_COMMCHAN,("%s:(%s)transition:preview -> send\r\n",_fx_,
  905. (bIsSendDirection)?"send":"recv"));
  906. // need to stop stream while configuring ( ***** check w/ RichP ******)
  907. hr = m_pMediaStream->Stop();
  908. LocalStreamFlagOff();
  909. }
  910. // notify upper layers of channel open now
  911. if(m_pH323ConfAdvise && m_pCtlChan)
  912. {
  913. DEBUGMSG(ZONE_COMMCHAN,("%s:issuing CHANNEL_OPEN notification\r\n",_fx_));
  914. m_pH323ConfAdvise->ChannelEvent(this, m_pCtlChan->GetIConnIF(), dwStatus);
  915. }
  916. dwStatus = CHANNEL_ACTIVE; // new status! notification is posted below
  917. ASSERT(m_pRTPChan);
  918. // get format info for Configure()
  919. hr = ConfigureStream(m_LocalFmt);
  920. if(!HR_SUCCEEDED(hr))
  921. {
  922. ERRORMESSAGE(("%s: Configure returned 0x%08lX\r\n", _fx_, hr));
  923. goto ERROR_NOTIFICATION;
  924. }
  925. SHOW_OBJ_ETIME("ImpICommChan::OnChannelOpen - configured stream");
  926. bConfigured = TRUE;
  927. // turn on flow to the network
  928. // SupressNotification() // pre-initialized above in both CHANNEL_OPEN_xxx cases
  929. PauseNet(FALSE, TRUE); // unpause,
  930. //dwStatus = CHANNEL_ACTIVE;
  931. SHOW_OBJ_ETIME("ImpICommChan::OnChannelOpen - unpaused");
  932. NOTIFICATION:
  933. if(m_pH323ConfAdvise && m_pCtlChan)
  934. {
  935. DEBUGMSG(ZONE_COMMCHAN,("%s:issuing notification 0x%08lX\r\n",_fx_, dwStatus));
  936. m_pH323ConfAdvise->ChannelEvent(this, m_pCtlChan->GetIConnIF(), dwStatus);
  937. }
  938. else
  939. DEBUGMSG(ZONE_COMMCHAN,("%s: *** not issuing notification 0x%08lX m_pH323ConfAdvise: 0x%08lX, m_pCtlChan:0x%08lX \r\n"
  940. ,_fx_, dwStatus,m_pH323ConfAdvise,m_pCtlChan));
  941. SHOW_OBJ_ETIME("ImpICommChan::OnChannelOpen - done ");
  942. return hr;
  943. ERROR_NOTIFICATION:
  944. dwStatus = CHANNEL_OPEN_ERROR;
  945. if(m_pMediaStream)
  946. {
  947. if(bNewStream) // was the media stream just created?
  948. {
  949. m_pMediaStream->Release();
  950. m_pMediaStream = NULL;
  951. }
  952. }
  953. if(m_pH323ConfAdvise && m_pCtlChan)
  954. {
  955. DEBUGMSG(ZONE_COMMCHAN,("%s:issuing notification 0x%08lX\r\n",_fx_, dwStatus));
  956. m_pH323ConfAdvise->ChannelEvent(this, m_pCtlChan->GetIConnIF(), dwStatus);
  957. }
  958. else
  959. DEBUGMSG(ZONE_COMMCHAN,("%s: *** not issuing notification 0x%08lX m_pH323ConfAdvise: 0x%08lX, m_pCtlChan:0x%08lX \r\n"
  960. ,_fx_, dwStatus,m_pH323ConfAdvise,m_pCtlChan));
  961. // close the channel.
  962. if(m_pCtlChan)
  963. {
  964. // close channel, but hr already contains the relevant return code
  965. m_pCtlChan->CloseChannel(this);
  966. }
  967. return hr;
  968. }
  969. HRESULT ImpICommChan::Open(MEDIA_FORMAT_ID idLocalFormat, IH323Endpoint *pConnection)
  970. {
  971. HRESULT hr;
  972. MEDIA_FORMAT_ID idRemoteFormat;
  973. IConfAdvise * pConfAdvise = NULL;
  974. if((m_dwFlags & COMCH_OPEN_PENDING) || IsComchOpen() || (idLocalFormat == INVALID_MEDIA_FORMAT) || !pConnection)
  975. return CHAN_E_INVALID_PARAM;
  976. if(!m_pCtlChan) // this channel is not part of a call
  977. {
  978. hr = pConnection->QueryInterface(IID_IConfAdvise, (void **)&pConfAdvise);
  979. if(!HR_SUCCEEDED(hr))
  980. goto EXIT;
  981. hr = pConfAdvise->AddCommChannel(this);
  982. if(!HR_SUCCEEDED(hr))
  983. goto EXIT;
  984. ASSERT(m_pCtlChan && m_pCapObject);
  985. }
  986. hr = m_pCapObject->ResolveToLocalFormat(idLocalFormat, &idRemoteFormat);
  987. if(!HR_SUCCEEDED(hr))
  988. goto EXIT;
  989. // start the control channel stuff needed to open the channel
  990. hr = m_pCtlChan->OpenChannel((ICtrlCommChan*)this, m_pCapObject,
  991. idLocalFormat, idRemoteFormat);
  992. EXIT:
  993. if(pConfAdvise)
  994. pConfAdvise->Release();
  995. return hr;
  996. }
  997. HRESULT ImpICommChan::Close()
  998. {
  999. HRESULT hr = CHAN_E_INVALID_PARAM;
  1000. if(!IsComchOpen() || !m_pCtlChan)
  1001. goto EXIT;
  1002. if(!bIsSendDirection)
  1003. goto EXIT;
  1004. hr = m_pCtlChan->CloseChannel(this);
  1005. EXIT:
  1006. return hr;
  1007. }
  1008. HRESULT ImpICommChan::BeginControlSession(IControlChannel *pCtlChan, LPIH323PubCap pCapObject)
  1009. {
  1010. // this channel is now "in a call".
  1011. // LOOKLOOK - it might help to notify (ICommChannel notifications to client)
  1012. // that the channel is part of a call now.
  1013. ASSERT((m_pCtlChan == NULL) && pCtlChan && pCapObject);
  1014. if(m_pCapObject)
  1015. {
  1016. m_pCapObject->Release();
  1017. }
  1018. m_pCtlChan = pCtlChan;
  1019. m_pCapObject = pCapObject;
  1020. m_pCapObject->AddRef();
  1021. return hrSuccess;
  1022. }
  1023. HRESULT ImpICommChan::EndControlSession()
  1024. {
  1025. // this channel is no longer "in a call".
  1026. m_pCtlChan = NULL;
  1027. return hrSuccess;
  1028. }
  1029. BOOL ImpICommChan::SelectPorts(LPIControlChannel pCtlChannel)
  1030. {
  1031. // create the RTP channel
  1032. HRESULT hr;
  1033. PSOCKADDR_IN psin=NULL;
  1034. pCtlChannel->GetLocalAddress(&psin);
  1035. PORT savedPort = psin->sin_port;
  1036. if (!m_pRTPChan) {
  1037. UINT sessFlags = bIsSendDirection ? SESSIONF_SEND : SESSIONF_RECV;
  1038. UINT sessId;
  1039. GUID mediaGuid;
  1040. GetMediaType(&mediaGuid);
  1041. if (mediaGuid == MEDIA_TYPE_H323VIDEO)
  1042. {
  1043. sessFlags |= SESSIONF_VIDEO;
  1044. sessId = 2;
  1045. }
  1046. else
  1047. {
  1048. sessId = 1;
  1049. sessFlags |= SESSIONF_AUDIO;
  1050. }
  1051. psin->sin_port = 0; // zero port forces RTP to choose a port
  1052. hr = g_pIRTP->OpenSession(sessId, sessFlags,
  1053. (BYTE *)psin, sizeof(PSOCKADDR_IN),
  1054. &m_pRTPChan);
  1055. }
  1056. else
  1057. hr = m_pRTPChan->SetLocalAddress((BYTE *)psin,sizeof(SOCKADDR_IN));
  1058. psin->sin_port = savedPort;
  1059. return hr==S_OK;
  1060. }
  1061. // get the address and port of the base port that was selected by SelectPorts().
  1062. // in this typical implementation, that is the address/port of the RTCP channel
  1063. PSOCKADDR_IN ImpICommChan::GetLocalAddress()
  1064. {
  1065. #ifdef OLDSTUFF
  1066. return m_pRTPChan ? m_pRTPChan->GetChannelDescription()->pLocalAddr : NULL;
  1067. #else
  1068. const BYTE *pAddr;
  1069. UINT cbAddr;
  1070. HRESULT hr;
  1071. hr = m_pRTPChan->GetLocalAddress(&pAddr, &cbAddr);
  1072. return (SUCCEEDED(hr)) ? (PSOCKADDR_IN) pAddr : NULL;
  1073. #endif
  1074. }
  1075. STDMETHODIMP ImpICommChan::GetRemoteAddress(PSOCKADDR_IN pAddrOutput)
  1076. {
  1077. HRESULT hr;
  1078. if (!pAddrOutput)
  1079. {
  1080. return CHAN_E_INVALID_PARAM;
  1081. }
  1082. const BYTE *pAddr;
  1083. UINT cbAddr;
  1084. hr = m_pRTPChan->GetRemoteRTPAddress(&pAddr, &cbAddr);
  1085. if(SUCCEEDED(hr))
  1086. {
  1087. ASSERT(cbAddr == sizeof(SOCKADDR_IN));
  1088. *pAddrOutput = *((PSOCKADDR_IN) pAddr);
  1089. }
  1090. return hrSuccess;
  1091. }
  1092. UINT ImpICommChan::Reset()
  1093. {
  1094. UINT uret;
  1095. ASSERT(!IsComchOpen());
  1096. if (m_pRTPChan) {
  1097. uret = m_pRTPChan->Release();
  1098. m_pRTPChan = NULL;
  1099. } else
  1100. uret = 0;
  1101. return uret;
  1102. }
  1103. PORT ImpICommChan::GetLocalRTPPort()
  1104. {
  1105. #ifdef OLDSTUFF
  1106. return (m_pRTPChan ? ntohs(m_pRTPChan->GetChannelDescription()->pLocalAddr->sin_port) : 0);
  1107. #else
  1108. const BYTE *pAddr;
  1109. UINT cbAddr;
  1110. HRESULT hr;
  1111. hr = m_pRTPChan->GetLocalAddress(&pAddr, &cbAddr);
  1112. return (SUCCEEDED(hr)) ? ntohs(((PSOCKADDR_IN) pAddr)->sin_port) : 0;
  1113. #endif
  1114. }
  1115. PORT ImpICommChan::GetLocalRTCPPort()
  1116. {
  1117. #ifdef OLDSTUFF
  1118. return (m_pRTPChan ? ntohs(m_pRTPChan->GetChannelDescription()->pLocalRTCPAddr->sin_port) : 0);
  1119. #else
  1120. const BYTE *pAddr;
  1121. UINT cbAddr;
  1122. HRESULT hr;
  1123. hr = m_pRTPChan->GetLocalAddress(&pAddr, &cbAddr);
  1124. return (SUCCEEDED(hr)) ? ntohs(((PSOCKADDR_IN) pAddr)->sin_port)+1 : 0;
  1125. #endif
  1126. }
  1127. HRESULT ImpICommChan::AcceptRemoteRTCPAddress(PSOCKADDR_IN pSinC)
  1128. {
  1129. HRESULT hr;
  1130. #ifdef OLDSTUFF
  1131. if (!m_pRTPChan) {
  1132. RTPCHANNELDESC chanDesc = {0};
  1133. GetMediaType(&chanDesc.mediaId);
  1134. chanDesc.pRemoteRTCPAddr = pSinC;
  1135. hr = CreateRTPChannel(&chanDesc, &m_pRTPChan);
  1136. } else
  1137. hr = m_pRTPChan->SetRemoteAddresses(NULL,pSinC);
  1138. #else
  1139. hr = m_pRTPChan->SetRemoteRTCPAddress((BYTE *)pSinC, sizeof(SOCKADDR_IN));
  1140. #endif
  1141. return hr;
  1142. }
  1143. HRESULT ImpICommChan::AcceptRemoteAddress(PSOCKADDR_IN pSinD)
  1144. {
  1145. HRESULT hr;
  1146. hr = m_pRTPChan->SetRemoteRTPAddress((BYTE *)pSinD, sizeof(SOCKADDR_IN));
  1147. return hr;
  1148. }
  1149. HRESULT ImpICommChan::SetAdviseInterface(IH323ConfAdvise *pH323ConfAdvise)
  1150. {
  1151. if (!pH323ConfAdvise)
  1152. {
  1153. return CHAN_E_INVALID_PARAM;
  1154. }
  1155. m_pH323ConfAdvise = pH323ConfAdvise;
  1156. return hrSuccess;
  1157. }
  1158. STDMETHODIMP ImpICommChan::PictureUpdateRequest()
  1159. {
  1160. FX_ENTRY ("ImpICommChan::PictureUpdateRequest");
  1161. HRESULT hr;
  1162. if (!m_pCtlChan)
  1163. {
  1164. return CHAN_E_NOT_OPEN;
  1165. }
  1166. if(bIsSendDirection || (MEDIA_TYPE_H323VIDEO != m_MediaID))
  1167. {
  1168. return CHAN_E_INVALID_PARAM;
  1169. }
  1170. // issue miscellaneous command for picture update
  1171. MiscellaneousCommand mc;
  1172. // mc.logicalChannelNumber = ?; ** call control fills this in **
  1173. mc.type.choice = videoFastUpdatePicture_chosen;
  1174. // do the control channel signaling for THIS channel
  1175. hr = m_pCtlChan->MiscChannelCommand(this, &mc);
  1176. // record the tick count of this command
  1177. m_dwLastUpdateTick = GetTickCount();
  1178. return hr;
  1179. }
  1180. STDMETHODIMP ImpICommChan::GetVersionInfo(
  1181. PCC_VENDORINFO *ppLocalVendorInfo,
  1182. PCC_VENDORINFO *ppRemoteVendorInfo)
  1183. {
  1184. FX_ENTRY ("ImpICommChan::GetVersionInfo");
  1185. if (!m_pCtlChan)
  1186. {
  1187. return CHAN_E_INVALID_PARAM;
  1188. }
  1189. return m_pCtlChan->GetVersionInfo(ppLocalVendorInfo, ppRemoteVendorInfo);
  1190. }
  1191. ImpICommChan::ImpICommChan ()
  1192. :pRemoteParams(NULL),
  1193. m_pMediaStream(NULL),
  1194. pLocalParams(NULL),
  1195. uLocalParamSize(0),
  1196. m_pCtlChan(NULL),
  1197. m_pH323ConfAdvise(NULL),
  1198. m_pCapObject(NULL),
  1199. m_dwFlags(0),
  1200. dwhChannel(0),
  1201. m_LocalFmt(INVALID_MEDIA_FORMAT),
  1202. m_RemoteFmt(INVALID_MEDIA_FORMAT),
  1203. m_TemporalSpatialTradeoff(0), // default to highest resolution
  1204. m_bPublicizeTSTradeoff(FALSE),
  1205. m_uRef(1)
  1206. {
  1207. ZeroMemory(&m_MediaID, sizeof(m_MediaID));
  1208. }
  1209. ImpICommChan::~ImpICommChan ()
  1210. {
  1211. if(pRemoteParams)
  1212. MemFree(pRemoteParams);
  1213. if(pLocalParams)
  1214. MemFree(pLocalParams);
  1215. if(m_pMediaStream)
  1216. {
  1217. m_pMediaStream->Stop(); // probably not necessary
  1218. m_pMediaStream->Release();
  1219. m_pMediaStream = NULL;
  1220. }
  1221. if(m_pCapObject)
  1222. m_pCapObject->Release();
  1223. }