Riconnessione dinamica

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 riconnettere i pin. Tuttavia, alcuni filtri supportano le riconnessioni dei pin durante l'esecuzione del grafico, 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.

dynamic graph-building diagram

Uno scenario per la riconnessione dinamica potrebbe essere rimuovere Il filtro 2 dal grafico, mentre il grafico è in esecuzione e sostituirlo con un altro filtro. Per il corretto funzionamento di questo scenario, è necessario che siano soddisfatte le condizioni seguenti:

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

La riconnessione dinamica prevede i passaggi seguenti:

  1. Bloccare il flusso di dati dal pin A.
  2. Riconnettere il pin A al pin D, possibilmente tramite un nuovo filtro intermedio.
  3. Sbloccare l'elemento A in modo che i dati inizino nuovamente a fluire.

Passaggio 1. Bloccare il flusso di dati

Per bloccare il flusso di dati, chiamare IPinFlowControl::Block al 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 di evento 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 dell'evento. Il metodo verrà bloccato fino al completamento dell'operazione. Questa situazione potrebbe non verificarsi finché il pin non è pronto per distribuire un nuovo esempio. Se il filtro è sospeso, questa operazione può richiedere un periodo 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, in modo che corrispondano 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, vedere la pagina di riferimento. Se il metodo Reconnect non è sufficientemente 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 Reconfigure, 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ù a valle della catena di riconnessione (pin D nell'esempio). Passare un handle a un evento Win32.
  2. Chiamare IPin::EndOfStream sul pin di input immediatamente a valle 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 è necessario chiamare EndOfStream sul pin B.
  3. Attendere che l'evento venga segnalato. Il pin di input (pin D) segnala l'evento quando riceve la notifica di fine flusso. Ciò indica che non sono presenti dati che si spostano 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 Reconfigure e passare un puntatore all'interfaccia di callback IGraphConfigCallback . Filter Graph Manager chiamerà il metodo IGraphConfigCallback::Reconfigure fornito.

Passaggio 3. Sbloccare il Flusso di dati

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

Nota

Se una riconnessione dinamica viene eseguita da un filtro, è necessario tenere presente alcuni problemi di threading. Se filter Graph Manager tenta di arrestare il filtro, può bloccarlo, perché il grafico attende che il filtro venga arrestato, mentre allo stesso tempo il filtro potrebbe attendere che i dati vengano inseriti nel grafico. Per evitare il possibile deadlock, 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.

 

Edificio Graph dinamico