c++ - DirectShow filter graph never completes on some machines -


i'm working on directshow filter graph retrieve imediasample video file. received original implementation contract developer while , i've been banging head against wall trying figure out why code working on development machine not on 2 other test servers have.

as best can tell filter graph never completing on "broken" machines. receive e_abort imediaevent->waitforcompletion() call. on "working" machine call returns s_ok after 2 loops.

update: directshow spy doesn't seem working me. perhaps that's because have custom, unregistered, ctransinplacefilter collect imediasample in chain? there no error both graphedit , graphstudio hang when trying connect remote graph. (<-- suggested message pumping resolved this)

using graphstudio able media subtype mpeg-4 decoder connects our ctransinplacefilter. on machine it's mediasubtype_yv12 on "broken" machine it's mediasubtype_iyuv. in checkinputtype method of our ctransinplacefilter accept mediasubtype_rgb24 leads me believe there 1 or more "magic filter" being inserted graph.

update: roman r. able directshow spy working. on "broken" machine @ least. on "working" machine access violation filter graph runs quick , torn down it's tough connect it.

i found had color space converter able handle mediasubtype_iyuv in mediasubtype_rgb24 out. added graph , should correct now.

directshow spy shows filter graph (looks complete me):

file source -> mpeg demux -> mpeg4 decoder -> color space converter -> ctransinplacefilter -> null render

however imediaevent->waitforcompletion() call never returns s_ok , filter graph runs forever. i'm stumped going on. there else should checking error state or something?

update: modified loop enumerate filters in graph , query state:

char debugstring[512];  int count = 0; long evcode; mediafilter->setsyncsource(null); hr = mediacontrol->run();  sprintf(debugstring, "mediacontrol->run() %d", hr); debuglog(debugstring);  while (!m_threadkill) {     hr = mediaevent->waitforcompletion(200, &evcode);      sprintf(debugstring, "mediaevent->waitforcompletion() %d, %d", hr, count);     debuglog(debugstring);     count++;      ienumfilters *penum = null;     ibasefilter *pfilter;     ulong cfetched;      graphbuilder->enumfilters(&penum);      while(penum->next(1, &pfilter, &cfetched) == s_ok)     {         filter_info filterinfo;         filter_state filterstate;          char szname[256];          pfilter->getstate(200, &filterstate);         pfilter->queryfilterinfo(&filterinfo);         widechartomultibyte(cp_acp, 0, filterinfo.achname, -1, szname, 256, 0, 0);          sprintf(debugstring, "filter: %s, %d", szname, filterstate);          debuglog(debugstring);          safe_release(filterinfo.pgraph);         safe_release(pfilter);     }      safe_release(penum);      if (hr == s_ok)     {         break;     } }  sprintf(debugstring, "mediacontrol->stop()"); debuglog(debugstring);  mediacontrol->stop(); 

they in "running" state. if filter connected correctly , filters running why graph never complete on "broken" machines?

update: suggested roman r. removed our ctransinplacefilter filter graph on broken machine , graph completed. ctransinplacefilter connected cpu usage drops zero. i'm not sure why following code works on machines not others. i'll start adding debug logging ctransinplacefilter try , figure out going on (or not going on).


solution: suggested roman r. (i feel i'm repeating myself :p) problem ended being deadlock. broken machines had single cpu/core working machines had multiple cpus/cores. application consists of thread per source video, merge thread, , destination thread.

the source thread(s) run filter graph (i assume filter graph runs in it's own thread) retrieve data imediasample , place cqueue<byte*>.

the merge thread loops through sources, retrieves sample data source cqueue<byte*>, merges frames single image, , sends them off cqueue<byte*> destination thread consumes.

the destination thread runs filter graph encode video/audio.

the cqueue<byte*> blocks on put until there free space. fine because merge thread removing items. on single cpu/core machines merge thread being blocked source threads.

long story short sleep(0); here , there allowed source threads yield merge threads , problem seems resolved.

playback completion internally includes sending end of stream notifications streams sources, relayed downstream filters, gathered on renderers , then, combined, reported application. so, successful completion depends on participants of filter graph acting right.

you discovered topology of graph, , need compare topologies on different machines. if see differences there, might suggest filter losing completion notifications.

however, if topologies match accurately, filters act differently other reasons. in particular, having own custom filter on graph has high chances losing notification , graph never completes. stops processing data , idling there (this thing want check - whether cpu consumption lowers 0 or processing still happening, in case re-qualify issue deadlock).

something more or less to approach problem start cutting filters off graph identify filter brings problem in. trying these graphs possibly find offender:

file source -> mpeg demux -> mpeg4 decoder -> color space converter -> null render file source -> mpeg demux -> mpeg4 decoder -> null render file source -> mpeg demux -> null render 

Comments

Popular posts from this blog

c# - Send Image in Json : 400 Bad request -

jquery - Fancybox - apply a function to several elements -

An easy way to program an Android keyboard layout app -