我正在使用windows media foundation api来枚举我的麦克风和可用的相机,两者都有效。
这是我的枚举代码:
class deviceInput {
public:
deviceInput( REFGUID source );
~deviceInput();
int listDevices(bool refresh = false);
IMFActivate *getDevice(unsigned int deviceId);
const WCHAR *getDeviceName(unsigned int deviceId);
private:
void Clear();
HRESULT EnumerateDevices();
UINT32 m_count;
IMFActivate **m_devices;
REFGUID m_source;
};
deviceInput::deviceInput( REFGUID source )
: m_devices( NULL )
, m_count( 0 )
, m_source( source )
{ }
deviceInput::~deviceInput()
{
Clear();
}
int deviceInput::listDevices(bool refresh)
{
if ( refresh || !m_devices ) {
if ( FAILED(this->EnumerateDevices()) ) return -1;
}
return m_count;
}
IMFActivate *deviceInput::getDevice(unsigned int deviceId)
{
if ( deviceId >= m_count ) return NULL;
IMFActivate *device = m_devices[deviceId];
device->AddRef();
return device;
}
const WCHAR *deviceInput::getDeviceName(unsigned int deviceId)
{
if ( deviceId >= m_count ) return NULL;
HRESULT hr = S_OK;
WCHAR *devName = NULL;
UINT32 length;
hr = m_devices[deviceId]->GetAllocatedString( MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, &devName, &length );
if ( FAILED(hr) ) return NULL;
return devName;
}
void deviceInput::Clear()
{
if ( m_devices ) {
for (UINT32 i = 0; i < m_count; i++) SafeRelease( &m_devices[i] );
CoTaskMemFree( m_devices );
}
m_devices = NULL;
m_count = 0;
}
HRESULT deviceInput::EnumerateDevices()
{
HRESULT hr = S_OK;
IMFAttributes *pAttributes = NULL;
Clear();
hr = MFCreateAttributes(&pAttributes, 1);
if ( SUCCEEDED(hr) ) hr = pAttributes->SetGUID( MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, m_source );
if ( SUCCEEDED(hr) ) hr = MFEnumDeviceSources( pAttributes, &m_devices, &m_count );
SafeRelease( &pAttributes );
return hr;
}
要抓取音频或相机捕捉设备,我指定MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID
或MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
,这没有问题,我可以获取设备的名称,以及IMFActivate。我有代码将网络摄像头录制到输出视频文件,但是,我很难搞清楚如何将音频录制到文件中。我的印象是我需要使用IMFSinkWriter,但我找不到任何使用音频捕获IMFActivate和IMFSinkWriter的示例。
我不是一个Windows api程序员,所以我确信这是一个相当直接的答案,但COM的东西只是我的头脑。至于音频格式,我并不在乎,只要它进入一个文件 - 可以是wav,wma或其他什么。即使我正在录制视频,我也需要将视频和音频文件分开,所以我不能弄清楚如何将音频添加到我的视频编码中。
答案 0 :(得分:7)
我为迟到的回应道歉,我希望你仍然能找到这个有价值的回复。我最近完成了一个类似于你的项目(将网络摄像头视频和选定的麦克风录制到带有音频的单个视频文件中)。关键是要创建一个聚合媒体源。
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd388085(v=vs.85).aspx
HRESULT CreateAggregateMediaSource(IMFMediaSource *videoSource, IMFMediaSource *audioSource, IMFMediaSource **aggregateSource)
{
*aggregateSource = NULL;
IMFCollection *pCollection = NULL;
HRESULT hr = MFCreateCollection(&pCollection);
if (SUCCEEDED(hr))
hr = pCollection->AddElement(videoSource);
if (SUCCEEDED(hr))
hr = pCollection->AddElement(audioSource);
if (SUCCEEDED(hr))
hr = MFCreateAggregateSource(pCollection, aggregateSource);
SafeRelease(&pCollection);
return hr;
}
配置接收器编写器时,您将添加2个流(一个用于音频,一个用于视频)。 当然,您还将为输入流类型正确配置编写器。
HRESULT hr = S_OK;
IMFMediaType *videoInputType = NULL;
IMFMediaType *videoOutputType = NULL;
DWORD videoOutStreamIndex = 0;
DWORD audioOutStreamIndex = 0;
IMFSinkWriter *writer = NULL;
// [other create and configure writer]
if (SUCCEEDED(hr))
hr = writer->AddStream(videoOutputType, &videoOutStreamIndex);
// [more configuration code]
if (SUCCEEDED(hr))
hr = writer->AddStream(audioOutputType, &audioOutStreamIndex);
然后在阅读样本时,您需要密切关注阅读器streamIndex,并将它们发送给作者。您还需要密切关注编解码器所期望的格式。例如,IEEE浮动与PCM等等。祝你好运,我希望不要迟到。
答案 1 :(得分:0)
您是否很难在Record directshow audio device to file中管理DirectShow音频捕获?
使用Media Foundation进行捕捉并不简单。甚至没有提到一般在DirectShow上有更多的资源....
MSDN为您提供WavSink Sample,将音频捕获实现到文件中:
显示如何在Microsoft Media Foundation中实现自定义媒体接收器。该示例实现了一个归档接收器,可将未压缩的PCM音频写入.wav文件。
我不确定为什么他们决定不把它作为标准组件。 Media Media在许多方面都不如DirectShow,他们至少可以把这个小东西作为一个优势。无论如何,你有样品,它看起来是一个良好的开端。