📄 processing.cpp
字号:
//
// configure the wave format we want
//
AM_MEDIA_TYPE MediaType;
MediaType.majortype = MEDIATYPE_Audio;
MediaType.subtype = MEDIASUBTYPE_PCM;
MediaType.bFixedSizeSamples = TRUE;
MediaType.bTemporalCompression = FALSE;
MediaType.lSampleSize = 0;
MediaType.formattype = FORMAT_WaveFormatEx;
MediaType.pUnk = NULL;
MediaType.cbFormat = sizeof(WAVEFORMATEX);
MediaType.pbFormat = (BYTE*)&WaveFormat;
//
// log the wave format we are setting on the terminal
//
LogMessage("SetAudioFormat: setting wave format on terminal. ");
LogFormat(&WaveFormat);
//
// set the format
//
hr = pITMediaFormat->put_MediaFormat(&MediaType);
if (FAILED(hr))
{
//
// try to see what format the terminal wanted
//
LogError("SetAudioFormat: failed to set format");
AM_MEDIA_TYPE *pMediaFormat = NULL;
HRESULT hr2 = pITMediaFormat->get_MediaFormat(&pMediaFormat);
if (SUCCEEDED(hr2))
{
if (pMediaFormat->formattype == FORMAT_WaveFormatEx)
{
//
// log the terminal's format
//
LogError("SetAudioFormat: terminal's format is");
LogFormat((WAVEFORMATEX*) pMediaFormat->pbFormat);
}
else
{
LogError("SetAudioFormat: "
"terminal's format is not WAVEFORMATEX");
}
//
// note: we are responsible for deallocating the format returned by
// get_MediaFormat
//
DeleteMediaType(pMediaFormat);
} // succeeded getting terminal's format
else
{
LogError("SetAudioFormat: failed to get terminal's format");
}
}
pITMediaFormat->Release();
pITMediaFormat = NULL;
LogError("SetAudioFormat: completed");
return hr;
}
///////////////////////////////////////////////////////////////////////////////
//
// SetAllocatorProperties
//
// suggest allocator properties to the terminal
//
///////////////////////////////////////////////////////////////////////////////
HRESULT SetAllocatorProperties(IN ITTerminal *pTerminal)
{
//
// different buffer sizes may produce different sound quality, depending
// on the underlying transport that is being used.
//
// this function illustrates how an app can control the number and size of
// buffers. A multiple of 30 ms (480 bytes at 16-bit 8 KHz PCM) is the most
// appropriate sample size for IP (especailly G.723.1).
//
// However, small buffers can cause poor audio quality on some voice boards.
//
// If this method is not called, the allocator properties suggested by the
// connecting filter will be used.
//
HRESULT hr = E_FAIL;
//
// get ITAllocator properties interface on the terminal
//
ITAllocatorProperties *pITAllocatorProperties = NULL;
hr = pTerminal->QueryInterface(IID_ITAllocatorProperties,
(void **)&pITAllocatorProperties);
if (FAILED(hr))
{
LogError("SetAllocatorProperties: "
"failed to QI terminal for ITAllocatorProperties");
return hr;
}
//
// configure allocator properties
//
// suggest the size and number of the samples for MST to pre-allocate.
//
ALLOCATOR_PROPERTIES AllocProps;
AllocProps.cBuffers = 5; // ask MST to allocate 5 buffers
AllocProps.cbBuffer = 4800; // 4800 bytes each
AllocProps.cbAlign = 1; // no need to align buffers
AllocProps.cbPrefix = 0; // no extra memory preceeding the actual data
hr = pITAllocatorProperties->SetAllocatorProperties(&AllocProps);
if (FAILED(hr))
{
LogError("SetAllocatorProperties: "
"failed to set allocator properties. hr = 0x%lx", hr);
pITAllocatorProperties->Release();
pITAllocatorProperties = NULL;
return hr;
}
//
// ask media streaming terminal to allocate buffers for us.
// TRUE is the default, so strictly speaking, we didn't have to call
// this method.
//
hr = pITAllocatorProperties->SetAllocateBuffers(TRUE);
pITAllocatorProperties->Release();
pITAllocatorProperties = NULL;
if (FAILED(hr))
{
LogError("SetAllocatorProperties: "
"failed to SetAllocateBuffers, hr = 0x%lx", hr);
return hr;
}
//
// succeeded setting allocator properties
//
LogMessage("SetAllocatorProperties: succeeded.");
return S_OK;
}
///////////////////////////////////////////////////////////////////////////////
//
// SelectAndInitializeTerminal
//
//
// Set audio format and allocator properties on the terminal and
// select the terminal on the stream
//
///////////////////////////////////////////////////////////////////////////////
HRESULT SelectAndInitializeTerminal(IN ITTerminal *pRecordTerminal,
IN ITStream *pStream)
{
HRESULT hr = E_FAIL;
//
// set audio format on the created terminal
//
hr = SetAudioFormat(pRecordTerminal);
if (FAILED(hr))
{
//
// the terminal does not support the wave format we wanted.
// no big deal for the receiver, we'll just have to create the
// file in the format requested by MST.
//
LogMessage("CreateAndSelectMST: "
"Failed to set audio format on recording terminal. "
"Continuing");
}
//
// set allocator properties for this terminal
//
hr = SetAllocatorProperties(pRecordTerminal);
if (FAILED(hr))
{
//
// not a fatal error. our allocator props were rejected,
// but this does not necessarily mean streaming will fail.
//
LogError("CreateAndSelectMST: Failed to set "
"allocator properties on recording terminal");
}
//
// select terminal on the stream
//
hr = pStream->SelectTerminal(pRecordTerminal);
if (FAILED(hr))
{
LogError("CreateAndSelectMST: Failed to select "
"terminal on the stream");
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////
//
// IsRenderingStream
//
// returns TRUE if the stream's direction is TD_RENDER
//
///////////////////////////////////////////////////////////////////////////////
BOOL IsRenderingStream(ITStream *pStream)
{
//
// check the stream's direction
//
TERMINAL_DIRECTION TerminalDirection;
HRESULT hr = pStream->get_Direction(&TerminalDirection);
if (FAILED(hr))
{
LogError("IsRenderingStream: Failed to get stream direction");
return FALSE;
}
if (TD_RENDER == TerminalDirection)
{
return TRUE;
}
else
{
return FALSE;
}
}
///////////////////////////////////////////////////////////////////////////////
//
// IsAudioStream
//
// returns TRUE if the stream's type is TAPIMEDIATYPE_AUDIO
//
///////////////////////////////////////////////////////////////////////////////
BOOL IsAudioStream(ITStream *pStream)
{
//
// check the stream's media type
//
long nMediaType = 0;
HRESULT hr = pStream->get_MediaType(&nMediaType);
if (FAILED(hr))
{
LogError("IsAudioStream: Failed to get media type");
return FALSE;
}
//
// return true if the stream is audio
//
if (TAPIMEDIATYPE_AUDIO == nMediaType)
{
return TRUE;
}
else
{
return FALSE;
}
}
///////////////////////////////////////////////////////////////////////////////
//
// CreateAndSelectMST
//
// check the call's streams. create media streaming terminal on the first
// incoming audio stream
//
// returns:
//
// S_OK if a terminal was created and selected
// S_FALSE if no appropriate stream was found
// error if failed
//
///////////////////////////////////////////////////////////////////////////////
HRESULT CreateAndSelectMST()
{
LogMessage("CreateAndSelectMST: started");
//
// we should already have the call
//
if (NULL == g_pCurrentCall)
{
LogError("CreateAndSelectMST: g_pCurrentCall is NULL");
return E_UNEXPECTED;
}
HRESULT hr = E_FAIL;
//
// get the ITStreamControl interface for this call
//
ITStreamControl *pStreamControl = NULL;
hr = g_pCurrentCall->QueryInterface(IID_ITStreamControl,
(void**)&pStreamControl);
if (FAILED(hr))
{
LogError("CreateAndSelectMST: failed to QI call for ITStreamControl");
return hr;
}
//
// enumerate the streams on the call
//
IEnumStream *pEnumStreams = NULL;
hr = pStreamControl->EnumerateStreams(&pEnumStreams);
pStreamControl->Release();
pStreamControl = NULL;
if (FAILED(hr))
{
LogError("CreateAndSelectMST: failed to enumerate streams on call");
return hr;
}
//
// walk through the list of streams on the call
// for the first incoming audio stream, create a media streaming terminal
// and select it on the stream
//
BOOL bTerminalCreatedAndSelected = FALSE;
while (!bTerminalCreatedAndSelected)
{
ITStream *pStream = NULL;
hr = pEnumStreams->Next(1, &pStream, NULL);
if (S_OK != hr)
{
//
// no more streams or error
//
LogError("CreateAndSelectMST: didn't find an incoming audio stream."
" terminal not selected.");
break;
}
//
// create and select media streaming terminal on the first incoming
// audio stream
//
if ( IsRenderingStream(pStream) && IsAudioStream(pStream))
{
LogMessage("CreateAndSelectMST: creating mst");
//
// create media streaming terminal and select it on the stream
//
ITTerminal *pRecordTerminal = NULL;
pRecordTerminal = CreateRenderMediaStreamingTerminal(g_pCurrentCall);
if (NULL != pRecordTerminal)
{
hr = SelectAndInitializeTerminal(pRecordTerminal, pStream);
pRecordTerminal->Release();
pRecordTerminal = NULL;
if (SUCCEEDED(hr))
{
//
// set the flag, so we can break out of the loop
//
bTerminalCreatedAndSelected = TRUE;
}
} // media streaming terminal created successfully
} // stream is rendering and audio
else
{
//
// the stream is of wrong direction, or type
//
}
pStream->Release();
pStream = NULL;
} // while (enumerating streams on the call)
//
// done with the stream enumeration. release
//
pEnumStreams->Release();
pEnumStreams = NULL;
if (bTerminalCreatedAndSelected)
{
LogMessage("CreateAndSelectMST: terminal selected");
return S_OK;
}
else
{
LogMessage("CreateAndSelectMST: no terminal selected");
return S_FALSE;
}
}
///////////////////////////////////////////////////////////////////////////////
//
// GetTerminalFromMediaEvent
//
//
// get the terminal selected on the event's stream
//
///////////////////////////////////////////////////////////////////////////////
HRESULT GetTerminalFromMediaEvent(IN ITCallMediaEvent *pCallMediaEvent,
OUT ITTerminal **ppTerminal)
{
HRESULT hr = E_FAIL;
//
// don't return garbage if we fail
//
*ppTerminal = NULL;
//
// get the stream corresponding to this event
//
ITStream *pStream = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -