Udostępnij przez


Podstawowy model przetwarzania MFT

W tym temacie opisano sposób, w jaki klient przetwarza dane przy użyciu przekształcenia programu Media Foundation (MFT). Klient to wszystko, co bezpośrednio wywołuje metody na platformie MFT. Może to być aplikacja lub struktura przetwarzania Media Foundation.

Przeczytaj ten temat, jeśli jesteś:

  • Pisanie aplikacji, która wykonuje bezpośrednie wywołania do co najmniej jednego MFT.
  • Pisanie niestandardowego protokołu MFT i zrozumienie oczekiwanego zachowania protokołu MFT.

W tym temacie opisano model przetwarzania synchronicznego . W tym modelu wszystkie metody przetwarzania danych blokują się do momentu ich ukończenia. MFTs może również obsługiwać asynchroniczny model, który jest opisany w temacie Asynchroniczne MFTs.

Podstawowy model przetwarzania

Utwórz MFT

Istnieje kilka sposobów tworzenia MFT:

  • Wywołaj funkcję MFTEnum.
  • Wywołaj funkcję MFTEnumEx.
  • Jeśli znasz już identyfikator CLSID MFT, po prostu wywołaj CoCreateInstance.

Niektóre MFT mogą udostępniać inne opcje, takie jak wyspecjalizowana funkcja tworzenia.

Pobieranie identyfikatorów strumienia

MFT ma co najmniej jeden strumień . Strumienie wejściowe odbierają dane wejściowe, a strumienie wyjściowe generują dane wyjściowe. Strumienie nie są reprezentowane jako odrębne obiekty. Zamiast tego różne metody MFT przyjmują identyfikatory strumienia jako parametry.

Niektóre MFTs umożliwiają klientowi dodawanie lub usuwanie strumieni wejściowych. Podczas przesyłania strumieniowego platforma MFT może dodawać lub usuwać strumienie wyjściowe. (Klient nie może dodawać ani usuwać strumieni wyjściowych).

  1. (Opcjonalnie). Wywołaj IMFTransform::GetStreamLimits, aby uzyskać minimalną i maksymalną liczbę strumieni, które może obsługiwać MFT. Jeśli wartość minimalna i maksymalna są takie same, funkcja MFT ma stałą liczbę strumieni.
  2. Wywołaj IMFTransform::GetStreamCount, aby uzyskać początkową liczbę strumieni.
  3. Wywołaj IMFTransform::GetStreamIDs, aby pobrać identyfikatory strumienia. Jeśli ta metoda zwraca E_NOTIMPL, oznacza to, że MFT ma stałą liczbę strumieni, a identyfikatory strumieni są kolejne i zaczynają się od zera.
  4. (Opcjonalnie). Jeśli MFT nie ma stałej liczby strumieni, wywołaj IMFTransform::AddInputStreams, aby dodać więcej strumieni wejściowych lub IMFTransform::D eleteInputStream, aby usunąć strumienie wejściowe. (Nie można dodawać ani usuwać strumieni wyjściowych).

Ustawianie typów multimediów

Przed przetwarzaniem danych przez MFT, klient musi ustawić typy multimediów dla każdego strumienia MFT. MFT może wymagać, aby klient ustawił typy danych wejściowych przed ustawieniem typów danych wyjściowych lub może wymagać odwrotnej kolejności (najpierw typów danych wyjściowych). Niektóre MFT nie mają wymagań co do kolejności.

Rozwiązanie MFT może udostępnić listę preferowanych typów multimediów dla strumienia. Ponadto MFTs mogą wskazywać obsługiwane przez nie ogólne formaty, dodając te informacje do rejestru.

Aby ustawić typy multimediów, wykonaj następujące czynności:

  1. (Opcjonalnie). Dla każdego strumienia wejściowego wywołaj IMFTransform::GetInputAvailableType, aby uzyskać listę preferowanych typów dla tego strumienia.
    • Jeśli ta metoda zwraca MF_E_TRANSFORM_TYPE_NOT_SET, należy najpierw ustawić typy danych wyjściowych; przejdź do kroku 3.
    • Jeśli metoda zwraca E_NOTIMPL, MFT nie ma listy preferowanych typów danych wejściowych; przejdź do kroku 2.
  2. Dla każdego strumienia wejściowego wywołaj IMFTransform::SetInputType, aby ustawić typ danych wejściowych. Możesz użyć typu nośnika z kroku 1 lub typu opisującego dane wejściowe. Jeśli dowolny strumień zwraca MF_E_TRANSFORM_TYPE_NOT_SET, przejdź do kroku 3.
  3. (Opcjonalnie). Dla każdego strumienia wyjściowego wywołaj metodę IMFTransform::GetOutputAvailableType, aby uzyskać listę preferowanych typów dla tego strumienia.
    • Jeśli ta metoda zwraca MF_E_TRANSFORM_TYPE_NOT_SET, należy najpierw ustawić typy wejściowe; wróć do kroku 1.
    • Jeśli jakikolwiek strumień zwraca E_NOTIMPL, MFT nie ma listy preferowanych typów danych wyjściowych; przejdź do kroku 4.
  4. Dla każdego strumienia wyjściowego wywołaj IMFTransform::SetOutputType, aby ustawić typ danych wyjściowych. Możesz użyć typu nośnika z kroku 3 lub typu opisującego wymagany format danych wyjściowych.
  5. Jeśli jakiekolwiek strumienie wejściowe nie mają typu nośnika, wróć do kroku 1.

Pobierz wymagania dotyczące buforu

Po skonfigurowaniu typów nośników klient powinien uzyskać wymagania buforu dla każdego strumienia:

Przetwarzanie danych

MFT został zaprojektowany tak, aby był niezawodną maszyną stanu. Nie wykonuje żadnych wywołań z powrotem do klienta.

  1. Wywołaj IMFTransform::P rocessMessage komunikatem MFT_MESSAGE_NOTIFY_BEGIN_STREAMING. Ten komunikat żąda MFT przydzielenia wszelkich potrzebnych zasobów podczas przesyłania strumieniowego.
  2. Wywołaj IMFTransform::ProcessInput na co najmniej jednym strumieniu wejściowym, aby dostarczyć próbkę danych wejściowych do MFT.
  3. (Opcjonalnie). Wywołaj IMFTransform::GetOutputStatus, aby zapytać, czy MFT może wygenerować przykład danych wyjściowych. Jeśli metoda zwraca S_OK, sprawdź parametr pdwFlags. Jeśli pdwFlags zawiera flagę MFT_OUTPUT_STATUS_SAMPLE_READY, przejdź do kroku 4. Jeśli pdwFlags wynosi zero, wróć do kroku 2. Jeśli metoda zwraca E_NOTIMPL, przejdź do kroku 4.
  4. Wywołaj IMFTransform::ProcessOutput w celu uzyskania danych wyjściowych.
    • Jeśli metoda zwraca MF_E_TRANSFORM_NEED_MORE_INPUT, oznacza to, że MFT wymaga większej ilości danych wejściowych; wróć do kroku 2.
    • Jeśli metoda zwraca MF_E_TRANSFORM_STREAM_CHANGE, oznacza to, że liczba strumieni wyjściowych uległa zmianie lub format danych wyjściowych uległ zmianie. Klient może potrzebować zapytań o nowe identyfikatory strumienia lub ustawić nowe typy multimediów. Aby uzyskać więcej informacji, zobacz dokumentację ProcessOutput.
  5. Jeśli dane wejściowe są nadal przetwarzane, przejdź do kroku 2. Jeśli platforma MFT używa wszystkich dostępnych danych wejściowych, przejdź do kroku 6.
  6. Wywołaj ProcessMessage przy użyciu komunikatu MFT_MESSAGE_NOTIFY_END_OF_STREAM.
  7. Wywołaj ProcessMessage za pomocą komunikatu MFT_MESSAGE_COMMAND_DRAIN.
  8. Wywołaj ProcessOutput, aby uzyskać pozostałe dane wyjściowe. Powtórz ten krok, aż metoda zwróci MF_E_TRANSFORM_NEED_MORE_INPUT. Ta wartość zwracana sygnalizuje, że wszystkie dane wyjściowe zostały opróżnione z protokołu MFT. (Nie traktuj tego jako warunku błędu).

Sekwencja opisana tutaj przechowuje jak najmniej danych w MFT. Po każdym wywołaniu ProcessInputklient próbuje pobrać dane wyjściowe. Do utworzenia jednego przykładu wyjściowego może być potrzebnych kilka przykładów wejściowych lub jeden przykład wejściowy może wygenerować kilka przykładów wyjściowych. Optymalnym zachowaniem klienta jest ściąganie przykładów wyjściowych z MFT, dopóki MFT nie wymaga większej ilości danych wejściowych.

Jednak MFT powinien być w stanie obsłużyć inną kolejność wywołań metod przez klienta. Na przykład klient może po prostu na przemian wywoływać ProcessInput i ProcessOutput. MFT powinien ograniczać ilość danych wejściowych, które pobiera, zwracając MF_E_NOTACCEPTING z ProcessInput za każdym razem, gdy ma do wygenerowania jakieś dane wyjściowe.

Kolejność wywołań metod opisanych tutaj nie jest jedyną prawidłową sekwencją zdarzeń. Na przykład kroki 3 i 4 zakładają, że klient rozpoczyna się od typów wejściowych, a następnie próbuje użyć typów danych wyjściowych. Klient może również odwrócić tę kolejność i rozpocząć od typów danych wyjściowych. W obu przypadkach, jeśli MFT wymaga odwrotnej kolejności, powinien zwrócić kod błędu MF_E_TRANSFORM_TYPE_NOT_SET.

Klient może wywoływać metody informacyjne, takie jak GetInputCurrentType i GetOutputStreamInfo, w dowolnym momencie podczas przesyłania strumieniowego. Klient może również w dowolnym momencie podjąć próbę zmiany typów multimediów. Jeśli nie jest to prawidłowa operacja, funkcja MFT powinna zwrócić kod błędu. Krótko mówiąc, MFTs powinny zakładać bardzo niewiele na temat kolejności operacji, poza tym, co jest udokumentowane w wywołaniach.

Na poniższym diagramie przedstawiono schemat blokowy procedur opisanych w tym temacie.

wykres blokowy, który rozpoczyna od pobierania identyfikatorów strumieni w ramach pętli, które ustawiają typy danych wejściowych, pobierają te dane wejściowe i przetwarzają dane wyjściowe

Rozszerzenia modelu podstawowego

Opcjonalnie MFT może obsługiwać niektóre rozszerzenia podstawowego modelu przesyłania strumieniowego.

  • Strumienie z opóźnieniem odczytu. Jeśli metoda IMFTransform::GetOutputStreamInfo zwraca flagę MFT_OUTPUT_STREAM_LAZY_READ strumienia wyjściowego, klient nie musi zbierać danych z tego strumienia. MFT nadal akceptuje dane wejściowe, a w pewnym momencie MFT odrzuci dane wyjściowe z tego strumienia. Jeśli wszystkie strumienie wyjściowe mają tę flagę, MFT nigdy nie zawiedzie w akceptacji danych wejściowych. Przykładem może być transformacja wizualizacji, w której klient pobiera dane wyjściowe tylko wtedy, gdy ma zapasowe cykle procesora CPU w celu narysowania wizualizacji.
  • Odrzucalne strumienie. Jeśli metoda GetOutputStreamInfo zwraca flagę MFT_OUTPUT_STREAM_DISCARDABLE dla strumienia wyjściowego, klient może zażądać od MFT odrzucenia danych wyjściowych, ale MFT nie odrzuci żadnych danych wyjściowych, chyba że zostanie to zażądane. Gdy MFT osiągnie maksymalny bufor wejściowy, klient musi zebrać dane wyjściowe lub zażądać od MFT odrzucenia danych wyjściowych.
  • Opcjonalne strumienie. Jeśli metoda GetOutputStreamInfo zwraca flagę MFT_OUTPUT_STREAM_OPTIONAL dla strumienia wyjściowego lub IMFTransform::GetInputStreamInfo metoda zwraca flagę MFT_INPUT_STREAM_OPTIONAL dla strumienia wejściowego, ten strumień jest opcjonalny. Klient nie musi ustawiać typu multimediów w strumieniu. Jeśli klient nie ustawi typu, strumień zostanie anulowany. Niewybrany strumień wyjściowy nie generuje próbek, a klient nie zapewnia bufora dla strumienia, gdy wywołuje ProcessOutput. Niezaznaczony strumień wejściowy nie akceptuje danych wejściowych. MFT może oznaczyć wszystkie strumienie wejściowe i wyjściowe jako opcjonalne. Oczekuje się jednak, że co najmniej jedno dane wejściowe i jedno wyjście musi zostać wybrane, aby MFT działał.
  • Przetwarzanie asynchroniczne. Model przetwarzania asynchronicznego został wprowadzony w systemie Windows 7. Opisano go w temacie Asynchroniczne MFT.

IMF2DBuffer

Jeśli MFT przetwarza nieskompresowane dane wideo, należy użyć interfejsu IMF2DBuffer do manipulowania buforami próbek. Aby uzyskać ten interfejs, wykonaj zapytanie dotyczące interfejsu IMFMediaBuffer na dowolnym buforze wejściowym lub wyjściowym. Nieużywanie tego interfejsu, gdy jest dostępny, może spowodować dodatkowe kopie buforu. Aby prawidłowo korzystać z tego interfejsu, operacja przekształcania nie powinna blokować buforu przy użyciu interfejsu IMFMediaBuffer, gdy jest dostępny IMF2DBuffer.

Aby uzyskać więcej informacji na temat przetwarzania danych wideo, zobacz Bufory nieskompresowanego wideo.

Opróżnianie MFT

Opróżnianie MFT powoduje odrzucenie wszystkich jego danych wejściowych. Może to spowodować przerwanie w strumieniu wyjściowym. Klient zazwyczaj czyści MFT, zanim przejdzie do nowego punktu w strumieniu wejściowym lub zmieni strumień wejściowy, jeśli nie zależy mu na utracie danych.

Aby opróżnić MFT, wywołaj IMFTransform::ProcessMessage z komunikatem MFT_MESSAGE_COMMAND_FLUSH.

Opróżnianie MFT

Opróżnienie MFT powoduje, że MFT generuje tyle danych wyjściowych, ile może z dowolnych dostępnych danych wejściowych, które już zostały wysłane. Jeśli MFT nie może utworzyć kompletnej próbki danych wyjściowych z dostępnych danych wejściowych, pominie dane wejściowe. Klient zazwyczaj opróżnia MFT po osiągnięciu końca strumienia źródłowego lub bezpośrednio przed zmianą formatu w strumieniu źródłowym. Aby opróżnić MFT, wykonaj następujące czynności:

  1. Wywołaj ProcessMessage za pomocą komunikatu MFT_MESSAGE_COMMAND_DRAIN. Ten komunikat powiadamia MFT, że powinien dostarczać tyle danych wyjściowych, ile może z danych wejściowych, które zostały już wysłane.
  2. Wywołaj ProcessOutput, aby pobrać dane wyjściowe, dopóki metoda nie zwróci MF_E_TRANSFORM_NEED_MORE_INPUT.

Podczas gdy MFT jest opróżniany, nie zaakceptuje więcej danych wejściowych.

Przykładowe atrybuty

Przykłady danych wejściowych mogą mieć atrybuty, które muszą zostać skopiowane do odpowiednich przykładów danych wyjściowych.

W przypadku protokołu MFT z jednym wejściem i jednym wyjściem można użyć następującej reguły ogólnej:

  • Jeśli każdy przykład danych wejściowych generuje dokładnie jedną próbkę danych wyjściowych, możesz zezwolić klientowi na skopiowanie atrybutów. Pozostaw właściwość MFPKEY_EXATTRIBUTE_SUPPORTED niezastawioną.
  • Jeśli między przykładami wejściowymi i przykładami wyjściowymi nie istnieje korespondencja jeden do jednego, MFT musi określić prawidłowe atrybuty dla przykładów danych wyjściowych. Ustaw właściwość MFPKEY_EXATTRIBUTE_SUPPORTED na wartość VARIANT_TRUE.

Przerwania

Przerwa w strumieniu audio lub wideo. Przerwania mogą być spowodowane przez porzucone pakiety w połączeniu sieciowym, uszkodzone dane plików, przełącznik z jednego strumienia źródłowego do innego lub szeroką gamę innych przyczyn. Nieciągłości są sygnalizowane przez ustawienie atrybutu MFSampleExtension_Discontinuity w pierwszej próbce po nieciągłości. Nie można zasygnalizować przerwania w środku próbki. W związku z tym wszelkie nieciągłe dane powinny być wysyłane w osobnych próbkach.

Niektóre przekształcenia, zwłaszcza te, które obsługują nieskompresowane dane, takie jak efekty audio i wideo, powinny ignorować braki podczas przetwarzania danych wejściowych. Te MFT są zwykle przeznaczone do obsługi danych ciągłych i powinny traktować wszystkie dane odbierane jako ciągłe, nawet po przerwaniu.

Jeśli MFT ignoruje nieciągłość danych wejściowych, nadal powinien ustawić flagę przerwania w próbce wyjściowej, jeśli próbka wyjściowa ma ten sam znacznik czasowy co próbka wejściowa. Jeśli jednak próbka wyjściowa ma inną sygnaturę czasową, MFT nie powinien propagować przerwania. (Na przykład w przypadku niektórych ponownych próbek dźwięku). Przerwanie w niewłaściwym miejscu w strumieniu jest gorsze niż brak przerwania.

Większość dekoderów nie może ignorować nieciągłości, ponieważ nieciągłość wpływa na interpretację następnej próbki. Każda technologia kodowania korzystająca z kompresji między ramami, takiej jak MPEG-2, należy do tej kategorii. Niektóre schematy kodowania używają tylko kompresji wewnątrz ramki, takiej jak DV i MJPEG. Dekodatory te mogą bezpiecznie ignorować przerwania.

Przekształcenia, które reagują na nieciągłości, powinny zwykle zwracać jak najwięcej danych przed nieciągłością i odrzucać resztę. Próbka danych wejściowych z flagą przerwania powinna zostać przetworzona tak, jakby była to pierwsza próbka w strumieniu. (To zachowanie jest zgodne z określonymi elementami komunikatu MFT_MESSAGE_COMMAND_DRAIN). Jednak dokładne szczegóły będą zależeć od formatu nośnika.

Jeśli dekoder nie robi nic, aby zapobiec przerwaniu działania, powinien skopiować flagę przerwania do danych wyjściowych. Demultipleksery i inne MFT, które działają całkowicie na skompresowanych danych, muszą przenosić wszelkie nieciągłości do swoich strumieni wyjściowych. W przeciwnym razie składniki podrzędne mogą nie być w stanie poprawnie zdekodować skompresowanych danych. Ogólnie rzecz biorąc, prawie zawsze jest poprawne, aby przekazać przerwy dalej, chyba że MFT zawiera jawny kod, aby wygładzić przerwy.

Zmiany formatu dynamicznego

Formaty mogą ulec zmianie podczas przesyłania strumieniowego. Na przykład współczynnik proporcji może ulec zmianie w środku strumienia wideo.

Aby uzyskać szczegółowe informacje na temat sposobu obsługi zmian strumienia przez MFT, zobacz Obsługa zmian strumienia.

Zdarzenia strumienia

Aby wysłać zdarzenie do MFT, wywołaj IMFTransform::ProcessEvent. Jeśli metoda zwróci MF_S_TRANSFORM_DO_NOT_PROPAGATE_EVENT, wówczas MFT przekaże zdarzenie do wywołującego podczas następnego wywołania ProcessOutput. Jeśli metoda zwróci dowolną inną wartość HRESULT, funkcja MFT nie zwróci zdarzenia do klienta w ProcessOutput. W takim przypadku klient jest odpowiedzialny za propagowanie zdarzenia do następnego składnika w ciągu przetwarzania, jeśli ma to zastosowanie. Aby uzyskać więcej informacji, zobacz IMFTransform::ProcessOutput.

przekształcenia Media Foundation