Grundläggande MFT-bearbetningsmodell
Det här avsnittet beskriver hur en klient använder en Media Foundation-transformering (MFT) för att bearbeta data. Den klienten är allt som direkt anropar metoder på MFT. Det kan vara applikationen eller Media Foundation-pipelinen.
Läs det här avsnittet om du är:
- Skriva ett program som gör direkta anrop till en eller flera MFT.
- Du vill skriva en anpassad MFT och lära dig om det förväntade beteendet för en MFT.
I det här avsnittet beskrivs en synkron bearbetningsmodell. I den här modellen blockeras alla databehandlingsmetoder tills de är slutförda. MFI kan också stödja en asynkron modell, som beskrivs i avsnittet Asynkrona MFI-.
- Grundläggande bearbetningsmodell
- tillägg till Basic Model
- IMF2DBuffer
- tömning av MFT-
- tömmer en MFT-
- exempelattribut
- Avbrott
- Dynamiska Formatändringar
- Stream-händelser
- Relaterade ämnen
Grundläggande bearbetningsmodell
Skapa MFT
Det finns flera sätt att skapa en MFT:
- Anropa funktionen MFTEnum.
- Anropa funktionen MFTEnumEx.
- Om du redan känner till CLSID för MFT anropar du bara CoCreateInstance.
Vissa MMFT:er kan ge andra alternativ, till exempel en specialiserad skapandefunktion.
Hämta Stream-identifierare
En MFT har en eller flera strömmar. Indataströmmar tar emot indata och utdataströmmar genererar utdata. Strömmar representeras inte som distinkta objekt. I stället tar olika MFT-metoder strömidentifierare som parametrar.
Vissa MMFT tillåter att klienten lägger till eller tar bort indataströmmar. Under strömning kan en MFT lägga till eller ta bort utdataströmmar. (Klienten kan inte lägga till eller ta bort utdataströmmar.)
- (Valfritt.) Anropa IMFTransform::GetStreamLimits för att få det lägsta och högsta antalet strömmar som MFT kan stödja. Om minimi- och maxvärdet är detsamma har MFT ett fast antal strömmar.
- Anropa IMFTransform::GetStreamCount för att hämta det första antalet strömmar.
- Anropa IMFTransform::GetStreamIDs för att hämta strömidentifierarna. Om den här metoden returnerar E_NOTIMPL innebär det att MFT har ett fast antal strömmar och att strömidentifierarna börjar från noll.
- (Valfritt.) Om MFT inte har ett fast antal strömmar anropar du IMFTransform::AddInputStreams för att lägga till fler indataströmmar eller IMFTransform::D eleteInputStream för att ta bort indataströmmar. (Du kan inte lägga till eller ta bort utdataströmmar.)
Ange medietyper
Innan en MFT kan bearbeta data måste klienten ange en medietyp för var och en av MFT:s strömmar. En MFT kan kräva att klienten anger indatatyperna innan utdatatyperna anges, eller att det kan krävas motsatt ordning (utdatatyper först). Vissa MMFT:er har inget krav på beställningen.
En MFT kan tillhandahålla en lista över önskade medietyper för en ström. MFI kan också ange de allmänna format som de stöder genom att lägga till den här informationen i registret.
Gör följande för att ange medietyperna:
- (Valfritt.) För varje indataström anropar du IMFTransform::GetInputAvailableType för att hämta listan över önskade typer för strömmen.
- Om den här metoden returnerar MF_E_TRANSFORM_TYPE_NOT_SET måste du först ange utdatatyperna. hoppa till steg 3.
- Om metoden returnerar E_NOTIMPL har MFT ingen lista över önskade indatatyper. hoppa till steg 2.
- För varje indataström anropar du IMFTransform::SetInputType för att ange indatatypen. Du kan använda en medietyp från steg 1 eller en typ som beskriver dina indata. Om någon ström returnerar MF_E_TRANSFORM_TYPE_NOT_SET går du vidare till steg 3.
- (Valfritt.) För varje utdataström anropar du IMFTransform::GetOutputAvailableType för att hämta en lista över önskade typer för strömmen.
- Om den här metoden returnerar MF_E_TRANSFORM_TYPE_NOT_SET måste du först ange indatatyperna. gå tillbaka till steg 1.
- Om någon ström returnerar E_NOTIMPL har MFT ingen lista över önskade utdatatyper. hoppa till steg 4.
- För varje utdataström anropar du IMFTransform::SetOutputType för att ange utdatatypen. Du kan använda en medietyp från steg 3 eller en typ som beskriver det utdataformat som krävs.
- Om indataströmmar inte har någon medietyp går du tillbaka till steg 1.
Hämta buffertkrav
När klienten har konfigurerat medietyperna bör den hämta buffertkraven för varje dataström:
- För varje indataström anropar du IMFTransform::GetInputStreamInfo.
- För varje utdataström anropar du IMFTransform::GetOutputStreamInfo.
Processdata
En MFT är utformad för att vara en tillförlitlig tillståndsdator. Den gör inga anrop tillbaka till klienten.
- Anropa IMFTransform::ProcessMessage med MFT_MESSAGE_NOTIFY_BEGIN_STREAMING-meddelandet . Det här meddelandet begär att MFT allokerar alla resurser som behövs under strömning.
- Anropa IMFTransform::ProcessInput på minst en indataström för att leverera ett exempel på indata till MFT.
- (Valfritt.) Anropa IMFTransform::GetOutputStatus för att fråga om MFT kan generera ett utdataexempel. Om metoden returnerar S_OK kontrollerar du parametern pdwFlags. Om pdwFlags innehåller flaggan MFT_OUTPUT_STATUS_SAMPLE_READY går du till steg 4. Om pdwFlags är noll går du tillbaka till steg 2. Om metoden returnerar E_NOTIMPL går du till steg 4.
- Anropa IMFTransform::ProcessOutput för att hämta utdata.
- Om metoden returnerar MF_E_TRANSFORM_NEED_MORE_INPUTinnebär det att MFT kräver mer indata. gå tillbaka till steg 2.
- Om metoden returnerar MF_E_TRANSFORM_STREAM_CHANGEinnebär det att antalet utdataströmmar har ändrats eller att utdataformatet har ändrats. Klienten kan behöva fråga efter nya strömidentifierare eller ange nya medietyper. Mer information finns i dokumentationen för ProcessOutput.
- Om det fortfarande finns indata att bearbeta går du till steg 2. Om MFT har förbrukat alla tillgängliga indata fortsätter du till steg 6.
- Anropa ProcessMessage med meddelandet MFT_MESSAGE_NOTIFY_END_OF_STREAM.
- Anropa ProcessMessage med meddelandet MFT_MESSAGE_COMMAND_DRAIN.
- Anropa ProcessOutput för att hämta återstående utdata. Upprepa detta steg tills metoden returnerar MF_E_TRANSFORM_NEED_MORE_INPUT. Det här returvärdet signalerar att alla utdata har tömts från MFT. (Behandla inte detta som ett feltillstånd.)
Sekvensen som beskrivs här behåller så lite data som möjligt i MFT. Efter varje anrop till ProcessInputförsöker klienten hämta utdata. Flera indataexempel kan behövas för att skapa ett utdataexempel, eller så kan ett enda indataexempel generera flera utdataexempel. Det optimala beteendet för klienten är att hämta utdataexempel från MFT tills MFT kräver mer indata.
MFT bör dock kunna hantera en annan ordning för metodanrop av klienten. Klienten kan till exempel bara växla mellan anrop till ProcessInput och ProcessOutput. MFT bör begränsa mängden indata som den får genom att returnera MF_E_NOTACCEPTING från ProcessInput när den har vissa utdata att producera.
Ordningen på metodanrop som beskrivs här är inte den enda giltiga sekvensen av händelser. Steg 3 och 4 förutsätter till exempel att klienten börjar med indatatyperna och sedan försöker använda utdatatyperna. Klienten kan också ångra den här ordningen och börja med utdatatyperna. I båda fallen, om MFT kräver motsatt ordning, bör den returnera felkoden MF_E_TRANSFORM_TYPE_NOT_SET.
Klienten kan anropa informationsmetoder, till exempel GetInputCurrentType och GetOutputStreamInfo, när som helst under strömning. Klienten kan också försöka ändra medietyperna när som helst. MFT ska returnera en felkod om detta inte är en giltig åtgärd. Kort sagt bör MFT:er anta väldigt lite om operationsordningen, förutom vad som dokumenteras i anropen själva.
Följande diagram visar ett flödesdiagram över de procedurer som beskrivs i det här avsnittet.
Tillägg till basicmodellen
Om du vill kan en MFT ha stöd för vissa tillägg till den grundläggande strömningsmodellen.
- Fördröjda läsströmmar. Om metoden IMFTransform::GetOutputStreamInfo returnerar flaggan MFT_OUTPUT_STREAM_LAZY_READ för en utdataström behöver klienten inte samla in data från den utdataströmmen. MFT fortsätter att acceptera indata och vid något tillfälle tar MFT bort utdata från strömmen. Om alla utdataströmmar har den här flaggan misslyckas MFT aldrig med att acceptera indata. Ett exempel kan vara en visualiseringstransformering, där klienten endast hämtar utdata när den har extra CPU-cykler för att rita visualiseringen.
- Borttagbara strömmar. Om metoden GetOutputStreamInfo returnerar flaggan MFT_OUTPUT_STREAM_DISCARDABLE för en utdataström kan klienten begära att MFT tar bort utdata, men MFT tar inte bort några utdata om det inte begärs. När MFT når sin maximala indatabuffert måste klienten antingen samla in vissa utdata eller begära att MFT tar bort utdata.
- Valfria strömmar. Om metoden GetOutputStreamInfo returnerar MFT_OUTPUT_STREAM_OPTIONAL-flaggan för en utdataström, eller metoden IMFTransform::GetInputStreamInfo returnerar MFT_INPUT_STREAM_OPTIONAL-flaggan för en indataström är dataströmmen valfri. Klienten behöver inte ange någon medietyp på strömmen. Om klienten inte anger typ avmarkeras strömmen. En avmarkerad utdataström producerar inga samplar och klienten tillhandahåller inte någon buffert för strömmen när den anropar ProcessOutput. En avmarkerad indataström tar inte emot indata. En MFT kan markera alla in- och utdataströmmar som valfria. Det förväntas dock att minst en inmatning och en utmatning måste väljas för att MFT ska fungera.
- Asynkron bearbetning. Den asynkrona bearbetningsmodellen introducerades i Windows 7. Det beskrivs i avsnittet Asynkrona MFTs.
IMF2DBuffer
Om en MFT bearbetar okomprimerade videodata bör den använda IMF2DBuffer- gränssnitt för att manipulera exempelbuffertar. Hämta det här gränssnittet genom att fråga efter IMFMediaBuffer-gränssnittet i valfri in- eller utdatabuffert. Om du inte använder det här gränssnittet när det är tillgängligt kan det resultera i ytterligare buffertkopior. För att kunna använda det här gränssnittet korrekt bör transformering inte låsa bufferten med hjälp av IMFMediaBuffer gränssnitt när IMF2DBuffer är tillgänglig.
Mer information om hur du bearbetar videodata finns i okomprimerade videobuffertar.
Rensa en MFT
Rensning av en MFT gör att MFT automatiskt tar bort all sin indata. Detta kan orsaka ett avbrott i utdataströmmen. En klient tömmer vanligtvis en MFT innan den söker till en ny punkt i indataströmmen eller växlar till en ny indataström, när klienten inte bryr sig om att förlora data.
Om du vill tömma en MFT anropar du IMFTransform::P rocessMessage med meddelandet MFT_MESSAGE_COMMAND_FLUSH.
Tömning av en MFT
Tömning av en MFT:n gör att MFT:n producerar så mycket utdata den kan från den indata som redan har skickats. Om MFT inte kan producera ett fullständigt utdataexempel från de tillgängliga indata kommer indata att tas bort. En klient tömmer vanligtvis en MFT när den når slutet av källströmmen, eller omedelbart före en formatändring i källströmmen. Gör följande för att tömma en MFT:
- Anropa ProcessMessage med meddelandet MFT_MESSAGE_COMMAND_DRAIN. Det här meddelandet meddelar MFT att det ska leverera så mycket utdata som möjligt från indata som redan har skickats.
- Anropa ProcessOutput för att hämta utdata tills metoden returnerar MF_E_TRANSFORM_NEED_MORE_INPUT.
Medan MFT töms accepterar den inte fler indata.
Exempelattribut
Indataexemplen kan ha attribut som måste kopieras till motsvarande utdataexempel.
- Om MFT returnerar VARIANT_TRUE för egenskapen MFPKEY_EXATTRIBUTE_SUPPORTED måste MFT kopiera attributen.
- Om egenskapen MFPKEY_EXATTRIBUTE_SUPPORTED antingen är VARIANT_FALSE eller inte har angetts måste klienten kopiera attributen.
För en MFT med en indata och en utdata kan du använda följande allmänna regel:
- Om varje indataexempel ger exakt ett utdataexempel kan du låta klienten kopiera attributen. Låt egenskapen MFPKEY_EXATTRIBUTE_SUPPORTED förbli olämnad.
- Om det inte finns en en-till-en-korrespondens mellan indataexempel och utdataexempel måste MFT fastställa rätt attribut för utdataexempel. Ange egenskapen MFPKEY_EXATTRIBUTE_SUPPORTED till VARIANT_TRUE.
Avbrott
En diskontinuitet är en paus i en ljud- eller videoström. Avbrott kan orsakas av borttagna paket på en nätverksanslutning, skadade fildata, en växling från en källström till en annan eller en mängd andra orsaker. Avbrott signaleras genom att ange attributet MFSampleExtension_Discontinuity i det första exemplet efter diskontinuiteten. Det går inte att signalera en diskontinuitet mitt i ett prov. Därför bör eventuella diskontinuerliga data skickas i separata exempel.
Vissa transformeringar, särskilt de som hanterar okomprimerade data, till exempel ljud- och videoeffekter, bör ignorera diskontinuiteter när de bearbetar indata. Dessa MFT är vanligtvis utformade för att hantera kontinuerliga data och bör behandla alla data som de får som kontinuerliga, även efter en diskontinuitet.
Om en MFT ignorerar avbrott i indata bör den fortfarande ange flaggan för diskontinuitet i utdataexemplet, om utdataexemplet har samma tidsstämpel som indataexemplet. Om utdataexemplet har en annan tidsstämpel bör dock MFT inte sprida diskontinuiteten. (Detta skulle vara fallet i vissa ljudsamplar, till exempel.) En diskontinuitet på fel plats i strömmen är värre än ingen diskontinuitet.
De flesta avkodare kan inte ignorera diskontinuiteter eftersom en diskontinuitet påverkar tolkningen av nästa exempel. All kodningsteknik som använder komprimering mellan ramar, till exempel MPEG-2, ingår i den här kategorin. Vissa kodningsscheman använder endast komprimering inom ramen, till exempel DV och MJPEG. Dessa avkodare kan på ett säkert sätt ignorera avbrott.
Transformeringar som svarar på avbrott bör i allmänhet mata ut så mycket av data som möjligt före diskontinuiteten och ta bort resten. Indataexemplet med flaggan för diskontinuitet bör bearbetas som om det vore det första exemplet i strömmen. (Det här beteendet matchar vad som anges för MFT_MESSAGE_COMMAND_DRAIN-meddelandet.) Den exakta informationen beror dock på medieformatet.
Om en avkodare inte gör något för att minska diskontinuiteten bör den kopiera flaggan för diskontinuitet till utdata. Demultiplexers och andra MMFT som fungerar helt med komprimerade data måste kopiera eventuella avbrott till sina utdataströmmar. Annars kanske de underordnade komponenterna inte kan avkoda komprimerade data korrekt. I allmänhet är det nästan alltid korrekt att skicka diskontinuiteter nedströms, om inte MFT innehåller explicit kod för att jämna ut diskontinuiteter.
Ändringar i dynamiskt format
Format kan ändras under strömning. Till exempel kan proportioner ändras mitt i en videoström.
Mer information om hur dataströmändringar hanteras av en MFT finns i Hantera streamändringar.
Stream-händelser
Om du vill skicka en händelse till en MFT anropar du IMFTransform::P rocessEvent. Om metoden returnerar MF_S_TRANSFORM_DO_NOT_PROPAGATE_EVENTreturnerar MFT händelsen till anroparen vid ett efterföljande anrop till ProcessOutput. Om metoden returnerar andra HRESULT- värde returnerar MFT inte händelsen till klienten i ProcessOutput. I så fall ansvarar klienten för att sprida händelsen nedströms till nästa komponent i pipelinen, om tillämpligt. Mer information finns i IMFTransform::ProcessOutput.
Relaterade ämnen