Riconnessione dinamica

[La funzionalità associata a questa pagina, DirectShow, è una funzionalità legacy. È stata sostituita da MediaPlayer, FMMediaEngine 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, FMMediaEngine e Audio/Video Capture in Media Foundation anziché DirectShow, quando possibile. Microsoft suggerisce che il codice esistente che usa le API legacy venga riscritto per usare le nuove API, se possibile.

Nella maggior parte dei filtri DirectShow i pin non possono essere riconnessi mentre il grafico trasmette attivamente i dati. L'applicazione deve arrestare il grafico prima di riconnettersi ai pin. Tuttavia, alcuni filtri supportano la riconnessione dei pin mentre il grafico è in esecuzione, un processo noto come riconnessione dinamica. Questa operazione può essere eseguita dall'applicazione o da un filtro nel grafico.

Si consideri, ad esempio, il grafico nella figura seguente.

diagramma grafico dinamico

Uno scenario per la riconnessione dinamica potrebbe essere rimuovere Filtro 2 dal grafico, mentre il grafico è in esecuzione e sostituirlo con un altro filtro. Per il funzionamento di questo scenario, è necessario che sia true quanto segue:

  • Il pin di input in Filter 3 (pin D) deve supportare l'interfaccia IPinConnection . Questa interfaccia consente la riconnessione del pin senza arrestare il filtro.
  • Il pin di output su Filter 1 (pin A) deve essere in grado di bloccare il flusso di dati multimediali mentre si verifica la riconnessione. Nessun dato può spostarsi tra pin A e pin D durante la riconnessione. In genere, questo significa che il pin di output deve supportare l'interfaccia IPinFlowControl . Tuttavia, se Filter 1 è il filtro che avvia la riconnessione, potrebbe avere un meccanismo interno per bloccare il proprio flusso di dati.

La riconnessione dinamica prevede la procedura seguente:

  1. Bloccare il flusso di dati dal pin A.
  2. Riconnettersi a A per aggiungere D, eventualmente tramite un nuovo filtro intermedio.
  3. Sbloccare il pin A in modo che i dati inizino di nuovo a fluire.

Passaggio 1. Bloccare il flusso di dati

Per bloccare il flusso di dati, chiamare IPinFlowControl::Block nel pin A. Questo metodo può essere chiamato in modo asincrono o sincrono. Per chiamare il metodo in modo asincrono, creare un oggetto evento Win32 e passare l'handle eventi al metodo Block . Il metodo restituirà immediatamente. Attendere che l'evento venga segnalato usando una funzione come WaitForSingleObject. Il pin segnala l'evento quando ha bloccato il flusso di dati. Ad esempio:

// Create an event
HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (hEvent != NULL)
{
    // Block the data flow.
    hr = pFlowControl->Block(AM_PIN_FLOW_CONTROL_BLOCK, hEvent); 
    if (SUCCEEDED(hr))
    {
        // Wait for the pin to finish.
        DWORD dwRes = WaitForSingleObject(hEvent, dwMilliseconds);
    }
}

Per chiamare il metodo in modo sincrono, è sufficiente passare il valore NULL anziché l'handle eventi. A questo momento il metodo bloccherà fino al completamento dell'operazione. Questo potrebbe non verificarsi finché il pin non è pronto per distribuire un nuovo esempio. Se il filtro viene sospeso, questo può richiedere un intervallo di tempo arbitrario. Pertanto, non effettuare la chiamata sincrona dal thread dell'applicazione principale. Usare un thread di lavoro oppure chiamare il metodo in modo asincrono.

Passaggio 2. Riconnettere i pin

Per riconnettere i pin, eseguire una query su Filter Graph Manager per l'interfaccia IGraphConfig e chiamare IGraphConfig::Reconnect o IGraphConfig::Reconfigure. Il metodo Reconnect è più semplice da usare; esegue le operazioni seguenti:

  • Arresta i filtri intermedi (Filtro 2 nell'esempio) e li rimuove dal grafico.
  • Aggiunge nuovi filtri intermedi, se necessario.
  • Connette tutti i pin.
  • Sospende o esegue nuovi filtri per corrispondere allo stato del grafico.

Il metodo Reconnect include diversi parametri facoltativi che possono essere usati per specificare il tipo di supporto per la connessione pin e il filtro intermedio da usare. Ad esempio:

pGraph->AddFilter(pNewFilter, L"New Filter for the Graph");
pConfig->Reconnect(
    pPinA,      // Reconnect this output pin...
    pPinD,      // ... to this input pin.
    pMediaType, // Use this media type.
    pNewFilter, // Connect them through this filter.
    NULL, 
    0);     

Per informazioni dettagliate, consultare la pagina di riferimento. Se il metodo Reconnect non è abbastanza flessibile, è possibile usare il metodo Reconfigure , che chiama un metodo di callback definito dall'applicazione per riconnettere i pin. Per usare questo metodo, implementare l'interfaccia IGraphConfigCallback nell'applicazione.

Prima di chiamare Riconfigurazione, bloccare il flusso di dati dal pin di output, come descritto in precedenza. Eseguire quindi il push di tutti i dati ancora in sospeso nella sezione del grafico che si sta riconnettendo, come indicato di seguito:

  1. Chiamare IPinConnection::NotifyEndOfStream sul pin di input più lungo verso il basso nella catena di riconnessione (pin D nell'esempio). Passare un handle a un evento Win32.
  2. Chiamare IPin::EndOfStream sul pin di input immediatamente downstream dal pin di output in cui è stato bloccato il flusso di dati. In questo esempio il flusso di dati è stato bloccato al pin A, quindi si chiamerebbe EndOfStream nel pin B.
  3. Attendere che l'evento venga segnalato. Il pin di input (pin D) segnala l'evento quando riceve la notifica end-of-stream. Ciò indica che nessun dato è in viaggio tra i pin e che il chiamante può riconnettere in modo sicuro i pin.

Si noti che il metodo IGraphConfig::Reconnect gestisce automaticamente i passaggi precedenti. È necessario eseguire questi passaggi solo se si usa il metodo Reconfigure .

Dopo il push dei dati nel grafico, chiamare Reconfigura e passare un puntatore all'interfaccia di callback IGraphConfigCallback . Filter Graph Manager chiamerà il metodo IGraphConfigCallback::Reconfigure specificato.

Passaggio 3. Sbloccare il Flusso di dati

Dopo aver riconnesso i pin, sbloccare il flusso di dati chiamando IPinFlowControl::Block con un valore pari a zero per il primo parametro.

Nota

Se viene eseguita una riconnessione dinamica da un filtro, è necessario tenere presente alcuni problemi di threading. Se Filter Graph Manager tenta di arrestare il filtro, può arrestare il filtro, perché il grafico attende l'arresto del filtro, mentre allo stesso tempo il filtro potrebbe attendere il push dei dati tramite il grafico. Per evitare il deadlock possibile, alcuni dei metodi descritti in questa sezione accettano un handle per un evento Win32. Il filtro deve segnalare l'evento se Filter Graph Manager tenta di arrestare il filtro. Per altre informazioni, vedere IGraphConfig e IPinConnection.

 

Compilazione dinamica del grafico