2012-10-16 5 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_GUID 또는 MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID을 지정하고 그 문제를 작동하지 않습니다, 나는 장치의 이름을 잡아뿐만 아니라 수 있습니다 여기에

내 열거 코드 IMFActivate. 웹캠을 출력 비디오 파일에 기록하는 코드가 있지만 오디오를 파일에 기록하는 방법을 파악하는 데 어려움을 겪고 있습니다. IMFSinkWriter를 사용해야한다는 인상하에 있지만, 오디오 캡처 IMFActivate 및 IMFSinkWriter를 사용하는 예제를 찾을 수 없습니다.

나는 윈도우 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; 
} 

싱크 작성기를 구성 할 때 두 개의 스트림 (오디오 용과 비디오 용)이 추가됩니다. 물론 입력 스트림 유형에 맞게 작성기를 올바르게 구성 할 수도 있습니다.

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 float vs PCM 등 행운을 빌며, 늦지 않기를 바랍니다.

+0

저는 그 프로젝트를 작업 한 이후로 오랜 시간이 걸렸습니다. 그리고 그 프로젝트는 다른 방향으로 가져간 다른 사람들에 의해 인계되었습니다. 그럼에도 불구하고 예제 코드를 사용하여 명확한 답변을 주셔서 감사합니다. 많은 도움이됩니다. 다른 누군가가 매우 유용 할 것입니다. :) – OzBarry

0

Record directshow audio device to file에서 DirectShow 오디오 캡처를 관리하는 데 어려움이 있습니까?

Media Foundation으로 캡처하는 것이 더 간단합니다.

가 표시하는 방법을 사용자 정의 미디어 싱크를 구현하는 방법 : 심지어

MSDN 당신에게 파일로 오디오 캡처를 구현하는 WavSink Sample을 제공합니다 .... 일반적으로 거기에 다이렉트에 더 많은 자원이 있다는 것을 언급하지 않음 Microsoft 미디어 재단 샘플에서는 압축되지 않은 PCM 오디오를 .wav 파일에 기록하는 보관 싱크를 구현합니다.

나는 왜 이것이 표준 구성 요소가되지 않기로 결정했는지 확신 할 수 없습니다. DirectShow에 비해 Media Foundation이 여러 가지면에서 열세를 보임에 따라이 작은 것이 장점으로 작용할 수 있습니다. 어쨌든, 샘플을 가지고 있고 좋은 시작처럼 보입니다.

+0

예, WavSink 예제를 확인했습니다. 문제는 실제로 트랜스 코더입니다. pcm 오디오 파일을 * .wav 파일로 변환하므로 장치에서 직접 오디오 데이터를 실제로 가져 오는 방법을 알 수 없습니다. 나는 directshow를 사용하고 있었지만, 내 상사가 미디어 재단을 사용하여 나를 격려했다. – OzBarry

+0

어쨌든 가장 중요한 부분을 제공합니다.예, 트랜스 코딩하지 않는 토폴로지를 만들 필요가 있지만 실제 오디오 캡처 장치를 사용해야합니다. –