bookmark_borderDirectShow 각 종 강좌 및 정보들 링크 모음.

 


2009/07/05 01:09 키보드예술




  1. DirectShow 강좌, 커뮤니티 혹은 각 종 정보



  2. DirectShow 관련 개발 보조 유틸리티



  3. DirectShow SDK



  4. COM 강좌



.
1. DirectShow 강좌, 커뮤니티 혹은 각 종 정보


– 멀티즘연합 – 디렉터  (★)


http://cafe.naver.com/multism 


네이버 카페로서 각 종 멀티미디어 개발 관련 분야를 다루는 곳이다.


DirectShow 분류에는 윤훈남님의 동영상 강의 뿐만 아니라 각종 팁들, 그리고 QnA까지 다루고 있다.



윤훈남의 DirectShow 강좌


1 DirectShow 개요1
2 DirectShow 개요2
3 COM 개념 이해
4 DirectShow, COM, 스마트 포인터(8장)
5 GraphBuilder의 인터페이스(9장)
6 프로그램 스킬과 PID(10장)
7 캡쳐디바이스


윤훈남의 DirectShow Filter 제작하기


1 DirectShow Filter FrameWork1-CMediaSample
2 DirectShow Filter FrameWork1-CBaseAllocator/CMemAllocator
3 DirectShow Filter FrameWork1-CMediaType
4 DirectShow Filter FrameWork1-CBasePin(타입 협상)
5 DirectShow Filter FrameWork1-CBaseOutputPin/CBaseInputPin(버퍼 협상)
6 DirectShow Filter FrameWork1-CDynamicOutputPin(동적 핀 연결)
7 DirectShow Filter FrameWork1-CBaseFilter
8 DirectShow Filter FrameWork1-CAMEvent/CAMThread 


__________


– DirectShow  (★)


http://www.dshowtech.com/ 


IT 백두대간 DirectShow 멀티미디어 프로그래밍의 저자 사이트이자 커뮤니티.


상당히 많은 양의 축적된 QnA들을 통해 정보를 얻기에 큰 도움이 된다.


또한 DirectShow 관련 정보와 강좌들이 있다. 


__________


DirectShow Multimedia project group(DMPG)  (★)


http://www.devpia.com/club_1092.MAEUL 


Devpia의 DirectShow 마을이다. 각 종 유명한 강좌나 팁 및 방대한 QnA 자료가 있다.


‘박성규’님의 DirectShow와 COM 강좌가 유명하다. 


__________


– CodeProject DirectShow Part


http://www.codeproject.com/ 


많은 양의 다양한 Directshow Application과 Code들이 깔끔하게 설명된 문서를 제공한다.


__________


– Looting – Game Programming


http://telnet.or.kr/main.html 


DIrectX 관련 문서 및 커뮤니티


DirectShow SDK 9.0 도움말(?)을 사이트 상에서 열람 할 수 있다. 


__________


– DirectShow MVP TMH’s Home


http://tmhare.mvps.org/ 


Microsoft MVP로써 DirectShow, Window Media and Multimedia들의 각 종 정보를 제공.


또한 Link페이지를 통해 유용한 사이트들을 제공한다. 


__________


– ‘도모네 IT 세상’ 블로그


http://blog.naver.com/netrance?redirect ··· 49276005 



DirectShow 관련 포스팅


[DirectShow][COM] COM 클라이언트와 COM 서버       
[Directshow][COM] COM 라이브러리 초기화하기       
[DirectShow][GraphEdit] 코덱을 추가로 설치하면 만들 수 있는 필터 그래프       
[DirectShow][GraphEdit] 필터 그래프 예       
[DirectShow][GraphEdit] GraphEdit로 필터 그래프를 생성하는 방법       
[DirectShow] 필터(filter), 핀(pin), 필터 그래프(filter graph), 필터 그래프 매니저(filter graph manager)       
[DirectShow] 최초 DirectShow 어플리케이션 만들어 보기       
[DirectShow] Platform SDK를 이용한 DirectShow SDK 설치하기      


__________


– ‘마법사 하르의 엉망진창 실험실’ 블로그


http://enshahar.tistory.com 



[DirectShow 기초] 필터그래프 안에서의 데이터 흐름
[DirectShow Reference] IGraphBuilder
[DirectShow 기초] 필터와 핀
[DirectShow 기초] 필터와 필터그래프
[DirectShow 기초] File Play
[DirectShow 기초] Introduction 


__________


– ‘김대영 입니다.’ 블로그


http://kostyoung.egloos.com/category/%e ··· 25b8x9.0 



3.1.5. 필터그래프와 하드웨어 장치들 연결
3.1.4.미디어 예제와 배치자(Allocator)에 관한것
3.1.3. 미디어 타입에 관한것 [2]
3.1.2. 필터그래프 매니져에 관한것
3.1.1. 다이렉트쇼 필터에 대한것
3.1. 필터그래프와 그의 컴포넌트들
3.1. 다이렉트쇼 시스템 개요
3.0. 다이렉트쇼에 관하여
2.1. How To Play a File
2.0. Getting Started
1.1. DirectShow 소개 [4]
1.0. DirectShow


__________


– COM (Component Object Model) 과 DirectShow


http://diehard98.tistory.com/entry/com- ··· rectshow 


__________


– DirectShow Filter 운영


http://devholic.tistory.com/2  


__________


– MPEG, DirectShow, Windows Media and Filter Merit


http://www.timna.org/dshowmpeg.html 


Filter 매핍과 관련된 글. 


__________


– TP, TS 샘플 파일 다운로드 구하기 HD 영상 HDTV 1080i 720p MPEG-2 파일


http://hallang.tistory.com/85  


– DirectShow Filter 에 Interface 간단 추가


http://dynaforce.tistory.com/21  


__________


– ‘당신은 거기에 있습니까?’ 블로그


http://titorus.com/category/프로그래밍/d ··· 2520show 



DShow 환경 설정
기본 Direct Show Filter 만들기 (변환필터)
VS 6.0 에서 Filter 만들기 설정
DirectShow Filter 제작
미디어 타입 맞추기  


__________


– 디버그 출력 함수


http://www.telnet.or.kr/directx/htm/deb ··· ions.htm 


 


2. DirectShow 관련 개발 보조 유틸리티


– DirectShow Filter Manager  (★)


http://www.softella.com/dsfm/ 


설치된 DirectShow Filter들을 리스트로 분류하여 각 종 정보를 제공하고, 검색 그리고 제거 등을 손쉽게 할 수 있게 해주는 유틸


필터 사용시 상당히 편리하다.


__________


– Media Info (★)


http://mediainfo.sourceforge.net/ko 


비디오나 오디오 파일을 분석하여 파일이나 코덱 정보들을 제공하는 유틸.  아래의 VideoInspector보다 깔끔하다.


__________


– VideoInspector


http://www.kcsoftwares.com/index.php?vtb 


Meida Info와 비슷한 툴로써 미디어 파일의 정보를 제공하는 유틸


__________


– DirectShow Filter Mapper Utility


http://www.timna.org/dshowmpeg.html 


DirectShow Filter를 검색하여 매핑 여부를 판단해주는 유틸(?)  (자세하게 사용해보지 않았다.)


3. DirectShow Sample Code 및 Demo Application


– guliverkli (★)


http://sourceforge.net/projects/guliverkli/ 


DIrectShow에선 유명한 프로젝트로서 각 종 Filter나 DirectShow를 이용한 Application등 많은 양의 소스를 얻을 수 있다.


__________


– GDCL



http://www.gdcl.co.uk/ 



상당량의 각 종 DirectShow Filter들에 관련 정보들과 샘플 소스를 제공한다.



20090702 Tools and Samples for Download


Windows Mobile ViewGraph tool
Monitor Filter
Serialize Filter
Mpeg-4 Demultiplexor and Multiplexor filters
WMV/WMA Parser
GMFBridge toolkit
MPEG-1 Parser
FSFWrap
AppFilter
IPFilter
OvTool
YUVXfm
InlineClasses.zip


4. DirectShow SDK 


– Microsoft Directshow MSDN


http://msdn.microsoft.com/en-us/library ··· %29.aspx 


__________


vc6.0을 마지막으로 지원하는 platform SDK와 DirectX


http://glintist.egloos.com/2337943 


__________


– Windows® Server 2003 SP1 Platform SDK Web Install


http://www.microsoft.com/downloads/deta ··· filelist 


__________


– DirectX 9.0 SDK Update (October 2004) Extras


http://www.microsoft.com/downloads/than ··· 53d%253d 


__________


– Visual Studio 6.0으로 DirectShow 프로그래밍을 하다 만나는 문제점들…


http://www.nohungry.net/tt1/84 


http://blog.naver.com/elkiss?redirect=l ··· 41578870 


5. COM 강좌


– Step by Step Com Tutorial


http://www.codeguru.com/cpp/com-tech/ac ··· %2Fc5567 

bookmark_borderVisual Studio 2008 에서 DirectShow Filter 개발환경 구축하기





Visual Studio 2008 에서 DirectShow Filter 개발환경 구축하기 MultiMedia

2009/07/09 00:19

복사 http://blog.naver.com/kimjb1216/10052492478




시중에 나온 DirectShow 서적을 보면 예제가 모두 Visual C++ 6.0 기반으로 작성되어 있고 개발환경을 구축하는 방법 역시 VC++ 6.0 기준으로 되어있다. 따라서 이 글은 초보자가 최신 환경에서 DirectShow Filter를 개발할 수 있도록 개발환경을 구축하는 정보를 제공하기 위해 작성되었다.

DirectShow를 기반으로 한 애플리케이션을 개발하기 위해서는 일반적으로 아래와 같은 파일들이 필요하다. 하지만 아래 파일들이 버전이 바뀌어 감에 따라 이리저리 옮겨가고 심지어는 직접 빌드해서 사용해야 하기 때문에 사용자들에게 혼란을 주고 초보자가 개발환경을 구축하는데 어려운 점이 발생해 흔히 말하는 ‘삽질’을 하게 된다. (-_-;)





















 종류 파일 명 비 고
헤더 파일
(Include File)
 dshow.h  
 라이브러리 파일
(Library File)
 strmiids.lib  
 quartz.lib  
 strmbasd.lib (Debug 용)
 strmbase.lib (Release 용)
 

DirectShow는 DirectX에 포함되어 배포되어 왔으나 DirectX 9.0 SDK (February 2005)를 마지막으로 이후부터 Windows SDK에 포함되기 시작하였다. 따라서 February 2005 이후 버전의 개발환경을 설정을 하려면 다른 방법을 사용해야만 한다.  

MSDN에 DirectShow 관련 페이지에 있는 안내 구문
http://msdn.microsoft.com/en-us/library/dd375454(VS.85).aspx

Previous versions of the DirectShow SDK shipped as part of the DirectX SDK. The last version of the DirectX SDK that included DirectShow was “DirectX 9.0 SDK Update – (February 2005) Extras.” The DirectShow SDK was moved to the Windows SDK starting with the Microsoft® Windows Server 2003 SP1 Platform SDK. To get the latest DirectShow SDK, download the latest version of the Windows SDK.


기준 환경 : Windows XP 이상, Visual Studio 2005, 2008 이상

1. Microsoft SDK 와 Microsoft DirectX 를 다운로드 받는다.




2. Microsoft SDK 와 Microsoft DirectX 를 설치한다.

3. Visual Studio 2008에 포함파일(Include File)과 라이브러리 파일(Library File) 경로를 등록해 준다.

Visual Studio 2008 메뉴에서 도구 < 옵션 < 프로젝트 및 솔루션 < VC++ 디렉토리에서

포함파일(Include File)을 선택한 후 아래의 경로를 추가해 준다.



  • 설치된 Microsoft SDK 경로\Windows\v6.0\Samples\Multimedia\DirectShow\BaseClasses
  • 설치된 Microsoft DirectX SDK 경로\Include
  • 설치된 Microsoft SDK 경로\Windows\v6.0\Include



라이브러리 파일(Library File)을 선택한 후 아래의 경로를 추가해 준다.

  • 설치된 Microsoft DirectX SDK 경로\Lib\x86
  • 설치된 Microsoft SDK 경로\Windows\v6.0\Lib\x86

4. BaseClasses 빌드

이전 버전의 DirectShow에서는 strmbasd.lib 파일이 함께 포함되어 있지만 Windows SDK로 옮겨진 후에는 이 파일을 등록된 라이브러리 디렉토리 안에서 찾을 수 없다. 따라서 아래 경로에 있는 BaseClasses 샘플을 빌드하여 라이브러리 디렉토리로 옮겨서 사용하여야만 한다.

먼저 설치된 Microsoft SDK 경로\Windows\v6.0\Samples\Multimedia\DirectShow\BaseClasses 경로에 있는 프로젝트를 연다.

Debug 모드로 빌드 후 아래와 같이 Debug 디렉토리 내 strmbasd.lib 파일이 생성된 것을 확인 할 수 있다. Release 모드로 빌드한 경우 역시 Release 디렉토리 내 strmbase.lib 파일이 생성되어 있을 것이다.

각각 두 파일의 용도는 서로 다르다. 디버그 모드에서 라이브러리를 링크할 때는 strmbasd.lib, 릴리즈 모드에서 라이브러리를 링크할 때는  strmbase.lib를 사용하면 된다.



strmbasd.lib 파일과 strmbase.lib 파일을 “설치된 Microsoft SDK 경로\Windows\v6.0\Lib” 로 옮긴다.
2~3까지 과정은 VS 2008의 VC++ 모든 프로젝트에 해당되므로 한번만 작업해주면 된다.

5. 개발환경 구축 완료

여기까지 DirectShow Filter를 개발하기 위한 개발환경을 구축하는 법을 알아보았다. 다음에는 간단한 필터 제작을 해보면서 개발환경이 잘 작동하는지 확인해 보도록 하겠다.




bookmark_border기본 Direct Show Filter 만들기 (변환필터)

첨부파일audio_volume-sampoo00.zip

1. 새 프로젝트

File -> New -> Project… 

 

 

Win32 / Win32 Project 선택 , 폴더를 선택하고 Name 을 입력합니다. 여기서는 “audio_volume” 프로젝트로
프로젝트 명을 정하겠습니다.

다음 페이지에서 Application type을 DLL 로 Application option 은 Empty project 로
선택합니다.

2. Filter 만들기

CLSID, interface IID, interface 정의 등을  가지는 헤더파일을 하나 만듭니다.

프로젝트의 헤더파일에서 추가> 새항목으로 새로운 헤더파일을 하나 추가합니다.

헤더파일의 이름은 audio_types.h” 로 합니다.

 

새로운 필터를 위한 class ID를 생성하기 위해서는 도구 -> GUID 만들기 를 사용합니다.

 필자는 “static const struct GUID ….” 항목을 주로 사용합니다.

새롭게 생성된 GUID를 위해 “CLSID_AudioVolume” 라는 이름을 사용하도록 하겠습니다.

아래는 audio_types.h 의 내용입니다.

// {212A25F7-7000-4f74-9E4C-6FFB3F595EE4}

static const GUID CLSID_AudioVolume =
{
0×212a25f7, 0×7000, 0×4f74, { 0×9e, 0×4c, 0×6f, 0xfb, 0×3f, 0×59, 0×5e, 0xe4 }
};

filter 를 위한 기본 헤더파일을 만듭니다. 파일명은 “audio_filter.h” 로 하고 아래의 코드를 추가시킵니다.

#pragma once

class AudioVolume : public CTransformFilter
{
private:
    CMediaType        mtIn;
public:
    // constructor &
destructor

    AudioVolume(LPUNKNOWN pUnk, HRESULT *phr);
   
virtual ~AudioVolume();
    static CUnknown *WINAPI CreateInstance(LPUNKNOWN pUnk,
HRESULT *phr);

   // CTransformFilter overriden
    virtual HRESULT CheckInputType(const CMediaType *mtIn);
    virtual HRESULT CheckTransform(const CMediaType *mtIn, const
CMediaType *mtOut);
    virtual HRESULT
DecideBufferSize(IMemAllocator *pAlloc,

                                                      ALLOCATOR_PROPERTIES
*pProp); 
    virtual HRESULT GetMediaType(int iPosition, CMediaType *pmt);
    virtual HRESULT SetMediaType(PIN_DIRECTION direction, const CMediaType *pmt);
    virtual HRESULT Transform(IMediaSample *pIn, IMediaSample
*pOut);
};

다음은 filter 구현을 위해 cpp 파일을 추가합니다. 파일명은 “audio_filter.cpp” 로 하고 다음 코드를
써줍니다.

아래는 생성자와 소멸자 그리고 audio filter 의 인스턴스를 넘겨주는 정적 메소드 입니다.

AudioVolume::AudioVolume(LPUNKNOWN pUnk, HRESULT *phr) :
   
CTransformFilter(NAME(“Audio Volume”), pUnk,
CLSID_AudioVolume)
{
    if (phr) *phr =
NOERROR;
}

AudioVolume::~AudioVolume()
{
}

CUnknown *WINAPI AudioVolume::CreateInstance(LPUNKNOWN pUnk, HRESULT *phr)

{
    AudioVolume *vol = new
AudioVolume(pUnk, phr);
    if (!vol) {

        if (phr) *phr = E_OUTOFMEMORY;
    }

    return vol;

}

이제 우리는 CTransformFilter 의 함수들을 오버라이딩 해야되는데요..

upstream 필터가 현재 필터에 연결되기 위해서는 첫번째로 적당한 media type을 협상하게 됩니다.

여기서는 16-bit raw PCM audio data만 허용할 것입니다.

그래서 AudioVolume::CheckMediaType 함수를 아래와 같이 override 합니다.

HRESULT AudioVolume::CheckInputType(const
CMediaType *mtIn)
{
    // we only want raw
audio

    if (mtIn->majortype !=
MEDIATYPE_Audio) return E_FAIL;
    if (mtIn->subtype != MEDIASUBTYPE_PCM) return E_FAIL;
    if
(mtIn->formattype != FORMAT_WaveFormatEx) return
E_FAIL;

   // and we only want 16-bit
   
WAVEFORMATEX    *wfx = (WAVEFORMATEX*)mtIn->pbFormat;
    if (wfx->wBitsPerSample != 16) return E_FAIL;

    return NOERROR;

}

우리 필터는 encode/decode 또는 데이터를 스크렘블 하지 않고 그냥 PCM audio 를 내보낼 것입니다.

HRESULT AudioVolume::CheckTransform(const
CMediaType *mtIn, const CMediaType *mtOut)
{

    HRESULT hr = CheckInputType(mtIn);
    if
(FAILED(hr)) return hr;

   // must also be PCM audio
    if (mtOut->majortype != MEDIATYPE_Audio) return E_FAIL;
    if
(mtOut->subtype != MEDIASUBTYPE_PCM) return
E_FAIL;

    return NOERROR;

}

입력 media type과 출력 media type을 동일하게 하기 위해 입력 type을 복사해 둡니다.

HRESULT AudioVolume::SetMediaType(PIN_DIRECTION direction, const CMediaType *pmt)
{
    //
ask the baseclass if it’s okay to go
    HRESULT    hr =
CTransformFilter::SetMediaType(direction, pmt);
    if (FAILED(hr)) return hr;

    // keep a local copy of the type

    if (direction == PINDIR_INPUT) {
        mtIn = *pmt;

    }

    return NOERROR;
}

HRESULT AudioVolume::GetMediaType(int iPosition,
CMediaType *pmt)
{
    if (iPosition < 0)
return E_INVALIDARG;
    if (iPosition > 0) return
VFW_S_NO_MORE_ITEMS;

    // the input pin must be connected first

    if (m_pInput->IsConnected() ==
FALSE) return VFW_S_NO_MORE_ITEMS;

   // we offer only one type – the same as input

    *pmt = mtIn;
    return NOERROR;

}

얼마나 큰 버퍼를 사용할 지 명시적으로 만들어 줍니다.

HRESULT AudioVolume::DecideBufferSize(IMemAllocator *pAlloc,
       
ALLOCATOR_PROPERTIES *pProp)
{
    WAVEFORMATEX    *wfx =
(WAVEFORMATEX*)mtIn.pbFormat;

   // this might be put too simly but
    // we
should be able to deliver max 1 second
    // of raw audio
   
pProp->cbBuffer        = wfx->nAvgBytesPerSec;

    // when working with audio always try to have
   
// some spare buffer free
    pProp->cBuffers        = 3;

    ALLOCATOR_PROPERTIES    act;
    HRESULT hr =
pAlloc->SetProperties(pProp, &act);
    if
(FAILED(hr)) return hr;

    if (act.cbBuffer < pProp->cbBuffer)
return E_FAIL;
    return NOERROR;

}

 

마지막 단계 – audio 처리를 합니다. 우리는 각 PCM sample 에 0.5 를 곱하도록 하고 있습니다. 이것은 -6.0205 dB
만큼 신호를 증폭시키는 것입니다.

(0.5를 곱하면 크게 차이가 나지 않는다. 실제 필터를
만들때 0을 곱해서 음소거를 알아볼수도 있고 2 정도를 곱해서 소리가 엄청 크게 됨을 알수도 있다.)

HRESULT AudioVolume::Transform(IMediaSample *pIn, IMediaSample *pOut)
{

    BYTE    *bufin, *bufout;
    long   
sizein;

    // get the input and output buffers
   
pIn->GetPointer(&bufin);
    pOut->GetPointer(&bufout);

    // and get the data size
    sizein =
pIn->GetActualDataLength();

   // since we’re dealing with 16-bit PCM
    // it
might be convenient to use “short”
    short    *src = (short*)bufin;

    short    *dst = (short*)bufout;
    int        samples = sizein / sizeof(short);

   // now deal with the samples and lower the volume

    for (int
i=0; i<samples; i++) {
        dst[i] = (short)(src[i] * 0.5);
    }

   // and set the data size
   
pOut->SetActualDataLength(samples * sizeof(short));
    return NOERROR;

}

기능적인 구현은 끝났습니다.

다음은 GraphBuilder 가 필터를 인식할수 있도록 여러가지를 추가시켜야 됩니다.

3. 레지스트리 정보

레지스트리 정보와 DLL entry points 를 위해 따로 파일을 만드는 것은 좋은 습관입니다.

필자는 “*_reg.cpp” 형태를 사용하곤 합니다. 그래서 여기서는 “audio_reg.cpp” 파일을 만들었습니다. 그리고 아래 코드를
추가합니다.

필자는 표준 merit 값을 사용하기를 강력하게 추천합니다. 특별한 일이 없으면 MERIT_UNLIKELY or
MERIT_NORMAL 을 사용하세요.

// Media Types
const AMOVIESETUP_MEDIATYPE sudPinTypes[] =  
{
   
{ &MEDIATYPE_Audio, &MEDIASUBTYPE_PCM }
};

// Pins
const
AMOVIESETUP_PIN psudPins[] =
{
    { L“Input”, FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL,
1, &sudPinTypes[0] },
    { L“Output”, FALSE,
TRUE, FALSE, FALSE, &CLSID_NULL, NULL, 1, &sudPinTypes[0] }
};  

// Filters
const
AMOVIESETUP_FILTER sudAudioVolume =
{
    &CLSID_AudioVolume, L“Audio Volume”, MERIT_UNLIKELY, 2, psudPins

};                    

// Templates
CFactoryTemplate g_Templates[]=

{
    { L“Audio Volume”,
&CLSID_AudioVolume, AudioVolume::CreateInstance, NULL, &sudAudioVolume }

};

int g_cTemplates = sizeof(g_Templates)/sizeof(g_Templates[0]);

DirectShow filter는 COM 객체입니다. 따라서 라이브러리를 등록하고 등록 해제 하기 위해서는 아래 코드를 추가하세요

STDAPI DllRegisterServer()
{
    return
AMovieDllRegisterServer2(TRUE);
}

STDAPI DllUnregisterServer()
{
    return
AMovieDllRegisterServer2(FALSE);
}

extern “C” BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);

BOOL APIENTRY DllMain(HANDLE hModule,
       DWORD  dwReason,
      
LPVOID lpReserved)
{
      return
DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved);
}

#pragma warning( disable:4514)

 

4. Headers

다음은 “headers.h” 파일을 만들고 아래 코드를 입력합니다.

#include <streams.h>

#include <initguid.h>
#include
“audio_types.h”
#include “audio_filter.h”

 

그리고 모든 *.cpp 파일에 header.h 파일을 include 시킵니다.

5. 외부기호

프로그래밍 하는 것은 다 했습니다. 이제 DLL 라이브러리는 외부로 함수를 함수를 노출시켜 주어야 되는데 COM 라이브러리는 아래와 같이
최소 4개의 함수를 노출시켜야 됩니다.

  • DllRegisterServer
  • DllUnregisterServer
  • DllGetClassObject
  • DllCanUnloadNow

 

처음 두개는 앞에서 이미 선언했고 뒤의 두개는 bassclasses 라이브러리에 구현되어 있습니다.

그러나 우리는 링커에게 우리가 진짜로 이 함수들을 노출시키고 싶다는 걸 알려야 됩니다.

그래서 새항목 추가를 통해 프로젝트에 “모듈 정의 파일(.def) 파일을 추가하고 “audio_volume.def” 파일이름을
정합니다.

그리고 아래와 같이 편집해 줍니다.

LIBRARY         audiovolume.ax
EXPORTS
    DllGetClassObject       
PRIVATE
    DllCanUnloadNow         PRIVATE
   
DllRegisterServer         PRIVATE
    DllUnregisterServer     
PRIVATE

 

 6. 프로젝트 옵션

  빌드 환경 설정 : 프로젝트 속성에서

   1) C/C++ > 고급 > 호출규칙: __stdcall 으로 변경

   2) 일반 > 문자집합: 멀티바이트 문자집합 사용 으로 변경

  
3) C/C++ 추가포함 디렉토리 에서 디렉토리 추가

  
    – C:\SKD\WSDK\Samples\Multimedia\DirectShow\BaseClasses

  
    – C:\SKD\WSDK\Include

      
– C:\SKD\WSDK\lib

  
    : BaseClasses를 맨 상위로 오도록 해야된다 그렇지 않으면

  
     
C:\Program Files\Microsof
SDKs\Windows\v6.0\Samples\Multimedia

        
\DirectShow\BaseClasses\refclock.h(80) : error C2061: syntax error :  identifier
‘CAMSchedule’

  
    에러가 발생할 수도 있습니다.

  
4) C/C++ > 코드생성 > 런타임 라이브러리 : 다중 쓰레드 디버그 DLL (/MDd) 으로 변경

  
5) 링커 > 입력 > 추가 종속성

  
    * Debug Build: Strmbasd.lib strmiids.lib  Msvcrtd.lib Winmm.lib

  
    * Debug Build: Strmbase.lib strmiids.lib  Msvcrt.lib Winmm.lib

  
6) 링커 > 출력파일의 확장자를 dll 에서 ax로 변경 ( dll 로 해도 상관은 없습니다만 .def 파일의 내용도 바꿔 주어야
됩니다.)      

  
7) C/C++ > 미리 컴파일된 헤더: 미리 컴파일된 헤더 사용 안함 으로 설정

   8) 링커 > 입력 > 모든 기본 라이브러리 무시:
예(/NODEFAULTLIB)

7. 테스트

GraphEdit 툴로 “Audio Volume” 필터를 추가하기 전에 음원 파일을 동작시키고 추가한 다음에 동작시키면 audio 볼륨에
대한 효과를 알수 있을 것입니다.

bookmark_borderVS 6.0 에서 Filter 만들기 설정

Filter 만들기 예제 (MS Visual Studio)









 


AppWizard의 C++ 프로젝트에서 Win32 Dynamic-Link Library를 선택하고 새로운 프로젝트를 만든다.








 


]



Project메뉴에서 Insert Project into Workspace선택해서 DirectX SDK sample내에 있는 BaseClasses Project를 선택해서 Workspace에 포함시킨다. 다른 프로젝트를 사용하기전에 미리 BaseClasses빌드한다.







 


빌드환경을 DirectShow를 이용가능하도록 맞춘다.


1. DirectX SDK 디렉토리 설정.

2. 헤더파일 dshow.h 라이브러리 파일  strmiids.lib  quartz.lib  strmbase.lib 를 프로젝트에 포함시킴.

3. Calling Convention을 __stdcall로 통일하면, 보다 편하고 안정적이다.

4. Setting 메뉴의 Link 에 있는 Entry-point Symbol을 DllEntryPoint@12로 한다. DllEntryPoint는 BaseClasses에 구현되어 있는 함수이다. 이러면 DllMain에 Dll을 초기화 하기위한 구현을 할 필요가 없다.








 


빌드환경을 DirectShow를 이용가능하도록 맞춘다.


1. DirectX SDK 디렉토리 설정.

2. 헤더파일 dshow.h 라이브러리 파일  strmiids.lib  quartz.lib  strmbase.lib 를 프로젝트에 포함시킴.

3. Calling Convention을 __stdcall로 통일하면, 보다 편하고 안정적이다.

4. Setting 메뉴의 Link 에 있는 Entry-point Symbol을 DllEntryPoint@12로 한다. DllEntryPoint는 BaseClasses에 구현되어 있는 함수이다. 이러면 DllMain에 Dll을 초기화 하기위한 구현을 할 필요가 없다.






DEF파일을 작성한다.


 이는 DLL파일을 외부에서 접근하기위해서는 DEF파일을 작성해야한다. 자세한 방법은 MSDN의 Dll 작성법을 참고하고, 예제는 아래와 같다.


EX)


LIBRARY     Filter.ax


DESCRIPTION ‘DirectShow Filter’


EXPORTS


            DllRegisterServer   PRIVATE


            DllUnregisterServer PRIVATE


            DllGetClassObject   PRIVATE


            DllCanUnloadNow     PRIVATE





Self-Registration 함수 구현


DllRegisterServer와 DllUnRegisterServer를 구현하면 쉽게 시스템 레지스트리에 등록시킬수 있다. BaseClasses Project에 있는 AMovieDllRegisterServer2함수를 이용하면, 쉽게 구현가능하다.


예제


STDAPI DllRegisterServer()


{


    return AMovieDllRegisterServer2(TRUE);


} // DllRegisterServer


 


 


//


// DllUnregisterServer


//


STDAPI DllUnregisterServer()


{


    return AMovieDllRegisterServer2(FALSE);


} // DllUnregisterServer





Filter 구현  


1.GUID 생성 유틸리티를 통해서, GUID를 생성후에 DEFINE_GUID매크로를 이용해서 GUID를 정의한다.


2.CTransFormFilter를 상속받은 C++클래스를 정의한다. Override로 구현해야할 함수는 아래와 같다.



// Overrides


protected:


    // Transform operation, which this filter does


    virtual HRESULT Transform(IMediaSample *pIn, IMediaSample *pOut);


    // check if you can support mtIn


    virtual HRESULT CheckInputType(const CMediaType *pmtIn);


    // check if you can support the transform from this input to this output


    virtual HRESULT CheckTransform(const CMediaType *pmtIn, const CMediaType *pmtOut);


    // call the SetProperties function with appropriate arguments


    virtual HRESULT DecideBufferSize(IMemAllocator *pAllocator, ALLOCATOR_PROPERTIES *pProperties);


    // override to suggest OUTPUT pin media types


    virtual HRESULT GetMediaType(int iPosition, CMediaType *pMediaType);



각함수의 기능은 앞에서 설명했다. 자세한 정의는 MSDN을 참고한다.





CFactoryTemplate 값을 초기화한다. (예제 하나하나의 전달인자의 값은 MSDN을 참고한다.)


const AMOVIESETUP_MEDIATYPE sudPinTypes =


{   &MEDIATYPE_NULL,    // Major CLSID


    &MEDIASUBTYPE_NULL  // Minor type


};


 


const AMOVIESETUP_PIN psudPins[] =


{


    {


        L”Input”,       // Pin’s string name


        FALSE,          // Is it rendered


        FALSE,          // Is it an output


        FALSE,          // Allowed none


        FALSE,          // Allowed many


        &CLSID_NULL,    // Connects to filter


        L”Output”,      // Connects to pin


        1,              // Number of types


        &sudPinTypes    // Pin type information


    },


    {


        L”Output”,      // Pin’s string name


        FALSE,          // Is it rendered


        TRUE,           // Is it an output


        FALSE,          // Allowed none


        FALSE,          // Allowed many


        &CLSID_NULL,    // Connects to filter


        L”Input”,       // Connects to pin


        1,              // Number of types


        &sudPinTypes    // Pin type information


    },


};


 


const AMOVIESETUP_FILTER sudAa =


{


    &CLSID_L544_Aa,     // CLSID of filter


    L”aa Filter”,           // Filter’s name


    MERIT_DO_NOT_USE,           // Filter merit


    2,                          // Number of pins


    psudPins                    // Pin information


};


 


//


//  Object creation template


//


CFactoryTemplate g_Templates[] =


{


    {


        L”aa Filter”,


        &CLSID_L544_Aa,


        CAaFilter::CreateInstance,


        NULL,


        &sudAa


    },


};





CreateInstance 구현


  새로운 COM 객체를 생성하기 위한 함수이다. 구현예는 아래와 같다.


CreateInstance(LPUNKNOWN punk, HRESULT *phr)


{


    ASSERT(phr);


   


    CContrast *pNewObject = new IUnknown(NAME(“Filter”), punk, phr);


    if (pNewObject == NULL) {


        if (phr)


            *phr = E_OUTOFMEMORY;


    }


 


    return pNewObject;


}





CTransformFilter::Transform 구현하기


Transform(IMediaSample *pIn, IMediaSample *pOut)


  이 함수의 전달인자로 입력버퍼와 출력 버퍼가 넘어온다.IMediaSample의 GetPointer Method를 통해서 입출력 버퍼의 비트스트림 포인터를 얻을수 있다. 이 비트스트림 포인터


가 참조하는 메모리에서 영상을 읽고 처리해서 출력 비트스트림 포인터 내보내면 된다.


 


예제


Transform(IMediaSample *pIn, IMediaSample *pOut)


{


    BYTE *pSourceBuffer, *pDestBuffer;


    pIn->GetPointer(pSourceBuffer);


    pOut->GetPointer(pDestBuffer);


    for(int i = 0; i < pIn->GetActualDataLength(); i++){


         *pOut =


    }


 


    return NO_ERROR;


} // Transform