Condividi tramite


Stati filtro

[La funzionalità associata a questa pagina, DirectShow, è una funzionalità legacy. È stata sostituita da MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation. Queste funzionalità sono state ottimizzate per Windows 10 e Windows 11. Microsoft consiglia vivamente che il nuovo codice usi MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation invece di DirectShow, quando possibile. Microsoft suggerisce che il codice esistente che usa le API legacy venga riscritto per usare le nuove API, se possibile.

I filtri hanno tre possibili stati: arrestati, sospesi e in esecuzione. Lo scopo dello stato sospeso è indicare i dati nel grafico, in modo che un comando di esecuzione risponda immediatamente. Filter Graph Manager controlla tutte le transizioni di stato. Quando un'applicazione chiama IMediaControl::Run, IMediaControl::P ause o IMediaControl::Stop, Filter Graph Manager chiama il metodo IMediaFilter corrispondente su tutti i filtri. Le transizioni tra l'arresto e l'esecuzione passano sempre allo stato sospeso, quindi se l'applicazione chiama Esegui su un grafico arrestato, Filter Graph Manager sospende il grafico prima di eseguirlo.

Per la maggior parte dei filtri, gli stati in esecuzione e sospesi sono identici. Si consideri il grafico di filtro seguente:

Renderer trasformazione > origine >

Si supponga ora che il filtro di origine non sia un'origine di acquisizione dinamica. Quando il filtro di origine viene sospeso, crea un thread che genera nuovi dati e lo scrive nei campioni multimediali il più rapidamente possibile. Il thread "esegue il push" degli esempi downstream chiamando IMemInputPin::Receive sul pin di input del filtro di trasformazione. Il filtro di trasformazione riceve gli esempi nel thread del filtro di origine. Può usare un thread di lavoro per recapitare gli esempi al renderer, ma in genere li recapita nello stesso thread. Mentre il renderer è sospeso, attende di ricevere un esempio. Dopo averne ricevuto uno, blocca e mantiene il campione per un periodo illimitato. Se si tratta di un renderer video, visualizza l'esempio come immagine poster, aggiornando l'immagine in base alle esigenze.

A questo punto, il flusso è completamente cued e pronto per il rendering. Se il grafico rimane sospeso, i campioni verranno "accumulati" nel grafico dietro il primo campione, fino a quando ogni filtro non viene bloccato in Receive o IMemAllocator::GetBuffer. Tuttavia, non viene perso alcun dato. Una volta sbloccato, il thread di origine riprende semplicemente dal punto in cui è bloccato.

Il filtro di origine e il filtro di trasformazione ignorano la transizione dall'esecuzione sospesa all'esecuzione, semplicemente continuano a elaborare i dati il più velocemente possibile. Tuttavia, quando viene eseguito il renderer, avvia il rendering degli esempi. Prima di tutto esegue il rendering dell'esempio mantenuto mentre è stato sospeso. Quindi, ogni volta che riceve un nuovo campione, calcola il tempo di presentazione dell'esempio. Per informazioni dettagliate, vedere Time and Clocks in DirectShow.) Il renderer contiene ogni esempio fino all'ora della presentazione, a quel punto esegue il rendering dell'esempio. Mentre attende l'ora di presentazione, si blocca nel metodo Receive o riceve nuovi esempi in un thread di lavoro con una coda. I filtri upstream dal renderer non sono coinvolti nella pianificazione.

Le origini live, ad esempio i dispositivi di acquisizione, sono un'eccezione a questa architettura generale. Con un'origine dinamica, non è appropriato in anticipo individuare i dati. L'applicazione potrebbe sospendere il grafico e attendere molto tempo prima di eseguirlo. Il grafico non deve eseguire il rendering di esempi "non aggiornati". Pertanto, un'origine dinamica non produce campioni durante la sospensione, solo durante l'esecuzione. Per segnalare questo fatto a Filter Graph Manager, il metodo IMediaFilter::GetState del filtro di origine restituisce VFW_S_CANT_CUE. Questo codice restituito indica che il filtro è passato allo stato sospeso, anche se il renderer non ha ricevuto dati.

Quando un filtro si arresta, rifiuta altri campioni recapitati. I filtri di origine arrestano i thread di streaming e altri filtri arrestano tutti i thread di lavoro che potrebbero aver creato. I pin decommettono i loro allocatori.

Transizioni di stato

Filter Graph Manager esegue tutte le transizioni di stato nell'ordine upstream, a partire dal renderer e eseguiti all'indietro nel filtro di origine. Questo ordinamento è necessario per impedire l'eliminazione dei campioni e per impedire che il grafico venga deadlocking. Le transizioni di stato più cruciali sono tra pause e arrestate:

  • Arrestato per essere sospeso: quando ogni filtro viene sospeso, diventa pronto per ricevere campioni dal filtro successivo. Il filtro di origine è l'ultimo da sospendere. Crea il thread di streaming e inizia a distribuire esempi. Poiché tutti i filtri downstream vengono sospesi, nessun filtro rifiuta alcun campione. Filter Graph Manager non completa la transizione fino a quando ogni renderer nel grafico non ha ricevuto un esempio, ad eccezione delle origini attive, come descritto in precedenza.
  • Sospeso per l'arresto: quando un filtro si arresta, rilascia tutti gli esempi contenuti, che sblocca tutti i filtri upstream in attesa in GetBuffer. Se il filtro è in attesa di una risorsa all'interno del metodo Receive , interrompe l'attesa e la restituzione da Receive, che sblocca il filtro chiamante. Pertanto, quando Filter Graph Manager arresta il filtro upstream successivo, tale filtro non è bloccato in GetBuffer o Receive e può rispondere al comando stop. Il filtro upstream potrebbe fornire alcuni esempi aggiuntivi prima di ottenere il comando stop, ma il filtro downstream li rifiuta semplicemente perché è già stato arrestato.

Flusso di dati nel grafico dei filtri