블로그 이미지
대갈장군

calendar

1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31

Notice

2009. 5. 16. 01:23 프로그래밍/DirectShow
제목부터 아리까리하다. 내가 교수님으로부터 이상한 프로그램 하나를 건네 받고 그 놈을 요리조리 뜯어보다 보니 그 원리가 제목과 같더라...

잘은 모르지만 OpenGL에서 동영상 파일 재생은 매우 제한적이다. NeHe 홈페이지에 가보면 단순한 Mpeg 파일 재생 OpenGL 프로그램이 있기는 하지만 Mpeg 버전에 따라 되는 파일도 있고 안되는 파일도 있다. 한마디로 불완전하다.

수많은 형태의 동영상 재생 파일을 손쉽게 읽고 재생하기 위해서는 DirectShow 의 강력한 필터가 필요하다. 다만 OpenGL을 기반으로 프로그램을 작성하게 되면 DirectShow와 어떻게 연동해야 할지가 문제다.

물론 DirectX 기반으로 작성하면 (안해봤지만) 훠어얼씬 쉽겠지. VMR-9이라는 멎진 놈이 존재하기 때문에 텍스쳐 맵핑을 걱정할 필요가 없다.

하지만 죽으라는 법은 없다고 하지 않았던가... DirectShow의 필터중에 동영상 샘플 추출 필터가 있으니 바로 ISampleGrabber 를 이용하는 것이다.

이놈을 이용하게 되면 디코더를 지나자 마자 샘플 추출기 필터로 데이터가 흘러 들아가게 되고 샘플 추출기 필터는 새로운 데이터가 들어오면 SampleCB() or BufferCB() 함수를 콜백으로 호출하게 된다.

이 두 방식의 차이는 IMediaSample 인터페이스를 직접 넘겨주는가 그렇지 않는가에 있다. 뭐 중요한 차이는 아닌듯 싶다. 직접 넘겨주지 않는다면 클래스 멤버 변수에 따로 변수들을 저장해 두면 그만이고..

데이터가 넘어오면 그 길이와 주소를 이용해서 적당한 작업을 하면 된다. 하지만 주의할 것은 콜백 함수가 리턴 되기 전까지 필터는 흐름이 멈추게 된다. 고로 메모리 복사 작업 (텍스쳐 복사 작업)은 콜백 함수 내부에서 하면 성능 저하를 가져 올수도 있겠다는 생각이 든다.

하지만 막무가내로 리턴하고 다음 데이터를 받아버리면 공유된 버퍼 자원에 대한 자원 경쟁이 발생하거나 새로운 이미지 데이터가 업데이트 되는 도중에 텍스쳐 복사를 한다거나 하는 문제가 발생하지 않을까? 

만약 그렇다면 해결방법은 Critical Section을 이용해야 한다... 라면 성능에는 아무런 문제가 없을까?...

아무튼 현재 사용중인 프로그램은 이런 형태의 흐름을 가지고 있으며 이를 이용해 다양한 형태의 입력 파일들 (mpg, jpg, avi 등) 을 아주 손쉽게 OpenGL 텍스처로 입혀서 사용중이다.


posted by 대갈장군
2009. 3. 17. 23:02 프로그래밍/DirectShow

앞서본 널 렌더링이나 필터 추가후 렌더링의 경우 RenderFile() 함수를 사용해서 자동으로 필터 그래프가 완성되도록 했으나 필터 렌더링은 필터의 Output 핀을 사용한 렌더링이다.

즉, 가장 세밀한 조작이 가능한 렌더링 방식이다. 그중에서도 소스 필터 자동 렌더링이 있는데 이는 RenderFile() 함수를 IGraphBuilder::AddSourceFilter() 함수와 IGraphBuilder::RenderFilter() 함수가 대체하는 방식이다.

1. 필터 그래프 매니저 생성
JIF(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&m_pGB);


2. AddSourceFilter() 함수로 소스 필터 추가하면서 pSourceFilter에 그 소스필터의 진입점(포인터) 얻어 오기
IBaseFilter *pSourceFilter;
JIF(m_pGB->AddSourceFilter(wFileName, wFileName, &pSourceFilter);


3. 필터 렌더링!
if(pSourceFilter != NULL)
      LIF(RenderFilter(m_pGB, pSourceFilter));


4. AddSourceFilter에 의해 추가로 생성된 필터 인터페이스 (리모컨) 삭제
SAFE_RELEASE(pSourceFilter);

근디... 자동 소스 필터 렌더링과 수동 소스 필터 렌더링은 그 차이가 크지 않네...

수동 소스 필터 렌더링은 우선적으로 소스로 사용할 필터를 추가시켜 놓고 자동 필터 렌더링과 마찬가지로 AddSourceFilter와 RenderFilter 함수를 차례로 호출하는 것일뿐 차이가 없다.

결국 정리하지만 자동 소스 필터 렌더링은 파일이나 URL를 이용해 AddSourceFilter() 를 수행하고 곧바로 RenderFilter를 이용해 Output Pins를 렌더링 한다.

반면 수동 소스 필터 렌더링은 소스 필터로 사용하고자 하는 필터를 우선 추가한 후, 필터들을 그래프에 추가시키고 그 다음에 AddSourceFilter()와 RenderFilter() 함수를 이용해 Pin 렌더링 수행.
posted by 대갈장군
2009. 3. 16. 23:49 프로그래밍/DirectShow
앞에서 본 NULL Rendering의 경우에는 입력 파일에서 곧바로 렌더링을 했지만 필터 추가후 렌더링은 원하는 특정 필터를 먼저 필터 그래프 매니져에 올려놓고 렌더링을 하는 것을 말한다.

이렇게 하면 필터 그래프가 만들어질때 이미 삽입시킨 필터를 최대한 포함시켜 렌더링을 하게 된단다.

1. 필터 그래프 매니저 생성
JIF(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&m_pGB);


2. 추가 시키고 싶은 필터 생성
IBaseFilter *pFilterOverlayMixer;
LIF(CoCreateInstance(CLSID_OverlayMixer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pFilterOverlayMixer));


3. 필터를 그래프 매니져에 추가
LIF(m_pGB->AddFilter(pFilterOverlayMixer, L"Overlay Mixer");


4. CoCreateInstance에 의해 생성된 필터 COM 객체 Release 시키기
SAFE_RELEASE(pFilterOverlayMixer);


5. Null Rednering 기술 사용
JIF(m_pGB->RenderFile(wFileName, NULL));

posted by 대갈장군
2009. 3. 16. 23:39 프로그래밍/DirectShow
DirectShow에서 Null Rendering 하는 방법

1. 우선 설명서 (CLSID_)와 기능 (IID_) 정의 해주고 CoCreateInstance 실행 하면 m_pGB 멤버 변수에 포인터 리턴됨. 이로써 필터 그래프 관리자 생성됨.
JIF(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&m_pGB));

2. 미리 가지고 있는 파일 이름을 넘겨주고 RenderFile() 명령 수행.
JIF(m_pGB->RenderFile(wFileName, NULL));

참 쉽죠잉~

재생중인 스트림이 있을경우 재생 중지 하고 필터 매니저 그래프 종료하기

1. IMediaControl interface를 QueryInterface 함수를 이용해 포인터 얻어오기.
IMediaControl * pMC;
JIF(m_pGB->QueryInterface(IID_IMediaControl, (void**)&pMC);

2. 재생중인 스트림이 있으면 정지 시키고 pMC 와 필터 그래프 관리자 해제
if(pMC != NULL)
     LIF(pMC->Stop()); // 재생하고 싶은 경우는 LIF(pMC->Run());
SAFE_RELEASE(pMC);

SAFE_RELEASE(m_pGB);

posted by 대갈장군
2009. 3. 14. 04:00 프로그래밍/DirectShow
참 이상한것이 DirectShow에 대한 책이나 정보가 한국어로 된것은 매우 드물다는 점이다. 신화선님이 출판한 DirectShow 멀티미디어 프로그래밍이란 책을 제외하고는 한국어로 된 DirectShow 서적은 없다고 봐야한다.

원어로 된 서적도 없기는 마찬가지다. 그래서 그런지 더더욱 자료를 찾기가 어렵다.

DirectShow의 각종 Application 작성에 대해서 블로그를 작성하기 전에 COM에 대해서 분명히 말해두고자 한다.

왜냐면 DirectShow의 필터들이 사실 전부 COM 기반이기 때문이다. 사실 따지고 보면 COM은 C++과 크게 다르지 않다. 다만 '어떻게 사용하나?' 를 알아야 한다는 점이 중요할뿐.

C++의 클래스는 전적으로 사용자에게 권한을 100% 준다. 내가 만들고 싶은 뭐든 내 맘대로 작성하면 그만이다. 멤버 함수, 변수 등 구현, 정의 모두 내 맘대로다.

헌데 거기서 한가지 문제점이 발생하는데 프로그램을 짜본 사람은 알겠지만 제법 규모가 있는 프로그램, 뭐 예를 들자면 동영상 재생 프로그램, 오디오 재생 프로그램 같은거를 만들고 싶다고 하자. 

C++의 내 맘대로 작성하여 만든 클래스를 사용하여 만드는 프로그램은 그 규모가 공사에 비교했을때 소형 주택 짓는 정도라면 동영상 재생 프로그램과 같은 것은 거의 10 층 빌딩 만드는 수준의 전문적 공사이다.

그렇다면 일반 프로그래머가 지하부터 공사시작해서 10층까지 빌딩을 완성시킬수 있을까? 불가능하다... 뭐 아주 불가능 하지는 않지만 시간이 오~~~래 걸린다.

바로 그렇기 때문에 프로그램 회사 (Microsoft) 같은 곳에서 일반 프로그래머도 10층 빌딩을 신속하게 지어 올릴수 있도록 친절하게 다양한 빌딩을 짓기 위한 '뼈대'와 '재료'를 제공을 해준다.

그것이 바로 COM기반의 DirectShow이다. DirectShow는 멀티미디어 (동영상, 오디오) 를 사용해 결과물을 작성해야 하는 개발자들을 위해 제공되는 다양한 함수와 클래스이다.

하지만 일반 C++ 클래스와는 달리 COM은 매우 인공지능적이다. 우선 스스로 자신의 객체가 몇번이나 복사되었는지를 스스로 관리하여 카운터가 0이되면 스스로 자신을 파괴한다. 고로 컴퓨터에 유령처럼 떠도는 메모리 leak를 원초적으로 차단하고자 했다.

물론 여전히 프로그래머가 메모리 leak를 유발할 수는 있지만 그래도 C++ 클래스 원조보다는 훨씬 영리하다.

또한 '조립'과 '대화'가 가능한 클래스이다. 조립이 가능하다는 것은 COM 객체 생성함수인 CoCreateInstance() 함수의 첫번째 인자와 네번째 인자를 사용자가 적절히 선택함으로써 어떤 '건물의 외관'에 '내부의 기능'을 만들것인지를 정할수 있게 했다.

건물의 외관이 바로 CLSID_ 머리말이 붙은 식별자이며 사실상 이것은 클래스이고 즉, '설명서' 일 뿐이다. CLSID는 Class ID의 약자임을 알았다면 당연한 이야기다.

네번째 인자인 '내부의 기능'IID_ 머리말이 붙은 식별자이며, 이것은 Interface ID의 약자이다. Interface는 한국어로 해석하기 좀 애매하지만 간단히 말하자면 걍 '함수'다. 이 인터페이스는 내가 어떤 기능 (함수)를 사용하고 싶다는 것을 알려준다.

고로 CoCreateInstance()는 사실 내가 만들고자 하는 클래스와 함수를 컴퓨터에 알려주고 COM 라이브러리에서 내가 원하는 형태의 객체를 뚝딱 만들어서 나에게 돌려준다.

다른 한가지 특별한 점으로 '대화'를 꼽았는데 이는 바로 QueryInterface()라는 함수 때문이다. 기본적으로 모든 COM객체는 IUnknown 인터페이스를 가지고 있다. 즉, 모든 COM 객체는 IUnknown 인터페이스가 제공하는 3가지의 함수(QueryInterface,AddRef,Release)를 가지는데 그중 하나가 바로 QueryInterface()함수이다.

이 함수는 COM 객체에게 '너 이 기능 할줄 아니?' 라고 물어보는 역활을 한다. 만약 가능하면 COM 객체는 그 기능으로 향하는 출입문인 Interface Pointer를 리턴하고 만약 안되면 NULL을 리턴하여 불가능 하다고 대답한다.

이전에 내가 COM에 대해서 쓴 글에서도 보면 이 점 때문에 COM은 '뇌를 가진 클래스'라고 했었다. 프로그램 개발자가 모든 함수를 다 알고 있어서 바로 그 함수를 찍어서 호출하는 방법보다 훨씬더 안정적이다. 왜냐면 컴퓨터마다 차이가 있으므로 어떤 컴퓨터에서는 되고 안되고를 알수 없는데 COM 객체를 이용해 QueryInterface를 하면 쉽게 현재의 컴퓨터에서 그 기능이 가능한지 알수 있기 때문이다.

예전에도 말했듯이 이런 COM과 같은 놈들은 C++과는 전혀다른 새로운 언어가 아니다. 이런 COM은 프로그램을 작성하는 '틀'과 '방법'을 제공해주는 거대한 도서관 같은 놈이다. 사용자가 알아야 하는 것은 몇 층의 무슨 책을 찾아야 하는지대출은 어떻게 하는지만 알면 된다. 

DirectShow에서 COM을 사용한 이유는 정확히는 모르지만 동영상과 오디오를 주로 다루는 DirectShow에서는 여러개의 필터들을 연결해서 재생하는데 이런 과정에서 필터 간의 안전한 연결과 실제로 중요한 부분인 Encoding 과 Decoding 부분의 완벽한 정보 은폐, 그리고 아마도 COM 기술을 프로그램 업계의 기반으로 만들려고 그러지 않았을까?... 그럴까?

posted by 대갈장군
2008. 1. 26. 01:39 프로그래밍/DirectShow
알고보니 DirectShow Application을 작성할때 (직접 코딩할때) 제일 중요한 것은 COM 의 개념을 이해하고 어떻게 그것을 이용/생성/해제 하는가와 필터 그래프 관리자와 그래프 에디터가 결국은 같은 것임을 깨닳는 것이다.

코딩시 그래프 에디터가 만들어주는 널 렌더링 기법을 위해서는 우선 필터 그래프 관리자를 생성해야 하는데, 이 놈은 바로 COM 컴포넌트이다.

이 컴포넌트에 원료를 줘서 생산을 해야 하는데 바로 그 명령이,

CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, llD_lGraphBuilder, (void **)&m_pGB));

이다. 필터 그래프는 첫번째 인자인 COM 컴포넌트에 들어가있음을 알려주고 세번째 인자가 요청하는 것이 필터그래프매니져 인터페이스인데, 조금 헷갈릴 수도 있다.

물론 그냥 그렇다라고 알고 가도 되지만, 좀더 해석해보자면, COM 컴포넌트는 추상 클래스이다. 이 추상클래스는 객체화 되지 않은 그냥 빈 틀인데 여기다가 내가 원하는 특정한 기능을 만들고 싶다면 그것이 무엇인지 COM 컴포넌트에게 알려줘야 하고 그게 바로 세번째 인자인것 같다.

결국은 그렇다면 첫번째 인자는 가장 위쪽에 위치한 할배 추상 클래스이고 세번째 인자는 자식이나 손주뻘쯤 되는 상속 클래스의 이름이라고 보면 되겠는가? :)

원래라면 사용자가 모두 객체화 하고 함수를 써줘야 하는데 DirectShow Application은 그럴필요가 전혀 없어 보인다. 과연 이것이 장점일까?

한가지 더 중요한 것은 Release() 함수인데 이것은 앞서 만든 객체를 해제 할때 사용하는 함수다. COM 객체는 똑똑해서 자신을 참조하는 객체의 갯수를 항상 세고 있다가 0이되면 알아서 자폭한다.

고로 마구마구 Release를 쓰면 아직 사용중인 COM 객체가 날아가는 수가 있다. 고로 항상 짝을 이루어 조심히 써라는 말.

그리고 널 렌더링시 알아서 필터를 구성해주는 기법은 어플리케이션에서 다음 한줄이면 끝이다.

m_pGB->RenderFile(wFileName,NULL);

엄청 간단하다... -_-
posted by 대갈장군
2008. 1. 24. 05:39 프로그래밍/DirectShow

이걸 모르면 문맥을 자꾸 놓치게 되니까 하나하나씩 정리해 놓자.

1. RIFF (Resource Interchange File Format) : 헤더에 압축 방식을 기술 해놓는 걸 말하나 보다. 아, 그래서 이것을 적용한 파일의 경우 다양한 필터의 적용이 가능해진다. 그렇구나..

2. PCM (Pulse Code Modulation) : 정통과에서 배운 아날로그 신호의 디지털화다. 계단으로 좌좍 나누어 디지털 정보로 표현하기.

3. ADPCM (Adaptive Differential PCM) : 이건 위키에도 안나와있군. 단지 목소리를 디지털 신호로 바꾸는 거랜다.

4. ACM (Audio Compression Manager) : 기존의 윈도우 기술에서 사용되는 오디오 압축/해제를 의미한다. 그래서 압축된 형태의 오디오 파일은 ACM 래퍼 필터를 통해 Decompress 된다는 거군.

5. VCM (Vedio Compression Manager) : ACM과 함께 윈도우에서 사용되는 비디오 압축/해제 기술.

posted by 대갈장군
prev 1 next