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.

Я не большой программист Windows API, так что я уверен, что есть довольно прямой ответ, но COM-вещи просто немного над моей головой. Что касается аудио формата, то мне все равно, если он попадает в файл — может быть wav, wma или что-то еще. Несмотря на то, что я записываю видео, мне нужны отдельные видео и аудио файлы, поэтому я не могу просто понять, как добавить звук в кодировку видео.

5

Решение

Я прошу прощения за поздний ответ, и я надеюсь, что вы все еще можете найти это ценным. Недавно я завершил проект, похожий на ваш (запись видео с веб-камеры вместе с выбранным микрофоном в один видеофайл со звуком). Ключ заключается в создании совокупного источника медиа.

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

Затем при чтении примеров вам нужно будет внимательно следить за читателем streamIndex и соответствующим образом отправлять их автору. Вам также необходимо обратить пристальное внимание на формат, который ожидает кодек. Например, IEEE float против PCM и т. Д. Удачи, и я надеюсь, что еще не поздно.

7

Другие решения

У вас были трудности с управлением записью звука DirectShow в Запись направляет аудиоустройство в файл?

Захватить с Media Foundation вряд ли проще. Даже не говоря о том, что в целом на DirectShow гораздо больше ресурсов ….

MSDN предлагает вам WavSink Sample который реализует захват звука в файл:

Показывает, как реализовать пользовательский приемник мультимедиа в Microsoft Media Foundation. В этом примере реализован приемник архива, который записывает несжатый звук PCM в файл .wav.

Я не уверен, почему они решили не делать это стандартным компонентом. Имея Media Foundation во многом уступая DirectShow, они могли бы, по крайней мере, сделать эту маленькую вещь преимуществом. Во всяком случае, у вас есть образец, и это выглядит как хорошее начало.

0

По вопросам рекламы [email protected]