Timing Wheel

2013. 12. 18. 17:25 from 프로그래밍 팁/기타

a4438aed0a7eea5a7840df89fe4cfdb6.png

Timing Wheel은 타이머를 구현할 때 유용하게 활용할 수 있는 자료구조다. 블로그에 한 번 정리해 둬야지 하고 미루기만 하다 이제야 끄적임. 정리라고 해봐야, 나중에 다시 검색할 때 키워드를 까먹지 않도록 자료구조 이름이라도 남겨두자는 것 뿐이다. NHN(이제는 Naver가 되어버린)의 hello world 블로그에 한글로 잘 정리된 포스팅이 있다. Timeing Wheel Data Structure를 구글링해도 자료는 많이 있음.

예전에 내가 직접 만들었던 서버 엔진에는 구조가 심플했고 독립적으로 정리된 타이머 모듈은 없었다. 이후에 간단한 타이머를 직접 만들어본 적은 있으나 그것도 boost::timer를 이용해서 대충 뚝딱 만들어본 단순한 구조였는데, 대량의 작업을 처리하기 위한 효율적인 타이머를 구현하려면 타이밍 휠을 이용해 만드는 것이 좋겠다.

Hello World 블로그의 글에 잘 설명되어 있지만 간략히 재정리 하자면, 배열을 이용해 일반적으로 만들면 O(n) 으로 처리해야 할 일들을 타이밍 휠을 써서 O(1)로 처리할 수 있게 된다. 타이머로 처리해야 할 task가 많다면 보다 효율적인 처리가 가능하다. 효율을 얻는 대신 감수해야 하는 단점도 있다. 메모리 사용량의 증가라든지, 고정된 단위시간 이하의 정밀한 시간 컨트롤이 어렵다든지, 미리 잡아놓은 circular-array 크기 * 단위시간 이상의 긴 시간에는 타이머를 걸 수 없다든지 하는 것들.

이 중 긴 시간을 쓸 수 없는 문제는 여분의 대기버퍼를 하나 더 마련하여 해결할 수 있다. 타이밍 휠에 바로 들어갈 수 없는 긴 시간의 task는 대기 버퍼에서 잠시 대기시키다 집어넣으면 됨. 나머지 단점 들이야 필요한 케이스에 맞춰 적절히 조절해주면 큰 문제랄 것도 없을 것 같다. 적어도 내가 겪어본 게임 서버 개발 시에는.

Posted by leafbird 트랙백 0 : 댓글 0

댓글을 달아 주세요

[아꿈사/110903] 도메인주도설계 4장
View more presentations from sung ki choi

Posted by leafbird 트랙백 0 : 댓글 0

댓글을 달아 주세요

   1: FOR /R %1 %%1 IN (.svn) DO RMDIR /S /Q "%%1"
   2: PAUSE 

(출처는 http://blog.naver.com/yhchoi78/90096166613)

위에 있는 스크립트를 배치파일로 만들어 root 폴더에 두고 실행하면 싹 사라진다.

검색해보면 마우스 우클릭 컨텍스트 메뉴에 등록하는 방식도 있지만 그렇게 많이 쓸 것 같지는 않고.. 배치파일이 좋음 ㅎ

Posted by leafbird 트랙백 0 : 댓글 0

댓글을 달아 주세요

UI 시스템을 구축하는 방법이야 여러 가지가 있겠지만 스케일폼 같은 외부 모듈을 갖다 붙이는 경우 아니고 자체 제작하는 경우라면 WOW의 xml + lua 구조를 참고하는 경우가 이제는 제법 흔해졌다.

굳이 사용자에게 API를 공개하는 수준으로까지 구축하지 않는다 하더라도, 이미 UI에서는 넘사벽 수준으로 인정받은 시스템의 구조를 참고하는 것만 해도 설계에 큰 도움이 된다.

UI는 OOP의 개념에 따른 설계에 아주 적합한 시스템이다. 조금만 신경써서 시스템을 다져 놓으면 사용하기도 편하고 확장하기에도 편한 시스템을 만들 수 있지만 일정에 쫓기는 바쁜 게임 개발팀들 대다수가 UI에 큰 정성을 쏟지 못하는 게 나는 참 아쉽다. 요즘은 많이 나아졌지만 예전엔 게임 UI들이 그야말로 형편 없어 보이는 게임들이 참 많았다.

UI의 애니메이션도 아주 재미있는 프로그래밍 거리라고 생각한다. 아무렇게나 만들어도 적당히 움직여주는 UI를 표현하는 건 큰 문제 없겠지만 3D 그래픽스 쪽에 잘 정리되어있는 애니메이션 개념을 익히고, 2D 수준으로 적당히 단순화해서 응용해보기에 안성맞춤인 과제다. 애니메이션 키를 정하고, 보간하고, 합성하는 일련의 과정을 잘 이해할 수 있게 된다.

대인배 블리자드는 애드인 개발자들을 위해 현재 서비스중인 WOW에서 사용중인 UI의 XML+LUA 스크립트와 텍스처 파일 전체를 다운로드 받을 수 있게 공개하고 있다.
http://us.blizzard.com/support/article.xml?locale=en_US&articleId=21465

wowprogramming.com 사이트의 레퍼런스 페이지에는 현재 제작되어 있는 WOW 위젯의 전체 리스트와 API의 설명이 상세하게 정리되어 있다.
http://wowprogramming.com/docs/widgets

WOW의 UI 시스템과 완벽히 호환되는 스크립트를 구축하게 되면, 실제 WOW 클라이언트에서 별도 애드인의 형태로 자체 게임의 UI 스크립트를 띄워볼 수도 있다. 이건 뭐 그냥 대. 박.

Posted by leafbird 트랙백 0 : 댓글 1

댓글을 달아 주세요

  1. addr | edit/del | reply Favicon of https://devnote.tistory.com BlogIcon leafbird 2011.05.25 16:38 신고

    UI에 관심 많은 특이한 서버 프로그래머 ㅋㅋ

이게 잘 안되서 얼마나 애를 먹었는지 ㅜㅠ...
Open SSL을 빌드하려면 Perl과 masm( 혹은 nasm )이 필요하다.
Perl은 윈도우에서 편하게 사용할 수 있는 Active Perl을 설치하면 되고 어셈블리는 아무거나 받으면 되는데
기본적인 통신을 위해서는 asm 없이 그냥 빌드해도 크게 무리 없는 듯 하다.
처음엔 asm 설정이 어려워서 한참을 헤맸는데 그냥 asm 없이 빌드해도 잘 되는 거였네...

인터넷 검색해보면 빌드하는 방법들이 많이 있다.
그 중에 내가 성공한 링크는 여기 : http://blog.daum.net/aswip/8429385
마음 같아선 죽 긁어서 옮겨붙이고 싶지만 그냥 링크만 건다 ;ㅁ;

윈도우에서는 자잘한 오류들 때문에 다운받은 소스를 그냥 빌드하면 컴파일 에러가 난다.
링크한 곳에서 설명하고 있는 곳을 모두 수정해 주어야 한다.

빌드에 성공한 output 파일을 포스팅에 첨부한다.


다음엔 이런 걸로 삽질하지 않기를 ㅜㅠ...

나중에는 OpenSSL 사용하는 클라이언트 클래스를 공개해 볼까 생각중.


ps : SSL_CTX_new 함수가 자꾸 NULL을 리턴하면 SSL_library_init() 함수를 호출해 초기화해준다.
(출처 : http://www.mail-archive.com/openssl-users@openssl.org/msg51543.html)
Posted by leafbird 트랙백 0 : 댓글 2

댓글을 달아 주세요

  1. addr | edit/del | reply Favicon of http://gamecodi.com BlogIcon 그건일 2011.08.23 11:45

    링크된 주소가 이상해졌어요
    다음블로그가 문제 인거 같습니다.
    debug 말고 release 버전 있었으면 좋아을텐데요.. ㅠㅠ

    • addr | edit/del Favicon of https://devnote.tistory.com BlogIcon leafbird 2011.08.24 09:46 신고

      ongameserver 카페에서 보았던 닉네임 이시군요 :)
      지금은 링크 주소 잘 연결 되는 것 같습니다.
      http://blog.daum.net/aswip/8429385
      일시적으로 뭔가 문제가 있었나보네요.

      릴리즈 빌드 성공하시면 저도 공유좀 ㅎㅎ

배치파일 만들 때 %cd%를 하면 현재 작업 경로를 얻을 수 있다.

작업 중인 경로를 옮겨서 처리하다가, 다시 원래의 경로로 돌아오고 싶으면 아래와 같이 처리한다.

rem 현재 경로 저장
set CURPATH=%cd%

rem 다른 경로로 이동한다.
cd d:\blah\blah

...

rem 이전 경로로 복귀
cd %CURPATH%

...

요즘 진행중인 팀에서 눈에 띄는 것 마다 하나하나씩 자동화를 진행하고 있다.

배포, 빌드, 테스트 등등 아직 자동화 커버리지가 높지 않은 편이지만 프로젝트 라이프 사이클로 볼 때 이젠 슬슬 늦지않게 준비해둬야 할 시간이 왔음.

배치파일만 해도 자동화 할 수 있는 부분이 꽤 많다.
윈도우 xp를 깔면 윈도우 경로 밑에 ( C:\WINDOWS\Help\ntcmds.chm ) 도움말 파일이 있는데
기본적인 명령어들에 대한 설명을 확인할 수 있다.


근데 이 파일은 서버 2008 설치하면 없더라. 서버에는 파워쉘이 2.0까지 나와 있으니깐.... 이런 도스 명령들은 한참 구식이긴 하겠지 ㅎ

이참에 파워쉘이나 한 번 공부해볼까 생각중... 서버 관리하는데 유용하게 쓰일 것 같고 공부해보면 재미있을거 같다.

누구 같이 하실 분 있으면 풋쳐핸접 ~ !
Posted by leafbird 트랙백 0 : 댓글 0

댓글을 달아 주세요

프로젝트에서 사용중인 임베팅 파이썬이 엄청난 메모리를 사용하고 있어서 파이썬 메모리 사용량의 분석이 필요하다.
SP님 능력자님들의 조언을 받아 heapy라는 녀석을 알게 됐다. 파이썬은 언어 특성상 객체의 사이즈를 알아낼 방법도 없고, 개발자가 그런 걸 신경쓰게 하고 싶지 않다는 컨셉이라 관심도 없는듯 하다.

좌우지간 이녀석을 당장 적용해보았지만...
인스톨 버전을 설치하자니 python 2.6이 필요하고 python 2.4 버전에서 소스로 직접 셋업하자니 vs2003이 필요하다.
무슨 이런... ㅡㅡ;...
혹시나 하는 마음에 보조 pc에 python 2.6을 깔고 인스톨 한다음 빌드된 결과물 (pyd 확장자) 만을 복사해서 python 2.4.4 설치된 메인 pc에서 사용해 봤더니 버전 에러가 난다.

cygwin을 설치하면 gcc를 이용해 빌드가 되는 것 같으니 이렇게하도 설치 해봐야겠다.
아직은 설치조차 못했지만... 레퍼런스 유지를 위해 먼저 포스팅.


Reference 

 
2010. 9. 6.

cygwin 설치.

python setup.py build -c mingw

error : don'w know how to compile C/C++ code on platform 'nt' with 'mingw' compiler

Posted by leafbird 트랙백 0 : 댓글 0

댓글을 달아 주세요

새회사 들어와서 처음으로 작업한 게 오픈위키 백업 작업.
근데 아무리 해도 잘 안되서 일주일을 고생하고, 야근에 주말출근까지 했었는데, 결국 아래 글 보고 바로 해결했습니다.
요긴한 정보일지는 모르겠지만, 저에겐 너무나 역사적인 아티클이었기에 역시나 긁어둡니다;;
출처 : http://blog.naver.com/goodfeel?Redirect=Log&logNo=80003914678

ps. 개인적으론 위키 엔진 이것저것 써보다가 결국 스프링노트에 안착. ㅡㅡ)v


Database 준비가 끝났으면, 이제 Web 사이트를 만드는 일만 남았습니다. 

IIS에서 새로 웹 사이트를 만드시고, web root는 '\openWiki\owbase'를 웹 root로 잡으시면 끝입니다. 
열어 보시면, 위키가 동작하는 것을 확인할 수 있습니다. 간단하죠??

그 다음 추가로 하나 해 주실 작업이 있는데... 기본 encoding이 영문으로 되어 있어, 한글이 깨지는 현상을 확인하실 수 있습니다. 물론 수작업으로 인코딩을 한글로 바꾸시면 되지만, 귀찮으시겠죠?? 
전 소스에서 encoding 지정하는 부분을 두 군데 바꿨더니 한글이 문제 없었는데...
그렇게 바꾸면 완벽하지 않은건지...  

www.whohwa.pe.kr 에 가면 openwiki 한글 지원되게 수정하는 코드가 있습니다. 

긁어 왔습니다. ( 형 괜찮지?? ㅋㅋ)

-------------------------------------

한글 패치

  1. owconfig_default.asp
     OPENWIKI_ENCODING = "EUC-KR" 
  2. owpreamble.asp 272 Line
     gFS = Chr(179) ==> Chr(127) 
  3. owpatterns.asp 97 Line
     vAnyLetter = "[-,.()'# _0-9A-Za-z"&chr(127)&"-"&chr(255)&"]" 
  4. xsl/owinc.xsl 15 Line
     return (pData); 
  5. owwikify.asp 520 Line
    Function URLDecode(pURL) Dim vPos Dim result Dim tempHex Dim i pURL = Replace(pURL, "+", " ") for i = 1 to len(pURL) If Mid(pURL, i, 1) = "%" Then If LCase(Mid(pURL, i + 1, 1)) = "u" Then result = result & Chr(CLng("&H" & Mid(pURL, i + 2, 4))) i = i + 5 Else tempHex = CLng("&H" & Mid(pURL, i + 1, 2)) If tempHex > 127 Then result = result & Chr(Clng("&H" & Mid(pURL, i + 1, 2)) * &H100 + clng("&H" & Mid(pURL, i + 4, 2))) i = i + 5 Else result = result & Chr(CLng("&H" & Mid(pURL, i + 1, 2))) i = i + 2 End If End If Else result = result & Mid(pURL, i, 1) End If next URLDecode = result End Function 

-------------------------------------------------------------------

출처 : http://aspqna.whohwa.pe.kr/ow.asp?%BF%C0%C7%C2%C0%A7%C5%B0

 입니다.

[출처] OpenWiki 설치 방법 #2|작성자


Posted by leafbird 트랙백 0 : 댓글 0

댓글을 달아 주세요

DirectShow를 사용하다 발생한 DeadLock을 해결하기 위해 구글을 뒤져보다가, DirectShow 개발자가 직접 답변한 듯한 FAQ 문서를 발견했다. (완전 레어) DirectShow 자료는 앞으로 점점 찾아보기 힘들게 될거 같아서... 일단 스크랩.
데드락에 관련된 내용은 문서의 가장 아래쪽에 있다.

원문 출처 : http://www.gdcl.co.uk/q_and_a.htm

해결방법 1에 제시한 IsSendMessage 함수에 대해서는 아래 링크 추가 참조.
2009/09/18 - [Win32/MFC] - Windows API 메시지 데드록(DeadLock) 관련 함수

핵심만 모아 프린트했던 자료. 머리를 식힐겸 프린트 들고 산책을 하며 읽어보자 :)

GDCL Home About GDCL DirectShow WinNt & WDM

 DirectShow Developer Q & A

All Tools and Samples are listed on the Downloads page.

General

What is IAsyncReader for and how can I use it? What is CPullPin?
What's the difference between stopped, paused and running states in DirectShow?
How many threads are there in a typical filter graph?
What is g_Templates and why won't my application link without it?
The DLL registers OK but the wrong module is registered for my filters.
How can I make IQueueCommand work?
Why is frame seeking so slow for Mpeg-1?
Media Player creates my filter twice
My app hangs in FilterGraph->Release() when there are several graphs

AVStream

Stream Format dialog does not work with AVSHWS sample driver: answer
Hangs in CKSQueue or CKSOutputPin during BeginFlush or graph stop: answer
Dynamic format change in AVStream driver: answer

How To...

How can I host DirectX Audio Plug-ins in my application?
How can I play back MPEG streams from live sources or the network?
How to overlay text and graphics on a running movie
How to use in-place transforms with the video renderer

Visual Basic

How can I use the File Writer filter from Visual Basic?
How can I select a reference clock from Visual Basic?
How can I show a filter's property pages from Visual Basic?
How can I set the interleaving properties of the AVI Mux filter from Visual Basic?
How can I select the left or right audio channels when playing MPEG-1 
How can I select the video capture format and capture parameters with the "Stream Format" dialog?
How can I specify a capture format from a VB program?
How can I grab still frames from a movie using Visual Basic?
Why does the DirectX Builder sample not work properly?
How can I list all the video capture filters (or any another category of filters)?
How can I remove filters from a graph in VB

 DirectShow

An overview of the DirectShow filter architecture
The filter graph manager and plug-in distributors
How the filtergraph manager builds graphs
Media types
Data transports
A technical Q & A for developers

What is IAsyncReader for and how can I use it? What is CPullPin?

Most streams in DirectShow use a requested push model. That is, you tell the upstream pin where it should start and stop, and it then delivers you that section of the stream in a sequence of samples delivered to your Receive method on its thread. This works fine for most playback scenarios, but there are some cases where it is not very efficient. One such case is the AVI file format: this is not really designed well for sequential playback, since the chunks you need are often in the wrong place, and must always be referenced via the index. To play this back efficiently, you need to be able to read more at random in the file, rather than just parsing chunks as they arrive as you would with MPEG for example.

In order to extract the file reading parts of both the MPEG parser and the AVI parser into a common filter (so that for example it could be replaced by a URL filter) it was necessary to have an interface at this point that was efficient in both cases. This is the IAsyncReader interface. Using this interface, each sample is requested separately with a random access style. You can either have the requests fulfilled synchronously on your own thread (SyncRead) or queue them and collect the completed requests later (Request and Wait).

CPullPin provides the client code for this interface for a downstream pin, and really is designed to let the input pin look the same whether it uses IAsyncReader or the normal push-model IMemInputPin::Receive. If you connect to an output pin that uses IMemInputPin::Receive, the data will be sent to your Receive method. If you connect to an output pin that only supports IAsyncReader, then CPullPin provides the 'glue' that pulls data from the output pin and delivers it to your Receive method. It doesn't really get any of the benefit of being able to read data from different positions in the stream. Accordingly you will not be surprised to learn that the mpeg parser uses CPullPin (in sync mode) whereas the AVI file parser uses the IAsyncReader interface in async mode, but using its own code to access discontiguous chunks independently.

In sync mode, the async reader just reads the file. When you call IAsyncReader::SyncReadAligned, it does an unbuffered ReadFile call and then returns. CPullPin in this mode just has a loop that gets a buffer, calls the sync-read method and then calls the (overridden) Receive method to get it to your pin.

In async mode you call Request to queue a request, which is passed to a worker thread within the async reader. At some point, you can then call WaitForNext to get a completed buffer back from the async reader. Win95 does not support overlapped i/o, and hence I don't believe the file reader uses overlapped i/o in the Windows NT case either even when it is available.

CPullPin in async mode has a loop that queues a request and waits for a completed request, but always keeping one request queued. So in this case, the only difference between the two modes is that in async mode, the next request will be sent to the disk almost immediately, whereas in sync mode, the next request is not queued to the disk until your Receive method has completed (in most of the standard parsers, this is very quick).

So in a high bandwidth case where you need to queue the next request before completing the Receive processing, you may want to consider async mode, but in other cases, you are ok in sync mode. If you want to receive data from many discontiguous parts of the file, you probably want to discard CPullPin entirely and write your own access code, but for most streaming cases, sync mode with CPullPin gives you what you want.

It's also worth noting that the DirectShow MPEG splitters use IAsyncReader methods to access parts of the file at pin-connection time: IMemInputPin would not provide data until the graph was running (see discussion below on live material)

What's the difference between stopped, paused and running states in DirectShow?

In a DirectShow graph, there are three possible states: stopped, paused and running. If a graph is stopped, filters hold a minimum set of resources and do not process data. If the graph is running, filters hold a maximal set of resources and data is processed and rendered.

If a graph is paused then data is processed but not rendered. Source filters will start (or continue) to push data into the graph and transform filters will process the data but the renderer will not draw or write the data. The transform filter will eventually block since its buffers are not being consumed by the renderer. Thus a graph can be cued for rapid starting simply by leaving it in paused mode: once some data arrives at the renderer, the rest of the graph will be blocked by the normal flow control mechanisms (GetBuffer or Receive will block) until the graph is run.

Media types that can be rendered statically, such as video (where you can show a frozen frame) but not, for example, audio, are typically rendered in paused state. Repainting the video window can simply be achieved by transitioning the graph to paused mode and back.

How many threads are there in a typical filter graph?

DirectShow filter graphs typically have one thread per stream segment -- that is, one thread would be active on a source filter's output pin and would push data right through the transform filters and into the renderer. The transform function and delivery downstream would normally occur on this thread during the Receive call. A parser or other filter that has more than one output pin would typically have a new thread for each output pin (plus the source filter's thread on which it receives data). This can be done straightforwardly using a COutputQueue class in each output pin.

In addition, there will typically be a filter graph manager thread and the application's thread

What is g_Templates and why won't my application link without it?

The DirectShow base class library strmbase.lib provides a COM class factory implementation to simplify the development of filters as COM objects. This class factory uses the template implementation you provide: your filter code will supply the templates for objects in your DLL in the g_Templates array, with a count of entries in g_cTemplates. If you are building a filter, you will need to supply this array and count.

If, however, you are writing an application that uses the DirectShow base classes, you do not need to define this -- you can set g_cTemplates to 0 and then g_Templates will not be referenced.

If your DLL is a COM dll that uses another class factory implementation (perhaps your dll is a ATL control) then you will be exporting DllGetClassFactory from your DLL. This is implemented in a number of places, including the ATL and MFC libraries as well as DirectShow's library. Make sure that the correct library is found first otherwise even if you define g_cTemplates you will not be able to create any of your ATL objects.

The DLL registers OK but the wrong module is registered for my filters.

You need to make sure that your DLL starts at DllEntryPoint, defined in dllentry.cpp in the class library. Otherwise the class library's global variable g_hInst is not set to the correct module handle, and registration will go wrong. The best way to make this work with C/C++ runtime initialization is the following code:

    extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
    BOOL WINAPI DllMain(HANDLE hDllHandle, DWORD dwReason, LPVOID lpReserved)
    {

    return DllEntryPoint(
    reinterpret_cast<HINSTANCE>(hDllHandle),
    dwReason, lpReserved);
    }

How can I make IQueueCommand work?

IQueueCommand allows you to queue up operations on OLE-automatable interfaces for times in the future. The interface allows you to specify accurate timing (eg when the filter is processing data to be presented at time X), but to date it has only ever been implemented with coarse timing (ie, command is executed when the graph reaches time X).

Watch out for three tricky points:

1. the IID is not stored -- instead the IID* is stored, so don't put the REFIID param on the stack.

2. You need to pass the dispid for the command to be executed. Use the type info to find this.

3. Don't forget that the time param is an old-style REFTIME double, in which the integers are the number of seconds.

The following sample code will cause the graph to stop after 5 seconds of playing

ITypeLib* ptlib;
LoadRegTypeLib(LIBID_QuartzTypeLib, 1, 0, 0, &ptlib);
ITypeInfo* pti;
ptlib->GetTypeInfoOfGuid(IID_IMediaControl, &pti);
ptlib->Release();
WCHAR* pMethod = L"Stop";
long dispid;
pti->GetIDsOfNames(&pMethod, 1, &dispid);
pti->Release();
IQueueCommand* pQ;
m_Player.Graph()->QueryInterface(IID_IQueueCommand, (void**)&pQ);
if (pQ) {
HRESULT hr = pQ->InvokeAtStreamTime(
&m_pCmd, 5,
(GUID*)&IID_IMediaControl,
dispid, DISPATCH_METHOD, 0, 0, 0, 0);
pQ->Release();
}

You can implement IQueueCommand in your filter - eg if you want it to apply with fine precision when you are processing the relevant sample. The base classes in ctlutil.h/cpp will help you there. But the distributor will not call your filter, so your app will need to find your filter and QI for IQueueCommand directly on your filter. The fact that this distributor feature was never implemented is probably why no-one ever used IQueueCommand.

Why is frame seeking so slow for Mpeg-1?

The Mpeg-1 stream splitter in DirectX 8 (and 8.0a) contains a bug which makes seeking to frames (with IMediaSeeking using TIME_FORMAT_FRAMES) slow and inaccurate. The time taken is proportional to the offset within the file, so that seeking 3 or 4 minutes into a file can take as much as 5 or 6 seconds. Use ConvertTimeFormat, or simply seek in time mode. The splitter in any case performs frame mode seeking by assuming a constant frame rate, so you can use this in your code to work around this bug.

Media Player creates my filter twice

This seems to be a bug in WMP8 that I think is fixed in WMP9. If you have a source filter that is registered as the handler for a private URL protocol "myproto://parameters...", WMP8 will create the filter twice. It will add both instances to the same graph and will call IFileSourceFilter::Load on both. Probably the best fix is to check in JoinFilterGraph if another instance of your filter already exists in this graph, and if so return an error from JoinFilterGraph.

My app hangs in FilterGraph->Release() when there are several graphs

I think this is an obscure deadlock in the FGControl component of the filter graph manager. There is a worker thread shared between all filter graphs in the same process. This worker thread is blocked waiting for a lock on graph A, which is held by the main app thread. While waiting for the lock, sent messages are processed which results in winproc code on the main app thread being executed. During this winproc execution, your code releases filter graph B. The destructor for graph B (still running on the main app thread) sends a message to the worker thread informing it that the graph is going away, and it blocks for a response which it never gets.

You will only hit this problem if the main app thread is handling events (such as video window activation and de-activation) for other filter graphs when it receives the message that causes your graph to be destroyed. If you control the application code, the simplest fix is to call InSendMessage before destroying the filtergraph, and if this returns true, postpone the graph destruction until later, using PostMessage.

Otherwise I think the fix is to use the "no threads" filter graph CLSID_FilterGraphNoThread. This must be created on a thread that has a message pump (which in most cases means having a dedicated thread that does the CoCreateInstance and then just pumps messages). If you think you are running into this problem, please let me know.

Posted by leafbird 트랙백 0 : 댓글 1

댓글을 달아 주세요

  1. addr | edit/del | reply Favicon of http://jaketkerenbandung.com BlogIcon jaket bandung online 2012.12.07 15:47

    좋은 콘텐츠입니다. 더 많은 우리를 표시합니다. 모든 방문자가 게시 된 게시물에서 도움이 될 것입니다.