Delen via


Voorbeelden en toewijzers

[De functie die is gekoppeld aan deze pagina, DirectShow, is een verouderde functie. Het is vervangen door MediaPlayer, IMFMediaEngineen Audio/Video Capture in Media Foundation. Deze functies zijn geoptimaliseerd voor Windows 10 en Windows 11. Microsoft raadt ten zeerste aan om nieuwe code te gebruiken MediaPlayer, IMFMediaEngine en Audio/Video Capture in Media Foundation in plaats van DirectShow, indien mogelijk. Microsoft stelt voor dat bestaande code die gebruikmaakt van de verouderde API's, indien mogelijk opnieuw worden geschreven om de nieuwe API's te gebruiken.]

Wanneer een pin mediagegevens aan een andere pin levert, geeft het geen directe pointer naar de geheugenbuffer door. In plaats daarvan wordt een aanwijzer naar een COM-object geleverd waarmee het geheugen wordt beheerd. Met dit object, een mediavoorbeeldgenoemd, wordt de interface IMediaSample weergegeven. De ontvangende pincode heeft toegang tot de geheugenbuffer door IMediaSample methoden aan te roepen, zoals IMediaSample::GetPointer, IMediaSample::GetSizeen IMediaSample::GetActualDataLength.

Voorbeelden reizen altijd downstream, van uitvoerpin naar invoerpin. In het pushmodel levert de uitvoerpin een voorbeeld door IMemInputPin::Receive op de invoerpin aan te roepen. De ingangspin zal de gegevens ofwel synchroon verwerken (dat wil zeggen, volledig binnen de methode Receive), of asynchroon verwerken op een werkdraad. De invoerpincode mag worden geblokkeerd binnen de methode Receive, als deze moet wachten op resources.

Een ander COM-object, een allocatorgenoemd, is verantwoordelijk voor het maken en beheren van mediavoorbeelden. Allocators bieden de IMemAllocator-interface aan. Wanneer een filter een mediavoorbeeld met een lege buffer nodig heeft, wordt de methode IMemAllocator::GetBuffer aangeroepen, waarmee een aanwijzer naar het voorbeeld wordt geretourneerd. Elke pinverbinding deelt één allocator. Wanneer twee pinnen verbinding maken, bepalen ze welk filter de allocator levert. De pinnen stellen ook eigenschappen in voor de allocator, zoals het aantal buffers en de grootte van elke buffer. (Zie voor meer informatie How Filters Connect en Negotiating Allocators.)

In de volgende afbeelding ziet u de relaties tussen de allocator, de mediavoorbeelden en het filter.

mediavoorbeelden en -toewijzingen

Media Monster Referentie Tellingen

Een allocator maakt een eindige pool met steekproeven. Op elk gewenst moment zijn sommige voorbeelden in gebruik, terwijl andere beschikbaar zijn voor GetBuffer-aanroepen. De allocator maakt gebruik van referentietelling om de samples bij te houden. De methode GetBuffer retourneert een voorbeeld met een referentieaantal van 1. Als de referentietelling nul bereikt, gaat de sample terug naar de pool van de allocator, waar deze kan worden gebruikt bij de volgende GetBuffer aanroep. Zolang het referentieaantal boven nul blijft, is het voorbeeld niet beschikbaar voor GetBuffer-. Als elke steekproef die hoort bij de allocator in gebruik is, blokkeert de GetBuffer methode totdat een steekproef beschikbaar is.

Stel dat een invoerpincode een voorbeeld ontvangt. Als het de steekproef synchroon verwerkt, wordt in de Receive-methode het aantal verwijzingen niet verhoogd. Nadat Receive retourneert, laat de uitvoerpin het sample los, wordt de referentieteller nul, en wordt het sample geretourneerd naar de pool van de allocator. Aan de andere kant, als de invoerpin het voorbeeld op een worker thread verwerkt, wordt het aantal verwijzingen verhoogd voordat u de methode Receive verlaat. Het aantal verwijzingen is nu 2. Wanneer de uitvoerpin het voorbeeld loslaat, wordt het aantal naar 1 verplaatst; het voorbeeld keert nog niet terug naar de pool. Nadat de werkdraad klaar is met het voorbeeld, wordt Release aangeroepen om het voorbeeld vrij te maken. Nu keert het voorbeeld terug naar de pool.

Wanneer een pincode een voorbeeld ontvangt, kan deze de gegevens naar een ander voorbeeld kopiëren of het oorspronkelijke voorbeeld wijzigen en deze aan het volgende filter leveren. Mogelijk kan een voorbeeld de hele lengte van de grafiek doorlopen, elk filter dat AddRef- aanroept en Release op zijn beurt. Daarom mag de uitvoerpin nooit opnieuw een voorbeeld gebruiken nadat deze Receiveaanroept, omdat een downstreamfilter mogelijk het voorbeeld gebruikt. De uitvoerpin moet altijd GetBuffer- aanroepen om een nieuw voorbeeld op te halen.

Dit mechanisme vermindert de hoeveelheid geheugentoewijzing, omdat filters dezelfde buffers opnieuw gebruiken. Het voorkomt ook dat filters per ongeluk gegevens kunnen schrijven die niet zijn verwerkt, omdat de allocator een lijst met beschikbare voorbeelden onderhoudt.

Een filter kan afzonderlijke toewijzingen gebruiken voor invoer en uitvoer. Dit kan worden uitgevoerd als de invoergegevens worden uitgebreid (bijvoorbeeld door deze te decomprimeren). Als de uitvoer niet groter is dan de invoer, kan een filter de gegevens verwerken zonder deze naar een nieuw voorbeeld te kopiëren. In dat geval kunnen twee of meer pinverbindingen één allocator delen.

Toewijzen en ontwijken van allocators

Wanneer een filter voor het eerst een allocator maakt, heeft de allocator geen geheugenbuffers gereserveerd. Op dit moment mislukken alle aanroepen naar de GetBuffer-methode. Wanneer het streamen start, roept de uitvoerpen IMemAllocator::Commitaan, wat de allocator activeert en daardoor geheugen toewijst. Pinnen kunnen nu GetBufferaanroepen.

Wanneer het streamen stopt, roept de pin IMemAllocator::Decommitaan, waardoor de allocator wordt gedecommitteerd. Alle volgende aanroepen naar GetBuffer mislukken totdat de allocator opnieuw is toegewezen. Als er momenteel aanroepen naar GetBuffer- worden geblokkeerd terwijl ze op een monster wachten, geven deze onmiddellijk een foutcode terug. De methode Decommit kan het geheugen al dan niet vrij maken, afhankelijk van de implementatie. De CMemAllocator klasse wacht bijvoorbeeld totdat de destructormethode geheugen vrijgeeft.

gegevensstroom in de filtergrafiek