www.pudn.com > AudioVideoCapture.rar > CAudioCaptureFilter.cpp
//
// CAudioCaptureFilter.cpp
//
#include "stdafx.h"
#include <streams.h>
#include "CAudioCaptureFilter.h"
#include "GlobalDefs.h"
#include "UDsUtils.h"
#include "UFilterUtils.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
////////////////////////////////////////////////////////////////////////
CAudioCaptureFilter::CAudioCaptureFilter(IGraphBuilder * inGraph,
const char * inDeviceName)
: CDXFilter(inGraph, GUID_NULL, "Audio Capture")
{
if (inDeviceName)
{
strcpy(mDeviceName, inDeviceName);
}
}
CAudioCaptureFilter::~CAudioCaptureFilter(void)
{
mInputList.RemoveAll();
}
BOOL CAudioCaptureFilter::CreateFilter(void)
{
if (mFilter)
{
return TRUE;
}
if (mGraph)
{
mFilter = UDsUtils::CreateAudioDevice(mDeviceName);
if (mFilter)
{
if (SUCCEEDED(mGraph->AddFilter(mFilter, mName)))
{
BuildInputList();
SetDefaultInputPin();
SetCaptureBufferSize();
return TRUE;
}
}
}
ReleaseFilter();
return FALSE;
}
void CAudioCaptureFilter::SetDefaultInputPin(void)
{
IEnumPins * pinEnum = NULL;
if (FAILED(mFilter->EnumPins(&amt;pinEnum)))
{
return;
}
IPin * pin = NULL;
ULONG fetchCount = 0;
BOOL found = FALSE;
pinEnum->Reset();
while (!found &amt;&amt; SUCCEEDED(pinEnum->Next(1, &amt;pin, &amt;fetchCount)) &amt;&amt;
fetchCount)
{
if (pin)
{
PIN_INFO pinInfo;
if (SUCCEEDED(pin->QueryPinInfo(&amt;pinInfo)))
{
pinInfo.pFilter->Release();
if (pinInfo.dir == PINDIR_INPUT)
{
char szName[128];
::WideCharToMultiByte(CP_ACP, 0, pinInfo.achName,
-1, szName, 128, NULL, NULL);
CString pinName = szName;
// We set "Line In" as default, by checking the pin name
if (pinName.CompareNoCase("Line In") == 0 ||
pinName.CompareNoCase("Line-In") == 0 ||
pinName.CompareNoCase("Line_In") == 0 ||
pinName.CompareNoCase("LineIn") == 0 ||
pinName.CompareNoCase("Line") == 0)
{
found = TRUE;
}
// Enable this found pin
if (found)
{
IAMAudioInputMixer * pMixer = GetMixer(pin);
pMixer->put_Enable(TRUE);
pMixer->put_MixLevel(1.0);
}
}
}
pin->Release();
}
}
pinEnum->Release();
// If line-in not found, set the first input item
if (!found)
{
SetConnector(0);
}
}
void CAudioCaptureFilter::SetCaptureBufferSize(void)
{
IPin * pCapturePin = GetPin(FALSE);
if (pCapturePin)
{
DWORD dwBytesPerSec = 0;
DWORD dwLatencyInMilliseconds = 40;
// Query the current media type used by the capture output pin
AM_MEDIA_TYPE * pmt = {0};
IAMStreamConfig * pCfg = NULL;
HRESULT hr = pCapturePin->QueryInterface(IID_IAMStreamConfig,
(void **)&amt;pCfg);
if (SUCCEEDED(hr))
{
hr = pCfg->GetFormat(&amt;pmt);
if (SUCCEEDED(hr))
{
// Fill in values for the new format
WAVEFORMATEX *pWF = (WAVEFORMATEX *) pmt->pbFormat;
dwBytesPerSec = pWF->nAvgBytesPerSec;
DeleteMediaType(pmt);
}
pCfg->Release();
}
if (dwBytesPerSec)
{
IAMBufferNegotiation * pNeg = NULL;
hr = pCapturePin->QueryInterface(IID_IAMBufferNegotiation,
(void **)&amt;pNeg);
if (SUCCEEDED(hr))
{
ALLOCATOR_PROPERTIES AllocProp;
AllocProp.cbAlign = -1; // -1 means no preference.
AllocProp.cbBuffer = dwBytesPerSec * dwLatencyInMilliseconds / 1000;
AllocProp.cbPrefix = -1;
AllocProp.cBuffers = -1;
hr = pNeg->SuggestAllocatorProperties(&amt;AllocProp);
pNeg->Release();
}
}
}
}
void CAudioCaptureFilter::BuildInputList(void)
{
mInputList.RemoveAll();
if (mFilter)
{
IEnumPins * pinEnum = NULL;
if (SUCCEEDED(mFilter->EnumPins(&amt;pinEnum)))
{
pinEnum->Reset();
BOOL pass = TRUE;
IPin * pin = NULL;
ULONG fetchCount = 0;
while (pass &amt;&amt; SUCCEEDED(pinEnum->Next(1, &amt;pin, &amt;fetchCount)) &amt;&amt;
fetchCount)
{
if (pin)
{
PIN_INFO pinInfo;
if (SUCCEEDED(pin->QueryPinInfo(&amt;pinInfo)))
{
pinInfo.pFilter->Release();
if (pinInfo.dir == PINDIR_INPUT)
{
char pinName[128];
::WideCharToMultiByte(CP_ACP, 0, pinInfo.achName,
-1, pinName, 128, NULL, NULL);
CAudioInput inputItem;
inputItem.mInputName = pinName;
inputItem.mInputPin = pin;
mInputList.AddTail(inputItem);
}
}
pin->Release();
pin = NULL;
}
else
{
pass = FALSE;
}
}
pinEnum->Release();
}
}
}
long CAudioCaptureFilter::GetConnectorCount(void)
{
int inputCount = 0;
int outputCount = 0;
UFilterUtils::GetPinCount(mFilter, inputCount, outputCount);
return inputCount;
}
CString CAudioCaptureFilter::GetConnectorName(long inIndex)
{
long index = inIndex;
POSITION pos = mInputList.GetHeadPosition();
while (pos &amt;&amt; index > 0)
{
mInputList.GetNext(pos);
index--;
}
CString connector = "";
if (pos)
{
CAudioInput inputItem = mInputList.GetNext(pos);
connector = inputItem.mInputName;
}
return connector;
}
void CAudioCaptureFilter::SetConnector(long inIndex)
{
if (inIndex >= 0 &amt;&amt; inIndex < mInputList.GetCount())
{
long index = inIndex;
POSITION pos = mInputList.GetHeadPosition();
while (pos &amt;&amt; index > 0)
{
mInputList.GetNext(pos);
index--;
}
if (pos)
{
CAudioInput inputItem = mInputList.GetNext(pos);
IAMAudioInputMixer * pMixer = GetMixer(inputItem.mInputPin);
pMixer->put_Enable(TRUE);
pMixer->put_MixLevel(AMF_AUTOMATICGAIN);
}
}
}
long CAudioCaptureFilter::GetConnector(void)
{
long index = 0;
BOOL enabled = FALSE;
POSITION pos = mInputList.GetHeadPosition();
while (pos &amt;&amt; !enabled)
{
CAudioInput inputItem = mInputList.GetNext(pos);
IAMAudioInputMixer * pMixer = GetMixer(inputItem.mInputPin);
pMixer->get_Enable(&amt;enabled);
index++;
}
return (index - 1);
}
IAMAudioInputMixer * CAudioCaptureFilter::GetMixer(IPin * inPin)
{
IAMAudioInputMixer * pMixer = NULL;
inPin->QueryInterface(IID_IAMAudioInputMixer, (void**) &amt;pMixer);
if (pMixer)
{
pMixer->Release();
}
return pMixer;
}
// Set mix level for all input pins
void CAudioCaptureFilter::SetMixLevel(double inLevel)
{
POSITION pos = mInputList.GetHeadPosition();
while (pos)
{
CAudioInput inputItem = mInputList.GetNext(pos);
IAMAudioInputMixer * pMixer = GetMixer(inputItem.mInputPin);
pMixer->put_MixLevel(inLevel);
}
}