Dela via


Skriva en anpassad mediekälla

Det här avsnittet beskriver hur du implementerar en anpassad mediekälla i Microsoft Media Foundation. Den innehåller följande avsnitt:

Skapa presentationsbeskrivningen

Metoden IMFMediaSource::CreatePresentationDescriptor returnerar en kopia av källans presentationsbeskrivning. Om du vill skapa presentationsbeskrivningen måste du känna till antalet strömmar i källinnehållet och möjliga format för varje ström. Skapa en strömbeskrivning för varje ström enligt följande:

  1. Skapa en matris med medietyper. Varje medietyp i matrisen representerar ett möjligt format för strömmen. Mer information om hur du skapar medietyper finns i Medietyper.
  2. Anropa MFCreateStreamDescriptor för att skapa strömbeskrivningen. Skicka in matrisen med medietyper. Funktionen returnerar en IMFStreamDescriptor-- pekare.
  3. Anropa IMFStreamDescriptor::GetMediaTypeHandler för att hämta dataströmbeskrivningens medietyphanterare.
  4. Anropa IMFMediaTypeHandler::SetCurrentMediaType för att ange standardformatet för dataströmmen. Använd en av de medietyper som du skapade i steg 1. I allmänhet bör du använda formatet med högsta kvalitet.
  5. Du kan också ange attribut på stream-beskrivningen. En lista över attribut som gäller för stream-beskrivningar finns i Stream Descriptor Attributes.

Skapa nu presentationsbeskrivningen:

  1. Anropa MFCreatePresentationDescriptor och skicka in matrisen med strömbeskrivningar. Funktionen returnerar en IMFPresentationDescriptor- pekare.
  2. Välj standardströmmarkeringen genom att anropa IMFPresentationDescriptor::SelectStream för att välja en eller flera strömmar. Minst en ström måste väljas i standardkonfigurationen.
  3. Du kan också ange attribut i presentationsbeskrivningen. En lista över attribut som gäller för strömbeskrivare finns i presentationsbeskrivarattribut.

Du bör skapa presentationsbeskrivningen en gång, antingen vid start eller efter att källan har parsat tillräckligt med källdata för att fastställa innehållet. Metoden CreatePresentationDescriptor ska returnera en kopia av presentationsbeskrivningen. Om du vill skapa kopian anropar du IMFPresentationDescriptor::Clone. Om du returnerar en kopia hindras klienten från att ändra tillståndet för den ursprungliga presentationsbeskrivningen, till exempel attributen eller strömmarkeringen. Tänk dock på att Clone skapar en ytlig kopia, så att klienten potentiellt kan ändra de underliggande strömbeskrivningarna.

Starta mediekällan

Metoden IMFMediaSource::Start startar mediekällan eller söker en ny position. Ett anrop till Start orsakar en sökning om det tidigare tillståndet antingen var pausat eller aktivt, och en ny starttid har angetts. Annars orsakar metoden Start en start. När åtgärden Starta slutförs skickar du följande händelser.

  1. Skicka en MENewStream- händelse för varje ny ström, det vill säga varje ström som tidigare har avmarkerats och nu väljs. Händelsedata är en pekare till strömmen.
  2. Skicka en MEUpdatedStream- händelse för varje flöde som tidigare har valts och som fortfarande är valt. Händelsedata är en pekare till strömmen. Skicka inte en händelse för avmarkerade flöden.
  3. Om källan söker efter något, skicka en MESourceSeeked-händelse. Annars skicka en MESourceStarted-händelse. Händelsedata är den starttid som angavs i metoden Start. Om starttiden är VT_EMPTY för MESourceStarted-händelsen anger du attributet MF_EVENT_SOURCE_ACTUAL_START för händelsen. Attributvärdet är den faktiska starttiden.
  4. Om källan söker för varje ström skickar du en MEStreamSeeked händelse. Annars skickar du en MEStreamStarted händelse. Händelsedata är starttiden. (Mediekällan kan köa en händelse i strömmen genom att anropa strömmens IMFMediaEventGenerator::QueueEvent -metoden.)

När en ström avmarkeras stänger du av den strömmen. Strömmen ska inte ställa fler händelser i kö vid den tidpunkten.

Tidsformatet för metoden Start anges i parametern pguidTimeFormat. Standardtidsformatet, som anges av GUID_NULL, är 100 nanosekundersenheter. En mediekälla måste ha stöd för det här tidsformatet.

Söker

När du söker kanske den begärda startpositionen inte hamnar på en exakt exempelgräns. För komprimerat innehåll kan startpositionen också falla mellan nyckelramar. En ström bör leverera prover från den tidigaste punkt som behövs för att producera ett okomprimerat prov vid den önskade startpositionen. För video innebär det att du börjar från den tidigare nyckelramen. Pipelinen ansvarar för att ta bort de extra bildrutorna från avkodaren, så att uppspelningen startar vid den begärda tidpunkten.

Starttiden som anges i källhändelserna (MESourceStarted, MESourceSeeked, MEStreamStartedoch MEStreamSeeked) är den begärda starttiden (värdet som anges i metoden Start), oavsett den faktiska startpositionen.

Anta till exempel att de första bildrutorna i en videoström har följande egenskaper:

Prov 1 2 3 4
Tid 33 msec 66 msec 100 msec 133 msec
Nyckelbild? Ja Nej Nej Ja

 

Om metoden Start anropas med värdet 100 millisekunder måste källan mata ut video från bildruta 1, den första nyckelramen före den här tiden. Starthändelsen visar fortfarande 100 millisekunder i händelsedata.

Pausa mediekällan

Metoden IMFMediaSource::Pause pausar mediekällan.

Medan källan har pausats kan en ström skapa nya exempel och lagra dem i en kö, men strömmen levererar inte exemplen. Här följer några undantag till den här regeln:

  • Livekällor bör släppa data när de är pausade.
  • Om källan hämtar data från ett nätverk kan den pausa servern.

Om klienten anropar IMFMediaStream::RequestSample medan källan pausas placeras även begäran i kö tills källan startas igen. Begäranden bör inte tas bort.

Pausning tillåts endast från det startade läget. Annars bör Pause returnera MF_E_INVALID_STATE_TRANSITION.

Generera källdata

Media Foundation använder en pull-modell, vilket innebär att strömmar genererar och levererar exempel som svar på begäranden från pipelinen. En dataström kan leverera prover när mediekällan är igång och dataströmmen har valts. En dataström levererar endast data när klienten begär ett nytt exempel.

Exempelbegäranden

Klienten begär ett nytt exempel genom att anropa IMFMediaStream::RequestSample. Här är åtgärdssekvensen:

  1. Klienten anropar IMFMediaStream::RequestSample. Argumentet är en pekare till en valfri token objekt som klienten använder för att spåra begäran. Klienten implementerar token. Token måste exponera gränssnittet IUnknown. Klienten kan också skicka in en NULL-pekare i stället för en token.

  2. Om klienten har angett en token anropar medieströmmen AddRef- på token och placerar token i en första-i-först-ut-kö. Metoden returnerar och de återstående stegen utförs asynkront.

  3. När mer data är tillgängliga skapar medieströmmen ett nytt exempel. (Det här steget beskrivs mer detaljerat i nästa avsnitt.)

  4. Medieströmmen hämtar den första symbolen från kön.

  5. Om token inte är NULL-anger medieströmmen attributet MFSampleExtension_Token i medieexemplet. Värdet för attributet är en pekare till token.

  6. Medieströmmen skickar en MEMediaSample-händelse. Händelsedata är en pekare till exemplets IMFSample- gränssnitt.

  7. Om klienten har angett en token, anropar medieströmmen Release på tokenobjektet.

Om medieströmmen inte kan uppfylla klientens RequestSample begäran, hämtar den token från kön och anropar Release på token, men skickar inte ett MEMediaSample-evenemang.

Klienten kan använda token för att spåra status för begäran. När klienten tar emot MEMediaSample--evenemanget kan den hämta token från provet och matcha det mot den ursprungliga begäran. Klienten kan också använda token för att identifiera om mediekällan har tagit bort begäran. Om tokens referensantal sjunker till noll och medieströmmen inte skickar en MEMediaSample-händelse innebär det att begäran togs bort.

Stegen som anges här förutsätter att metoden RequestSample implementeras som en asynkron åtgärd. Om metoden är synkron behöver du inte placera begärandetoken i en kö. Men om det tar lång tid att generera data rekommenderas en asynkron metod, till exempel om källan läser data från en byteström.

Dataströmmen tar hand om buffringen av all data som ackumuleras mellan anrop till RequestSample.

När medieströmmen når slutet av strömmen skickar den en MEEndOfStream- händelse efter det senaste exemplet. När varje ström har avslutats skickar mediekällan en händelse av typen MEEndOfPresentation. När en medieström skickar händelsen MEEndOfStream returnerar metoden RequestSampleMF_E_END_OF_STREAM tills källan startas om.

Allokera exempel

När strömmen är redo att fylla en väntande exempelbegäran skapar den ett nytt exempel och lägger till en eller flera mediebuffertar i exemplet. Mer information om hur du skapar mediebuffertar finns i Mediebuffertar.

Strömmen måste ange tidsstämpeln och, om det är känt, varaktigheten. Tidsstämpeln är relativ till källan. I de flesta fall motsvarar början av innehållet en tidsstämpel på noll. Om källan till exempel läser från en mediefil skulle början av filen ha en tidsstämpel på noll.

Tidsstämpeln för exemplet är inte nödvändigtvis lika med presentationstiden. Mediasessionen översätts från källtid till presentationstid. För komprimerade data ska dataströmmen generera data från närmaste nyckelram före starttiden. På så sätt kan avkodaren leverera den bildruta som visas vid den begärda starttiden. (Annars skulle avkodaren behöva vänta tills följande nyckelram.)

Om uppspelningshastigheten är snabbare eller långsammare än 1,0 justerar pipelinen presentationsklockans hastighet. Källan justerar inte tidsstämplarna på prover.

Källan kan ange ytterligare information om exemplet genom att ange attribut. En lista över exempelattribut finns i Exempelattribut.

Luckor i strömmen

Om en ström innehåller ett mellanrum med betydande längd rekommenderar vi att strömmen skickar en MEStreamTick- händelse. Den här händelsen meddelar klienten att ett exempel saknas. Händelsedata är tidsstämpeln för det saknade exemplet i 100 nanosekunder (VT_I8). Den här händelsen kan bespara underordnade komponenter från att vänta på prover som inte kommer att anlända. Strömmen kan skicka så många MEStreamTick-händelser som behövs för att täcka gapet i strömmen.

Stänga av mediekällan

När klienten har avslutat användningen av mediekällan anropas IMFMediaSource::Shutdown. I den här metoden ska mediekällan bryta alla cirkulära referensantal. Vanligtvis finns det cirkelreferenser mellan mediekällan och medieströmmarna.

Om du använder händelsekön för att implementera IMFMediaEventGeneratoranropar du IMFMediaEventQueue::Stäng i händelsekön. Den här metoden stänger av händelsekön och signalerar alla anropare som för närvarande väntar på en händelse.

Efter avstängningen returnerar alla metoder på källan MF_E_SHUTDOWN, med undantag för IUnknown metoder.

Live-källor

Från och med Windows 7 stöder Media Foundation automatiskt ljud- och videoinspelningsenheter. För video måste enheten tillhandahålla en KS-minidriver (kernel streaming) i videoinspelningskategori. Media Foundation använder PnP-sökvägen för att räkna upp enheten. För ljud använder Media Foundation API:et för Windows Multimedia Device (MMDevice) för att räkna upp ljudslutpunktsenheter. Om enheten uppfyller dessa kriterier behöver du inte implementera en anpassad mediekälla.

Du kanske dock vill implementera en anpassad mediekälla för någon annan typ av enhet eller annan live-datakälla. Det finns bara några skillnader mellan en livekälla och andra mediekällor:

  • I IMFMediaSource::GetCharacteristics-metoden ska du returnera flaggan MFMEDIASOURCE_IS_LIVE.
  • Det första exemplet ska ha en tidsstämpel på noll.
  • Händelser och strömningstillstånd hanteras på samma sätt som mediekällor, med undantag för pausat tillstånd.
  • Under pausen, köa inte prover. Släpp alla data som genereras under pausen.
  • Livekällor stöder vanligtvis inte sökning, omvänd uppspelning eller frekvenskontroll.

Mediekällor

Handledning: Skriva en anpassad mediekälla