R
rep_movsd
Hi
I have developed a simple free library that is used for creating and
managing Directshow filter graphs, that I (and possibly several
others ) have been using for more than a year now...
Recently I thought of rewriting it with a more "intuitive" usage style
( mostly to satisfy my desire to play with template metaprogramming ),
and gain a bit of static error checking ( and making the user code
look like magic )
Heres some equivalent code for the old and new libraries ( its a bit
specific to the dshow framework, but it is fairly obvious what the
code does, also all the includes etc have been omitted )
Old library usage :
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void BuildGraph(CGraph &g)
{
g.Connect(L"SOURCE", L"TEE");
g.Connect(L"TEE", L"RENDERER");
g.Connect(L"TEE", L"RENDERER2", 1, 0); // connect 2nd output pin
of tee to renderer2's first pin
}
void BuildGraphBad(CGraph &g)
{
g.Connect(L"SOURCE", L"TEE");
g.Connect(L"TEE", L"RENDERERER"); // Runtime error "filter
not found "
g.Connect(L"TEE", L"RENDERER2", 1, 0);
}
int main(int argc, char **argv)
{
CGraph g;
g.AddSourceFilter(argv[1], L"SOURCE"); // Create a source
filter based on filename
g.AddFilter(CLSID_InfTee, L"TEE"); // Create a Tee
g.AddFilter(CLSID_VideoRenderer, L"RENDERER"); // Create
renderers
g.AddFilter(CLSID_VideoRenderer, L"RENDERER2");
BuildGraph(g);
BuildGraphBad(g);
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
New library usage:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DECLARE_FILTER(SOURCE);
DECLARE_FILTER(TEE);
DECLARE_FILTER(RENDERER);
DECLARE_FILTER(RENDERER2);
void BuildGraph()
{
FILTER(SOURCE);
FILTER(TEE);
FILTER(RENDERER);
FILTER(RENDERER2);
SOURCE >> TEE >> RENDERER; // Chain the filters
TEE >> RENDERER2; // Add an extra renderer
}
void BuildGraphBad()
{
FILTER(SOURCE);
FILTER(TEE);
FILTER(RENDERERER); // Misspelling - compile error
SOURCE >> TEE >> RENDERER; // Compile error
}
int main(int argc, char **argv)
{
CGraf g;
FILTER(SOURCE);
FILTER(TEE);
FILTER(RENDERER);
FILTER(RENDERER2);
SOURCE = argv[1]; // Create a source filter
based on filename
TEE = CLSID_InfTee; // Create filters based on
CLSIDs
RENDERER = CLSID_VideoRenderer;
RENDERER2 = CLSID_VideoRenderer;
g += SOURCE, TEE, RENDERER, RENDERER2; // FIlters get added to the
graph
BuildGraph();
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Some of the advantages of the new style are :
1) FIlter names are identifiers, so u get intellisense and compile
time checking
2) A filter with a given name always refers to the same object, so
there is no need to store a bunch of pointers to filter objects and
pass them around various functions ( or worse yet keep them global as
most directshow code does )
3) The operator overloading makes the code very readable,
The only disadvantage I see is that the implementation is complex and
I am not 100% confident that my code is perfect.
I was wondering to overload the unary minus operator to remove
filters from the graph and the divide by operator to disconnect
filters. I would also add some manipulator stuff ( like in iostreams)
to control the way filters are
connected with >> e.g.
// Remove renderer2 from graph
g -= RENDERER2;
// Connect the first audio pin of the source to the renderer
SOURCE >> pinType(MEDIATYPE_Audio) >> AUDIORENDER;
// Disconnect any connection betwen these 2 filters
SOURCE / AUDIORENDER;
Any opinions, suggestions?
Vivek
I have developed a simple free library that is used for creating and
managing Directshow filter graphs, that I (and possibly several
others ) have been using for more than a year now...
Recently I thought of rewriting it with a more "intuitive" usage style
( mostly to satisfy my desire to play with template metaprogramming ),
and gain a bit of static error checking ( and making the user code
look like magic )
Heres some equivalent code for the old and new libraries ( its a bit
specific to the dshow framework, but it is fairly obvious what the
code does, also all the includes etc have been omitted )
Old library usage :
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void BuildGraph(CGraph &g)
{
g.Connect(L"SOURCE", L"TEE");
g.Connect(L"TEE", L"RENDERER");
g.Connect(L"TEE", L"RENDERER2", 1, 0); // connect 2nd output pin
of tee to renderer2's first pin
}
void BuildGraphBad(CGraph &g)
{
g.Connect(L"SOURCE", L"TEE");
g.Connect(L"TEE", L"RENDERERER"); // Runtime error "filter
not found "
g.Connect(L"TEE", L"RENDERER2", 1, 0);
}
int main(int argc, char **argv)
{
CGraph g;
g.AddSourceFilter(argv[1], L"SOURCE"); // Create a source
filter based on filename
g.AddFilter(CLSID_InfTee, L"TEE"); // Create a Tee
g.AddFilter(CLSID_VideoRenderer, L"RENDERER"); // Create
renderers
g.AddFilter(CLSID_VideoRenderer, L"RENDERER2");
BuildGraph(g);
BuildGraphBad(g);
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
New library usage:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DECLARE_FILTER(SOURCE);
DECLARE_FILTER(TEE);
DECLARE_FILTER(RENDERER);
DECLARE_FILTER(RENDERER2);
void BuildGraph()
{
FILTER(SOURCE);
FILTER(TEE);
FILTER(RENDERER);
FILTER(RENDERER2);
SOURCE >> TEE >> RENDERER; // Chain the filters
TEE >> RENDERER2; // Add an extra renderer
}
void BuildGraphBad()
{
FILTER(SOURCE);
FILTER(TEE);
FILTER(RENDERERER); // Misspelling - compile error
SOURCE >> TEE >> RENDERER; // Compile error
}
int main(int argc, char **argv)
{
CGraf g;
FILTER(SOURCE);
FILTER(TEE);
FILTER(RENDERER);
FILTER(RENDERER2);
SOURCE = argv[1]; // Create a source filter
based on filename
TEE = CLSID_InfTee; // Create filters based on
CLSIDs
RENDERER = CLSID_VideoRenderer;
RENDERER2 = CLSID_VideoRenderer;
g += SOURCE, TEE, RENDERER, RENDERER2; // FIlters get added to the
graph
BuildGraph();
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Some of the advantages of the new style are :
1) FIlter names are identifiers, so u get intellisense and compile
time checking
2) A filter with a given name always refers to the same object, so
there is no need to store a bunch of pointers to filter objects and
pass them around various functions ( or worse yet keep them global as
most directshow code does )
3) The operator overloading makes the code very readable,
The only disadvantage I see is that the implementation is complex and
I am not 100% confident that my code is perfect.
I was wondering to overload the unary minus operator to remove
filters from the graph and the divide by operator to disconnect
filters. I would also add some manipulator stuff ( like in iostreams)
to control the way filters are
connected with >> e.g.
// Remove renderer2 from graph
g -= RENDERER2;
// Connect the first audio pin of the source to the renderer
SOURCE >> pinType(MEDIATYPE_Audio) >> AUDIORENDER;
// Disconnect any connection betwen these 2 filters
SOURCE / AUDIORENDER;
Any opinions, suggestions?
Vivek