簡體   English   中英

Windows Media Foundation 錄制音頻

[英]Windows Media Foundation recording audio

我正在使用 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_GUIDMF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID並且沒有問題,我可以獲取設備的名稱以及 IMFActivate。 我有將網絡攝像頭錄制到輸出視頻文件的代碼,但是,我很難弄清楚如何將音頻錄制到文件中。 我的印象是我需要使用 IMFSinkWriter,但我找不到任何使用音頻捕獲 IMFActivate 和 IMFSinkWriter 的示例。

我不是一個 Windows api 程序員,所以我確信有一個相當直接的答案,但 COM 的東西只是有點超出我的頭腦。 至於音頻格式,我並不在乎,只要它進入一個文件 - 可以是 wav、wma 或其他任何格式。 即使我正在錄制視頻,我也需要將視頻和音頻文件分開,所以我無法弄清楚如何將音頻添加到我的視頻編碼中。

對於遲到的回復,我深表歉意,我希望你仍然能發現這很有價值。 我最近完成了一個與您類似的項目(將網絡攝像頭視頻與選定的麥克風一起錄制到帶有音頻的單個視頻文件中)。 關鍵是創建聚合媒體源。

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

配置接收器編寫器時,您將添加 2 個流(一個用於音頻,一個用於視頻)。 當然,您還將為輸入流類型正確配置編寫器。

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

然后在閱讀樣本時,您將需要密切關注閱讀器streamIndex,並適當地將它們發送給編寫者。 您還需要密切注意編解碼器期望的格式。 例如,IEEE float vs PCM 等等。祝你好運,我希望現在還為時不晚。

您是否很難在將directshow 音頻設備錄制到文件中管理 DirectShow 音頻捕獲?

使用 Media Foundation 進行捕獲幾乎沒有任何簡單。 甚至沒有提到總的來說 DirectShow 上有更多的資源......

MSDN 為您提供了一個WavSink 示例,用於將音頻捕獲到文件中:

演示如何在 Microsoft Media Foundation 中實現自定義媒體接收器。 該示例實現了一個存檔接收器,它將未壓縮的 PCM 音頻寫入 .wav 文件。

我不確定他們為什么決定不將其作為標准組件。 Media Foundation在很多方面都不如DirectShow,他們至少可以把這個小東西當成優勢。 不管怎樣,你有樣品,它看起來是一個好的開始。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM