동적 다시 연결

[이 페이지와 연결된 기능인 DirectShow는 레거시 기능입니다. MediaPlayer, IMFMediaEngine 및 Media Foundation의 오디오/비디오 캡처로 대체되었습니다. 이러한 기능은 Windows 10 및 Windows 11 최적화되었습니다. 가능한 경우 새 코드가 DirectShow 대신 Media Foundation에서 MediaPlayer, IMFMediaEngine오디오/비디오 캡처를 사용하는 것이 좋습니다. 가능한 경우 레거시 API를 사용하는 기존 코드를 다시 작성하여 새 API를 사용하도록 제안합니다.]

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

예를 들어 다음 그림에서 그래프를 고려합니다.

동적 그래프 작성 다이어그램

동적 다시 연결의 한 가지 시나리오는 그래프가 실행되는 동안 그래프에서 필터 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)를 중지하고 그래프에서 제거합니다.
  • 필요한 경우 새 중간 필터를 추가합니다.
  • 모든 핀을 연결합니다.
  • 그래프의 상태와 일치하도록 새 필터를 일시 중지하거나 실행합니다.

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

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

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

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

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

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

데이터가 그래프를 통해 푸시된 후 Reconfigure 를 호출하고 IGraphConfigCallback 콜백 인터페이스에 포인터를 전달합니다. Filter Graph Manager는 제공한 IGraphConfigCallback::Reconfigure 메서드를 호출합니다.

3단계: Data Flow 차단 해제

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

참고

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

 

동적 그래프 빌드