다음을 통해 공유


DirectShow에 대한 원본 필터를 작성하는 방법

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

이 항목에서는 DirectShow에 대한 사용자 지정 원본 필터를 작성하는 방법을 설명합니다.

참고

이 항목에서는 푸시 원본에 대해서만 설명합니다. 비동기 판독기 필터와 같은 끌어오기 원본 또는 끌어오기 원본에 연결하는 분할기 필터는 설명하지 않습니다. 푸시 소스와 끌어오기 원본을 구분하려면 필터 개발자에 대한 Data Flow 참조하세요.

DirectShow 스트리밍 모델

원본 필터를 작성할 때는 푸시 소스가 라이브 원본과 동일하지 않다는 것을 이해하는 것이 중요합니다. 라이브 원본은 카메라 또는 네트워크 스트림과 같은 일부 외부 원본에서 데이터를 가져옵니다. 일반적으로 라이브 원본은 들어오는 데이터 속도를 제어할 수 없습니다. 다운스트림 필터가 데이터를 충분히 빠르게 사용하지 않는 경우 원본은 샘플을 삭제해야 합니다.

그러나 푸시 소스는 라이브 소스일 필요는 없습니다. 예를 들어 푸시 소스는 로컬 파일에서 데이터를 읽을 수 있습니다. 이 경우 다운스트림 렌더러 필터는 참조 클록 및 샘플 타임스탬프를 기반으로 원본의 데이터를 사용하는 속도를 결정합니다. 원본 필터는 가능한 한 빨리 샘플을 제공하지만 실제 데이터 흐름은 렌더러에 의해 제한됩니다. 데이터 흐름을 제어하는 메커니즘은 필터 개발자를 위한 Data Flow 설명되어 있습니다.

원본 필터의 각 출력 핀은 스트리밍 스레드라는 스레드를 만듭니다. 핀은 스트리밍 스레드에서 샘플을 제공합니다. 일반적으로 모든 디코딩, 처리 및 렌더링은 이 스레드에서 발생하지만 일부 다운스트림 필터는 출력 샘플을 큐에 대기시키는 추가 스레드를 만들 수 있습니다.

스트리밍 스레드는 다음 구조로 루프를 실행합니다.

until (stopped)
  1. Get a media sample from the allocator.
  2. Fill the sample with data.
  3. Time stamp the sample. 
  4. Deliver the sample downstream.

사용할 수 있는 샘플이 없는 경우 샘플을 사용할 수 있게 될 때까지 1단계가 차단됩니다. 4단계는 차단할 수도 있습니다. 예를 들어 그래프가 일시 중지되는 동안 차단할 수 있습니다.

루프는 가능한 한 빨리 실행되지만 렌더러 필터가 각 샘플을 렌더링하는 빈도에 따라 제한됩니다. 필터 그래프에 참조 클록이 있다고 가정하면 샘플의 프레젠테이션 시간에 따라 속도가 결정됩니다. 참조 클록이 없으면 렌더러는 가능한 한 빨리 샘플을 사용합니다.

CSource 및 CSourceStream 사용

DirectShow 기본 클래스에는 푸시 원본을 지원하는 두 가지 클래스인 CSource 및 CSourceStream 이 포함 됩니다.

  • CSource 는 필터의 기본 클래스이며 IBaseFilter 인터페이스를 구현합니다.
  • CSourceStream 은 출력 핀의 기본 클래스이며 IPin 인터페이스를 구현합니다.

출력 핀

원본 필터에는 둘 이상의 출력 핀이 있을 수 있습니다. 필터의 생성자 메서드에서 CSourceStream 에서 파생된 하나 이상의 핀을 만듭니다(출력 스트림당 하나의 핀). 핀에 대한 포인터를 저장할 필요가 없습니다. 핀을 만들 때 자동으로 필터에 추가합니다.

출력 형식

출력 핀은 다음 CSourceStream 메서드를 사용하여 형식 협상을 처리합니다.

메서드 Description
GetMediaType 출력 핀에서 미디어 형식을 가져옵니다.
핀은 다운스트림 필터가 형식을 제안하지 않을 수 있으므로 하나 이상의 미디어 형식을 제안해야 합니다. 대부분의 경우 다운스트림 필터는 소스 필터가 압축된 데이터 또는 압축되지 않은 데이터를 제공하는지 여부에 따라 디코더 또는 렌더러가 됩니다. 렌더러 필터에는 일반적으로 스트림을 렌더링하는 데 필요한 모든 형식 정보를 포함하는 전체 미디어 형식이 필요합니다. 디코더의 경우 미디어 형식에 필요한 정보의 양은 인코딩 형식에 따라 크게 달라집니다.
CheckMediaType 출력 핀이 지정된 미디어 형식을 허용하는지 확인합니다. GetMediaType을 구현하는 방법에 따라 이 메서드를 재정의하는 것은 선택 사항입니다.

GetMediaType 메서드가 오버로드됩니다.

원본 필터의 출력 핀이 정확히 하나의 미디어 형식을 지원하는 경우 (1)을 재정의하여 해당 형식으로 CMediaType 개체를 초기화해야 합니다. (2)의 기본 구현을 그대로 두고 CheckMediaType의 기본 구현도 그대로 둡니다.

핀이 둘 이상의 형식을 지원하는 경우 재정의(2)합니다. 인덱스 변수의 값에 따라 CMediaType 개체를 초기화합니다. 핀은 순서가 지정된 목록으로 형식을 반환해야 합니다. 이 경우 미디어 형식을 형식 목록에 검사 CheckMediaType도 재정의해야 합니다.

압축되지 않은 비디오 형식의 경우 다운스트림 필터는 다양한 보폭 값이 있는 형식을 제안할 수 있습니다. 필터는 유효한 보폭 값을 수락해야 합니다. 자세한 내용은 BITMAPINFOHEADER를 참조하세요.

또한 순수 가상 CBaseOutputPin::D ecideBufferSize 메서드를 재정의 해야 합니다. 이 메서드를 사용하여 샘플 버퍼의 크기를 설정합니다.

스트리밍

CSourceStream 클래스는 핀에 대한 스트리밍 스레드를 만듭니다. 스레드 프로시저는 CSourceStream::D oBufferProcessingLoop 메서드에서 구현됩니다. 이 메서드는 파생 클래스가 재정의해야 하는 순수 가상 CSourceStream::FillBuffer 메서드를 호출합니다. 이 메서드는 핀이 버퍼를 데이터로 채우는 위치입니다. 예를 들어 필터가 압축되지 않은 비디오를 제공하는 경우 비디오 프레임을 그릴 수 있습니다.

기본 클래스는 필터가 일시 중지되거나 중지되는 적절한 시간에 스레드 루프를 자동으로 시작하고 중지합니다. 이 경우 CSourceStream 클래스는 파생 클래스에 알리기 위해 몇 가지 메서드를 호출합니다.

특수 처리를 추가해야 하는 경우 이러한 메서드를 재정의할 수 있습니다. 그렇지 않으면 기본 구현은 단순히 S_OK 반환합니다.

추구

하나의 출력 핀이 있는 원본 필터가 있는 경우 CSourceSeeking 클래스를 검색을 구현하기 위한 시작점으로 사용할 수 있습니다. CSourceStreamCSourceSeeking 모두에서 핀 클래스를 상속합니다.

참고

출력 핀이 두 개 이상 있는 필터에는 CSourceSeeking을 사용하지 않는 것이 좋습니다. 기본 문제는 한 핀만 요청 요청에 응답해야 한다는 것입니다. 일반적으로 이를 위해서는 핀과 필터 간의 통신이 필요합니다.

CSourceSeeking 클래스는 재생 속도, 시작 시간, 중지 시간 및 기간을 관리합니다. 파생 클래스는 초기 중지 시간과 기간을 설정해야 합니다. 이러한 값 중 하나가 변경되면 CSourceSeeking::ChangeRate, CSourceSeeking::ChangeStart 또는 CSourceSeeking::ChangeStop 메서드가 적절하게 호출됩니다. 메서드는 모두 순수 가상 메서드입니다. 파생 핀 클래스는 다음을 수행하도록 이러한 메서드를 재정의합니다.

  1. 다운스트림 핀에서 IPin::BeginFlush 를 호출합니다. 이로 인해 다운스트림 필터가 보유하고 있는 샘플을 해제하고 새 샘플을 거부합니다.
  2. CSourceStream::Stop을 호출하여 스트리밍 스레드를 중지합니다. 원본 필터는 새 데이터 생성을 일시 중단합니다.
  3. 다운스트림 핀에서 IPin::EndFlush 를 호출합니다. 그러면 다운스트림 필터가 새 데이터를 수락하도록 신호를 보냅니다.
  4. 새 시작 및 중지 시간과 속도로 IPin::NewSegment 를 호출합니다.
  5. 다음 샘플에서 불연속성 속성을 설정합니다.

자세한 내용은 원본 필터에서 검색 지원을 참조하세요.

필터가 검색을 지원하는 경우 스트림 위치는 이제 프레젠테이션 시간과 독립적입니다. 검색 후 타임스탬프는 0으로 다시 설정됩니다. 타임스탬프를 위한 일반적인 수식은 다음과 같습니다.

  • 샘플 시작 시간 = 시간 경과/재생 속도
  • 샘플 종료 시간 = 샘플 시작 시간 + (프레임당 시간/재생 속도)

여기서 시간이 경과된 시간은 필터가 실행되기 시작한 이후 또는 마지막 seek 명령 이후 경과된 시간입니다.

검색을 위한 시간 형식

기본적으로 seek 명령은 100나노초 단위입니다. 원본 필터는 프레임 번호별 검색과 같은 추가 시간 형식을 지원할 수 있습니다. 형식이 GUID로 식별될 때마다 시간 형식 GUID를 참조하세요.

추가 시간 형식을 지원하려면 출력 핀에 다음 메서드를 구현해야 합니다.

애플리케이션이 새 시간 형식을 설정하는 경우 IMediaSeeking 메서드의 모든 위치 매개 변수가 새 시간 형식으로 해석됩니다. 예를 들어 시간 형식이 프레임인 경우 IMediaSeeking::GetDuration 메서드는 프레임에서 기간을 반환해야 합니다.

실제로 추가 시간 형식을 지원하는 DirectShow 필터는 거의 없으며, 결과적으로 이 기능을 사용하는 DirectShow 애플리케이션은 거의 없습니다.

원본 필터 작성