Vytváření vlastního mediálního zdroje
Toto téma popisuje, jak implementovat vlastní zdroj médií ve službě Microsoft Media Foundation. Obsahuje následující části:
- Vytvoření prezentačního popisovače
- spuštění zdroje médií
- pozastavení zdroje médií
- generování zdrojových dat
- Vypnutí zdroje médií
- Živé Zdroje
- související témata
Vytvoření popisovače prezentace
Metoda IMFMediaSource::CreatePresentationDescriptor vrátí kopii popisovače prezentace zdroje. Pokud chcete vytvořit popisovač prezentace, musíte znát počet datových proudů ve zdrojovém obsahu a možné formáty jednotlivých datových proudů. Pro každý datový proud vytvořte popisovač datového proudu následujícím způsobem:
- Vytvořte pole typů médií. Každý typ média v poli představuje možný formát datového proudu. Další informace o vytváření typů médií naleznete v tématu Typy médií.
- Vyvolejte MFCreateStreamDescriptor k vytvoření popisovače datového proudu. Předejte pole typů médií. Funkce vrátí POINTERSTREAMDescriptor.
- Volání IMFStreamDescriptor::GetMediaTypeHandler pro získání popisovače typu média streamu.
- Zavolejte IMFMediaTypeHandler::SetCurrentMediaType k nastavení výchozího formátu datového proudu. Použijte jeden z typů médií, které jste vytvořili v kroku 1. Obecně byste měli použít formát s nejvyšší kvalitou.
- Volitelně můžete nastavit atributy popisovače datového proudu. Seznam atributů, které se vztahují na popisovače datových proudů, naleznete v tématu Atributy popisovače streamu.
Teď vytvořte popisovač prezentace:
- Volejte MFCreatePresentationDescriptor a předejte pole popisovačů datových proudů. Funkce vrátí MMFPresentationDescriptor ukazatel.
- Zvolte výběr výchozího datového proudu zavoláním IMFPresentationDescriptor::SelectStream pro výběr jednoho nebo více datových proudů. Ve výchozí konfiguraci musí být vybrán alespoň jeden datový proud.
- Volitelně můžete nastavit atributy popisovače prezentace. Seznam atributů, které se vztahují na popisovače datových proudů, naleznete v tématu Atributy popisovače prezentace.
Popisovač prezentace byste měli vytvořit jednou, a to buď při spuštění, nebo po zpracování dostatečného množství zdrojových dat k určení obsahu. Metoda CreatePresentationDescriptor by měla vrátit kopii popisovače prezentace. Chcete-li vytvořit kopii, zavolejte IMFPresentationDescriptor::Clone. Vrácení kopie zabrání klientovi v úpravě stavu původního popisovače prezentace, jako jsou atributy nebo výběr datového proudu. Mějte ale na paměti, že Clone vytvoří mělkou kopii, takže klient může potenciálně upravit popisovače podkladového datového proudu.
Spuštění zdroje médií
Metoda MMFMediaSource::Start spustí zdroj médií nebo se pokusí o novou pozici. Volání Zahájení způsobí přesun, pokud byl předchozí stav pozastaven nebo spuštěn, a je zadán nový čas zahájení. Jinak metoda Start způsobí spuštění. Po dokončení operace Spuštění odešlete následující události.
- Odešlete událost MENewStream pro každý nový datový proud – tedy pro každý datový proud, který byl dříve odznačen a nyní je znovu vybrán. Data události jsou ukazatelem na datový proud.
- Odeslat událost MEUpdatedStream pro každý datový proud, který byl dříve vybrán a je stále vybraný. Data události jsou ukazatelem na datový proud. (Neposílejte událost pro nevybrané streamy.)
- Pokud zdroj hledá, odešlete UDÁLOST MESourceSeeked. V opačném případě odešlete událost MESourceStarted. Data události jsou počáteční čas zadaný v metodě Start. Pro událost MESourceStarted, pokud je čas spuštění VT_EMPTY, nastavte atribut MF_EVENT_SOURCE_ACTUAL_START na události. Hodnota atributu je skutečný čas zahájení.
- Pro každý datový proud, pokud zdroj hledá, odešle MEStreamSeeked událost. V opačném případě odešlete událost MEStreamStarted. Data události je počáteční čas. (Zdroj médií může zařadit událost do fronty datového proudu voláním IMFMediaEventGenerator::QueueEvent metoda.)
Když se zruší výběr datového proudu, vypněte datový proud. Stream by v tomto okamžiku neměl zařadovat žádné další události do fronty.
Formát času pro metodu Start je uveden v parametru pguidTimeFormat. Standardní formát času označený GUID_NULLje 100 nanosekundových jednotek. Zdroj médií musí tento formát času podporovat.
Hledání
Při hledání nemusí požadovaná počáteční pozice spadat na přesnou hranici vzorku. U komprimovaného obsahu může počáteční pozice spadat mezi klíčové snímky. Proud by měl dodávat vzorky od počátečního bodu potřebného k vytvoření nekomprimovaného vzorku na požadované zahajovací pozici. Pro video to znamená, že se začíná od předchozího klíčového snímku. Kanál je zodpovědný za vyřazení dalších snímků z dekodéru, aby se přehrávání spouštělo v požadované době.
Počáteční čas zadaný ve zdrojových událostech (MESourceStarted, MESourceSeeked, MEStreamStarteda MEStreamSeeked) je požadovaný počáteční čas (hodnota zadaná v metodě Start), bez ohledu na skutečnou počáteční pozici.
Předpokládejme například, že několik prvních snímků streamu videa má následující charakteristiky:
Ukázka | 1 | 2 | 3 | 4 |
---|---|---|---|---|
Čas | 33 msec | 66 msec | 100 msec | 133 msec |
Klíčový snímek? | Ano | Ne | Ne | Ano |
Pokud je volána metoda Start s hodnotou 100 milisekund, zdroj musí vyprodukovat video od snímku 1, klíčového snímku, který je před tímto časem. Počáteční událost bude stále indikovat 100 milisekund v datech události.
Pozastavení zdroje médií
Metoda IMFMediaSource::Pause pozastaví zdroj médií.
Zatímco je zdroj pozastaven, stream může vytvářet nové vzorky a ukládat je do fronty, ale stream tyto vzorky nedoručuje. Toto pravidlo má několik výjimek:
- Živé zdroje by měly během pozastavení vypustit data.
- Pokud zdroj získává data ze sítě, může server pozastavit.
Pokud klient volá IMFMediaStream::RequestSample, zatímco je zdroj pozastaven, požadavek se zařadí do fronty, dokud se zdroj znovu nespustí. Požadavky by neměly být opomenuty.
Pozastavení je povoleno pouze ze spuštěného stavu. V opačném případě by měla pozastavit a vrátit MF_E_INVALID_STATE_TRANSITION.
Generování zdrojových dat
Media Foundation používá pull model, což znamená, že streamy generují a doručují vzorky v reakci na požadavky z pipeline. Tok může doručovat ukázky, když je mediální zdroj spuštěný a tok je vybraný. Datový proud doručuje data pouze v případech, kdy klient požádá o novou ukázku.
Ukázkové požadavky
Klient požádá o novou ukázku voláním MMFMediaStream::RequestSample. Tady je posloupnost operací:
Klient volá MMFMediaStream::RequestSample. Argument je ukazatel na volitelný token objekt, který klient používá ke sledování požadavku. Klient implementuje token. Tokeny musí vystavit rozhraní IUnknown. Klient může místo tokenu předat také ukazatel NULL.
Pokud klient poskytl token, mediální stream zavolá AddRef na token a umístí token do fronty podle principu první dovnitř, první ven. Metoda se vrátí a zbývající kroky probíhají asynchronně.
Pokud je k dispozici více dat, datový proud médií vytvoří nový vzorek. (Tento krok je podrobněji popsán v další části.)
Datový proud médií načítá první token z fronty.
Pokud token není NULL, mediální proud nastaví atribut MFSampleExtension_Token na mediálním vzorku. Hodnota atributu je ukazatel na token.
Mediální datový proud odešle událost MEMediaSample. Data události jsou ukazatelem na rozhraní MMFSample ukázky.
Pokud klient poskytl token, datový proud médií volá Release objektu tokenu.
Pokud datový proud médií nemůže splnit požadavek RequestSample klienta, vytáhne token z fronty a vyvolá Release na tokenu, ale neodešle událost MEMediaSample.
Klient může token použít ke sledování stavu požadavku. Když klient obdrží událost MEMediaSample, může získat token z ukázky a spárovat ho s původním požadavkem. Klient může také pomocí tokenu zjistit, jestli zdroj médií žádost zrušil. Pokud referenční počet tokenu klesne na nulu a událost MEMediaSample není odesílána datovým proudem médií, znamená to, že požadavek byl zamítnut.
Zde uvedené kroky předpokládají, že RequestSample metoda je implementována jako asynchronní operace. Pokud je metoda synchronní, není nutné dávat token požadavku do fronty. Pokud však generování dat trvá nějakou dobu, doporučuje se asynchronní přístup – například pokud zdroj čte data z bajtového streamu.
Stream zodpovídá za ukládání všech dat do vyrovnávací paměti, která se hromadí mezi voláními RequestSample.
Když datový proud médií dosáhne konce proudu, odešle MEEndOfStream událost po posledním vzorku. Po ukončení každého datového proudu odešle zdroj médií událost MEEndOfPresentation. Jakmile datový proud médií odešle událost MEEndOfStream, RequestSample metoda vrátí MF_E_END_OF_STREAM, dokud se zdroj nerestartuje.
Přidělování ukázek
Když je stream připraven k vyplnění čekající žádosti o vzorky, vytvoří nový vzorek a přidá k němu jednu nebo více vyrovnávacích pamětí médií. Další informace o vytváření mediálních vyrovnávacích pamětí naleznete pod tématem vyrovnávací paměti médií.
Datový proud musí nastavit časové razítko a dobu trvání, pokud je to známo. Časové razítko je relativní vzhledem ke zdroji. Ve většině případů začátek obsahu odpovídá časovému razítku nula. Pokud například zdroj čte z mediálního souboru, začátek souboru by měl časové razítko nuly.
Časové razítko vzorku nemusí nutně odpovídat času prezentace. Mediální relace převádí ze zdrojového času na čas prezentace. U komprimovaných dat by datový proud měl generovat data od nejbližšího rámce klíče před počátečním časem. Tím se umožní dekodéru doručit snímek, který bude zobrazen ve stanoveném počátečním čase. (V opačném případě by dekodér potřeboval počkat na následující klíčový snímek.)
Pokud je rychlost přehrávání rychlejší nebo pomalejší než 1,0, zpracovatelský řetězec upraví rychlost hodin prezentace. Zdroj neupravuje časové razítka u ukázek.
Zdroj může nastavit další informace o ukázce nastavením atributů. Pro seznam ukázkových atributů viz Ukázkové atributy.
Mezery ve streamu
Pokud datový proud obsahuje mezeru s významnou délkou, doporučuje se, aby stream odeslal událost MEStreamTick. Tato událost upozorní klienta, že chybí vzorek. Data události jsou časové razítko chybějícího vzorku v 100 nanosekundových jednotkách (VT_I8). Tato událost může ušetřit následující komponenty od čekání na vzorky, které nedorazí. Stream může posílat libovolný počet událostí MEStreamTick podle potřeby, aby překlenul mezeru v datovém proudu.
Vypnutí zdroje médií
Když klient dokončí používání zdroje médií, volá IMFMediaSource::Shutdown. V rámci této metody by měl zdroj médií přerušit všechny počty cyklických referencí. Mezi zdrojem médií a mediálními proudy se obvykle budou vyskytovat cyklické odkazy.
Pokud používáte frontu událostí k implementaci IMFMediaEventGenerator, zavolejte IMFMediaEventQueue::Shutdown ve frontě událostí. Tato metoda vypne frontu událostí a signalizuje všechny volající, kteří aktuálně čekají na událost.
Po vypnutí vrátí všechny metody na zdroji MF_E_SHUTDOWN, s výjimkou metod IUnknown .
Živé zdroje
Počínaje Windows 7 služba Media Foundation automaticky podporuje zařízení pro zachytávání zvuku a videa. Pro video musí zařízení poskytnout minidriver streamování jádra (KS) v kategorii zachycení videa. Služba Media Foundation používá k vytvoření výčtu zařízení cestu PnP. Pro zvuk používá Media Foundation rozhraní API Windows Multimedia Device (MMDevice) k výčtu zařízení zvukových koncových bodů. Pokud zařízení splňuje tato kritéria, není nutné implementovat vlastní zdroj médií.
Můžete ale chtít implementovat vlastní zdroj médií pro nějaký jiný typ zařízení nebo jiný živý zdroj dat. Mezi živým zdrojem a jinými zdroji médií existuje jen několik rozdílů:
- V metodě IMFMediaSource::GetCharacteristics vraťte příznak MFMEDIASOURCE_IS_LIVE.
- První ukázka by měla mít časové razítko s hodnotou nula.
- Události a stavy streamování se zpracovávají stejně jako zdroje médií s výjimkou pozastaveného stavu.
- Během pozastavení nezařazujte vzorky do fronty. Odstraňte všechna data vygenerovaná při pozastavení.
- Živé zdroje obvykle nepodporují hledání, zpětné přehrávání nebo řízení rychlosti.
Související témata