Media Foundation — Проблемы с использованием aggregate media source с захватом аудио / видео

#video-capture #ms-media-foundation #audio-capture

#захват видео #ms-media-foundation #захват аудио

Вопрос:

Мне было поручено создать приложение, которое принимает вход для захвата аудио / видео (используя ссылку Elgato Cam) и выводит его обратно пользователю. Согласно документации Microsoft по захвату аудио / видео в Media Foundation, предлагается «Если вы хотите объединить захват аудио с захватом видео, используйте aggregate media source.«

Я извлек большую часть кода, который мне был нужен, из исходного кода topoedit, но topoedit нигде не использует aggregate sources, поэтому я несколько ослеплен, когда дело доходит до их правильного использования.

Я сталкиваюсь с двумя разными проблемами при использовании aggregate media source.

  1. Частота кадров
    У меня есть одно устройство захвата (Elgato Cam Link), которое успешно воспроизводит аудио и видео при использовании aggregate media source, но по какой-то причине частота кадров хуже, чем если бы я просто запускал две совершенно разные топологии (одну для видео, другую для аудио).

  2. Ошибка MF_E_TOPO_CODEC_NOT_FOUND (0xC00D5212) при вызове IMFTopoloader::Load()
    Когда я пытаюсь использовать aggregate media source на двух разных ноутбуках (используя любую встроенную веб-камеру / микрофон), я сталкиваюсь с этой ошибкой. Эта ошибка сбивает меня с толку, потому что она работает просто отлично, если я использую две совершенно разные топологии (одну для видео, другую для аудио).

Первичная настройка:

  • Операционная система: Windows 10
  • Устройство захвата: Elgato Cam Link (USB-накопитель с входом HDMI)
  • Язык: C

Просто чтобы заранее исключить некоторые предложения…

  • Просто используйте DirectShow!
    Я хотел бы, чтобы я мог. Единственная причина, по которой мне было поручено это сделать, заключается в том, что наше решение DirectShow имеет серьезные проблемы с частотой кадров для устройства Elgato Cam Link. Мы не смогли понять почему, поэтому Media Foundation показался нам лучшим выбором.

  • Используйте две отдельные топологии!
    Вот как у меня это работает в настоящее время. Это просто кажется неправильным, понимаете? В документации говорится об использовании aggregate source, поэтому я хотел проявить должную осмотрительность. В конце концов, если я не получу ответа на этот вопрос, я могу, по крайней мере, быть спокойным, зная, что у меня есть что-то функциональное, но я в основном задаю этот вопрос на случай, если я мог бы сделать что-то лучше. Skype должен делать что-то подобное, верно? (Если подумать, Skype не выводит ваш звук обратно из ваших собственных динамиков, так что, возможно, нет) Наверняка кто-нибудь знает, как использовать aggregate source.

Учитывая, что моя программа успешно работает с устройством Elgato, я подозреваю, что я не делаю ничего ужасно неправильного. Если есть проблема, она, вероятно, в коде, которого у меня нет, а не в чем-либо, что я мог бы показать.

С учетом сказанного, вот где я создаю aggregate source (исключая проверку ошибок для краткости).

 HRESULT GenerateAggregateSource(IMFMediaSource*amp; pAggSource, IMFMediaSource* pSource1, IMFMediaSource* pSource2)
{
    pAggSource = NULL;

    HRESULT hr = S_OK;

    IMFCollection* pSourceCollection = NULL;
    hr = ::MFCreateCollection(amp;pSourceCollection);

    hr = pSourceCollection->AddElement(pSource1);

    hr = pSourceCollection->AddElement(pSource2);

    hr = ::MFCreateAggregateSource(pSourceCollection, amp;pAggSource);
    pSourceCollection->Release();   // Done with this

    return hr;
}
  

и позже я подключаю EVR к дескриптору потока 0, а SAR — к дескриптору потока 1.

И здесь я вызываю IMFTopoloader::Load(), если вы больше заинтересованы в решении проблемы № 2 (опять же, исключая проверку ошибок для краткости).

 HRESULT ResolveTopology(IMFTopology*amp; pTopology, IMFMediaSession* pMediaSession)
{
    HRESULT hr = S_OK;

    IMFTopoLoader* pTopoLoader = NULL;
    hr = ::MFCreateTopoLoader(amp;pTopoLoader);

    IMFTopology* pFullTopology = NULL;
    hr = pTopoLoader->Load(pTopology, amp;pFullTopology, NULL);
    // Laptop webcams seem to encounter this error here
    //MF_E_TOPO_CODEC_NOT_FOUND

    hr = pMediaSession->SetTopology(MFSESSION_SETTOPOLOGY_IMMEDIATE, pFullTopology);

    // Swap the topology we're holding
    pTopology->Release();
    pTopology = pFullTopology;

    // Done with this
    pTopoLoader->Release();

    return hr;
}
  

Обновление с запрошенной топологией:

Вот грубый пример моей частичной топологии. Вероятно, это то, что вы ожидаете, поскольку я не пытаюсь сделать что-то необычное.

                  ⇗ EVR
Agg. Source (A/V)
                 ⇘ SAR
  

Как только я разрешу топологию, какие дополнительные материалы будут введены? Я не уверен, как пройти цепочку и запросить, что все есть в топологии на данный момент. Если вы доверяете тому, что topoedit делает с аудио- и видеоисточниками по отдельности, то это выглядит примерно так.

                  ⇗ {CF862982-23B0-4E3D-8C76-D03FEF084AF8} ⇒ EVR
Agg. Source (A/V)
                 ⇘ SAR
  

Что такое {CF862982-23B0-4E3D-8C76-D03FEF084AF8} ? Я не уверен, и я не уверен, как это выяснить.

Я обновлю вышеуказанную топологию, когда у меня снова будет доступ к Elgato. В настоящее время я им не владею.

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

Комментарии:

1. Я бы сказал, что aggregate source не может замедлить захват сам по себе. Проблема скорости, скорее всего, возникнет из-за того, что у вас есть видео и аудио в одной топологии с общими часами, а затем приемник или другой нижестоящий примитив регулирует обработку. Боюсь, виновата не агрегация.

2. Также было бы полезно знать, где именно DirectShow замедляет работу. Очевидно, что MF упрощает правильное использование аппаратного кодирования, а с DS это сложнее. Кроме этого, захват DS в целом выполняется так же быстро, как MF. Выявление узкого места DS — хорошая помощь, чтобы не иметь такого же в топологии MF.

3. На самом деле, первоначальная причина, по которой я хотел использовать aggregate source, заключалась в том, чтобы убедиться, что аудио и видео были должным образом синхронизированы. То, что вы сказали, в какой-то степени имеет смысл, но я не понимаю, почему что-то может регулировать обработку, когда a / v объединены в одной топологии, но работают лучше по отдельности. Я согласен, что было бы полезно узнать, что такое зависание в DirectShow, но я, конечно, не эксперт здесь. Если у вас есть какие-либо предложения о том, как я мог бы это сделать, это было бы очень полезно.

4. Возможно, вам следует включить свою топологию в вопрос. Я лично считаю, что это sink, который ограничивает вашу обработку, и с этой точки зрения стоит разобраться.

5. можете ли вы предоставить полный тип носителя из источника аудио и видео?