Injecting raw audio data into media pipeline (Russian)

I am reposting a Q+A from elsewhere on injecting raw audio data obtained externally into Windows API media pipeline (in Russian).


Q: … какой самый простой способ превратить порции байтов в формате PCM в сжатый формат, например WMA используя только средства Windows SDK? […] я так понял, что без написания своего фильтра DirectShow (DS) – source или capture? – поток байтов не сконвертировать. В случае же Media Foundation (MF) я надеялся найти пример в инете, но почему-то есть хороший пример записи loopback в WAV файл или конвертации из WAV в WMA, но использование промежуточного файла очень неэффективно, тем более что следующей задачей будет потоковая передача этого звука по сети параллельно с записью в файл. Сейчас я пытаюсь разобраться с IMFTransform::ProcessInput, но он требует на вход не байты, а IMFSample, а конкретных примеров затащить байты в IMFSample я пока не нашёл. Просто у меня сложилось впечатление, что и DS и MF для такой, казалось бы, простой задачи требуют создания COM-объектов да ещё и их регистрацию в системе. Неужто нет более простого способа?

A: Готового решения для вталкивания данных в тракт DS или MF нет. Сделать самостоятельно необходимую стыковку – довольно посильная задача и поэтому, видимо, Microsoft устранились в предоставлении готового решения, которое всё равно не каждому подойдёт по разным причинам.

Аудиопоток – это всегда не только поток байтов, но и формат, и привязка ко времени, а поэтому те компоненты, которые работают с байтами, обычно оперируют мультиплексированными форматами (типа .WAV, к примеру). Раз у вас именно порции PCM данных, то это задача для, действительно, или custom DirectShow source filter, или custom Media Foundation media/stream source. Их реализация даст вам необходимую склейку и, вообще говоря, это и есть простой способ. В частности, он куда проще, чем попытаться сделать это через файл.

Ни в случае DS, ни в случае MF не требуется регистрация в системе. Можно, конечно, и с ней, но это необязательно. Когда у вас реализован необходимый класс, то собирая топологию его можно использовать непосредственно, без включения в топологию через системную регистрацию.

В случае DS вам нужно сделать собственный audio source filter. Сложная часть задачи заключается в том, что вам придётся опереться на довольно старый code base (DirectShow base classes) и в том, что, как бы там ни было, DirectShow API – в конце своего жизненного пути. Тем не менее, в старых SDK есть пример Synth Filter Sample, есть еще пример Ball Filter Sample для видео и другие, которые показывают как сделать source filter и, честно говоря, они довольно компактны. Необходимый вам фильтр будет достаточно простым, когда вы разберётесь что к чему. по использованию фильтра без регистрации вы также сможете найти информацию, к примеру, отсюда Using a DirectShow filter without registering it, via a private CoCreateInstance.

В случае MF, ситуация в какой-то мере схожая. Можно было бы, конечно, формировать в памяти поток формата .WAV и передавать его в топологию MF как поток байтов. Такая возможность и гибкость API имеется, но я бы посоветовал также использовать собственный media source который генерирует поток данных PCM из тех кусков, которые вы в него подкладываете. К преимуществам MF относится то, что это более новое и текущее API, у которого шире охват на современных платформах. Возможно, также, что необходимый код вы сможете сделать на C#, если опять же в этом есть нужда. Плохие новости заключаются в том, что по своей структуре такой COM класс будет определенно сложнее и понадобится чуть глубже копнуть API. Информации и примеров немного, и кроме этого сам MF едва ли предлагает лучшие и/или более понятные возможности по стандартным кодекам, возможности отправлять данные в файл и сеть, по инструментам разработки. Ближайший пример из SDK, будет, видимо, MPEG1Source Sample и, как мне кажется, в нём непросто сходу разобраться.

Если у вас нет конкретных предпочтений в плане API, то для этой задачи и с учётом описанной вами ситуации я бы предложил DirectShow. Однако если помимо описанного вопроса у вас есть причины, ограничения, основания по которым необходимо использовать Media Foundation, то в таком случае, возможно, будет предпочтительнее разрабатывать и обработку аудио данных в рамках этого API. Вместе с тем создание источников данных для обоих API, как я написал сначала, являются вполне посильной задачей и будут работать надёжно и эффективно.

Leave a Reply