"virtual camera" source filter (DirectShow)

Hi Tim,

I started making that filter as you said.
(For Skype to add special effects to a video stream in DirectShow)
I have a problem with Skype.

I read about base classes for example CTransformFilter,CSource,CTransInPlaceFilter …etc.
And I chose CTransInPlaceFilter (for these special effect) ,
I registered my filter under CLSID_VideoInputDeviceCategory,
and I implemented all the functions for my baseclass ,
when a program puts my filter in a graph ,
in JoinFilterGraph() function I load the webcam filter , a conversion filter and
I connect the the pins to eachother so it looks like:
[WebCam]->[Converter]->[Myfilter]->

It works correctly so when I load my filter in Graphedit ,automatically sets up it’s own graph . And with a Render I see the special effects I’ve added.

The only problem is with Skype. Cause Skype instanciates my filter ,but than it somehow not appears in the “webcam list”.

Am I on a wrong way to implement this for Skype ? And if I am then how should I continue?

Thanks in advance for any help you are able to provide,
Andrew

xxxxx@gmail.com wrote:

The only problem is with Skype. Cause Skype instanciates my filter ,but than it somehow not appears in the “webcam list”.

Am I on a wrong way to implement this for Skype ? And if I am then how should I continue?

Skype can be picky about the formats it accepts. Does the web camera by
itself appear in Skype’s list?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

>Skype can be picky about the formats it accepts. Does the web camera by itself appear in Skype’s list?

My filter gets (because of AVI Decompressor Filter) ,and forwards only RGB24. Yes, it does.
For now the problem almost solved, cause I read that Skype does not support “simple filters”, so I had to implement IKsPropertySet functions and IAMStreamConfig functions for my output pin. Now Skype lists my filter, but when I chose it sais:

“cannot capture video on Skype, web cam may be already in use”

I tried to debug this, so I placed some MessageBox() in my functions to track this.
In the case of skype,
just IKsPropertySet functions (Set,Get,QuerySupported)
and IAMStreamConfig functions (SetFormat,GetFormat,GetNumberOfCapabilities,GetStreamCaps)
have called and then something happens after the second GetStreamCaps() function call.

And I have no more functions called. So I think all of these happens before am added to any graph.
I tried to search for some information how this “pin handshake” prucedure works,… without success.

What can be the problem? I’ve seen Vivek’s capture source , he/she used CSource for baseclass. But my filter works well in graph edit ,however graph edit does not call IKsPropertySet functions on my output pin.

Thank you for your help,
Andrew

xxxxx@gmail.com wrote:

My filter gets (because of AVI Decompressor Filter) ,and forwards only RGB24. Yes, it does.
For now the problem almost solved, cause I read that Skype does not support “simple filters”, so I had to implement IKsPropertySet functions and IAMStreamConfig functions for my output pin.

I was going to mention that next, actually. In your implementation of
IKsPropertySet, you need to handle GET for the AMPROPERTY_PIN_CATEGORY
property in the AMPROPSET_Pin property set. You have to return
PIN_CATEGORY_CAPTURE. You do not have to handle SET. For
IAMStreamConfig, you have to provide a reasonably intelligent answer for
all four methods. GetFormat is called many times during graph negotiation.

I tried to debug this, so I placed some MessageBox() in my functions to track this.

OutputDebugString is a better way to do this, because (a) you don’t have
to dismiss a box every time, and (b) the debug record sticks around.
Use DebugView to capture the output.

You might want to print out the GUIDs in your QueryInterface handler to
see if they are asking for other interfaces. That requires some
deductive thinking, because these apps often ask for interfaces that are
optional, or only applicable for certain types of filters.

What can be the problem? I’ve seen Vivek’s capture source , he/she used CSource for baseclass. But my filter works well in graph edit ,however graph edit does not call IKsPropertySet functions on my output pin.

That’s correct. Graphedt is perhaps the most liberal of DirectShow
applications; it will happily attempt connect any two pins together.
Skype has additional requirements beyond that, and those requirements
are not documented.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

>I was going to mention that next, actually. In your implementation of IKsPropertySet, you need to handle GET for the AMPROPERTY_PIN_CATEGORY property in the AMPROPSET_Pin property set. You >have to return PIN_CATEGORY_CAPTURE. You do not have to handle SET. For IAMStreamConfig, you have to provide a reasonably intelligent answer for all four methods. GetFormat is called many >times during graph negotiation.

I’ve just noticed that in the case of Skype, my JoinFilterGraph() is not called by
Filter Graph Manager when I am added to the graph. It is important to build in somehow my filters to that graph. Can I make it work somehow or is there any other solution for this ?

OutputDebugString is a better way to do this, because (a) you don’t have to dismiss a box every >time, and (b) the debug record sticks around. Use DebugView to capture the output.

Thanks, I will use that.

Andrew

xxxxx@gmail.com wrote:

I’ve just noticed that in the case of Skype, my JoinFilterGraph() is not called by
Filter Graph Manager when I am added to the graph. It is important to build in somehow my filters to that graph. Can I make it work somehow or is there any other solution for this ?

Are you sure you are being added to the graph? During an “intelligent
connect” negotiation, the graph manager instantiates almost every
registered filter to attempt to make a connection. That process can
cause your method to be calls without actually adding you to the graph.

You might break into a debugger and see what the call stack looks like
when you get called.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

>Are you sure you are being added to the graph? During an “intelligent connect” negotiation, the graph manager instantiates almost every registered filter to attempt to make a connection. That process can cause your method to be calls without actually adding you to the graph.

Yes , I’am almost sure, cause I’ve created an another thread and my filter’s “m_pGraph” member gets the pointer to that graph , the problem is I’am not notified during this action …
Can be that, the Skype developers somehow block that notification ? …, cause this happens only with Skype.

Andrew

xxxxx@gmail.com wrote:

> Are you sure you are being added to the graph? During an “intelligent connect” negotiation, the graph manager instantiates almost every registered filter to attempt to make a connection. That process can cause your method to be calls without actually adding you to the graph.
Yes , I’am almost sure, cause I’ve created an another thread and my filter’s “m_pGraph” member gets the pointer to that graph , the problem is I’am not notified during this action …

How did you get control, in order to create the thread? Was that in
your constructor?

Can be that, the Skype developers somehow block that notification ? …, cause this happens only with Skype.

That’s unlikely (besides being counterproductive). That callback
happens during IFilterGraph::AddFilter, which is handled by DirectShow
code, not by the application.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

>How did you get control, in order to create the thread? Was that in your constructor?

Sorry I missed something,… I tried once again as you said it can’t be …
and now I see there is no pointer to that graph …
I was something like this :
#######################################
#######################################
My constructor :

this->m_pOutput=new OutPin(this,&hr);
this->m_pGraph=NULL;
th = CreateThread(NULL,NULL,
TransformFilter::ThreadProc,// entry
this,// param
CREATE_SUSPENDED,
NULL
);
SetThreadPriority(th,THREAD_PRIORITY_TIME_CRITICAL);
ResumeThread(th);
#######################################
My thread entry:
static DWORD WINAPI ThreadProc(
LPVOID lpParameter
){
while( !((TransformFilter*) lpParameter)->m_pGraph ){
}
OutputDebugString(L"There is my graph …");
return 0;
}
#######################################
My Destructor:
~TransformFilter(){
Sleep(4000);
TerminateThread(th,0);
}
#######################################
#######################################

I’ve printed the GUIDs as you said and Skype only needs IAMStreamConfig and IKsPropertySet interfaces …I put OutputDebugString() to every function I’ve implemented and Skype calls
SetFormat(AM_MEDIA_TYPE *pmt) last … then writes
“cannot capture video on Skype, web cam may be already in use” … Thats why I tried to create an another thread to see that if I am already put in a graph without notification.
Now I have no idea what can be the problem. I tried to implement every Available , GetConnected , CheckMediaType …etc. functions on my Output pin and on my Filter too,… to see where the problem is … but there is no problem … something happens during “intelligent connect” or before that makes Skype write that line (“cannot capture video on Skype, web cam may be already in use”) … I know that’s my failure but , I don’t know where can be this “big” problem …

Thank you for your help.

xxxxx@gmail.com wrote:

#######################################
My Destructor:

I hope what you posted was just pseudo-code. What you wrote creates an
infinite loop at real-time priority, which will completely lock up a
CPU. If you didn’t not have a multi-core machine, your Windows session
would have been over. You would have had to cycle the power.

And TerminateThread is always a bad idea. The only safe way to end a
thread is to send the thread a signal and have it return.

I’ve printed the GUIDs as you said and Skype only needs IAMStreamConfig and IKsPropertySet interfaces …I put OutputDebugString() to every function I’ve implemented and Skype calls
SetFormat(AM_MEDIA_TYPE *pmt) last … then writes
“cannot capture video on Skype, web cam may be already in use” …

Does your SetFormat succeed? That is, does it seem like both ends have
negotiated a mutually-agreeable format? Have you dumped the
AM_MEDIA_TYPE structure to check that it makes sense?

There is some buzz on the web saying that, as of Skype 6, they are
checking the moniker and refusing to connect to any capture filter that
is not backed by a WDM driver. The last time I tried this, my virtual
webcam worked in MSN Messenger but not in Skype.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

>I hope what you posted was just pseudo-code. What you wrote creates an infinite loop at real-time priority, which will completely lock up a CPU. If you didn’t not have a multi-core machine, your Windows session would have been over. …

That was just a try to find out the truth about that pointer. And I’ve tested it on a multi-core machine.

Finally I could fix the problem. It was with my output pin’s media enumerator … I have to make a “fake” one to return my supported mediatype … and it works with microsoft samples, skype , google+ …etc. so I have finished it. …
I can say that was a real fun, working with this API.
And I think I 'd like to use it again later.

Once again , thank you for everything !

Andrew