Udostępnij za pośrednictwem


Asynchroniczne MFTs

W tym temacie opisano asynchroniczne przetwarzanie danych dla przekształceń programu Media Foundation (MFT).

Nuta

Ten temat dotyczy systemu Windows 7 lub nowszego.

 

Informacje o asynchronicznych interfejsach MFTs

Po wprowadzeniu funkcji MFTs w systemie Windows Vista interfejs API został zaprojektowany pod kątem synchronicznego przetwarzania danych. W tym modelu MFT zawsze czeka na uzyskanie danych wejściowych lub oczekuje na wygenerowanie danych wyjściowych.

Rozważ typowy dekoder wideo. Aby uzyskać zdekodowany ramkę, klient wywołuje IMFTransform::P rocessOutput. Jeśli dekoder ma wystarczającą ilość danych do dekodowania ramki, ProcessOutput bloki, podczas gdy MFT dekoduje ramkę. W przeciwnym razie ProcessOutput zwraca wartość MF_E_TRANSFORM_NEED_MORE_INPUT, wskazując, że klient powinien wywołać IMFTransform::P rocessInput.

Ten model działa dobrze, jeśli dekoder wykonuje wszystkie operacje dekodowania w jednym wątku. Załóżmy jednak, że dekoder używa kilku wątków do dekodowania ramek równolegle. Aby uzyskać najlepszą wydajność, dekoder powinien otrzymywać nowe dane wejściowe za każdym razem, gdy wątek dekodowania stanie się bezczynny. Jednak szybkość, z jaką wątki zakończą operacje dekodowania, nie będą dokładnie zgodne z wywołaniami klienta do ProcessInput i ProcessOutput, co powoduje oczekiwanie wątków na pracę.

W systemie Windows 7 wprowadzono oparte na zdarzeniach asynchroniczne przetwarzanie dla jednostek MFT. W tym modelu za każdym razem, gdy MFT potrzebuje danych wejściowych lub wyjściowych, wysyła zdarzenie do klienta.

Wymagania ogólne

W tym temacie opisano, jak asynchroniczne MFTs różnią się od synchronicznych MFT. Z wyjątkiem przypadków, w których wspomniano w tym temacie, dwa modele przetwarzania są takie same. (W szczególności negocjowanie formatu jest takie samo).

Asynchroniczny MFT musi zaimplementować następujące interfejsy:

Zdarzenia

Asynchroniczny MFT używa następujących zdarzeń do sygnalizatora stanu przetwarzania danych:

Zdarzenie Opis
METransformNeedInput Wysłane, gdy MFT może zaakceptować więcej danych wejściowych.
METransformHaveOutput Wysłane, gdy MFT ma dane wyjściowe.
METransformDrainComplete Wysłane po zakończeniu operacji opróżniania. Zobacz opróżnianie.
METransformMarker Wysyłane, gdy znacznik jest procesem. Zobacz Znaczniki.

 

Te zdarzenia są wysyłane poza pasmem. Ważne jest, aby zrozumieć różnicę między zdarzeniami poza pasmem i poza pasmem w kontekście MFT.

Oryginalny projekt MFT obsługuje zdarzenia w pasmie. Zdarzenie w pasmie zawiera informacje o strumieniu danych, takie jak informacje o zmianie formatu. Klient wysyła zdarzenia w pasmie do MFT, wywołując IMFTransform::P rocessEvent. MFT może wysyłać zdarzenia w pasmie z powrotem do klienta w metodzie ProcessOutput. (W szczególności zdarzenia są przekazywane w pEvents składowej struktury MFT_OUTPUT_DATA_BUFFER).

MFT wysyła zdarzenia poza pasmem za pośrednictwem interfejsu IMFMediaEventGenerator w następujący sposób:

  1. MFT implementuje interfejsIMFMediaEventGenerator, zgodnie z opisem w Media Event Generators.
  2. Klient wywołuje IUnknown::QueryInterface na platformie MFT dla interfejsu IMFMediaEventGenerator. Asynchroniczny MFT musi uwidocznić ten interfejs. Synchroniczne MFTs nie powinny uwidaczniać tego interfejsu.
  3. Klient wywołuje IMFMediaEventGenerator::BeginGetEvent i IMFMediaEventGenerator::EndGetEvent w celu odbierania zdarzeń poza pasmem z MFT.

ProcessInput

Metoda IMFTransform::P rocessInput jest modyfikowana w następujący sposób:

  1. Po uruchomieniu przesyłania strumieniowego klient wysyła komunikat MFT_MESSAGE_NOTIFY_START_OF_STREAM.
  2. Podczas przesyłania strumieniowego usługa MFT żąda danych, wysyłając zdarzenie METransformNeedInput. Dane zdarzenia to identyfikator strumienia.
  3. Dla każdego zdarzenia METransformNeedInput klient wywołuje ProcessInput dla określonego strumienia.
  4. Po zakończeniu przesyłania strumieniowego klient może wywołać ProcessMessage z komunikatem MFT_MESSAGE_NOTIFY_END_OF_STREAM.

Uwagi dotyczące implementacji:

ProcessOutput

Metoda IMFTransform::P rocessOutput jest modyfikowana w następujący sposób:

  1. Za każdym razem, gdy MFT ma dane wyjściowe, wysyła zdarzenie METransformHaveOutput.
  2. Dla każdego zdarzenia METransformHaveOutput klient wywołuje ProcessOutput.

Uwagi dotyczące implementacji:

  • Jeśli klient wywołuje ProcessOutput w dowolnym momencie, metoda zwraca E_UNEXPECTED.
  • Asynchroniczny MFT nigdy nie powinien zwracać MF_E_TRANSFORM_NEED_MORE_INPUT z metody ProcessOutput. Jeśli MFT wymaga większej ilości danych wejściowych, wysyła zdarzenie METransformNeedInput.

Opróżniania

Opróżnianie MFT powoduje, że MFT generuje tyle danych wyjściowych, ile może z dowolnego danych wejściowych, które zostały już wysłane. Opróżnianie asynchronicznego MFT działa w następujący sposób:

  1. Klient wysyła komunikat MFT_MESSAGE_COMMAND_DRAIN.
  2. MFT nadal wysyła METransformHaveOutput zdarzeń, dopóki nie ma więcej danych do przetworzenia. W tym czasie nie wysyła meTransformNeedInput zdarzeń.
  3. Po wysłaniu ostatniego zdarzenia METransformHaveOutput protokołu MFT wysyła zdarzenie METransformDrainComplete.

Po zakończeniu opróżniania MFT nie wysyła innego zdarzenia METransformNeedInput, dopóki nie otrzyma komunikatu MFT_MESSAGE_NOTIFY_START_OF_STREAM od klienta.

Spłukiwanie

Klient może opróżnić MFT, wysyłając komunikat MFT_MESSAGE_COMMAND_FLUSH. MFT odrzuca wszystkie próbki danych wejściowych i wyjściowych, które przechowuje.

MFT nie wysyła innego zdarzenia METransformNeedInput, dopóki nie otrzyma komunikatu MFT_MESSAGE_NOTIFY_START_OF_STREAM od klienta.

Znaczniki

Klient może oznaczyć punkt w strumieniu, wysyłając komunikat MFT_MESSAGE_COMMAND_MARKER. MFT odpowiada w następujący sposób:

  1. Narzędzie MFT generuje dowolną liczbę przykładów wyjściowych, jak to możliwe z istniejących danych wejściowych, wysyłając zdarzenie METransformHaveOutput dla każdego przykładu wyjściowego.
  2. Po wygenerowaniu wszystkich danych wyjściowych usługa MFT wysyła zdarzenie METransformMarker. To zdarzenie musi zostać wysłane po wszystkich zdarzeniach METransformHaveOutput.

Załóżmy na przykład, że dekoder ma wystarczającą ilość danych wejściowych, aby wygenerować cztery próbki wyjściowe. Jeśli klient wyśle komunikat MFT_MESSAGE_COMMAND_MARKER, MFT będzie w kolejce cztery METransformHaveOutput zdarzeń (jeden na przykład danych wyjściowych), a następnie zdarzenie METransformMarker.

Komunikat znacznika jest podobny do komunikatu opróżniania. Jednak opróżnianie jest uznawane za przerwę w strumieniu, podczas gdy znacznik nie jest. Opróżnianie i znaczniki mają następujące różnice.

Opróżniania:

  • Podczas opróżniania, MFT nie wysyła METransformNeedInput zdarzeń.
  • Rozwiązanie MFT odrzuca wszystkie dane wejściowe, których nie można użyć do utworzenia przykładu danych wyjściowych.
  • Niektóre MFTs tworzą "ogon" na końcu danych. Na przykład efekty dźwiękowe, takie jak odgłos lub echo, generują dodatkowe dane po zatrzymaniu danych wejściowych. MFT, który generuje ogon, powinien to zrobić na końcu operacji opróżniania.
  • Po zakończeniu opróżniania MFT oznacza następny przykład danych wyjściowych za pomocą atrybutu MFSampleExtension_Discontinuity, aby wskazać przerwanie w strumieniu.

Marker:

  • Przed wysłaniem zdarzenia znacznika MFT nadal wysyła METransformNeedInput zdarzenia.
  • MFT nie odrzuca żadnych danych wejściowych. Jeśli istnieją dane częściowe, powinny być przetwarzane po punkcie znacznika.
  • MFT nie tworzy ogona w punkcie znacznika.
  • MFT nie ustawia flagi przerwania po punkcie znacznika.

Formatowanie zmian

Asynchroniczna funkcja MFT musi obsługiwać zmiany formatu dynamicznego zgodnie z opisem w Obsługa zmian strumienia.

Atrybuty

Asynchroniczny MFT musi zaimplementować metodę IMFTransform::GetAttributes, aby zwrócić prawidłowy magazyn atrybutów. Następujące atrybuty mają zastosowanie do asynchronicznych jednostek MFTs:

Atrybut Opis
MF_TRANSFORM_ASYNC MFT musi ustawić ten atrybut na wartość true (1). Klient może wysłać zapytanie do tego atrybutu, aby dowiedzieć się, czy MFT jest asynchroniczna.
MF_TRANSFORM_ASYNC_UNLOCK
MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE MFT musi ustawić ten atrybut na wartość true (1). Klient może założyć, że ten atrybut jest ustawiony.

 

Odblokowywanie asynchronicznych jednostek MFT

Asynchroniczne MFTs nie są zgodne z oryginalnym modelem przetwarzania danych MFT. Aby zapobiec przerywaniu działania istniejących aplikacji asynchronicznych, zdefiniowany jest następujący mechanizm:

Klient wywołuje IMFTransform::GetAttributes na platformie MFT. Klient wysyła zapytanie do tego atrybutu MF_TRANSFORM_ASYNC. W przypadku asynchronicznego protokołu MFT wartość tego atrybutu to **TRUE**. Aby odblokować MFT, klient musi ustawiać atrybut MF_TRANSFORM_ASYNC_UNLOCK na **TRUE**.

Dopóki klient nie odblokuje protokołu MFT, wszystkie metody IMFTransform powinny zwrócić MF_E_TRANSFORM_ASYNC_LOCKED, z następującymi wyjątkami:

Poniższy kod pokazuje, jak odblokować asynchroniczny MFT:

HRESULT UnlockAsyncMFT(IMFTransform *pMFT)
{
    IMFAttributes *pAttributes = NULL;

    HRESULT hr = hr = pMFT->GetAttributes(&pAttributes);

    if (SUCCEEDED(hr))
    {
        hr = pAttributes->SetUINT32(MF_TRANSFORM_ASYNC_UNLOCK, TRUE);
        pAttributes->Release();
    }
    
    return hr;
}

Zamykanie MFT

Asynchroniczne MFTs muszą zaimplementować interfejs IMFShutdown.

  • zamknij: MFT musi zamknąć kolejkę zdarzeń. Jeśli używasz standardowej kolejki zdarzeń, wywołaj metodę IMFMediaEventQueue::Shutdown. Opcjonalnie rozwiązanie MFT może zwolnić inne zasoby. Klient nie może używać protokołu MFT po wywołaniu Shutdown.
  • GetShutdownStatus: po wywołaniu shutdown protokół MFT powinien zwrócić wartość MFSHUTDOWN_COMPLETED w parametrze pStatus. Nie powinna zwracać wartości MFSHUTDOWN_INITIATED.

Rejestracja i wyliczenie

Aby zarejestrować asynchroniczny MFT, wywołaj funkcję MFTRegister i ustaw flagę MFT_ENUM_FLAG_ASYNCMFT w parametrze flagi. (Wcześniej ta flaga była zarezerwowana).

Aby wyliczyć asynchroniczne MFTs, wywołaj funkcję MFTEnumEx i ustaw flagę MFT_ENUM_FLAG_ASYNCMFT w parametrze Flags. W przypadku zgodności z poprzednimi wersjami funkcjaMFTEnumnie wylicza asynchronicznych numerów MFTs. W przeciwnym razie zainstalowanie asynchronicznego MFT na komputerze użytkownika może spowodować przerwanie istniejących aplikacji.

przekształcenia Media Foundation