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.
863 lines
20 KiB
863 lines
20 KiB
/*++
|
|
|
|
Copyright (c) 1998 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
bgaudio.cpp
|
|
|
|
Abstract:
|
|
|
|
Implementation of the audio bridge filters.
|
|
|
|
Author:
|
|
|
|
Mu Han (muhan) 11/16/1998
|
|
|
|
--*/
|
|
|
|
#include "stdafx.h"
|
|
|
|
CTAPIAudioBridgeSinkFilter::CTAPIAudioBridgeSinkFilter(
|
|
IN LPUNKNOWN pUnk,
|
|
IN IDataBridge * pIDataBridge,
|
|
OUT HRESULT * phr
|
|
)
|
|
: CTAPIBridgeSinkFilter(pUnk, pIDataBridge, phr)
|
|
{
|
|
}
|
|
|
|
HRESULT CTAPIAudioBridgeSinkFilter::CreateInstance(
|
|
IN IDataBridge * pIDataBridge,
|
|
OUT IBaseFilter ** ppIBaseFilter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This method create a instance of the bridge's sink filter.
|
|
|
|
Arguments:
|
|
|
|
ppIBaseFilter - the returned filter interface pointer.
|
|
|
|
Return Value:
|
|
|
|
E_OUTOFMEMORY - no memory for the new object.
|
|
|
|
--*/
|
|
{
|
|
ENTER_FUNCTION("CTAPIAudioBridgeSinkFilter::CreateInstance");
|
|
|
|
BGLOG((BG_TRACE, "%s entered.", __fxName));
|
|
|
|
HRESULT hr = S_OK;
|
|
CUnknown* pUnknown = new CTAPIAudioBridgeSinkFilter(NULL, pIDataBridge, &hr);
|
|
|
|
if (pUnknown == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
BGLOG((BG_ERROR,
|
|
"%s, out of memory creating the filter",
|
|
__fxName));
|
|
}
|
|
else if (FAILED(hr))
|
|
{
|
|
BGLOG((BG_ERROR,
|
|
"%s, the filter's constructor failed, hr:%d",
|
|
__fxName, hr));
|
|
|
|
delete pUnknown;
|
|
}
|
|
else
|
|
{
|
|
pUnknown->NonDelegatingAddRef();
|
|
|
|
hr = pUnknown->NonDelegatingQueryInterface(
|
|
__uuidof(IBaseFilter), (void **)ppIBaseFilter
|
|
);
|
|
|
|
pUnknown->NonDelegatingRelease();
|
|
}
|
|
|
|
BGLOG((BG_TRACE,
|
|
"%s, returning:%p, hr:%x", __fxName, *ppIBaseFilter, hr));
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CTAPIAudioBridgeSinkFilter::GetMediaType(
|
|
IN int iPosition,
|
|
OUT CMediaType *pMediaType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get the media type that this filter wants to support. Currently we
|
|
only support PCM L16 8KHz samples.
|
|
|
|
Arguments:
|
|
|
|
IN int iPosition,
|
|
the index of the media type, zero based..
|
|
|
|
In CMediaType *pMediaType
|
|
Pointer to a CMediaType object to save the returned media type.
|
|
|
|
Return Value:
|
|
|
|
S_OK - success
|
|
E_OUTOFMEMORY - no memory
|
|
|
|
--*/
|
|
{
|
|
ENTER_FUNCTION("CTAPIAudioBridgeSinkFilter::GetMediaType");
|
|
|
|
BGLOG((BG_TRACE,
|
|
"%s, iPosition:%d, pMediaType:%p",
|
|
__fxName, iPosition, pMediaType));
|
|
|
|
HRESULT hr = VFW_S_NO_MORE_ITEMS;
|
|
|
|
BGLOG((BG_TRACE, "%s returns %d", __fxName, hr));
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CTAPIAudioBridgeSinkFilter::CheckMediaType(
|
|
const CMediaType *pMediaType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Check the media type that this filter wants to support. Currently we
|
|
only support PCM L16 8KHz samples.
|
|
|
|
Arguments:
|
|
|
|
In CMediaType *pMediaType
|
|
Pointer to a CMediaType object to save the returned media type.
|
|
|
|
Return Value:
|
|
|
|
S_OK - success
|
|
E_OUTOFMEMORY - no memory
|
|
E_UNEXPECTED - internal media type not set
|
|
VFW_E_TYPE_NOT_ACCEPTED - media type rejected
|
|
VFW_E_INVALIDMEDIATYPE - bad media type
|
|
|
|
--*/
|
|
{
|
|
ENTER_FUNCTION("CTAPIAudioBridgeSinkFilter::CheckMediaType");
|
|
|
|
BGLOG((BG_TRACE,
|
|
"%s, pMediaType:%p", __fxName, pMediaType));
|
|
|
|
ASSERT(!IsBadReadPtr(pMediaType, sizeof(AM_MEDIA_TYPE)));
|
|
|
|
// media type is only stored in source filter
|
|
// return S_OK here
|
|
// if error, the source filter will detect it anyway
|
|
HRESULT hr = S_OK;
|
|
|
|
BGLOG((BG_TRACE, "%s returns %d", __fxName, hr));
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
CTAPIAudioBridgeSourceFilter::CTAPIAudioBridgeSourceFilter(
|
|
IN LPUNKNOWN pUnk,
|
|
OUT HRESULT * phr
|
|
)
|
|
: CTAPIBridgeSourceFilter(pUnk, phr)
|
|
{
|
|
m_fPropSet = FALSE; // allocator properties not set yet
|
|
m_fMtSet = FALSE; // media type not set yet
|
|
|
|
// m_last_wall_time, m_last_stream_time not initiated
|
|
m_fClockStarted = FALSE;
|
|
m_fJustBurst = FALSE;
|
|
|
|
m_nInputSize = 0;
|
|
m_nOutputSize = 0;
|
|
m_nOutputFree = 0;
|
|
m_pOutputSample = NULL;
|
|
}
|
|
|
|
CTAPIAudioBridgeSourceFilter::~CTAPIAudioBridgeSourceFilter ()
|
|
{
|
|
if (m_fMtSet)
|
|
{
|
|
FreeMediaType (m_mt);
|
|
}
|
|
|
|
if (NULL != m_pOutputSample)
|
|
{
|
|
m_pOutputSample->Release ();
|
|
}
|
|
}
|
|
|
|
HRESULT CTAPIAudioBridgeSourceFilter::CreateInstance(
|
|
OUT IBaseFilter ** ppIBaseFilter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This method create a instance of the bridge's sink filter.
|
|
|
|
Arguments:
|
|
|
|
ppIBaseFilter - the returned filter interface pointer.
|
|
|
|
Return Value:
|
|
|
|
E_OUTOFMEMORY - no memory for the new object.
|
|
|
|
--*/
|
|
{
|
|
ENTER_FUNCTION("CTAPIAudioBridgeSourceFilter::CreateInstance");
|
|
|
|
BGLOG((BG_TRACE, "%s entered.", __fxName));
|
|
|
|
HRESULT hr = S_OK;
|
|
CUnknown* pUnknown = new CTAPIAudioBridgeSourceFilter(NULL, &hr);
|
|
|
|
if (pUnknown == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
BGLOG((BG_ERROR,
|
|
"%s, out of memory creating the filter",
|
|
__fxName));
|
|
}
|
|
else if (FAILED(hr))
|
|
{
|
|
BGLOG((BG_ERROR,
|
|
"%s, the filter's constructor failed, hr:%d",
|
|
__fxName, hr));
|
|
|
|
delete pUnknown;
|
|
}
|
|
else
|
|
{
|
|
pUnknown->NonDelegatingAddRef();
|
|
|
|
hr = pUnknown->NonDelegatingQueryInterface(
|
|
__uuidof(IBaseFilter), (void **)ppIBaseFilter
|
|
);
|
|
|
|
pUnknown->NonDelegatingRelease();
|
|
}
|
|
|
|
BGLOG((BG_TRACE,
|
|
"%s, returning:%p, hr:%x", __fxName, *ppIBaseFilter, hr));
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CTAPIAudioBridgeSourceFilter::GetMediaType(
|
|
IN int iPosition,
|
|
OUT CMediaType *pMediaType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get the media type that this filter wants to support. Currently we
|
|
only support PCM L16 8KHz samples.
|
|
|
|
Arguments:
|
|
|
|
IN int iPosition,
|
|
the index of the media type, zero based..
|
|
|
|
In CMediaType *pMediaType
|
|
Pointer to a CMediaType object to save the returned media type.
|
|
|
|
Return Value:
|
|
|
|
S_OK - success
|
|
E_OUTOFMEMORY - no memory
|
|
|
|
--*/
|
|
{
|
|
ENTER_FUNCTION("CTAPIAudioBridgeSourceFilter::GetMediaType");
|
|
|
|
BGLOG((BG_TRACE,
|
|
"%s, iPosition:%d, pMediaType:%p",
|
|
__fxName, iPosition, pMediaType));
|
|
|
|
ASSERT(!IsBadWritePtr(pMediaType, sizeof(AM_MEDIA_TYPE)));
|
|
|
|
HRESULT hr;
|
|
if (iPosition == 0)
|
|
{
|
|
AM_MEDIA_TYPE *pmt = NULL;
|
|
hr = m_pOutputPin->GetFormat (&pmt);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
*pMediaType = *pmt;
|
|
FreeMediaType (*pmt);
|
|
free (pmt);
|
|
}
|
|
else
|
|
{
|
|
hr = VFW_S_NO_MORE_ITEMS;
|
|
}
|
|
// END
|
|
|
|
BGLOG((BG_TRACE, "%s returns %d", __fxName, hr));
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CTAPIAudioBridgeSourceFilter::CheckMediaType(
|
|
const CMediaType *pMediaType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Check the media type that this filter wants to support. Currently we
|
|
only support PCM L16 8KHz samples.
|
|
|
|
Arguments:
|
|
|
|
In CMediaType *pMediaType
|
|
Pointer to a CMediaType object to save the returned media type.
|
|
|
|
Return Value:
|
|
|
|
S_OK - success
|
|
E_OUTOFMEMORY - no memory
|
|
VFW_E_TYPE_NOT_ACCEPTED - media type rejected
|
|
VFW_E_INVALIDMEDIATYPE - bad media type
|
|
|
|
--*/
|
|
{
|
|
ENTER_FUNCTION("CTAPIAudioBridgeSourceFilter::CheckMediaType");
|
|
|
|
BGLOG((BG_TRACE,
|
|
"%s, pMediaType:%p", __fxName, pMediaType));
|
|
|
|
ASSERT(!IsBadReadPtr(pMediaType, sizeof(AM_MEDIA_TYPE)));
|
|
|
|
if (!m_fMtSet)
|
|
{
|
|
BGLOG ((BG_ERROR, "%s tries to check media type before setting", __fxName));
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
// create media type based on stored AM_MEDIA_TYPE
|
|
CMediaType *pmediatype = new CMediaType (m_mt);
|
|
if (NULL == pmediatype)
|
|
{
|
|
BGLOG ((BG_ERROR, "%s failed to new media type class", __fxName));
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
HRESULT hr;
|
|
if (*pMediaType == *pmediatype)
|
|
hr = S_OK;
|
|
else
|
|
{
|
|
hr = VFW_E_TYPE_NOT_ACCEPTED;
|
|
BGLOG ((BG_TRACE, "%s rejects media type class %p", __fxName, pMediaType));
|
|
}
|
|
|
|
delete pmediatype;
|
|
|
|
BGLOG((BG_TRACE, "%s returns %d", __fxName, hr));
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CTAPIAudioBridgeSourceFilter::SendSample(
|
|
IN IMediaSample *pSample
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Process a sample from the bridge sink filter. Overides the base implementation
|
|
|
|
Arguments:
|
|
|
|
pSample - The media sample object.
|
|
|
|
Return Value:
|
|
|
|
HRESULT.
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr;
|
|
|
|
ENTER_FUNCTION ("CTAPIAudioBridgeSourceFilter::SendSample");
|
|
|
|
CAutoLock Lock(m_pLock);
|
|
|
|
_ASSERT(m_pOutputPin != NULL);
|
|
|
|
// we don't deliver anything if the filter is not in running state.
|
|
if (m_State != State_Running)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
// if the sample is the 1st of the burst
|
|
if (S_OK == pSample->IsDiscontinuity ())
|
|
{
|
|
LONGLONG start, end;
|
|
|
|
m_fJustBurst = TRUE;
|
|
if (S_OK != (hr = pSample->GetTime (&start, &end)))
|
|
{
|
|
BGLOG ((BG_TRACE, "%s, 1st sample in a burst, GetTime returns %x", __fxName, hr));
|
|
|
|
// timestampes stored remain unchange
|
|
return S_OK;
|
|
}
|
|
// else. in NT 5.1, 1st sample has valid timestamp.
|
|
}
|
|
|
|
// check if allocator properties is set
|
|
if (!m_fPropSet)
|
|
{
|
|
BGLOG ((BG_ERROR, "%s tries to send sample before setting allocator property", __fxName));
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
// check if media type is set
|
|
if (!m_fMtSet)
|
|
{
|
|
BGLOG ((BG_ERROR, "%s tries to send sample before setting media type", __fxName));
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
/*
|
|
* get size info
|
|
*/
|
|
// get input sample size and output allocator size
|
|
HRESULT nInputSize, nOutputSize;
|
|
|
|
nInputSize = pSample->GetActualDataLength ();
|
|
nOutputSize = m_prop.cbBuffer;
|
|
|
|
// 1st run, record size
|
|
if (m_nInputSize == 0 || m_nOutputSize == 0)
|
|
{
|
|
m_nInputSize = nInputSize;
|
|
m_nOutputSize = nOutputSize;
|
|
}
|
|
|
|
if (
|
|
m_nInputSize != nInputSize ||
|
|
m_nOutputSize != nOutputSize ||
|
|
m_nInputSize == 0 ||
|
|
m_nOutputSize == 0
|
|
)
|
|
{
|
|
BGLOG ((BG_ERROR, "%s, sample size (%d => %d) or output size (%d => %d) is changed",
|
|
__fxName, m_nInputSize, nInputSize, m_nOutputSize, nOutputSize));
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
/*
|
|
* get time info
|
|
*/
|
|
REFERENCE_TIME wall;
|
|
|
|
// wall time
|
|
if (FAILED (hr = m_pClock->GetTime (&wall)))
|
|
{
|
|
BGLOG ((BG_ERROR, "%s failed to get wall time", __fxName));
|
|
return hr;
|
|
}
|
|
|
|
// if timestamp not initiated
|
|
if (!m_fClockStarted)
|
|
{
|
|
m_last_stream_time = 0;
|
|
m_last_wall_time = wall;
|
|
m_fClockStarted = TRUE;
|
|
|
|
// delta is the time of playing sample:
|
|
m_output_sample_time = nOutputSize * 80000; // s->10000ns, bits->bytes
|
|
m_output_sample_time /= ((WAVEFORMATEX*)m_mt.pbFormat)->wBitsPerSample *
|
|
((WAVEFORMATEX*)m_mt.pbFormat)->nSamplesPerSec;
|
|
m_output_sample_time *= 1000; // bytes/100ns
|
|
}
|
|
|
|
/*
|
|
* calculate new stream time
|
|
*/
|
|
if (m_fJustBurst)
|
|
{
|
|
// 1st useful sample after burst
|
|
m_last_stream_time += (wall - m_last_wall_time);
|
|
m_last_wall_time = wall;
|
|
|
|
m_fJustBurst = FALSE;
|
|
|
|
// clear buffer
|
|
if (NULL != m_pOutputSample)
|
|
{
|
|
m_pOutputSample->Release ();
|
|
m_pOutputSample = NULL;
|
|
m_nOutputFree = 0;
|
|
}
|
|
}
|
|
|
|
REFERENCE_TIME end = m_last_stream_time + m_output_sample_time;
|
|
|
|
/*
|
|
* case 1: input size == output size
|
|
*/
|
|
if (m_nInputSize == m_nOutputSize)
|
|
{
|
|
if (FAILED (pSample->SetTime (&m_last_stream_time, &end)))
|
|
{
|
|
BGLOG ((BG_ERROR, "%s failed to set time", __fxName));
|
|
}
|
|
|
|
// adjust time
|
|
m_last_stream_time = end;
|
|
m_last_wall_time += m_output_sample_time;
|
|
|
|
// deliver directly
|
|
return m_pOutputPin->Deliver(pSample);
|
|
}
|
|
|
|
/*
|
|
* case 2: size differs
|
|
*/
|
|
BYTE *pInputBuffer, *pOutputBuffer;
|
|
|
|
if (FAILED (hr = pSample->GetPointer (&pInputBuffer)))
|
|
{
|
|
BGLOG ((BG_ERROR, "%s failed to get buffer pointer from input sample %p",
|
|
__fxName, pSample));
|
|
return hr;
|
|
}
|
|
|
|
LONG nNextPos = 0;
|
|
|
|
// old fashion goto
|
|
DELIVERY_BUFFER:
|
|
|
|
// get delivery buffer if it's null
|
|
if (NULL == m_pOutputSample)
|
|
{
|
|
hr = m_pOutputPin->GetDeliveryBuffer (
|
|
&m_pOutputSample, // media sample **
|
|
NULL, // start time
|
|
NULL, // end time
|
|
AM_GBF_NOTASYNCPOINT // dynamic format changes are not allowed,
|
|
);
|
|
if (FAILED (hr))
|
|
{
|
|
BGLOG ((BG_ERROR, "%s, output pin failed to get delivery buffer. return %d",
|
|
__fxName, hr));
|
|
return hr;
|
|
}
|
|
|
|
if (m_pOutputSample->GetSize() < m_nOutputSize)
|
|
{
|
|
// oops, what happend, the size should be the same
|
|
BGLOG ((BG_ERROR, "%s, delivery buffer size %d and output size %d are inconsistent",
|
|
__fxName, m_pOutputSample->GetSize(), m_nOutputSize));
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
// set size
|
|
if (FAILED (hr = m_pOutputSample->SetActualDataLength (m_nOutputSize)))
|
|
{
|
|
BGLOG ((BG_ERROR, "%s failed to set output sample size", __fxName));
|
|
return hr;
|
|
}
|
|
/*
|
|
// set format
|
|
if (FAILED (hr = m_pOutputSample->SetMediaType (&m_mt)))
|
|
{
|
|
BGLOG ((BG_ERROR, "%s failed to set media type for delivery buffer", __fxName));
|
|
return hr;
|
|
}
|
|
*/
|
|
// set time
|
|
if (FAILED (hr = m_pOutputSample->SetTime (&m_last_stream_time, &end)))
|
|
{
|
|
BGLOG ((BG_ERROR, "%s failed to set stream time for delivery buffer", __fxName));
|
|
return hr;
|
|
}
|
|
|
|
// the whole buffer is free
|
|
m_nOutputFree = m_nOutputSize;
|
|
}
|
|
|
|
// get buffer in output sample
|
|
if (FAILED (hr = m_pOutputSample->GetPointer (&pOutputBuffer)))
|
|
{
|
|
BGLOG ((BG_ERROR, "%s failed to get buffer pointer from output sample %p",
|
|
__fxName, m_pOutputSample));
|
|
|
|
// release output sample
|
|
m_pOutputSample->Release ();
|
|
m_pOutputSample = NULL;
|
|
m_nOutputFree = 0;
|
|
|
|
return hr;
|
|
}
|
|
|
|
// if input buffer is smaller than free output buffer
|
|
// copy input to output and return
|
|
if (m_nInputSize-nNextPos < m_nOutputFree)
|
|
{
|
|
CopyMemory (
|
|
(PVOID)(pOutputBuffer + (m_nOutputSize - m_nOutputFree)),
|
|
(PVOID)(pInputBuffer + nNextPos),
|
|
(DWORD)(m_nInputSize - nNextPos)
|
|
);
|
|
|
|
// reduce free buffer size
|
|
m_nOutputFree -= m_nInputSize - nNextPos;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// else: input buffer is greater or equal to free output buffer
|
|
CopyMemory (
|
|
(PVOID)(pOutputBuffer + (m_nOutputSize - m_nOutputFree)),
|
|
(PVOID)(pInputBuffer + nNextPos),
|
|
(DWORD)(m_nOutputFree)
|
|
);
|
|
|
|
// now output sample is full, deliver it
|
|
if (FAILED (hr = m_pOutputPin->Deliver (m_pOutputSample)))
|
|
{
|
|
BGLOG ((BG_ERROR, "%s failed to deliver copied sample. return %x", __fxName, hr));
|
|
|
|
// clear sample
|
|
m_pOutputSample->Release ();
|
|
m_pOutputSample = NULL;
|
|
m_nOutputFree = 0;
|
|
|
|
return hr;
|
|
}
|
|
|
|
// adjust next position in input buffer
|
|
nNextPos += m_nOutputFree;
|
|
|
|
// clear output sample since it was deliverd
|
|
m_pOutputSample->Release ();
|
|
m_pOutputSample = NULL;
|
|
m_nOutputFree = 0;
|
|
|
|
// adjust time
|
|
m_last_stream_time = end;
|
|
m_last_wall_time += m_output_sample_time;
|
|
|
|
// check if nothing left
|
|
if (nNextPos == m_nInputSize)
|
|
return S_OK;
|
|
|
|
// there is more in input buffer
|
|
goto DELIVERY_BUFFER;
|
|
}
|
|
|
|
HRESULT CTAPIAudioBridgeSourceFilter::GetAllocatorProperties (OUT ALLOCATOR_PROPERTIES *pprop)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns the allocator properties
|
|
|
|
Arguments:
|
|
|
|
pprop -
|
|
The pointer to an ALLOCATOR_PROPERTIES
|
|
|
|
Return Value:
|
|
|
|
E_POINTER -
|
|
if pprop is NULL
|
|
|
|
S_OK
|
|
|
|
--*/
|
|
{
|
|
ENTER_FUNCTION ("CTAPIAudioBridgeSourceFilter::GetAllocatorProperties");
|
|
_ASSERT(pprop);
|
|
|
|
if (!pprop)
|
|
return E_POINTER;
|
|
|
|
if (!m_fPropSet)
|
|
{
|
|
BGLOG ((BG_INFO, "%s retrieves allocator properties before setting", __fxName));
|
|
// return default value anyway
|
|
// buffer size = (16bits / 8bits) * 8khz * 30 ms = 480 bytes
|
|
pprop->cBuffers = 1;
|
|
pprop->cbBuffer = 480; // default
|
|
pprop->cbAlign = 0;
|
|
pprop->cbPrefix = 0;
|
|
return S_OK;
|
|
}
|
|
|
|
// properties were set
|
|
pprop->cBuffers = m_prop.cBuffers;
|
|
pprop->cbBuffer = m_prop.cbBuffer;
|
|
pprop->cbAlign = m_prop.cbAlign;
|
|
pprop->cbPrefix = m_prop.cbPrefix;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CTAPIAudioBridgeSourceFilter::SuggestAllocatorProperties (IN const ALLOCATOR_PROPERTIES *pprop)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Asks the pin to use the allocator buffer properties
|
|
|
|
Arguments:
|
|
|
|
pprop -
|
|
The pointer to an ALLOCATOR_PROPERTIES
|
|
|
|
Return Value:
|
|
|
|
E_POINTER
|
|
|
|
S_OK
|
|
|
|
--*/
|
|
{
|
|
_ASSERT (pprop);
|
|
|
|
if (!pprop)
|
|
return E_POINTER;
|
|
|
|
m_prop.cBuffers = pprop->cBuffers;
|
|
m_prop.cbBuffer = pprop->cbBuffer;
|
|
m_prop.cbAlign = pprop->cbAlign;
|
|
m_prop.cbPrefix = pprop->cbPrefix;
|
|
m_fPropSet = TRUE;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CTAPIAudioBridgeSourceFilter::GetFormat (OUT AM_MEDIA_TYPE **ppmt)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Retrieves the stream format
|
|
|
|
Arguments:
|
|
|
|
ppmt -
|
|
Address of a pointer to an AM_MEDIA_TYPE structure
|
|
|
|
Return Value:
|
|
|
|
E_PONTER
|
|
|
|
E_OUTOFMEMORY
|
|
|
|
HRESULT of SetFormat
|
|
|
|
S_OK
|
|
|
|
--*/
|
|
{
|
|
ENTER_FUNCTION ("CTAPIAudioBridgeSourceFilter::GetFormat");
|
|
|
|
_ASSERT (ppmt);
|
|
if (NULL == ppmt)
|
|
return E_POINTER;
|
|
|
|
if (NULL != *ppmt)
|
|
BGLOG ((BG_INFO, "is media type structure freed when passed in %s?", __fxName));
|
|
|
|
*ppmt = new AM_MEDIA_TYPE;
|
|
if (NULL == *ppmt)
|
|
{
|
|
BGLOG ((BG_ERROR, "%s out of memory", __fxName));
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
if (!m_fMtSet)
|
|
{
|
|
BGLOG ((BG_INFO, "%s retrieves media type before setting. Default is to set.", __fxName));
|
|
|
|
// st format
|
|
HRESULT hr;
|
|
AM_MEDIA_TYPE mt;
|
|
WAVEFORMATEX wfx;
|
|
|
|
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
|
wfx.wBitsPerSample = 16;
|
|
wfx.nChannels = 1;
|
|
wfx.nSamplesPerSec = 8000;
|
|
wfx.nBlockAlign = wfx.wBitsPerSample * wfx.nChannels / 8;
|
|
wfx.nAvgBytesPerSec = ((DWORD) wfx.nBlockAlign * wfx.nSamplesPerSec);
|
|
wfx.cbSize = 0;
|
|
|
|
mt.majortype = MEDIATYPE_Audio;
|
|
mt.subtype = MEDIASUBTYPE_PCM;
|
|
mt.bFixedSizeSamples = TRUE;
|
|
mt.bTemporalCompression = FALSE;
|
|
mt.lSampleSize = 0;
|
|
mt.formattype = FORMAT_WaveFormatEx;
|
|
mt.pUnk = NULL;
|
|
mt.cbFormat = sizeof(WAVEFORMATEX);
|
|
mt.pbFormat = (BYTE*)&wfx;
|
|
|
|
hr = SetFormat (&mt);
|
|
if (FAILED (hr))
|
|
{
|
|
BGLOG ((BG_ERROR, "%s, failed to set default format", __fxName));
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
CopyMediaType (*ppmt, &m_mt);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CTAPIAudioBridgeSourceFilter::SetFormat (IN AM_MEDIA_TYPE *pmt)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sets the stream format
|
|
|
|
Arguments:
|
|
|
|
pmt -
|
|
Pointer to an AM_MEDIA_TYPE structure
|
|
|
|
Return Value:
|
|
|
|
E_POINTER
|
|
|
|
S_OK
|
|
|
|
--*/
|
|
{
|
|
_ASSERT (pmt);
|
|
|
|
if (NULL == pmt)
|
|
return E_POINTER;
|
|
|
|
CopyMediaType (&m_mt, pmt);
|
|
m_fMtSet = TRUE;
|
|
return S_OK;
|
|
}
|