DMO 클래스 템플릿 사용
[이 페이지와 연결된 기능인 DirectShow는 레거시 기능입니다. MediaPlayer, IMFMediaEngine 및 Media Foundation의 오디오/비디오 캡처로 대체되었습니다. 이러한 기능은 Windows 10 및 Windows 11 최적화되었습니다. 가능한 경우 새 코드가 DirectShow 대신 Media Foundation에서 MediaPlayer, IMFMediaEngine 및 오디오/비디오 캡처를 사용하는 것이 좋습니다. 가능한 경우 레거시 API를 사용하는 기존 코드를 다시 작성하여 새 API를 사용하도록 제안합니다.]
DirectShow에는 DMA를 구현하기 위한 클래스 템플릿 IMediaObjectImpl이 포함되어 있습니다. 템플릿은 입력 매개 변수 유효성 검사와 같은 많은 "부기" 작업을 처리합니다. 템플릿을 사용하면 DMO와 관련된 기능에 집중할 수 있습니다. 또한 템플릿을 사용하면 강력한 구현을 만들 수 있습니다. 템플릿은 SDK의 Include 디렉터리에 있는 헤더 파일 Dmoimpl.h에 정의됩니다.
IMediaObjectImpl 템플릿은 IMediaObject 인터페이스를 상속합니다. 템플릿을 사용하여 DMO를 만들려면 IMediaObjectImpl에서 파생되는 새 클래스를 정의합니다. 템플릿은 모든 IMediaObject 메서드를 구현합니다. 대부분의 경우 템플릿은 파생 클래스에서 해당 프라이빗 메서드를 호출합니다. 템플릿은 다음과 같은 기능을 제공합니다.
- 기본 매개 변수 검사. 템플릿 메서드는 필요한 매개 변수가 NULL이 아니고, 스트림 인덱스가 범위 내에 있고, 플래그가 유효한지 확인합니다.
- 잠금. 템플릿 메서드는 두 개의 내부 메서드인 Lock 및 Unlock를 호출하여 DMO에서 작업을 직렬화합니다. 이 기능은 DMO가 스레드로부터 안전한지 확인합니다.
- 미디어 유형. 템플릿은 클라이언트에서 설정한 미디어 형식을 저장하고 미디어 형식에 대한 접근자 메서드를 제공합니다.
- 스트리밍. 템플릿은 클라이언트가 선택 사항이 아닌 모든 스트림에 대한 미디어 형식을 설정할 때까지 스트리밍을 방지합니다. 또한 스트리밍이 시작되기 전에 IMediaObject::AllocateStreamingResources 메서드가 호출되어 리소스가 할당되도록 보장합니다.
파생 클래스는 IUnknown 인터페이스를 구현해야 합니다. 템플릿은 이 인터페이스를 제공하지 않습니다. ATL(활성 템플릿 라이브러리)을 사용하여 IUnknown을 구현하거나 다른 구현을 제공할 수 있습니다. 템플릿은 잠금 메커니즘도 구현하지 않습니다. 파생 클래스는 Lock 및 Unlock 메서드를 구현해야 합니다. ATL을 사용하여 클래스를 만드는 경우 기본 ATL 구현을 사용할 수 있습니다.
파생 클래스 선언
IMediaObjectImpl 클래스 템플릿은 다음과 같이 선언됩니다.
template <class _DERIVED_, int NUMBEROFINPUTS, int NUMBEROFOUTPUTS>
class IMediaObjectImpl : public ImediaObject
세 가지 템플릿 매개 변수는 _DERIVED_, NUMBEROFINPUTS 및 NUMBEROFOUTPUTS입니다. _DERIVED_를 클래스의 이름과 동일하게 설정합니다. 다른 두 매개 변수는 DMO의 입력 스트림 수와 출력 스트림 수를 정의합니다. 예를 들어 하나의 입력 스트림과 두 개의 출력 스트림을 지원하는 CMyDmo라는 DMO 클래스를 만들려면 다음 선언을 사용합니다.
class CMyDmo : public IMediaObjectImpl<CMyDmo, 1, 2>
이 섹션의 나머지 부분에서는 템플릿이 IMediaObject에서 다양한 메서드를 구현하는 방법을 설명합니다.
미디어 형식 설정 방법
다음 메서드는 DMO에서 미디어 형식을 설정하거나 검색합니다.
- GetInputType, GetOutputType. 이러한 메서드는 스트림 번호 및 형식 인덱스별로 기본 미디어 형식을 반환합니다. 템플릿은 파생 클래스에서 InternalGetInputType 또는 InternalGetOutputType 을 호출합니다.
- SetInputType, SetOutputType. 이러한 메서드는 스트림에서 미디어 형식을 설정하거나, 미디어 형식을 테스트하거나, 미디어 형식을 지웁 수 있습니다. 미디어 형식의 유효성을 검사하기 위해 템플릿은 파생 클래스에서 InternalCheckInputType 또는 InternalCheckOutputType 을 호출합니다. 파생 클래스는 형식을 수락하는 S_OK 반환하거나 형식을 거부하는 DMO_E_INVALIDTYPE 반환합니다. 템플릿은 미디어 형식 설정 또는 지우기를 처리합니다.
- GetInputCurrentType, GetOutputCurrentType. 이러한 메서드는 스트림의 현재 미디어 형식을 반환하거나 형식이 설정되지 않은 경우 DMO_E_TYPE_NOT_SET. 템플릿은 이러한 메서드를 완전히 구현합니다.
정보 메서드
다음 메서드는 DMO에 대한 정보를 제공합니다.
- GetInputMaxLatency, SetInputMaxLatency. 이러한 메서드는 최대 대기 시간을 검색하거나 설정합니다. 템플릿은 파생 클래스 에서 InternalGetInputMaxLatency 또는 InternalSetInputMaxLatency 를 호출합니다.
- GetInputSizeInfo, GetOutputSizeInfo. 이러한 메서드는 지정된 스트림에 대한 DMO의 버퍼 요구 사항을 반환합니다. 해당 스트림에 미디어 형식이 설정되지 않은 경우 템플릿은 DMO_E_TYPE_NOT_SET 반환합니다. 그렇지 않으면 파생 클래스에서 InternalGetInputSizeInfo 또는 InternalGetOutputSizeInfo 를 호출합니다.
- GetInputStreamInfo, GetOutputStreamInfo. 이러한 메서드는 클라이언트가 데이터의 형식을 지정하는 방법을 나타내는 다양한 플래그를 반환합니다. 템플릿은 파생 클래스 에서 InternalGetInputStreamInfo 또는 InternalGetOutputStreamInfo 를 호출합니다.
- GetStreamCount. 이 메서드는 입력 및 출력 스트림의 수를 반환합니다. 템플릿은 템플릿 매개 변수를 사용하여 이 메서드를 구현합니다.
리소스 할당 방법
- AllocateStreamingResources 메서드는 스트리밍을 시작하기 전에 DMO에 필요한 모든 리소스를 할당합니다. FreeStreamingResources 메서드는 동일한 리소스를 해제합니다. 템플릿은 각각 InternalAllocateStreamingResources 및 InternalFreeStreamingResources를 호출합니다.
DMO의 클라이언트는 이러한 메서드를 호출할 필요가 없지만 스트리밍이 시작되기 전에 템플릿 에서 AllocateStreamingResources 를 자동으로 호출합니다. 따라서 DMO는 ProcessInput 이 호출된 시간까지 리소스가 올바르게 할당되었다고 가정할 수 있습니다. DMO는 소멸자에서 FreeStreamingResources 를 호출해야 합니다.
또한 템플릿이 InternalAllocateStreamingResources를 호출할 때 InternalFreeStreamingResources를 호출할 때까지 해당 메서드를 다시 호출하지 않도록 내부 플래그를 설정합니다. 이렇게 하면 리소스가 실수로 다시 할당되지 않으므로 메모리 누수가 발생할 수 있습니다.
스트리밍 메서드
다음 메서드는 데이터를 스트리밍하는 데 사용됩니다.
- GetInputStatus. 이 메서드는 DMO가 현재 입력을 허용할 수 있는지 여부를 나타냅니다. 템플릿은 파생 클래스에서 InternalAcceptingInput 을 호출합니다. DMO가 입력을 수락할 수 있는 경우 파생 클래스는 S_OK 반환하고 템플릿은 dwFlags 매개 변수에서 DMO_INPUT_STATUSF_ACCEPT_DATA 비트를 설정합니다. 그렇지 않으면 파생 클래스는 S_FALSE 반환하고 템플릿은 dwFlags를 0으로 설정합니다.
- ProcessInput. 이 메서드는 입력 버퍼를 처리합니다. 템플릿은 이전에 설명한 AllocateStreamingResources를 호출합니다. 그런 다음 파생 클래스에서 InternalAcceptingInput 을 호출합니다. DMO가 새 입력을 수락할 수 있는 경우 템플릿은 InternalProcessInput을 호출합니다.
- ProcessOutput. 이 메서드는 각 출력 스트림에 대해 하나의 버퍼인 출력 버퍼 집합을 처리합니다. 템플릿은 AllocateStreamingResources를 호출한 다음 InternalProcessOutput을 호출합니다.
- 불연속성. 이 메서드는 입력 스트림에서 불연속성을 알릴 수 있습니다. 템플릿은 파생 클래스에서 InternalAcceptingInput 을 호출합니다. 해당 메서드가 S_OK 반환하는 경우 템플릿은 파생 클래스에서 InternalDiscontinuity 를 호출합니다.
- 플러시. 이 메서드는 DMO를 플러시합니다. 템플릿은 파생 클래스에서 InternalFlush 를 호출합니다. DMO는 여전히 처리해야 하는 모든 입력 버퍼를 삭제해야 합니다.
템플릿은 IMediaObjectInPlace 인터페이스에 대한 직접적인 지원을 제공하지 않습니다.
잠금 메서드
잠금은 다중 스레드 환경에서 DMO의 상태를 보호하는 데 사용됩니다. ATL 프로젝트에서 IMediaObject::Lock 메서드는 이름이 ATL Lock 메서드와 충돌합니다. 충돌을 resolve 위해 템플릿은 IMediaObject 메서드의 이름을 DMOLock으로 바꿉니다. 파생 클래스를 컴파일할 때 헤더 파일 Dmo.h를 포함하기 전에 FIX_LOCK_NAME 정의합니다.
#define FIX_LOCK_NAME
#include <dmo.h>
이 지시문은 전처리기가 IMediaObject 인터페이스 선언에서 Lock용 DMOLock을 대체하도록 합니다. 애플리케이션은 vtable 순서가 변경되지 않으므로 Lock이라는 이름을 사용하여 메서드를 호출할 수 있습니다. DMOLock 메서드는 파생 클래스에서 Lock 또는 Unlock를 호출합니다. ATL을 사용하여 파생 클래스를 구현하는 경우 이러한 메서드는 이미 ATL에 의해 정의되어 있으므로 추가 코드가 필요하지 않습니다. ATL을 사용하지 않는 경우 파생 클래스에서 Lock 및 Unlock 메서드를 제공해야 합니다.
템플릿은 각 IMediaObject 메서드에서 DMO를 자동으로 잠가줍니다. 파생 클래스는 구현하는 다른 공용 메서드 내에서 DMO를 잠가야 할 수 있습니다(예: IMediaObjectInPlace를 지원하는 경우). 클래스 템플릿은 내부 도우미 클래스인 IMediaObjectImpl::LockIt도 제공합니다. 이 클래스는 DMO를 잠그고 잠금 해제하는 데 유용합니다.
요약
다음 IMediaObject 메서드의 경우 템플릿은 파생 클래스에서 동일한 서명을 가진 해당 메서드를 호출합니다. 파생 클래스는 두 번째 열에 표시된 각 메서드를 구현해야 합니다.
IMediaObject 메서드 | 파생 클래스 메서드 |
---|---|
AllocateStreamingResources | InternalAllocateStreamingResources |
불연속 | InternalDiscontinuity |
플러시 | InternalFlush |
FreeStreamingResources | InternalFreeStreamingResources |
GetInputMaxLatency | InternalGetInputMaxLatency |
GetInputSizeInfo | InternalGetInputSizeInfo |
GetInputStreamInfo | InternalGetInputStreamInfo |
GetInputType | InternalGetInputType |
GetOutputSizeInfo | InternalGetOutputSizeInfo |
GetOutputStreamInfo | InternalGetOutputStreamInfo |
GetOutputType | InternalGetOutputType |
ProcessInput | InternalProcessInput |
ProcessOutput | InternalProcessOutput |
SetInputMaxLatency | InternalSetInputMaxLatency |
나머지 IMediaObject 메서드의 경우 템플릿 메서드와 파생 클래스 메서드 간에는 일대일 대응이 없습니다. 다음 표에는 템플릿에서 완전히 구현되는 메서드와 파생 클래스에서 다른 메서드를 호출하는 메서드가 요약되어 있습니다.
IMediaObject 메서드 | 파생 클래스 메서드 |
---|---|
GetInputCurrentType | 완전히 구현됨 |
GetOutputCurrentType | 완전히 구현됨 |
GetStreamCount | 완전히 구현됨 |
GetInputStatus | InternalAcceptingInput |
잠금 ( DMOLock으로 구현) | 잠금, 잠금 해제 |
SetInputType | InternalCheckInputType |
SetOutputType | InternalCheckOutputType |
관련 항목