동적 다시 연결

대부분의 DirectShow 필터에서 그래프가 데이터를 적극적으로 스트리밍하는 동안에는 핀을 다시 연결할 수 없습니다. 애플리케이션은 핀을 다시 연결하기 전에 그래프를 중지해야 합니다. 그러나 일부 필터는 그래프가 실행되는 동안 핀 다시 연결을 지원하며 동적 다시 연결이라고 하는 프로세스입니다. 이 작업은 애플리케이션 또는 그래프의 필터를 통해 수행할 수 있습니다.

예를 들어 다음 그림에서 그래프를 고려해 보세요.

dynamic graph-building diagram

동적 다시 연결의 한 가지 시나리오는 그래프가 실행되는 동안 그래프에서 필터 2를 제거하고 다른 필터로 바꾸는 것입니다. 이 시나리오가 작동하려면 다음이 true여야 합니다.

  • 필터 3(핀 D)의 입력 핀은 IPinConnection 인터페이스를 지원해야 합니다. 이 인터페이스를 사용하면 필터를 중지하지 않고 핀을 다시 연결할 수 있습니다.
  • 필터 1(핀 A)의 출력 핀은 다시 연결이 발생하는 동안 미디어 데이터의 흐름을 차단할 수 있어야 합니다. 다시 연결하는 동안 핀 A와 핀 D 사이를 이동할 수 있는 데이터는 없습니다. 일반적으로 출력 핀은 IPinFlowControl 인터페이스를 지원해야 합니다. 그러나 필터 1이 다시 연결을 시작하는 필터인 경우 자체 데이터 흐름을 차단하는 몇 가지 내부 메커니즘이 있을 수 있습니다.

동적 다시 연결에는 다음 단계가 포함됩니다.

  1. A 핀에서 데이터 스트림을 차단합니다.
  2. 핀 A를 다시 연결하여 새 중간 필터를 통해 D를 고정합니다.
  3. 데이터가 다시 흐르기 시작하도록 핀 A의 차단을 해제합니다.

1단계. 데이터 스트림 차단

데이터 스트림을 차단하려면 핀 A에서 IPinFlowControl::Block 을 호출합니다. 이 메서드는 비동기적으로 또는 동기적으로 호출할 수 있습니다. 메서드를 비동기적으로 호출하려면 Win32 이벤트 개체를 만들고 이벤트 핸들을 Block 메서드에 전달합니다. 메서드가 즉시 반환됩니다. WaitForSingleObject와 같은 함수를 사용하여 이벤트가 신호를 받을 때까지 기다립니다. 핀은 데이터 흐름을 차단했을 때 이벤트를 신호로 표시합니다. 예를 들어:

// 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);
    }
}

메서드를 동기적으로 호출하려면 이벤트 핸들 대신 NULL 값을 전달하면 됩니다. 이제 메서드는 작업이 완료될 때까지 차단됩니다. 핀이 새 샘플을 제공할 준비가 될 때까지는 이 작업이 수행되지 않을 수 있습니다. 필터가 일시 중지되면 임의의 시간이 걸릴 수 있습니다. 따라서 주 애플리케이션 스레드에서 동기 호출을 수행하지 마세요. 작업자 스레드를 사용하거나 메서드를 비동기적으로 호출합니다.

2단계. 핀 다시 연결

핀을 다시 연결하려면 IGraphConfig 인터페이스에 대한 Filter Graph Manager를 쿼리하고 IGraphConfig::Reconnect 또는 IGraphConfig::Reconfigure를 호출합니다. 다시 연결 메서드는 더 간단하게 사용할 수 있습니다. 다음을 수행합니다.

  • 중간 필터(예제의 필터 2)를 중지하고 그래프에서 제거합니다.
  • 필요한 경우 새 중간 필터를 추가합니다.
  • 모든 핀을 연결합니다.
  • 그래프의 상태와 일치하도록 새 필터를 일시 중지하거나 실행합니다.

다시 연결 메서드에는 핀 연결의 미디어 유형과 사용할 중간 필터를 지정하는 데 사용할 수 있는 몇 가지 선택적 매개 변수가 있습니다. 예를 들어:

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);     

자세한 내용은 참조 페이지를 참조하세요. 다시 연결 메서드가 충분히 유연하지 않은 경우 애플리케이션 정의 콜백 메서드를 호출하여 핀을 다시 연결하는 Reconfigure 메서드를 사용할 수 있습니다. 이 메서드를 사용하려면 애플리케이션에서 IGraphConfigCallback 인터페이스를 구현합니다.

Reconfigure를 호출하기 전에 앞에서 설명한 대로 출력 핀에서 데이터 흐름을 차단합니다. 그런 다음, 다음과 같이 다시 연결하려는 그래프 섹션에 보류 중인 모든 데이터를 푸시합니다.

  1. 재연결 체인의 가장 먼 다운스트림 입력 핀에서 IPinConnection::NotifyEndOfStream 을 호출합니다(예제의 핀 D). Win32 이벤트에 핸들을 전달합니다.
  2. 데이터 흐름을 차단한 출력 핀에서 즉시 다운스트림되는 입력 핀에서 IPin::EndOfStream 을 호출합니다. (이 예제에서는 핀 A에서 데이터 흐름이 차단되었으므로 핀 B에서 EndOfStream 을 호출합니다.)
  3. 이벤트가 신호를 받을 때까지 기다립니다. 입력 핀(핀 D)은 스트림 종료 알림을 받을 때 이벤트를 신호로 표시합니다. 이는 핀 사이를 이동하는 데이터가 없으며 호출자가 핀을 안전하게 다시 연결할 수 있음을 나타냅니다.

IGraphConfig::Reconnect 메서드는 이전 단계를 자동으로 처리합니다. Reconfigure 메서드를 사용하는 경우에만 이러한 단계를 수행해야 합니다.

데이터가 그래프를 통해 푸시되면 Reconfigure 를 호출하고 IGraphConfigCallback 콜백 인터페이스에 포인터를 전달합니다. 필터 Graph 관리자가 제공한 IGraphConfigCallback::Reconfigure 메서드를 호출합니다.

3단계: Data Flow 차단 해제

핀을 다시 연결한 후 첫 번째 매개 변수에 대해 값이 0인 IPinFlowControl::Block 을 호출하여 데이터 흐름의 차단을 해제합니다.

참고

필터에서 동적 다시 연결을 수행하는 경우 알아야 할 몇 가지 스레딩 문제가 있습니다. 필터 Graph 관리자가 필터를 중지하려고 하면 그래프가 필터가 중지될 때까지 대기하는 동시에 필터가 그래프를 통해 데이터가 푸시될 때까지 대기할 수 있으므로 교착 상태가 될 수 있습니다. 가능한 교착 상태를 방지하기 위해 이 섹션에 설명된 일부 메서드는 Win32 이벤트에 대한 핸들을 사용합니다. 필터 Graph 관리자가 필터를 중지하려고 하면 필터가 이벤트에 신호를 보내야 합니다. 자세한 내용은 IGraphConfigIPinConnection을 참조하세요.

 

동적 Graph 빌딩