简体   繁体   English

Windows Media Foundation 录制音频

[英]Windows Media Foundation recording audio

I'm using the windows media foundation api to enumerate both my microphones and available cameras, which both work.我正在使用 windows media Foundation api 来枚举我的麦克风和可用的摄像头,它们都可以工作。

Here is my enumeration code:这是我的枚举代码:

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;
}

To grab audio or camera capture devices, I specify either MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID or MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID and that works no problem, and I can grab the names of the devices, as well as the IMFActivate.要获取音频或相机捕获设备,我指定MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUIDMF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID并且没有问题,我可以获取设备的名称以及 IMFActivate。 I have code to record the webcam to an output video file, however, I'm having a tough time figuring out how to record the audio to a file.我有将网络摄像头录制到输出视频文件的代码,但是,我很难弄清楚如何将音频录制到文件中。 I'm under the impression that I need to use an IMFSinkWriter, but I can't find any examples that use an audio capture IMFActivate and IMFSinkWriter.我的印象是我需要使用 IMFSinkWriter,但我找不到任何使用音频捕获 IMFActivate 和 IMFSinkWriter 的示例。

I'm not much of a windows api programmer, so I'm sure there's a fairly straight forward answer, but COM stuff is just a bit over my head.我不是一个 Windows api 程序员,所以我确信有一个相当直接的答案,但 COM 的东西只是有点超出我的头脑。 As far as audio format, I don't really care, as long as it gets into a file - can be wav, wma, or whatever.至于音频格式,我并不在乎,只要它进入一个文件 - 可以是 wav、wma 或其他任何格式。 Even though I'm recording video, I need the video and audio files separate, so I can't just figure out how to add the audio into my video encoding.即使我正在录制视频,我也需要将视频和音频文件分开,所以我无法弄清楚如何将音频添加到我的视频编码中。

I apologize for the late response, and I hope you can still find this valuable.对于迟到的回复,我深表歉意,我希望你仍然能发现这很有价值。 I recently completed a project similar to yours (recording webcam video along with a selected microphone to a single video file with audio).我最近完成了一个与您类似的项目(将网络摄像头视频与选定的麦克风一起录制到带有音频的单个视频文件中)。 The key is to creating an aggregate media source.关键是创建聚合媒体源。

// http://msdn.microsoft.com/en-us/library/windows/desktop/dd388085(v=vs.85).aspx
HRESULT CreateAggregateMediaSource(IMFMediaSource *videoSource,
                                   IMFMediaSource *audioSource,
                                   IMFMediaSource **aggregateSource)
{
    *aggregateSource = nullptr;
    IMFCollection *pCollection = nullptr;

    HRESULT hr = ::MFCreateCollection(&pCollection);

    if (S_OK == hr)
        hr = pCollection->AddElement(videoSource);

    if (S_OK == hr)
        hr = pCollection->AddElement(audioSource);

    if (S_OK == hr)
        hr = ::MFCreateAggregateSource(pCollection, aggregateSource);

    SafeRelease(&pCollection);
    return hr;
}

When configuring the sink writer, you will add 2 streams (one for audio and one for video).配置接收器编写器时,您将添加 2 个流(一个用于音频,一个用于视频)。 Of course, you will also configure the writer correctly for the input stream types.当然,您还将为输入流类型正确配置编写器。

HRESULT        hr                  = S_OK;
IMFMediaType  *videoInputType      = nullptr;
IMFMediaType  *videoOutputType     = nullptr;
DWORD          videoOutStreamIndex = 0u;
DWORD          audioOutStreamIndex = 0u;
IMFSinkWriter *writer              = nullptr;

// [other create and configure writer]

if (S_OK == hr))
    hr = writer->AddStream(videoOutputType, &videoOutStreamIndex);    

// [more configuration code]

if (S_OK == hr)
    hr = writer->AddStream(audioOutputType, &audioOutStreamIndex);

Then when reading the samples, you will need to pay close attention to the reader streamIndex, and sending them to the writer appropriately.然后在阅读样本时,您将需要密切关注阅读器streamIndex,并适当地将它们发送给编写者。 You will also need to pay close attention to the format that the codec expects.您还需要密切注意编解码器期望的格式。 For instance, IEEE float vs PCM, etc. Good luck, and I hope it is not too late.例如,IEEE float vs PCM 等等。祝你好运,我希望现在还为时不晚。

Did you have hard time to manage DirectShow audio capture in Record directshow audio device to file ?您是否很难在将directshow 音频设备录制到文件中管理 DirectShow 音频捕获?

Capturing with Media Foundation is hardly any simpler.使用 Media Foundation 进行捕获几乎没有任何简单。 Not even mentioning that in general there are a lot more resources on DirectShow out there....甚至没有提到总的来说 DirectShow 上有更多的资源......

MSDN offers you a WavSink Sample that implements audio capture into file: MSDN 为您提供了一个WavSink 示例,用于将音频捕获到文件中:

Shows how to implement a custom media sink in Microsoft Media Foundation.演示如何在 Microsoft Media Foundation 中实现自定义媒体接收器。 The sample implements an archive sink that writes uncompressed PCM audio to a .wav file.该示例实现了一个存档接收器,它将未压缩的 PCM 音频写入 .wav 文件。

I am not sure why they decided to not make this a standard component.我不确定他们为什么决定不将其作为标准组件。 Having Media Foundation inferior to DirectShow in many ways, they could at least make this small thing as an advantage. Media Foundation在很多方面都不如DirectShow,他们至少可以把这个小东西当成优势。 Anyway, you have the sample and it looks like a good start.不管怎样,你有样品,它看起来是一个好的开始。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM