DEFINE_GUID(CLSID_WaveParser,
0xd51bd5a1, 0x7548,
0x11cf, 0xa5,
0x20, 0x0,
0x80, 0xc7,
0x7e, 0xf5,
0x8a);
#define
SOURCE_FILE L"c:\\stuff\\6ch_96khz.wav"
#define
OUTPUT_FILE L"C:\\stuff\\6ch_96khz.wma"
#define
PRO_FILE _T("C:\\WMMedia\\Encoder\\Profiles\\6.1_96khz_profb.prx")
#define
MAX_PROFILE_SIZE_W 4096
HRESULT FindFilter(LPWSTR FilterName, const GUID
Category, IBaseFilter **ppFilter)
{
HRESULT hr =
S_OK;
IEnumMoniker
*pEnumCat = NULL;
ICreateDevEnum *pSysDevEnum = NULL;
if ( SUCCEEDED(hr) )
hr = ::CoCreateInstance( CLSID_SystemDeviceEnum, NULL,
CLSCTX_INPROC, IID_ICreateDevEnum, (LPVOID *)&pSysDevEnum );
if ( SUCCEEDED(hr) )
hr = pSysDevEnum->CreateClassEnumerator(Category, &pEnumCat,
0);
if ( SUCCEEDED(hr) )
{
// Enumerate the monikers.
IMoniker *pMoniker = NULL;
ULONG cFetched; VFW_E_DDRAW_CAPS_NOT_SUITABLE;
while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
{
IPropertyBag *pPropBag = NULL;
IPropertyBag2 *pPropBag2 = NULL;
hr = pMoniker->BindToStorage(0,
0, IID_IPropertyBag2, (LPVOID *)&pPropBag2);
if ( SUCCEEDED(hr) )
{
ULONG nProps;
pPropBag2->CountProperties(&nProps);
pPropBag2->Release();
}
hr = pMoniker->BindToStorage(0,
0, IID_IPropertyBag, (LPVOID *)&pPropBag);
if ( SUCCEEDED(hr) )
{
// To retrieve the filter's friendly name, do
the following:
VARIANT varName;
VARIANT var_CLSID;
VARIANT var_FD;
VARIANT var_guid;
var_CLSID.vt = VT_BSTR;
VariantInit(&varName);
var_FD.vt = VT_UI1 | VT_ARRAY;
var_FD.parray = 0;
// docs say to zero this
hr = pPropBag->Read(L"GUID", &var_guid,
NULL);
hr = pPropBag->Read(L"CLSID", &var_CLSID,
NULL);
hr = pPropBag->Read(L"FriendlyName",
&varName, 0);
hr = pPropBag->Read(L"FilterData",
&var_FD, NULL);
if (SUCCEEDED(hr))
{
CString t;
//t.Format("CLSID:%S Friendly:%S\n",
var_CLSID.bstrVal, varName.bstrVal);
//OutputDebugString(t);
if ( lstrcmpW( varName.bstrVal,
FilterName ) == 0 )
{
// To create an instance of the filter, do the
following:
hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)ppFilter);
}
}
VariantClear(&varName);
pPropBag->Release();
}
pMoniker->Release();
}
pEnumCat->Release();
pSysDevEnum->Release();
}
return hr;
}
// Build and run an encoding graph that converts a multichannel wave file to a WMA
file
// using the WMA DMO Encoder. The
AudioTypeConvert filter is also used automatically
// in this sample if the source file does not have a WAVEFORMATEXTENSIBLE
structure.
// The AudioTypeConvert filter must be registered for that step to happen.
void
BuildTheOtherGraph()
{
HRESULT hr =
S_OK;
CComPtr<IGraphBuilder>
pGraph;
CComPtr<IBaseFilter>
source;
CComPtr<IBaseFilter>
splitter;
CComPtr<IBaseFilter>
compressor;
CComPtr<IBaseFilter>
asfWriter;
CComQIPtr<IMediaControl>
control;
CComQIPtr<IMediaEvent>
pEvent;
hr =
pGraph.CoCreateInstance(CLSID_FilterGraph);
if ( pGraph )
{
control = pGraph;
pEvent = pGraph;
}
hr =
pGraph->AddSourceFilter(SOURCE_FILE, L"Source",
&source);
if ( SUCCEEDED(hr) )
hr = pGraph->AddFilter( source, L"WAV Source"
);
hr =
splitter.CoCreateInstance(CLSID_WaveParser);
if ( SUCCEEDED(hr) )
hr = pGraph->AddFilter( splitter, L"WAV Splitter"
);
hr =
FindFilter(L"WMAudio Encoder DMO",
CLSID_AudioCompressorCategory, &compressor);
if ( SUCCEEDED(hr) )
{
hr = pGraph->AddFilter( compressor, L"WMA DMO
Encoder" );
}
hr =
asfWriter.CoCreateInstance(CLSID_WMAsfWriter);
if ( SUCCEEDED(hr) )
hr = pGraph->AddFilter( asfWriter, L"ASF Writer"
);
CComPtr<IPin> sourcepin;
CComPtr<IPin> sin;
// splitter input
CComPtr<IPin> sout0; // splitter output
CComPtr<IPin> compin;
// compressor input
CComPtr<IPin> compout; // compressor output
source->FindPin(L"Output", &sourcepin);
if (splitter)
{
// find the splitter input pin
splitter->FindPin(L"input pin", &sin);
if (sin)
{
// connect the WAV source to the WAV Splitter
hr = pGraph->ConnectDirect( sourcepin, sin, NULL);
if (hr == S_OK)
{
// find the splitter output pin
splitter->FindPin(L"output", &sout0);
}
}
}
if (sout0)
{
// find the pins for the WMA DMO filter
hr = compressor->FindPin(L"in0", &compin);
hr = compressor->FindPin(L"out0",
&compout);
// Connect the WAV Splitter output pin to the
WMA Compressor. We are not using
ConnectDirect
// because we want the AudioTypeConvert filter
to be inserted inbetween to make the media type
// WAVEFORMATEXTENSIBLE as the WMA DMO
Compressor desires.
hr = pGraph->Connect(sout0, compin);
}
{
CComQIPtr<IConfigAsfWriter2>
pConfigWriter;
CComPtr<IWMProfileManager>
pProfileManager;
CComPtr<IWMProfile>
pProfile;
hr = WMCreateProfileManager(&pProfileManager);
WCHAR szProfile[MAX_PROFILE_SIZE_W];
{
// makes the assumption that the .prx file is
Unicode
CFile prof("C:\\WMMedia\\Encoder\\Profiles\\6.1_96khz_profb.prx",
CFile::modeRead);
UINT nBytesRead = prof.Read(szProfile, MAX_PROFILE_SIZE_W*2);
szProfile[nBytesRead/2] =
0;
}
hr = pProfileManager->LoadProfileByData(szProfile, &pProfile);
pConfigWriter = asfWriter;
if (pConfigWriter)
{
hr = pConfigWriter->SetParam(AM_CONFIGASFWRITER_PARAM_DONTCOMPRESS, TRUE,
0);
hr = pConfigWriter->ConfigureFilterUsingProfile(pProfile);
CComPtr<IPin> writerPin;
hr = asfWriter->FindPin(L"Audio Input 01",
&writerPin);
{
CComQIPtr<IFileSinkFilter> pFileSink;
pFileSink = asfWriter;
// make sure the file isn't in use by a player
or this will fail
DeleteFileW(OUTPUT_FILE);
if (pFileSink)
hr = pFileSink->SetFileName(OUTPUT_FILE, NULL);
}
// connect the WMA Compressor to the ASF Writer
hr = pGraph->ConnectDirect(compout, writerPin, NULL);
}
}
// optionally add the graph to ROT - not much use
unless you use the long sample
//DWORD dwReg = 0;
//hr = AddGraphToRot(pGraph, &dwReg);
hr =
control->Pause();
hr =
control->Run();
long code;
hr =
pEvent->WaitForCompletion(20000, &code);
//RemoveGraphFromRot(dwReg);
return;
}