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
426 lines
11 KiB
/*******************************************************************************
|
|
|
|
Module: bgcall.cpp
|
|
|
|
Author: Qianbo Huai
|
|
|
|
Abstract:
|
|
|
|
implements bridge call object
|
|
|
|
*******************************************************************************/
|
|
|
|
#include "stdafx.h"
|
|
#include "work.h"
|
|
|
|
#include <bridge.h>
|
|
|
|
// to change
|
|
const BSTR CLSID_String_BridgeTerminal = L"{581d09e5-0b45-11d3-a565-00c04f8ef6e3}";
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////////
|
|
constructor
|
|
////*/
|
|
CBridgeCall::CBridgeCall (CBridge *pBridge)
|
|
{
|
|
m_pBridge = pBridge;
|
|
m_pH323Call = NULL;
|
|
m_pSDPCall = NULL;
|
|
}
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////////
|
|
////*/
|
|
CBridgeCall::~CBridgeCall ()
|
|
{
|
|
Clear ();
|
|
m_pBridge = NULL;
|
|
}
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////////
|
|
select terminals and connect the call
|
|
////*/
|
|
HRESULT
|
|
CBridgeCall::BridgeCalls ()
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = SelectBridgeTerminals ();
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = SetupParticipantInfo ();
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = SetMulticastMode ();
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
// connect h323 call
|
|
hr = m_pH323Call->Answer ();
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
// connect sdp call
|
|
hr = m_pSDPCall->Connect (VARIANT_TRUE);
|
|
if (FAILED(hr))
|
|
{
|
|
m_pH323Call->Disconnect (DC_NORMAL);
|
|
return hr;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////////
|
|
////*/
|
|
HRESULT
|
|
CBridgeCall::SelectBridgeTerminals ()
|
|
{
|
|
HRESULT hr;
|
|
ITAddress *pAddress = NULL;
|
|
ITMSPAddress *pMSPAddress = NULL;
|
|
ITTerminal *pH323ToSDPVideoBT = NULL;
|
|
ITTerminal *pH323ToSDPAudioBT = NULL;
|
|
ITTerminal *pSDPToH323VideoBT = NULL;
|
|
ITTerminal *pSDPToH323AudioBT = NULL;
|
|
|
|
ITStreamControl *pStreamControl = NULL;
|
|
IEnumStream *pEnumStreams = NULL;
|
|
ITStream *pStream = NULL;
|
|
|
|
// get SDP address
|
|
hr = m_pBridge->GetSDPAddress (&pAddress);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
// get MSP address
|
|
hr = pAddress->QueryInterface (IID_ITMSPAddress, (void**)&pMSPAddress);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
IConfBridge *pBridge = NULL;
|
|
// create CConfBridge
|
|
hr = CoCreateInstance (
|
|
__uuidof(ConfBridge),
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IConfBridge,
|
|
(LPVOID *)&pBridge
|
|
);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
// create terminal: video H323->SDP
|
|
hr = pBridge->CreateBridgeTerminal (
|
|
// (MSP_HANDLE)pMSPAddress,
|
|
// CLSID_String_BridgeTerminal,
|
|
TAPIMEDIATYPE_VIDEO,
|
|
// TD_RENDER, // not used
|
|
&pH323ToSDPVideoBT
|
|
);
|
|
if (FAILED(hr))
|
|
goto Error;
|
|
|
|
// create terminal: audio H323->SDP
|
|
hr = pBridge->CreateBridgeTerminal (
|
|
// (MSP_HANDLE)pMSPAddress,
|
|
// CLSID_String_BridgeTerminal,
|
|
TAPIMEDIATYPE_AUDIO,
|
|
// TD_RENDER, // not used
|
|
&pH323ToSDPAudioBT
|
|
);
|
|
if (FAILED(hr))
|
|
goto Error;
|
|
|
|
// create terminal: video SDP->H323
|
|
hr = pBridge->CreateBridgeTerminal (
|
|
// (MSP_HANDLE)pMSPAddress,
|
|
// CLSID_String_BridgeTerminal,
|
|
TAPIMEDIATYPE_VIDEO,
|
|
// TD_RENDER, // not used
|
|
&pSDPToH323VideoBT
|
|
);
|
|
if (FAILED(hr))
|
|
goto Error;
|
|
|
|
// create terminal: audio SDP->H323
|
|
hr = pBridge->CreateBridgeTerminal (
|
|
// (MSP_HANDLE)pMSPAddress,
|
|
// CLSID_String_BridgeTerminal,
|
|
TAPIMEDIATYPE_AUDIO,
|
|
// TD_RENDER, // not used
|
|
&pSDPToH323AudioBT
|
|
);
|
|
if (FAILED(hr))
|
|
goto Error;
|
|
|
|
pMSPAddress->Release ();
|
|
pMSPAddress = NULL;
|
|
|
|
pAddress->Release ();
|
|
pAddress = NULL;
|
|
|
|
pBridge->Release ();
|
|
pBridge = NULL;
|
|
|
|
// get stream control on H323
|
|
hr = m_pH323Call->QueryInterface (
|
|
IID_ITStreamControl,
|
|
(void **)&pStreamControl
|
|
);
|
|
if (FAILED(hr))
|
|
goto Error;
|
|
|
|
// get enum stream on H323
|
|
hr = pStreamControl->EnumerateStreams (&pEnumStreams);
|
|
if (FAILED(hr))
|
|
goto Error;
|
|
|
|
pStreamControl->Release ();
|
|
pStreamControl = NULL;
|
|
|
|
// iterate each stream on H323, select terminals
|
|
while (S_OK == pEnumStreams->Next (1, &pStream, NULL))
|
|
{
|
|
if (IsStream (pStream, TAPIMEDIATYPE_VIDEO, TD_CAPTURE))
|
|
{
|
|
// video: h323 to sdp
|
|
hr = pStream->SelectTerminal (pH323ToSDPVideoBT);
|
|
if (FAILED(hr))
|
|
goto Error;
|
|
}
|
|
else if (IsStream (pStream, TAPIMEDIATYPE_VIDEO, TD_RENDER))
|
|
{
|
|
// video: sdp to h323
|
|
hr = pStream->SelectTerminal (pSDPToH323VideoBT);
|
|
if (FAILED(hr))
|
|
goto Error;
|
|
|
|
IKeyFrameControl* pIKeyFrameControl;
|
|
hr = pStream->QueryInterface(&pIKeyFrameControl);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pIKeyFrameControl->PeriodicUpdatePicture(TRUE, 5);
|
|
pIKeyFrameControl->Release();
|
|
}
|
|
|
|
|
|
}
|
|
else if (IsStream (pStream, TAPIMEDIATYPE_AUDIO, TD_CAPTURE))
|
|
{
|
|
// audio: h323 to sdp
|
|
hr = pStream->SelectTerminal (pH323ToSDPAudioBT);
|
|
if (FAILED(hr))
|
|
goto Error;
|
|
}
|
|
else if (IsStream (pStream, TAPIMEDIATYPE_AUDIO, TD_RENDER))
|
|
{
|
|
// video: sdp to h323
|
|
hr = pStream->SelectTerminal (pSDPToH323AudioBT);
|
|
if (FAILED(hr))
|
|
goto Error;
|
|
}
|
|
pStream->Release ();
|
|
pStream = NULL;
|
|
}
|
|
|
|
if (pStream)
|
|
{
|
|
pStream->Release ();
|
|
pStream = NULL;
|
|
}
|
|
|
|
pEnumStreams->Release ();
|
|
pEnumStreams = NULL;
|
|
|
|
// get stream control on SDP
|
|
hr = m_pSDPCall->QueryInterface (
|
|
IID_ITStreamControl,
|
|
(void **)&pStreamControl
|
|
);
|
|
if (FAILED(hr))
|
|
goto Error;
|
|
|
|
// get enum stream on SDP
|
|
hr = pStreamControl->EnumerateStreams (&pEnumStreams);
|
|
if (FAILED(hr))
|
|
goto Error;
|
|
|
|
pStreamControl->Release ();
|
|
pStreamControl = NULL;
|
|
|
|
// iterate each stream on SDP, select terminals
|
|
while (S_OK == pEnumStreams->Next (1, &pStream, NULL))
|
|
{
|
|
if (IsStream (pStream, TAPIMEDIATYPE_VIDEO, TD_CAPTURE))
|
|
{
|
|
// video: sdp to h323
|
|
hr = pStream->SelectTerminal (pSDPToH323VideoBT);
|
|
if (FAILED(hr))
|
|
goto Error;
|
|
}
|
|
else if (IsStream (pStream, TAPIMEDIATYPE_VIDEO, TD_RENDER))
|
|
{
|
|
// video: h323 to sdp
|
|
hr = pStream->SelectTerminal (pH323ToSDPVideoBT);
|
|
if (FAILED(hr))
|
|
goto Error;
|
|
}
|
|
else if (IsStream (pStream, TAPIMEDIATYPE_AUDIO, TD_CAPTURE))
|
|
{
|
|
// audio: sdp to h323
|
|
hr = pStream->SelectTerminal (pSDPToH323AudioBT);
|
|
if (FAILED(hr))
|
|
goto Error;
|
|
}
|
|
else if (IsStream (pStream, TAPIMEDIATYPE_AUDIO, TD_RENDER))
|
|
{
|
|
// video: h323 to sdp
|
|
hr = pStream->SelectTerminal (pH323ToSDPAudioBT);
|
|
if (FAILED(hr))
|
|
goto Error;
|
|
}
|
|
pStream->Release ();
|
|
pStream = NULL;
|
|
}
|
|
|
|
Cleanup:
|
|
// release streams
|
|
if (pStream)
|
|
pStream->Release ();
|
|
if (pEnumStreams)
|
|
pEnumStreams->Release ();
|
|
if (pStreamControl)
|
|
pStreamControl->Release ();
|
|
|
|
// release terminals
|
|
if (pH323ToSDPVideoBT)
|
|
pH323ToSDPVideoBT->Release ();
|
|
if (pH323ToSDPAudioBT)
|
|
pH323ToSDPAudioBT->Release ();
|
|
if (pSDPToH323VideoBT)
|
|
pSDPToH323VideoBT->Release ();
|
|
if (pSDPToH323AudioBT)
|
|
pSDPToH323AudioBT->Release ();
|
|
|
|
if (pBridge)
|
|
pBridge->Release ();
|
|
|
|
return hr;
|
|
|
|
Error:
|
|
goto Cleanup;
|
|
}
|
|
|
|
HRESULT
|
|
CBridgeCall::SetupParticipantInfo ()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
ITCallInfo *pCallInfo = NULL;
|
|
BSTR CallerIDName = NULL;
|
|
BSTR CallerIDNumber = NULL;
|
|
|
|
ITLocalParticipant *pLocalParticipant = NULL;
|
|
BSTR CName = NULL;
|
|
|
|
// get the caller info from the H323 side.
|
|
hr = m_pH323Call->QueryInterface(&pCallInfo);
|
|
if (FAILED(hr)) goto cleanup;
|
|
|
|
hr = pCallInfo->get_CallInfoString(CIS_CALLERIDNAME, &CallerIDName);
|
|
if (FAILED(hr)) goto cleanup;
|
|
|
|
hr = pCallInfo->get_CallInfoString(CIS_CALLERIDNUMBER, &CallerIDNumber);
|
|
if (FAILED(hr)) goto cleanup;
|
|
|
|
|
|
// construct the CName for the SDP side.
|
|
CName = SysAllocStringLen(NULL,
|
|
SysStringLen(CallerIDName) + SysStringLen(CallerIDNumber) + 2);
|
|
|
|
wsprintfW(CName, L"%ws@%ws", CallerIDName, CallerIDNumber);
|
|
|
|
|
|
// set the CName on the SDP side.
|
|
hr = m_pSDPCall->QueryInterface(&pLocalParticipant);
|
|
if (FAILED(hr)) goto cleanup;
|
|
|
|
hr = pLocalParticipant->put_LocalParticipantTypedInfo(
|
|
PTI_CANONICALNAME, CName
|
|
);
|
|
if (FAILED(hr)) goto cleanup;
|
|
|
|
hr = pLocalParticipant->put_LocalParticipantTypedInfo(
|
|
PTI_NAME, CallerIDName
|
|
);
|
|
|
|
if (FAILED(hr)) goto cleanup;
|
|
|
|
|
|
cleanup:
|
|
if (pCallInfo) pCallInfo->Release();
|
|
if (CallerIDName) SysFreeString(CallerIDName);
|
|
if (CallerIDNumber) SysFreeString(CallerIDNumber);
|
|
|
|
if (pLocalParticipant) pLocalParticipant->Release();
|
|
if (CName) SysFreeString(CName);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CBridgeCall::SetMulticastMode ()
|
|
{
|
|
IMulticastControl * pIMulticastControl = NULL;
|
|
|
|
HRESULT hr = m_pSDPCall->QueryInterface(&pIMulticastControl);
|
|
if (FAILED(hr)) return hr;
|
|
|
|
hr = pIMulticastControl->put_LoopbackMode(MM_SELECTIVE_LOOPBACK);
|
|
|
|
pIMulticastControl->Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////////
|
|
clear calls, return to initial state
|
|
////*/
|
|
void
|
|
CBridgeCall::Clear ()
|
|
{
|
|
if (m_pH323Call)
|
|
{
|
|
m_pH323Call->Disconnect (DC_NORMAL);
|
|
m_pH323Call->Release ();
|
|
m_pH323Call = NULL;
|
|
}
|
|
if (m_pSDPCall)
|
|
{
|
|
m_pSDPCall->Disconnect (DC_NORMAL);
|
|
m_pSDPCall->Release ();
|
|
m_pSDPCall = NULL;
|
|
}
|
|
}
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////////
|
|
////*/
|
|
BOOL CBridgeCall::IsStream (
|
|
ITStream *pStream,
|
|
long lMediaType,
|
|
TERMINAL_DIRECTION tdDirection
|
|
)
|
|
{
|
|
long mediatype;
|
|
TERMINAL_DIRECTION direction;
|
|
|
|
if (FAILED (pStream->get_Direction(&direction)))
|
|
return false;
|
|
if (FAILED (pStream->get_MediaType(&mediatype)))
|
|
return false;
|
|
return ((direction == tdDirection) &&
|
|
(mediatype == lMediaType));
|
|
}
|
|
|