2012-10-16 88 views
5

私はWindows Media Foundation APIを使用して、マイクと使用可能なカメラの両方を列挙しています。どちらも動作します。ここでWindows Media Foundationの録音オーディオ

は私の列挙コードです:

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、その他何でもかまいません。私はビデオを録音していますが、ビデオとオーディオファイルを別々にする必要があります。そのため、ビデオエンコーディングにオーディオを追加する方法を理解できません。

答えて

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

サンプルを読み込むときは、readerのstreamIndexに細心の注意を払い、ライターに適切に送信する必要があります。コーデックが期待する形式にも細心の注意を払う必要があります。例えば、IEEE floatとPCMの違いなど。幸運にも、遅くないことを願っています。

+0

私はそのプロジェクトに取り組んでからずっとずっと時間がかかりました。それ以来、それは別の方向にそれを取った何人かの人々によって引き継がれました。それにかかわらず、サンプルコードの明確な答えをいただきありがとうございます。それは非常に高く評価されています。 – OzBarry

0

Record directshow audio device to fileでDirectShowのオーディオキャプチャを管理するのに苦労しましたか?

Media Foundationでキャプチャするのは簡単ではありません。

の方法を示しカスタムメディアシンクを実装する方法:でも

MSDNはあなたのファイルにオーディオキャプチャを実装WavSink Sampleを提供しています....一般的にはそこDirectShowの上の多くのリソースがあることを言及していませんMicrosoft Media Foundationにあります。サンプルでは、​​圧縮されていないPCMオーディオを.wavファイルに書き込むアーカイブシンクが実装されています。

私はなぜこれを標準コンポーネントにしないと決めるのか分かりません。 Media FoundationはDirectShowよりも多くの点で劣っているため、少なくともこの小さなことを利点にすることができます。とにかく、サンプルがあり、それは良いスタートのように見えます。

+0

ええ、私はWavSinkの例に気付きました。実際にはトランスコーダの問題です。 pcmのオーディオファイルが* .wavファイルに変換されるため、実際にデバイスから直接オーディオデータを取得する方法はわかりません。 私はdirectshowを使用していましたが、私の上司はメディア基盤の使用を強く勧めました。 – OzBarry

+0

それはあなたに最も重要な部分を与えます。はい、トポロジをトランスコードしないで、実際のオーディオキャプチャデバイスを使用する必要があります。 –

関連する問題