Distribuzione di esempi

[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.

Questo articolo descrive come un filtro fornisce un esempio. Descrive sia il modello push che i metodi IMemInputPin e il modello pull usando IAsyncReader.

Modello push: distribuzione di un esempio

Il pin di output fornisce un esempio chiamando il metodo IMemInputPin::Receive o il metodo IMemInputPin::ReceiveMultiple , equivalente ma fornisce una matrice di esempi. Il pin di input può bloccarsi all'interno di Receive (o ReceiveMultiple). Se il pin potrebbe bloccarsi, il metodo IMemInputPin::ReceiveCanBlock deve restituire S_OK. Se il pin non viene mai bloccato, ReceiveCanBlock deve restituire S_FALSE. Il valore restituito S_OK non significa che Receive blocchi sempre, solo che potrebbe.

Anche se Receive può bloccare l'attesa della disponibilità di una risorsa, non deve bloccare l'attesa di altri dati dal filtro upstream. In questo modo può verificarsi un deadlock in cui il filtro upstream attende il rilascio del filtro downstream, che non si verifica mai perché il filtro downstream è in attesa del filtro upstream. Se un filtro ha più pin di input, tuttavia, un pin può attendere che un altro pin riceva i dati. Ad esempio, il filtro AVI Mux esegue questa operazione in modo che possa interleave i dati audio e video.

Un pin può rifiutare un campione per diversi motivi:

  • Il pin sta scaricando (vedi Scaricamento).
  • Il pin non è connesso.
  • Il filtro viene arrestato.
  • Si è verificato un altro errore.

Il metodo Receive deve restituire S_FALSE nel primo caso e un codice di errore negli altri casi. Il filtro upstream deve interrompere l'invio di campioni quando il codice restituito è diverso da S_OK.

È possibile considerare i primi tre casi come errori "previsti", nel senso che il filtro si trovava nello stato errato per ricevere campioni. Un errore imprevisto è quello che fa sì che il pin rifiuti un campione anche se il pin si trova in uno stato di ricezione. Se si verifica un errore di questo tipo, il pin deve inviare una notifica end-of-stream downstream e inviare un evento EC_ERRORABORT a Filter Graph Manager.

Nelle classi di base DirectShow il metodo CBaseInputPin::CheckStreaming verifica la presenza di casi di errore generali, ovvero scaricamento, arresto e così via. La classe derivata dovrà verificare la presenza di errori specifici del filtro. In caso di errore, il metodo CBaseInputPin::Receive invia la notifica end-of-stream e l'evento EC_ERRORABORT.

Modello pull: richiesta di un esempio

Nell'interfaccia IAsyncReader il pin di input richiede esempi dal pin di output chiamando uno dei metodi seguenti:

Il metodo Request è asincrono; il pin di input chiama IAsyncReader::WaitForNext per attendere il completamento della richiesta. Gli altri due metodi sono sincroni.

Quando recapitare i dati

Un filtro fornisce sempre campioni mentre è in esecuzione. Nella maggior parte dei casi, un filtro fornisce anche campioni durante la sospensione. In questo modo il grafico rileva i dati in modo che la riproduzione venga avviata immediatamente quando viene chiamato Esegui (vedere Stati filtro). Se il filtro non recapita i dati durante la sospensione, il metodo IMediaFilter::GetState del filtro deve restituire VFW_S_CANT_CUE nello stato sospeso. Questo codice restituito segnala al grafico di filtro di non attendere i dati dal filtro prima di completare la transizione di sospensione. In caso contrario, il metodo Pause verrà bloccato per un periodo illimitato. Ad esempio, vedere CBaseFilter::GetState.

Ecco alcuni esempi di quando un filtro potrebbe dover restituire VFW_S_CANT_CUE:

  • Le origini attive, ad esempio i filtri di acquisizione, non devono inviare dati durante la sospensione. Vedere Produzione di dati in un filtro di acquisizione.
  • Un filtro di divisione potrebbe o non inviare dati durante la sospensione, a seconda dell'implementazione. Se il filtro usa thread separati per accodare i dati in ogni pin di output, può inviare dati durante la sospensione. Tuttavia, se il filtro usa un singolo thread per ogni pin di output, il primo pin potrebbe bloccare il thread quando chiama Receive, che impedirà agli altri pin di inviare dati. In tal caso, è necessario restituire VFW_S_CANT_CUE.
  • Un filtro potrebbe recapitare i dati sporadicamente. Ad esempio, potrebbe analizzare un flusso di dati personalizzato e filtrare alcuni pacchetti durante il recapito di altri. In tal caso, il filtro potrebbe non essere garantito per recapitare i dati durante la sospensione.

Un filtro di origine (usando il modello push) o un filtro parser (usando il modello push/pull) crea uno o più thread di streaming, che forniscono i campioni il più rapidamente possibile. I filtri downstream, ad esempio decodificatori e trasformazioni, in genere inviano dati solo quando Receive viene chiamato sui relativi pin di input.

Ricezione e distribuzione di esempi