Creazione di un'origine multimediale personalizzata
Questo argomento descrive come implementare un'origine multimediale personalizzata in Microsoft Media Foundation. Contiene le sezioni seguenti:
- Creazione del descrittore di presentazione
- Avvio della sorgente multimediale
- Sospensione della sorgente multimediale
- Generazione di dati di origine
- Spegnimento della sorgente multimediale
- origini live
- argomenti correlati
Creazione del descrittore di presentazione
Il metodo IMFMediaSource::CreatePresentationDescriptor restituisce una copia del descrittore di presentazione dell'origine. Per creare il descrittore di presentazione, è necessario conoscere il numero di flussi nel contenuto di origine e i possibili formati di ogni flusso. Per ogni flusso, creare un descrittore di flusso come segue:
- Creare una matrice di tipi di supporti. Ogni tipo di supporto nella matrice rappresenta un formato possibile per il flusso. Per ulteriori informazioni su come creare tipi di supporto, vedere Tipi di supporto.
- Chiamare MFCreateStreamDescriptor per creare il descrittore di flusso. Passare l'array di tipi di media. La funzione restituisce un puntatore IMFStreamDescriptor.
- Chiamare IMFStreamDescriptor::GetMediaTypeHandler per ottenere il gestore del tipo di media del descrittore di flusso.
- Chiamare IMFMediaTypeHandler::SetCurrentMediaType per impostare il formato di flusso predefinito. Utilizza uno dei tipi di supporto creati nel passaggio 1. In genere, è consigliabile usare il formato con la massima qualità.
- Facoltativamente, impostare gli attributi nel descrittore di flusso. Per un elenco di attributi applicabili ai descrittori di flusso, vedere attributi del descrittore di flusso.
Creare ora il descrittore di presentazione:
- Chiamare MFCreatePresentationDescriptor e passare la matrice di descrittori di flusso. La funzione restituisce un puntatore IMFPresentationDescriptor.
- Scegliere la selezione del flusso predefinita chiamando IMFPresentationDescriptor::SelectStream per selezionare uno o più flussi. Nella configurazione predefinita deve essere selezionato almeno un flusso.
- Facoltativamente, impostare gli attributi nel descrittore di presentazione. Per un elenco di attributi applicabili ai descrittori di flusso, vedere attributi del descrittore di presentazione.
È necessario creare il descrittore di presentazione una sola volta, all'avvio o dopo che l'origine ha analizzato abbastanza dati di origine per determinare il contenuto. Il metodoCreatePresentationDescriptordeve restituire una copia del descrittore di presentazione. Per creare la copia, chiamare IMFPresentationDescriptor::Clone. La restituzione di una copia impedisce al client di modificare lo stato del descrittore di presentazione originale, ad esempio gli attributi o la selezione del flusso. Tenere tuttavia presente che Clone crea una copia superficiale, in modo che il client possa potenzialmente modificare i descrittori di flusso sottostanti.
Avvio dell'origine multimediale
Il metodo IMFMediaSource::Start avvia l'origine multimediale o effettua una ricerca verso una nuova posizione. Una chiamata a Start causa un di ricerca quando lo stato precedente è stato sospeso o in esecuzione e viene specificata una nuova ora di inizio. In caso contrario, il metodo Start provoca un avvio . Al termine dell'operazione Start, inviare gli eventi seguenti.
- Inviare un evento MENewStream per ogni nuovo flusso, ovvero ogni flusso deselezionato in precedenza ed è ora selezionato. I dati dell'evento sono un puntatore al flusso.
- Invia un evento MEUpdatedStream per ogni flusso che è stato selezionato in precedenza e risulta ancora selezionato. I dati dell'evento sono un puntatore al flusso. Non inviare un evento per i flussi deselezionati.
- Se l'origine sta cercando, inviare un MESourceSeeked evento. In caso contrario, inviare un evento MESourceStarted. I dati dell'evento sono l'ora di inizio specificata nel metodo Start. Per l'evento MESourceStarted, se l'ora di inizio è VT_EMPTY, assegnare l'attributo MF_EVENT_SOURCE_ACTUAL_START sull'evento. Il valore dell'attributo è l'ora di inizio effettiva.
- Per ogni flusso, se l'origine effettua una ricerca, inviare un evento MEStreamSeeked. In caso contrario, inviare un evento MEStreamStarted. I dati dell'evento sono l'ora di inizio. La sorgente multimediale può accodare un evento nel flusso chiamando il metodo IMFMediaEventGenerator::QueueEvent del flusso.
Quando un flusso viene deselezionato, arrestare il flusso. Il flusso non deve accodare ulteriori eventi a quel punto.
Il formato dell'ora per il metodo Start è specificato nel parametro pguidTimeFormat. Il formato ora standard, indicato da GUID_NULL, è di 100 nanosecondi. Una sorgente multimediale deve supportare questo formato orario.
Cercare
Durante la ricerca, la posizione iniziale richiesta potrebbe non rientrare in un confine di campione esatto. Inoltre, per il contenuto compresso, la posizione iniziale potrebbe essere compresa tra i fotogrammi chiave. Un flusso deve fornire campioni di dati dal punto iniziale necessario per produrre un campione non compresso alla posizione di inizio richiesta. Per il video, significa partire dal fotogramma chiave precedente. La pipeline è responsabile dell'eliminazione dei fotogrammi aggiuntivi dal decodificatore, in modo che la riproduzione venga avviata al momento richiesto.
L'ora di inizio specificata negli eventi di origine (MESourceStarted, MESourceSeeked, MEStreamStartede MEStreamSeeked) è l'ora di inizio richiesta (il valore specificato nel metodo Start), indipendentemente dalla posizione iniziale effettiva.
Si supponga, ad esempio, che i primi fotogrammi di un flusso video abbiano le caratteristiche seguenti:
Campione | 1 | 2 | 3 | 4 |
---|---|---|---|---|
Tempo | 33 msec | 66 millisecondi | 100 msec | 133 msec |
Fotogramma chiave? | Sì | No | No | Sì |
Se il metodo Start viene chiamato con un valore di 100 millisecondi, l'origine deve iniziare a riprodurre il video a partire dal fotogramma 1, il primo fotogramma chiave prima di questo momento. L'evento di avvio indicherà comunque 100 millisecondi nei dati dell'evento.
Sospensione della fonte multimediale
Il metodo IMFMediaSource::Pause sospende l'origine multimediale.
Quando la sorgente è sospesa, un flusso può creare nuovi campioni e archiviarli in una coda, ma non consegna i campioni. Ecco alcune eccezioni a questa regola:
- Le sorgenti live devono eliminare i dati in pausa.
- Se l'origine ottiene dati da una rete, potrebbe sospendere il server.
Se il client chiama IMFMediaStream::RequestSample mentre la sorgente è in pausa, la richiesta viene messa in coda finché la sorgente non viene riavviata. Le richieste non devono essere scartate.
La sospensione è consentita solo dallo stato avviato. In caso contrario, Pause dovrebbe restituire MF_E_INVALID_STATE_TRANSITION.
Generazione di dati di origine
Media Foundation usa un modello di pull , ovvero i flussi generano e recapitano campioni in risposta alle richieste dalla pipeline. Un flusso può consegnare campioni quando la sorgente multimediale è attiva e il flusso è selezionato. Un flusso recapita i dati solo quando il client richiede un nuovo esempio.
Richieste di esempio
Il client richiede un nuovo esempio chiamando IMFMediaStream::RequestSample. Ecco la sequenza di operazioni:
Il client chiama IMFMediaStream::RequestSample. L'argomento è un puntatore a un oggetto token facoltativo che il client usa per tenere traccia della richiesta. Il client implementa il token. I token devono esporre l'interfaccia IUnknown. Il client può anche passare un puntatore NULL anziché un token.
Se il client ha fornito un token, il flusso multimediale chiama AddRef sul token e inserisce il token in una coda FIFO (first-in, first-out). Il metodo restituisce e i passaggi rimanenti vengono eseguiti in modo asincrono.
Quando sono disponibili più dati, il flusso multimediale crea un nuovo esempio. Questo passaggio è descritto in modo più dettagliato nella sezione successiva.
Il flusso multimediale recupera il primo token dalla coda.
Se il token non è NULL, il flusso multimediale imposta l'attributo MFSampleExtension_Token nell'esempio multimediale. Il valore dell'attributo è un puntatore al token.
Il flusso multimediale invia un evento MEMediaSample. I dati dell'evento sono un puntatore all'interfaccia IMFSample dell'esempio.
Se il client ha fornito un token, il flusso multimediale chiama Release sull'oggetto token.
Se il flusso multimediale non riesce a soddisfare la richiesta di RequestSample del client, estrae il token dalla coda e chiama Release sul token, ma non invia un evento MEMediaSample.
Il client può usare il token per tenere traccia dello stato della richiesta. Quando il client riceve l'evento MEMediaSample, può ottenere il token dall'esempio e abbinarlo alla richiesta originale. Il client può anche usare il token per rilevare se l'origine multimediale ha eliminato la richiesta. Se il conteggio dei riferimenti del token è pari a zero e il flusso multimediale non invia un evento MEMediaSample, significa che la richiesta è stata eliminata.
I passaggi elencati di seguito presuppongono che metodo RequestSample venga implementato come operazione asincrona. Se il metodo è sincrono, non è necessario inserire il token di richiesta in una coda. Tuttavia, se la generazione di dati richiede una quantità significativa di tempo, è consigliabile un approccio asincrono, ad esempio se l'origine legge i dati da un flusso di byte.
Il flusso è responsabile del buffering di tutti i dati accumulati tra le chiamate a RequestSample.
Quando il flusso multimediale raggiunge la fine del flusso, invia un evento MEEndOfStream dopo l'ultimo esempio. Dopo la conclusione di ogni flusso, l'origine multimediale invia un evento MEEndOfPresentation. Dopo che un flusso multimediale invia l'evento MEEndOfStream, il metodo RequestSample restituisce MF_E_END_OF_STREAM fino al riavvio dell'origine.
Allocazione di esempi
Quando il flusso è pronto per compilare una richiesta di esempio in sospeso, crea un nuovo esempio e aggiunge uno o più buffer multimediali all'esempio. Per altre informazioni sulla creazione di buffer multimediali, vedere Buffer multimediali.
Il flusso deve impostare il marcatempo e la durata, se conosciuta. La marca temporale è relativa all'origine. Nella maggior parte dei casi, l'inizio del contenuto corrisponde a un timestamp pari a zero. Ad esempio, se l'origine legge da un file multimediale, l'inizio del file avrà un timestamp pari a zero.
Il timestamp dell'esempio non corrisponde necessariamente all'ora di presentazione. La sessione multimediale converte dal tempo di origine al tempo di presentazione. Per i dati compressi, il flusso deve generare dati a partire dal fotogramma chiave più vicino prima dell'ora di inizio. Ciò consente al decodificatore di fornire il fotogramma che appare all'orario di inizio richiesto. In caso contrario, il decodificatore dovrà attendere fino al fotogramma chiave seguente.
Se la velocità di riproduzione è più veloce o più lenta di 1,0, la pipeline regola la frequenza dell'orologio della presentazione. L'origine non regola i timestamp sui campioni.
L'origine può impostare informazioni aggiuntive sull'esempio impostando attributi. Per un elenco degli attributi di esempio, vedere attributi di esempio.
Lacune nel flusso
Se un flusso contiene una distanza di lunghezza significativa, è consigliabile che il flusso invii un evento MEStreamTick. Questo evento notifica al cliente che manca un campione. I dati dell'evento sono il timestamp del campione mancante, in unità di 100 nanosecondi (VT_I8). Questo evento può salvare i componenti downstream dall'attesa di campioni che non arriveranno. Il flusso può inviare tanti eventi MEStreamTick quanti necessari per colmare il gap nel flusso.
Chiusura della fonte multimediale
Quando il client termina l'utilizzo dell'origine multimediale, chiama IMFMediaSource::Shutdown. All'interno di questo metodo, l'origine multimediale deve interrompere qualsiasi conteggio di riferimenti circolari. In genere, ci saranno riferimenti circolari tra l'origine multimediale e i flussi multimediali.
Se si usa la coda di eventi per implementare IMFMediaEventGenerator, chiamare IMFMediaEventQueue::Shutdown nella coda di eventi. Questo metodo arresta la coda di eventi e segnala qualsiasi chiamante in attesa di un evento.
Dopo l'arresto, tutti i metodi sull'origine restituiscono MF_E_SHUTDOWN, ad eccezione dei metodi IUnknown.
Fonti dal vivo
A partire da Windows 7, Media Foundation supporta automaticamente i dispositivi di acquisizione audio e video. Per il video, il dispositivo deve fornire un minidriver di streaming kernel (KS) nella categoria di acquisizione video. Media Foundation usa il percorso PnP per enumerare il dispositivo. Per l'audio, Media Foundation usa l'API MMDevice (Windows Multimedia Device) per enumerare i dispositivi endpoint audio. Se il dispositivo soddisfa questi criteri, non è necessario implementare un'origine multimediale personalizzata.
Tuttavia, è possibile implementare un'origine multimediale personalizzata per un altro tipo di dispositivo o un'altra origine dati live. Esistono solo alcune differenze tra un'origine live e altre origini multimediali:
- Nel metodo IMFMediaSource::GetCharacteristics, restituisce il flag MFMEDIASOURCE_IS_LIVE.
- Il primo esempio deve avere un timestamp pari a zero.
- Gli eventi e gli stati di streaming vengono gestiti come origini multimediali, ad eccezione dello stato di pausa.
- Durante la pausa, non mettere in coda i campioni. Eliminare tutti i dati generati durante la pausa.
- Le fonti in diretta in genere non supportano la ricerca, la riproduzione inversa o il controllo della velocità.
Argomenti correlati