Как сделать так, чтобы пользовательские медиа / потоковые потоки запрашивали кадры RGB32 в основании мультимедиа? - PullRequest
0 голосов
/ 06 сентября 2018

Я пытаюсь создать пользовательский приемник мультимедиа для воспроизведения видео в приложении OpenGL (без различных WGL_NV_DX_INTEROP, поскольку я не уверен, что все мои целевые устройства поддерживают это).

На данный момент я написал собственный потоковый приемник, который принимает RGB32 сэмплов и настраивает воспроизведение с сеансом мультимедиа, однако я столкнулся с проблемой при первоначальном тестировании воспроизведения файла mp4:

  • один (или более) из MFT с в сгенерированной топологии продолжают сбой с кодом ошибки MF_E_TRANSFORM_NEED_MORE_INPUT , поэтому мой приемник потока никогда не получает выборки
  • После того, как было запрошено несколько образцов, медиа-сессия получает событие MF_E_ATTRIBUTENOTFOUND , но я до сих пор не знаю, откуда оно

Если, однако, я сконфигурирую приемник потока для получения NV12 семплов, похоже, все работает нормально.

Мое лучшее предположение, что преобразователь цвета MFT, сгенерированный TopologyLoader, нуждается в некоторой дополнительной настройке, но я не знаю, как это сделать, учитывая, что мне нужно сохранить весь этот процесс независимым от исходных типов файлов.

1 Ответ

0 голосов
/ 09 сентября 2018

Я сделал минимальный тестовый пример, который демонстрирует использование пользовательского видео рендерера с классической медиа-сессией.

Я использую big_buck_bunny_720p_50mb.mp4 и не вижу проблем с использованием формата RGB32.

Пример кода здесь: https://github.com/mofo7777/Stackoverflow под MinimalSinkRenderer.

EDIT

Ваша программа хорошо работает с big_buck_bunny_720p_50mb.mp4. Я думаю, что ваш файл mp4 является проблемой. Поделись, если сможешь.

Я только что внес несколько изменений:

Вы останавливаетесь на MESessionEnded и закрываетесь на MESessionStopped.

case MediaEventType.MESessionEnded:
    Debug.WriteLine("MediaSession:SesssionEndedEvent");
    hr = mediaSession.Stop();
    break;
case MediaEventType.MESessionClosed:
    Debug.WriteLine("MediaSession:SessionClosedEvent");
    receiveSessionEvent = false;
    break;
case MediaEventType.MESessionStopped:
    Debug.WriteLine("MediaSession:SesssionStoppedEvent");
    hr = mediaSession.Close();
    break;
default:
    Debug.WriteLine("MediaSession:Event: " + eventType);
    break;

Добавление этого для ожидания звука и проверки сэмпла в порядке:

internal HResult ProcessSample(IMFSample s)
{
    //Debug.WriteLine("Received sample!");

    CurrentFrame++;

    if (s != null)
    {
        long llSampleTime = 0;
        HResult hr = s.GetSampleTime(out llSampleTime);

        if (hr == HResult.S_OK && ((CurrentFrame % 50) == 0))
        {
            TimeSpan ts = TimeSpan.FromMilliseconds(llSampleTime / (10000000 / 1000));
            Debug.WriteLine("Frame {0} : {1}", CurrentFrame.ToString(), ts.ToString());
        }

        // Do not call SafeRelease here, it is done by the caller, it is a parameter
        //SafeRelease(s);
    }

    System.Threading.Thread.Sleep(26);

    return HResult.S_OK;
}

В

public HResult SetPresentationClock(IMFPresentationClock pPresentationClock)

добавление

SafeRelease(PresentationClock);

до

if (pPresentationClock != null)
    PresentationClock = pPresentationClock;
...