Dela via


Asynkrona MFI

Det här avsnittet beskriver asynkron databehandling för Media Foundation-transformeringar (MFI).

Not

Det här avsnittet gäller för Windows 7 eller senare.

 

Om asynkrona MFI

När MMFT introducerades i Windows Vista utformades API:et för synkron databearbetning. I den modellen väntar MFT alltid på att få indata eller väntar på att generera utdata.

Överväg en typisk videodekodare. För att få en avkodad ram anropar klienten IMFTransform::P rocessOutput. Om avkodaren har tillräckligt med data för att avkoda en ram ProcessOutput block medan MFT avkodar ramen. Annars returnerar ProcessOutputMF_E_TRANSFORM_NEED_MORE_INPUT, vilket anger att klienten ska anropa IMFTransform::P rocessInput.

Den här modellen fungerar bra om avkodaren utför alla sina avkodningsåtgärder på en tråd. Men anta att avkodaren använder flera trådar för att avkoda bildrutor parallellt. För bästa prestanda bör avkodaren ta emot nya indata när en avkodningstråd blir inaktiv. Men den hastighet med vilken trådar slutför avkodningsåtgärder överensstämmer inte exakt med klientens anrop till ProcessInput och ProcessOutput, vilket resulterar i trådar som väntar på arbete.

Windows 7 introducerar händelsedriven asynkron bearbetning för MFI. I den här modellen, när MFT behöver indata eller har utdata, skickar den en händelse till klienten.

Allmänna krav

Det här avsnittet beskriver hur asynkrona MMFT skiljer sig från synkron MFT. Förutom i det här avsnittet är de två bearbetningsmodellerna desamma. (I synnerhet är formatförhandlingen densamma.)

En asynkron MFT måste implementera följande gränssnitt:

Evenemang

En asynkron MFT använder följande händelser för att signalera dess databehandlingsstatus:

Händelse Beskrivning
METransformNeedInput Skickas när MFT kan acceptera fler indata.
METransformHaveOutput Skickas när MFT har utdata.
METransformDrainComplete Skickas när en avloppsåtgärd är klar. Se Tömning.
METransformMarker Skickas när en markör bearbetas. Se markörer.

 

Dessa händelser skickas out-of-band. Det är viktigt att förstå skillnaden mellan in-band- och out-of-band-händelser i samband med en MFT.

Den ursprungliga MFT-designen stöder in-band- händelser. En in-band-händelse innehåller information om dataströmmen, till exempel information om en formatändring. Klienten skickar in-band-händelser till MFT genom att anropa IMFTransform::P rocessEvent. MFT kan skicka in-band-händelser tillbaka till klienten i metoden ProcessOutput. (Mer specifikt förmedlas händelser i pEvents medlem i MFT_OUTPUT_DATA_BUFFER-strukturen.)

En MFT skickar out-of-band-händelser via IMFMediaEventGenerator- gränssnitt enligt följande:

  1. MFT implementerar gränssnittet IMFMediaEventGenerator, enligt beskrivningen i Media Event Generators.
  2. Klienten anropar IUnknown::QueryInterface på MFT för gränssnittet IMFMediaEventGenerator. En asynkron MFT måste exponera det här gränssnittet. Synkrona MMFT:er bör inte exponera det här gränssnittet.
  3. Klienten anropar IMFMediaEventGenerator::BeginGetEvent och IMFMediaEventGenerator::EndGetEvent för att ta emot out-of-band-händelser från MFT.

ProcessInput

Metoden IMFTransform::P rocessInput ändras på följande sätt:

  1. När direktuppspelningen startar skickar klienten meddelandet MFT_MESSAGE_NOTIFY_START_OF_STREAM.
  2. Under strömning begär MFT data genom att skicka en METransformNeedInput- händelse. Händelsedata är dataströmidentifieraren.
  3. För varje METransformNeedInput- händelse anropar klienten ProcessInput- för den angivna strömmen.
  4. I slutet av direktuppspelningen kan klienten anropa ProcessMessage med meddelandet MFT_MESSAGE_NOTIFY_END_OF_STREAM.

Implementeringsanteckningar:

ProcessOutput

Metoden IMFTransform::P rocessOutput ändras på följande sätt:

  1. När MFT har utdata skickar den en METransformHaveOutput- händelse.
  2. För varje METransformHaveOutput- händelse anropar klienten ProcessOutput.

Implementeringsanteckningar:

  • Om klienten anropar ProcessOutput vid något annat tillfälle returnerar metoden E_UNEXPECTED.
  • En asynkron MFT bör aldrig returnera MF_E_TRANSFORM_NEED_MORE_INPUT från metoden ProcessOutput. Om MFT kräver mer indata skickar den en METransformNeedInput- händelse.

Dränering

Tömning av en MFT gör att MFT producerar så mycket utdata som möjligt från de indata som redan har skickats. Tömning av en asynkron MFT fungerar på följande sätt:

  1. Klienten skickar meddelandet MFT_MESSAGE_COMMAND_DRAIN.
  2. MFT fortsätter att skicka METransformHaveOutput händelser tills den inte har fler data att bearbeta. Den skickar inte METransformNeedInput händelser under den här tiden.
  3. När MFT har skickat den senaste METransformHaveOutput--händelsen skickar den en METransformDrainComplete- händelse.

När tömningen är klar skickar MFT inte någon annan METransformNeedInput- händelse förrän den tar emot ett MFT_MESSAGE_NOTIFY_START_OF_STREAM meddelande från klienten.

Spolning

Klienten kan tömma MFT genom att skicka MFT_MESSAGE_COMMAND_FLUSH meddelandet. MFT släpper alla in- och utdataexempel som den håller i.

MFT skickar inte någon annan METransformNeedInput- händelse förrän den tar emot ett MFT_MESSAGE_NOTIFY_START_OF_STREAM meddelande från klienten.

Markörer

Klienten kan markera en punkt i strömmen genom att skicka MFT_MESSAGE_COMMAND_MARKER meddelandet. MFT svarar på följande sätt:

  1. MFT genererar så många utdataexempel som möjligt från befintliga indata och skickar en METransformHaveOutput- händelse för varje utdataexempel.
  2. När alla utdata har genererats skickar MFT en METransformMarker- händelse. Den här händelsen måste skickas efter alla METransformHaveOutput- händelser.

Anta till exempel att en avkodare har tillräckligt med indata för att skapa fyra utdataexempel. Om klienten skickar meddelandet MFT_MESSAGE_COMMAND_MARKER köar MFT fyra METransformHaveOutput händelser (ett per utdataexempel), följt av en METransformMarker- händelse.

Markörmeddelandet liknar tömningsmeddelandet. Ett avlopp anses dock vara en paus i strömmen, medan en markör inte är det. Tömning och markörer har följande skillnader.

Dränering:

  • Vid tömning skickar MFT inte METransformNeedInput- händelser.
  • MFT tar bort alla indata som inte kan användas för att skapa ett utdataexempel.
  • Vissa MMFT:er skapar en "tail" i slutet av data. Till exempel ger ljudeffekter som reverb eller eko extra data när indata har stoppats. En MFT som genererar en svans bör göra det i slutet av en avloppsåtgärd.
  • När MFT har tömts markerar det nästa utdataexempel med attributet MFSampleExtension_Discontinuity för att indikera en diskontinuitet i strömmen.

Markör:

  • MFT fortsätter att skicka METransformNeedInput händelser innan markörhändelsen skickas.
  • MFT tar inte bort några indata. Om det finns partiella data bör de bearbetas efter markörpunkten.
  • MFT producerar inte en stjärt vid markörpunkten.
  • MFT anger inte diskontinuitetsflaggan efter markörpunkten.

Formatera ändringar

En asynkron MFT måste ha stöd för ändringar i dynamiskt format enligt beskrivningen i Hantera stream-ändringar.

Attribut

En asynkron MFT måste implementera metoden IMFTransform::GetAttributes för att returnera ett giltigt attributarkiv. Följande attribut gäller för asynkrona MFI:

Attribut Beskrivning
MF_TRANSFORM_ASYNC MFT måste ange det här attributet till TRUE (1). Klienten kan köra frågor mot det här attributet för att ta reda på om MFT är asynkront.
MF_TRANSFORM_ASYNC_UNLOCK
MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE MFT måste ange det här attributet till TRUE (1). Klienten kan anta att det här attributet har angetts.

 

Låsa upp asynkrona MFI

Asynkrona MMFT är inte kompatibla med den ursprungliga MFT-databearbetningsmodellen. För att förhindra att asynkrona MMFT:ar bryter befintliga program definieras följande mekanism:

Klienten anropar IMFTransform::GetAttributes på MFT. Klienten frågar efter attributet för det här MF_TRANSFORM_ASYNC. För en asynkron MFT är värdet för det här attributet **TRUE**. För att låsa upp MFT måste klienten ange attributet MF_TRANSFORM_ASYNC_UNLOCK till **TRUE**.

Tills klienten låser upp MFT bör alla IMFTransform- metoder returnera MF_E_TRANSFORM_ASYNC_LOCKED, med följande undantag:

Följande kod visar hur du låser upp en asynkron 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;
}

Stänga av MFT

Asynkrona MMFT måste implementera IMFShutdown- gränssnitt.

  • Avstängning: MFT måste stänga av sin händelsekö. Om du använder standardhändelsekön anropar du IMFMediaEventQueue::Shutdown. Om du vill kan MFT frigöra andra resurser. Klienten får inte använda MFT efter att ha anropat Avstängning.
  • GetShutdownStatus: När Avstängning har anropats ska MFT returnera värdet MFSHUTDOWN_COMPLETED i parametern pStatus. Det bör inte returnera värdet MFSHUTDOWN_INITIATED.

Registrering och uppräkning

Om du vill registrera en asynkron MFT anropar du funktionen MFTRegister och anger flaggan MFT_ENUM_FLAG_ASYNCMFT i parametern Flags. (Tidigare var den här flaggan reserverad.)

Om du vill räkna upp asynkrona MMFT anropar du funktionen MFTEnumEx och anger flaggan MFT_ENUM_FLAG_ASYNCMFT i parametern Flags. För bakåtkompatibilitet räknas inte funktionen MFTEnum upp asynkrona MMFT. Annars kan installation av en asynkron MFT på användarens dator bryta befintliga program.

Media Foundation transformerar