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, (<-- suggested message pumping resolved this)ctransinplacefilter
collect imediasample
in chain? there no error both graphedit , graphstudio hang when trying connect remote graph.
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
Post a Comment