I was wondering if it is possible to adjust the thread priority of a
filter graph. For example, using a DirectShow filter graph to transcode
a file will result in 100% CPU usage in which case it would be nice to
run the filter graph (and therefore any threads used by its filters) at
(say) idle priority.
Similarily when using a Filter graph to record from a capture card (or
playback etc) it would be nice to be able to set a high priority so
that a normal priority process using 100% CPU would cause problems.
(Other ways to achieve the above desired effects are of course welcome)
Im hoping to be able to do this from C# btw, as thats the
implementation language of the application which creates and runs these
graphs, but C++ API hints would also be nice.
Please note that im not able to change the source code of the filters
involved in the graph.
In regards to all this, could someone perhaps (just briefly) explain
how many threads are involved in a filter graph? That is, when you
start a filter graph will it sometimes(always?) create a seperate
thread per filter in the graph?
I note that in MS Media Center video playback is not affected by high
CPU usage(though GUI interaction is) so im guessing this is possible
somehow.
> Hi,
>
> I was wondering if it is possible to adjust the thread priority of a
> filter graph. For example, using a DirectShow filter graph to transcode
> a file will result in 100% CPU usage in which case it would be nice to
> run the filter graph (and therefore any threads used by its filters) at
> (say) idle priority.
You'd need to get the handle of the thread that you wanted to change the
priority on. Then, call SetThreadPriority. Since you're probably not
creating the threads and don't readily have a thread handle to reference,
you'd probably have to enumerate the threads in your process.
The System.Threading.Thread class exposes managed threads, not native
threads, so if you wanted to set the thread priority from managed code, you'd
have to do it through interop and then call the aforementioned functions.
If you don't need to change the priority for given threads, but just for an
entire process, you could use SetPriorityClass or the
System.Diagnostics.Process.PriorityClass from a .NET application.
> In regards to all this, could someone perhaps (just briefly) explain
> how many threads are involved in a filter graph? That is, when you
> start a filter graph will it sometimes(always?) create a seperate
> thread per filter in the graph?
There is a section in the DShow documentation devoted to this subject; see
"The Streaming and Application Threads." In a nutshell: "Any directshow
application contains at least two important threads: the application thread,
and one or more streaming threads. Samples are delivered on the streaming
threads, and state changes happen on the application threads. The main
streaming thread is created by a source or parser filter. Other filters
might create worker threads that deliver samples, and these are considered
streaming threads as well."
> I note that in MS Media Center video playback is not affected by high
> CPU usage(though GUI interaction is) so im guessing this is possible
> somehow.
They may have bumped up the priority of the dshow filter graphs. You could
easily interfere with their playback, however, by launching a porky
application with an unnecessarily high priority.
> You'd need to get the handle of the thread that you wanted to change the
> priority on. Then, call SetThreadPriority. Since you're probably not
> creating the threads and don't readily have a thread handle to reference,
> you'd probably have to enumerate the threads in your process.
How would i be able to decide which thread belonged to the filter graph
in question?
The application in question is already multithreaded, and is likely to
run several filter graphs at once(for example one doing transcoding to
disc, while another performs playback), so i need way to deciding if a
thread belongs to a given graph.
> There is a section in the DShow documentation devoted to this subject; see
> "The Streaming and Application Threads." In a nutshell: "Any directshow
> application contains at least two important threads: the application thread,
> and one or more streaming threads. Samples are delivered on the streaming
> threads, and state changes happen on the application threads. The main
> streaming thread is created by a source or parser filter. Other filters
> might create worker threads that deliver samples, and these are considered
> streaming threads as well."
I did actually read that, but was not entirely sure how to interpret
it. Is this correctly understood:
The application thread is the thread that starts the filtergraph,
right? Upon being started the source filter in the graph creates a new
thread for the graph to run in, and returns, but each filter in the
graph can (and will) create worked threads.
Do you happen to know how common it is to create worker threads for
each filter? If it was rare it seemed to would be easy to just add a
filter to the graph, which could then modify the initial streaming
thread.
> > I note that in MS Media Center video playback is not affected by high
> > CPU usage(though GUI interaction is) so im guessing this is possible
> > somehow.
>
> They may have bumped up the priority of the dshow filter graphs. You could
> easily interfere with their playback, however, by launching a porky
> application with an unnecessarily high priority.
For my use it would be sufficient that it is 'immune' to interference
by normal priority processes (and specifically other filter graphs
running in the same process).
Btw, i have been trying to locate a decent book on the topic of
DirectShow, but i have been completely unable to find anything other
than outdated and (according to reviews) really badly written material.
You wouldnt happen to know about good resources, would you? Especially
regarding DVB video capture, transcoding and video playback.
> How would i be able to decide which thread belonged to the filter graph
> in question?
> The application in question is already multithreaded, and is likely to
> run several filter graphs at once(for example one doing transcoding to
> disc, while another performs playback), so i need way to deciding if a
> thread belongs to a given graph.
Good question. It could be difficult for a number of reasons:
1. If you're using the Intelligent Connect feature of DirectShow, it could
be somewhat unpredictable what your graph actually looks like. Different
machines with different filters may load up different graphs to render the
stream.
2. If you're not using Intelligent Connect, it may still be difficult: I
have never seen MSFT or anyone publish what threads are created by a given
filter. Some other MVPs may have some insight into that particular issue,
but DirectShow filters can and will produce threads that aren't documented
(for example, I have a source filter I wrote that creates two threads).
If a filter names a thread (we do this in our application), you could
probably locate it by enumerating the threads in a process, but again: if the
thread name isn't published, this is probably unwise. (might change the
naming between releases, removing the naming, etc.)
You might take a look at this conversation:
Maybe you could launch your graphs in another process, and then lower the
entire process's priority.
> The application thread is the thread that starts the filtergraph,
> right?
Correct.
> Upon being started the source filter in the graph creates a new
> thread for the graph to run in, and returns, but each filter in the
> graph can (and will) create worked threads.
> Do you happen to know how common it is to create worker threads for
> each filter?
Correct again, and it is very common for filters to create threads. In
fact, take a look at CSource and CSourceStream in the baseclasses: by
default, filters derived from CSource have a worker thread for composing
samples. If it's your filter, it's easy enough to change the priority of the
worker thread, but if it's someone else's filter....not so easy.
> Btw, i have been trying to locate a decent book on the topic of
> DirectShow, but i have been completely unable to find anything other
> than outdated and (according to reviews) really badly written material.
> You wouldnt happen to know about good resources, would you? Especially
> regarding DVB video capture, transcoding and video playback.
Sadly, not really. Your best resources are the newsgroups, the DShow
documentation, the included DShow samples, the baseclasses, and google. Many
of the more advanced features of DShow are not well documented (custom
allocator-presentor, for example--not exactly friendly). Mark Pesce has a
decent book, although IMO it's suitable only for relatively basic tasks.
>> How would i be able to decide which thread belonged to the filter graph
>> in question?
>> The application in question is already multithreaded, and is likely to
>> run several filter graphs at once(for example one doing transcoding to
>> disc, while another performs playback), so i need way to deciding if a
>> thread belongs to a given graph.
The approach I've heard recommended is
create a graph
enumerate the threads in the process
pause the graph (which creates all the stream threads)
enumerate all the threads in the graph
subract the orginal list and uprate the remaining thread priorities
Iain
--
Iain Downs (DirectShow MVP)
Commercial Software Therapist
www.idcl.co.uk
That would work i guess, but its a bit of a hack. The problem is that
the program in question is a HTPC application, so the recorder part of
the program might decide to start a recording graph between the two
enumerations, or an unrelated thread might start(unlikely to occur just
at that point but may happen), which might cause you to change priority
of some threads belonging to another part of the program.
In order for it to work always, you need some means of preventing other
new threads being created by threads other than the current when you
enumerate and pause. I guess a hack would be to raise the current
thread priority temporarily to realtime priority or one could introduce
some kind of locking mechanism but the latter would require excessive
changes throughout the program.
Intelligent Connect is not used, all the graphs are built manually.
> If a filter names a thread (we do this in our application), you could
> probably locate it by enumerating the threads in a process, but again: if the
> thread name isn't published, this is probably unwise. (might change the
> naming between releases, removing the naming, etc.)
Im not completely up to date on multi-threading, but isnt there some
way to identify which thread started a given thread(in either C++ or
C#)? With that information it would be possible to enumerate and id the
relevant threads, by first id'ing the initial streaming thread as the
most recent thread created by the application thread, and then looking
to see what was created by the streaming thread, etc, until all threads
involved in the filter have been found.
> Im not completely up to date on multi-threading, but isnt there some
> way to identify which thread started a given thread(in either C++ or
> C#)? With that information it would be possible to enumerate and id the
> relevant threads, by first id'ing the initial streaming thread as the
> most recent thread created by the application thread, and then looking
> to see what was created by the streaming thread, etc, until all threads
> involved in the filter have been found.
Not sure, but, IIRC, the technique that has been mentioned when this has
come up in the past is to:
1. Enumerate the threads in the app.
2. Build and start the graph.
3. Enumerate the threads in the app again and the new threads are likely
to be those used by the graph.
--
Please read this before replying:
1. Dshow & posting help: http://tmhare.mvps.org/help.htm
2. Trim & respond inline (please don't top post or snip everything)
3. Benefit others: follow up if you are helped or you found a solution
> Im not completely up to date on multi-threading, but isnt
> there some way to identify which thread started a given
> thread(in either C++ or C#)?
I can't think of any function to get a thread's parent
thread and I think a thread does not keep a reference to its
parent so that threads in a process do not for a tree like
processes in the system.
However, you can hook CreateThread() and gather this
information yourself right after the thread is created, or
just set its priority, in which case you would do better to
also hook SetThreadPriority() to prevent some code outside
your control to change the priority at a later time.
--
// Alessandro Angeli
// MVP :: DirectShow / MediaFoundation
// a dot angeli at psynet dot net
> 2. If you're not using Intelligent Connect, it may still be difficult: I
> have never seen MSFT or anyone publish what threads are created by a given
> filter. Some other MVPs may have some insight into that particular issue,
> but DirectShow filters can and will produce threads that aren't documented
> (for example, I have a source filter I wrote that creates two threads).
Another approach you might try is inserting a custom
inplace-transform-filter at every place where you suppose a seperate
streaming-thread (e.g before the decoder and after the decoder). The
inplace's transfrom procedure will be called in the streaming-threads
context, so you're able to bump up it's priority.
The disadvantage to this is, that you won't be able to access any seperate
thread that e.g. the decoder might create internally to process/decode
samples.
However I've used this technique and (at least for my needs) it worked as
expected...
--
Peter Feldbaumer
p dot feldbaumer at utanet dot at
Thats also a good idea, but from a development time point of view, i
actually think it would be easier to hook CreateThread, it also has the
advantage that it will always give the desired behavior.
I think ill start out by trying the 'hacky' approach of just upping the
app thread priority, pausing the graph, and then look what threads were
created. Then i can do the hook stuff if the priority changes helps.