Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
[Funkce přidružená k této stránce DirectShow je starší funkce. Byla nahrazena MediaPlayer, MMFMediaEnginea Audio/Video Capture v Media Foundation. Tyto funkce jsou optimalizované pro Windows 10 a Windows 11. Microsoft důrazně doporučuje, aby nový kód používal MediaPlayer, MMFMediaEngine a Audio/Video Capture v Media Foundation místo DirectShow, pokud je to možné. Microsoft navrhuje, aby se stávající kód, který používá starší rozhraní API, přepsal, aby se nová rozhraní API používala, pokud je to možné.]
Když pin doručí mediální data jinému pinu, nepředá přímý ukazatel do paměťového bufferu. Místo toho doručí ukazatel na objekt COM, který spravuje paměť. Tento objekt, označovaný jako ukázka média, poskytuje rozhraní IMediaSample. Přijímající pin přistupuje k vyrovnávací paměti voláním metod IMediaSample, jako je IMediaSample::GetPointer, IMediaSample::GetSizea IMediaSample::GetActualDataLength.
Vzorky vždy proudí po směru, od výstupního pinu až po vstupní pin. V modelu push výstupní pin doručí ukázku voláním IMemInputPin::Receive na vstupním pinu. Vstupní pin buď zpracuje data synchronně (tj. zcela uvnitř metody Receive), nebo je zpracuje asynchronně v pracovním vlákně. Vstupní pin smí blokovat v metodě Receive, pokud potřebuje čekat na zdroje.
Další objekt COM, nazývaný alokátor, zodpovídá za vytváření a správu vzorků médií. Alokátory zpřístupňují IMemAllocator rozhraní. Pokaždé, když filtr potřebuje ukázku média s prázdnou vyrovnávací pamětí, volá IMemAllocator::GetBuffer metoda, která vrátí ukazatel na ukázku. Každé pinové spojení sdílí jeden alokátor. Když se dva piny spojí, určí se, který filtr poskytne alokátor. Kolíky také nastavují vlastnosti pro alokátor, například počet vyrovnávacích pamětí a velikost každé vyrovnávací paměti. (Podrobnosti najdete v tématu Jak se filtry připojují a vyjednávání o alokátorech.)
Následující obrázek znázorňuje vztahy mezi alokátorem, ukázkami médií a filtrem.
Referenční počty ukázek médií
Alokátor vytvoří konečný fond vzorků. Kdykoli se mohou některé ukázky používat, zatímco jiné jsou k dispozici pro volání GetBuffer. Alokátor pomocí počítání referencí sleduje vzorky. Metoda GetBuffer vrátí vzorek s počtem odkazů rovným 1. Pokud počet odkazů klesne na nulu, vzorek se vrátí do fondu alokátoru, kde může být použit v příštím volání GetBuffer. Pokud počet odkazů zůstává nad nulou, není vzorek k dispozici pro GetBuffer. Pokud se používá každý vzorek, který patří do alokátoru, metoda GetBuffer blokuje, dokud není dostupný žádný vzorek.
Předpokládejme, že vstupní pin dostane vzorek. Pokud zpracovává ukázku synchronně uvnitř metody Receive, nezvýšuje počet odkazů. Jakmile receive vrátí, výstupní špendlík uvolní ukázku, počet odkazů přejde na nulu a ukázka se vrátí do fondu alokátoru. Na druhou stranu, pokud vstupní kolík zpracovává ukázku na pracovním vlákně, zvýší počet referencí před opuštěním metody Receive. Počet odkazů je teď 2. Když výstupní pin uvolní vzorek, počet přejde na 1; vzorek se ještě nevrátí do zásobníku. Po dokončení pracovního vlákna s ukázkou volá Release, aby uvolnilo ukázku. Teď se vzorek vrátí do bazénu.
Když pin obdrží vzorek, může zkopírovat data do jiného vzorku, nebo může upravit původní vzorek a doručit jej do dalšího filtru. Vzorek může cestovat potenciálně celou délkou grafu, přičemž každý filtr volá AddRef a Release. Výstupní pin proto nesmí po zavolání funkce Receivenikdy znovu použít vzorek, protože následující filtr může tento vzorek používat. Výstupní pin musí vždy volat GetBuffer, aby získal nový vzorek.
Tento mechanismus snižuje množství alokace paměti, protože filtry znovu používají stejné vyrovnávací paměti. Také zabraňuje tomu, aby filtry náhodně přepsaly data, která nebyla zpracována, protože alokátor udržuje seznam dostupných vzorků.
Filtr může pro vstup a výstup použít samostatné alokátory. Může to udělat, pokud rozšíří vstupní data (například dekomprimací). Pokud výstup není větší než vstup, může filtr zpracovávat data na místě, aniž by je zkopíroval do nové ukázky. V takovém případě můžou dvě nebo více propojení pinů sdílet jeden alokátor.
Přiřazení a uvolnění alokátorů
Když filtr poprvé vytvoří alokátor, alokátor nezahradí žádné vyrovnávací paměti. V tuto chvíli se nezdaří všechna volání metody GetBuffer. Při spuštění streamování výstupní pin volá IMemAllocator::Commit, který potvrdí alokátor, a tím přidělí paměť. Piny nyní mohou volat GetBuffer.
Když se streamování zastaví, špendlík volá IMemAllocator::Decommit, čímž uvolní alokátor. Všechna následná volání GetBuffer selžou, dokud nedojde k opětovnému přidělení alokátoru. Pokud jsou některá volání GetBuffer aktuálně zablokována při čekání na vzorek, okamžitě vrátí kód selhání. Metoda Decommit může nebo nemusí uvolnit paměť v závislosti na implementaci. Například třída CMemAllocator čeká, až její metoda destruktoru uvolní paměť.
Související témata