Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Internal Graph inside a Source Filter

34 views
Skip to first unread message

cyrus

unread,
Feb 9, 2009, 6:54:12 PM2/9/09
to
Last time I posted a thread questioning how to implement a virtual
camera
http://groups.google.com/group/microsoft.public.win32.programmer.directx.video/browse_thread/thread/ce5535e717850bab/f4095a6485c53ccd

Thanks to Alessandro Angeli and Chris. P, I got the Source-
>SampleGrabber->NullRenderer going, and SampleCB callback function of
the SampleGrabber is also functioning properly; now I'm back to
integrate the internal graph into a source filter and get the CUDA
processing module to work.


One problem that keeps happening is that I can preview the virtual cam
in Skype, but it freezes after several seconds. However rendering the
source filter in Graph Edit or MSN poses no problem (despite a little
lag here and there).

Some more information about the system:

1. Skype is set to favor 640x480 resolution, and I hard-coded to make
sure the internal graph of the source filter also produces 640x480
buffer samples.

2. Two of the classes I used are:
CVcam (inherits from CSource)
CVcamStream (inherits from CSourceStream)

3. The internal graph (with all the interfaces and filters) is kept in
CVcamStream class.
Internal Graph is built (All filters and interfaces initialized and
RenderStream used to build the graph) in Ctor of CVcamStream
Internal Graph is released in Dtor of CVcamStream
IMediaControl::Run of the internal graph is called in
CVcamStream::OnThreadStartPlay()
IMediaControl::Stop of the internal graph is called in
CVcamStream::OnThreadDestroy()

4. CVcamStream::FillBuffer and CSampleGrabberCB::SampleCB share the
same buffer area and CCritSec, for data exchange and synchronization


Anyone senses something wrong in my implementation that might lead to
the anomaly with Skype? Any input would be much appreciated. Thanks!

Cyrus
CS, Univ. of Alberta

cyrus

unread,
Feb 10, 2009, 12:29:12 PM2/10/09
to
*Lemme reformat to make it clearer*

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

Thanks to Alessandro Angeli and Chris. P, I got the

CaptureSourceFilter->SampleGrabber->NullRenderer going, and SampleCB


callback function of the SampleGrabber is also functioning properly;
now I'm back to integrate the internal graph into a source filter and
get the CUDA processing module to work.

One problem that keeps happening is that I can preview the virtual cam
in Skype, but it freezes after several seconds. However rendering the

virtual cam source filter in Graph Edit or MSN poses no problem


(despite a little lag here and there).

Some more information about the system:
1. Skype is set to favor 640x480 resolution, and I hard-coded to make
sure the internal graph of the source filter also produces 640x480
buffer samples.

2. Two of the classes I created are:


CVcam (inherits from CSource)
CVcamStream (inherits from CSourceStream)

They are close clones of Vivek's vcam demo, thank you Vivek!
http://tmhare.mvps.org/downloads.htm

3. The internal graph (with all the interfaces and filters) is kept in
CVcamStream class.
Internal Graph is built (All filters and interfaces initialized and
RenderStream used to build the graph) in Ctor of CVcamStream
Internal Graph is released in Dtor of CVcamStream
IMediaControl::Run of the internal graph is called in
CVcamStream::OnThreadStartPlay()
IMediaControl::Stop of the internal graph is called in
CVcamStream::OnThreadDestroy()

4. CVcamStream::FillBuffer and CSampleGrabberCB::SampleCB share the
same buffer area and CCritSec, for data exchange and synchronization


Anyone senses something wrong in my implementation that might lead to
the anomaly with Skype? Any input would be much appreciated. Thanks!


-----------------------------------------------------------------------------------------------------
More

I found a pretty old thread by Alessandro Angeli that says more on
Internal Graph stuff. It tries to create a source filter that playback
in a reverse order by buffering all the frames in the internal graph
http://groups.google.com/group/microsoft.public.win32.programmer.directx.video/browse_thread/thread/d114e7947926994f?tvc=2

The flow will be something like that (-: outside world, +: inside
MySourceFilter):
1- you create an instance of MySourceFilter and call
IFileSourceFilter::Load() on it (2-6 are inside Load())
2+ MySourceFilter creates an instance of MyDataSink
3+ MySourceFilter calls some custom method on MyDataSink to notify it
about
MyCustomCallback which is implemented by MySourceFilter itself
4+ MySourceFilter creates an empty graph, InternalGraph
5+ MySourceFilter adds MyDataSink to InternalGraph
6+ MySourceFilter calls RenderFile() with the filename it received
from the
call to Load()
7- you create an empty graph, ExternalGraph
8- you add MySourceFilter to ExternalGraph
9- you Render() MySourceFilter's output pin
10- you Run() the graph
11+ MySourceFilter spawns a thread to handle InternalGraph and returns
from Run() (so the rest of the operations are carried out by the new
thread)
12+ MySourceFilter seeks InternalGraph where the frame group it's
going to buffer starts
13+ MySourceFilter Run()s InternalGraph
14+ MyDataSink starts receiving samples and forwarding them to
MyCustomCallback
15+ MySourceFilter receives the data from MyCustomCallback and copies
it in its buffer (e.g. a linked list of preallocated media samples,
since they are all of the same size and same media type)
16+ MySourceFilters receives the last sample and Stop()s
InternalGraph
17- MySourceFilter delivers the samples from its buffer in reverse
order to ExternalGraph
18- MySourceFilter repeats 12-18 until it reaches the beginning of the
file


It is said that a new thread is to be spawned to handle InternalGraph
in Step 11. To my understanding, IMediaControl::Run actually spawns a
new thread to handle the data pushing? Or we need to actually write a
new thread class to handle all these?

Thanks

Cyrus
Computing Science Department
University of Alberta

cyrus

unread,
Feb 11, 2009, 4:42:55 PM2/11/09
to
Update:

In this thread, author ran into problem of freezing. In this case, he
constructed a simple graph that consisting a webcam capture source,
renderer, and necessary color transformer in between.

He uses IMediaControl::Run to start the graph, without providing a
proper message dispatching routine; the graph freezes after several
seconds.

http://groups.google.com/group/microsoft.public.win32.programmer.directx.video/browse_thread/thread/d956fa8c31695b23/af4a501b99cc4f07


I think that is what happens in my case. Only difference is that, I am
dealing with an Internal Graph within my CSourceStream class. I might
need a message pump rather than simply embed IMediaControl::Run in
CSourceStream::ThreadStartPlay, IMediaControl::Stop in
CSourceStream::ThreadDestroy, then expect everything will flow.

I'll implement this and see what happens. At the same, any ideas would
be appreciated on how to properly set up a internal graph!

cyrus

unread,
Feb 17, 2009, 8:29:27 PM2/17/09
to

I've made it work...

I start to think that it might be because I didn't do the message
dispatching properly, as someone else has ran into graph frozen
condition before (http://groups.google.com/group/
microsoft.public.win32.programmer.directx.video/browse_thread/thread/
d956fa8c31695b23/af4a501b99cc4f07)


But later I found out that, the time stamp of the sample is not sent
properly in my FillBuffer function. I didn't do IMediaSample::SetTime.
Seems Skype is not happy dealing with media sample without time
stamps.... Some one might have some better and thorough explanation
on this.... After properly setting it, the freezing problem just went
away~!~


Back to the Message Pump issue, which is stated here
http://groups.google.com/group/microsoft.public.win32.programmer.directx.video/browse_thread/thread/bb3eaefeff05f483/6984004347576ffc;
so it seems the internal graph somehow is still kept running. I guess
CSourceStream::DoBufferProcessingLoop and CSourceStream::ThreadProc
already acts the message pump responsibility, for both the internal
graph and the source filter itself?

Some more explanation is more than welcome....

Thanks!

0 new messages