我的代码如下:
//cpp file
//--------------------------------------------------------------------------- #include
#pragma hdrstop #include "main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TMainFrame *MainFrame;
//---------------------------------------------------------------------------
__fastcall TMainFrame::TMainFrame(TComponent* Owner)
: TForm(Owner)
{
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
HRESULT hr = BuildCaptureGraph();
if(FAILED(hr))
{
FreeCapture();
PostQuitMessage(0);
}
}
//---------------------------------------------------------------------------
void __fastcall TMainFrame::WinProc(TMessage &Msg)
{
switch (Msg.Msg)
{
case WM_GRAPHNOTIFY:
{
if (Msg.LParam == RECORD_EVENT)
HandleGraphEvent();
}
}
MainFrame->Dispatch(&Msg);
}
//---------------------------------------------------------------------------
void __fastcall TMainFrame::FormCreate(TObject *Sender)
{
MainFrame->WindowProc = WinProc;
}
//---------------------------------------------------------------------------
HRESULT TMainFrame:: HandleGraphEvent()
{
long evCode, evParam1, evParam2;
HRESULT hr=S_OK; if (!m_pME)
return S_OK; // Read all events currently on the event queue
while(SUCCEEDED(m_pME->GetEvent(&evCode, (LONG_PTR *) &evParam1,
(LONG_PTR *) &evParam2, 0)))
{
if(EC_DEVICE_LOST == evCode)
{
// Device was removed
if (evParam2 == 0)
{
btnStopClick(NULL);
FreeCapture();
SetDefaults();
MessageBeep(0);
}
// Device was reattached
else
{
BuildCaptureGraph();
MessageBeep(0);
}
} // Free event parameters to prevent memory leaks
hr = m_pME->FreeEventParams(evCode, evParam1, evParam2);
} return hr;
} void __fastcall TMainFrame::SetDefaults()
{
m_pGB = 0;
m_pMC = 0;
m_pME = 0;
m_pCapture = 0;
m_pInputDevice =0;
pAudioEncoder = NULL;
ppf=NULL;
m_pWAVDest=NULL;
}
HRESULT TMainFrame::GetInterfaces()
{
HRESULT hr; // Create the filter graph
hr = CoCreateInstance (CLSID_FilterGraph, NULL, CLSCTX_INPROC,
IID_IGraphBuilder, (void **) &m_pGB);
if (FAILED(hr))
return hr; // Create the capture graph builder
hr = CoCreateInstance (CLSID_CaptureGraphBuilder2 , NULL, CLSCTX_INPROC,
IID_ICaptureGraphBuilder2, (void **) &m_pCapture);
if (FAILED(hr))
return hr;
// Obtain interfaces for media control and Video Window
if(FAILED(hr = m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC)))
return hr;
if(FAILED(hr = m_pGB->QueryInterface(IID_IMediaEventEx, (void **)&m_pME)))
return hr; // Have the graph signal events via window callbacks
hr = m_pME->SetNotifyWindow((OAHWND)MainFrame->Handle, WM_GRAPHNOTIFY, RECORD_EVENT); return hr;
}
HRESULT TMainFrame::GetCaptureDevice(IBaseFilter **ppSrcFilter)
{
HRESULT hr;
IBaseFilter * pSrc = NULL; // Create the system device enumerator
ICreateDevEnum *pDevEnum =NULL;
hr = CoCreateInstance (CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
IID_ICreateDevEnum, (void ** ) &pDevEnum);
if (FAILED(hr))
{
return hr;
} // Create an enumerator for the audio capture devices
IEnumMoniker *pClassEnum = NULL;
hr = pDevEnum->CreateClassEnumerator (CLSID_AudioInputDeviceCategory, &pClassEnum, 0);
pDevEnum->Release();
if (FAILED(hr))
{
return hr;
} // If there are no enumerators for the requested type, then
// CreateClassEnumerator will succeed, but pClassEnum will be NULL.
if (pClassEnum == NULL)
{
return E_FAIL;
} // Use the first video capture device on the device list.
// Note that if the Next() call succeeds but there are no monikers,
// it will return S_FALSE (which is not a failure). Therefore, we
// check that the return code is S_OK instead of using SUCCEEDED() macro.
IMoniker *pMoniker =NULL;
ULONG cFetched;
if (S_OK == (pClassEnum->Next (1, &pMoniker, &cFetched)))
{
// Bind Moniker to a filter object
hr = pMoniker->BindToObject(0,0,IID_IBaseFilter, (void**)&pSrc);
if (FAILED(hr))
{
pClassEnum->Release();
pMoniker->Release();
return hr;
}
}
else
{
pClassEnum->Release();
return E_FAIL;
} // Copy the found filter pointer to the output parameter.
// Do NOT Release() the reference, since it will still be used
// by the calling function.
*ppSrcFilter = pSrc;
pClassEnum->Release();
pMoniker->Release();
return hr;
} HRESULT TMainFrame::GetMP3EncoderFilter(IBaseFilter **ppSrcFilter)
{
HRESULT hr = E_FAIL;
WideString encoderName("MPEG Layer-3");
IBaseFilter *pFilter = NULL;
// Create the System Device Enumerator.
ICreateDevEnum *pDevEnum =NULL;
hr = CoCreateInstance (CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
IID_ICreateDevEnum, (void ** ) &pDevEnum);
if (FAILED(hr))
{
return hr;
} // Obtain a class enumerator for the Audio compressor category.
IEnumMoniker *pClassEnum = NULL;
hr = pDevEnum->CreateClassEnumerator (CLSID_AudioCompressorCategory, &pClassEnum, 0);
pDevEnum->Release();
if (FAILED(hr))
{
return hr;
}
// Enumerate the monikers.
IMoniker *pMoniker = NULL;
ULONG cFetched; while(pClassEnum->Next(1, &pMoniker, &cFetched) == S_OK)
{
IPropertyBag *pProp=NULL;
pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pProp);
VARIANT varName;
VariantInit(&varName); // Try to match the friendly name.
hr = pProp->Read(L"FriendlyName", &varName, 0);
if (SUCCEEDED(hr) && (wcscmp(encoderName, varName.bstrVal) == 0))
{
hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pFilter);
break;
}
VariantClear(&varName);
pMoniker->Release(); // Release for the next loop.
if(pProp)pProp->Release();
}
*ppSrcFilter = pFilter; return hr;
} HRESULT TMainFrame::BuildCaptureGraph()
{
SetDefaults();
HRESULT hr=GetInterfaces();
if(FAILED(hr))
return hr; hr = m_pCapture->SetFiltergraph(m_pGB);
if (FAILED(hr))
{
return hr;
}
hr = GetCaptureDevice(&m_pInputDevice);
if (FAILED(hr))
{
// Don't display a message because FindCaptureDevice will handle it
return hr;
} hr = m_pGB->AddFilter(m_pInputDevice, L"Audio Capture");
if (FAILED(hr))
{
m_pInputDevice->Release();
return hr;
} //Build the File-Writing Section
hr = m_pCapture->SetOutputFileName(&MEDIASUBTYPE_Avi,
L"C:\\Example.mp3", &ppf, NULL);
if(FAILED(hr))
{
return hr;
} hr = GetMP3EncoderFilter(&pAudioEncoder);
if (FAILED(hr))
{
return hr;
} hr = m_pGB->AddFilter(pAudioEncoder, L"Audio Encoder");
if (FAILED(hr))
{
return hr;
} hr = CoCreateInstance(CLSID_WavDest, NULL, CLSCTX_INPROC,
IID_IBaseFilter, (void **)&m_pWAVDest);
if (FAILED(hr))
{
return hr;
}
hr = m_pGB->AddFilter(m_pWAVDest, L"WAV Dest");
if (FAILED(hr))
return hr; // Render streams.
hr = m_pCapture->RenderStream(
&PIN_CATEGORY_CAPTURE, // Pin category
&MEDIATYPE_Audio, // Media type
m_pInputDevice, // Capture filter
pAudioEncoder, // Compression filter (optional)
ppf // Multiplexer or renderer filter
);
return hr;
}
void __fastcall TMainFrame::FreeCapture()
{
if (m_pME)
m_pME->SetNotifyWindow((OAHWND)NULL, 0, 0); SAFE_RELEASE(m_pMC);
SAFE_RELEASE(m_pME);
SAFE_RELEASE(m_pInputDevice);
SAFE_RELEASE(m_pGB);
SAFE_RELEASE(m_pCapture);
SAFE_RELEASE(ppf);
SAFE_RELEASE(pAudioEncoder);
SAFE_RELEASE(m_pWAVDest);
}
void __fastcall TMainFrame::FormClose(TObject *Sender,
TCloseAction &Action)
{
FreeCapture();
CoUninitialize();
}
//---------------------------------------------------------------------------
void __fastcall TMainFrame::btnStopClick(TObject *Sender)
{
if (m_pMC)
m_pMC->StopWhenReady();
btnRecord->Enabled =true;
}
//--------------------------------------------------------------------------- void __fastcall TMainFrame::btnRecordClick(TObject *Sender)
{
m_pMC->Run();
btnRecord->Enabled =false;
}
//--------------------------------------------------------------------------- void __fastcall TMainFrame::btnPauseClick(TObject *Sender)
{
m_pMC->Pause() ;
btnContinue->Enabled =true;
btnPause->Enabled =false;
}
//--------------------------------------------------------------------------- void __fastcall TMainFrame::btnContinueClick(TObject *Sender)
{
m_pMC->Run();
btnContinue->Enabled =false;
btnPause->Enabled =true;
}
//---------------------------------------------------------------------------