2012-10-16 7 views
5

Ich verwende die Windows Media Foundation API, um sowohl meine Mikrofone und verfügbaren Kameras aufzuzählen, die beide funktionieren.Windows Media Foundation Aufnahme Audio

Hier ist meine Aufzählung 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; 
} 

Audio- oder Kamera-Capture-Geräte zu packen, ich entweder MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID oder MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID angeben und das funktioniert kein Problem, und ich kann die Namen der Geräte, als auch greifen als das IMFActivate. Ich habe Code, um die Webcam zu einer Ausgangsvideodatei aufzuzeichnen, jedoch habe ich eine harte Zeit herauszufinden, wie man das Audio in eine Datei aufzeichnet. Ich habe den Eindruck, dass ich einen IMFSinkWriter verwenden muss, aber ich kann keine Beispiele finden, die ein Audio Capture IMFActivate und IMFSinkWriter verwenden.

Ich bin nicht viel von einem Windows-API-Programmierer, also bin ich mir sicher, es gibt eine ziemlich direkte Antwort, aber COM-Zeug ist nur ein bisschen über meinen Kopf. Was das Audioformat betrifft, ist mir das egal, solange es in eine Datei kommt - kann wav, wma oder was auch immer sein. Obwohl ich Videos aufnehme, brauche ich separate Video- und Audiodateien, damit ich nicht einfach herausfinden kann, wie ich das Audio in meine Videokodierung einfüge.

Antwort

7

Ich entschuldige mich für die späte Antwort, und ich hoffe, Sie können immer noch diese wertvolle finden. Ich habe kürzlich ein ähnliches Projekt abgeschlossen (Aufnahme eines Webcam-Videos zusammen mit einem ausgewählten Mikrofon in eine einzelne Videodatei mit Audio). Der Schlüssel ist das Erstellen einer aggregierten Medienquelle.

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

Wenn Sie den Sink Writer konfigurieren, fügen Sie zwei Streams hinzu (einen für Audio und einen für Video). Natürlich konfigurieren Sie den Writer auch korrekt für die Eingabe-Stream-Typen.

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

Dann, wenn die Proben zu lesen, müssen Sie besonderes Augenmerk auf die Leser streamIndex zu zahlen, und in geeigneter Weise sie an den Verfasser senden. Sie müssen auch genau auf das Format achten, das der Codec erwartet. Zum Beispiel, IEEE Float vs PCM, etc. Viel Glück, und ich hoffe, es ist nicht zu spät.

+0

Es ist lange her, seit ich an diesem Projekt arbeite, und es wurde seitdem von einigen anderen Leuten übernommen, die es in eine andere Richtung nahmen. Nichtsdestotrotz, danke für die klare Antwort mit dem Beispielcode, es ist sehr geschätzt, und vielleicht jemand anderes wird es sehr nützlich finden :) – OzBarry

0

Hatten Sie Schwierigkeiten, die DirectShow-Audioaufnahme in Record directshow audio device to file zu verwalten?

Das Erfassen mit Media Foundation ist kaum einfacher. Nicht einmal zu erwähnen, dass in der Regel gibt es viel mehr Ressourcen auf Directshow sind da draußen ....

MSDN bietet Ihnen eine WavSink Sample, die Audio-Aufnahme in die Datei implementiert:

Zeigt an, wie eine benutzerdefinierte Mediensenke implementieren in der Microsoft Media Foundation. Das Beispiel implementiert eine Archiv-Senke, die unkomprimiertes PCM-Audio in eine WAV-Datei schreibt.

Ich bin mir nicht sicher, warum sie beschlossen, dies nicht zu einer Standardkomponente zu machen. Da Media Foundation in vieler Hinsicht DirectShow unterlegen ist, könnten sie dieses kleine Ding zumindest als Vorteil darstellen. Wie auch immer, Sie haben die Probe und es sieht nach einem guten Start aus.

+0

Ja, ich habe das WavSink-Beispiel bemerkt, das Problem ist, dass es tatsächlich ein Transcoder ist; Es nimmt eine PCM-Audiodatei und konvertiert sie in eine * .wav-Datei, so dass es mir nicht wirklich sagt, wie man die Audiodaten direkt von einem Gerät bekommt. Ich benutzte DirectShow, aber mein Chef ermutigte mich stark (lesen Sie, wie mir gesagt wurde), Media Foundation zu verwenden. – OzBarry

+0

Es gibt Ihnen das wichtigste Stück sowieso.Ja, Sie müssen die Topologie nicht transkodieren, sondern ein echtes Audio-Capture-Gerät verwenden. –

Verwandte Themen