Http://www.hpu405.com/simple/index.php? T30.html
Although there are a lot of information about DirectShow writing source filter on the Internet, many of my friends at the beginning are not very clear about it (maybe the author omitted many simple processes he thought ), readers always want to see how to do the first step and how to do the second step .... this demo. In fact, it is difficult to write your first filter. It will be much easier if you pass this filter.
Recently, I need to write a source filter in Push mode, and I am sorry that there is no article on the blog, so I will write down the process of writing this filter, to take care of friends who have just started learning, I will take the first step and the second step .... this method is as detailed as possible. I believe you can follow this step without any problem. I will not explain the configuration of the DirectShow development environment in VC. Start as follows:
(VC 6.0 + DirectShow 9.0)
I also remember the confusion when I was learning, so I tried to detail every process as much as possible, so many of them were SDK examples that I did not change, I didn't talk about the source code I provided. I added more detailed notes, which can be used with the source code I provided.
Step 1: Create a project
File-> New-> Project: Select Win32 dynamic-link library. (because it is a demo, the name push_test_01 is used) -> next, select a simple DLL Project (an empty DLL project is not selected to avoid the trouble of writing dllmain).-> you can finish the project and the project is established.
Step 2: related settings and files to be added
First, change the debug mode to release. Change the output file name in project-> seetings-> link from release/push_test_01.dll to release/push_test_01.ax.
Create a text file in the project directory and change it to push_test_01.def. Add it to the project: Project-> Add to project-> files select push_test_01.def and then add it.
Modify push_test_01.def. After FileView-> source files, double-click push_test_01.def and enter:
Library push_test_01.ax
Exports
Dllmain private
Dllgetclassobject private
Dllcanunloadnow private
Dllregisterserver private
Dllunregisterserver private
, Choose Project> seetings> link. The object/library modules under the link is as follows:
Strmbase. Lib msvcrt. Lib quartz. Lib vfw32.lib winmm. Lib kernel32.lib advapi32.lib version. Lib largeint. Lib user32.lib
Gdi32.lib comctl32.lib ole32.lib olepro32.lib oleaut32.lib UUID. Lib
Add header file:
# Include <streams. h>
# Include <olectl. h>
# Include <initguid. h>
Generate a globally unique identifier.
Define_guid (clsid_pushtest,
0xfd501041, 0x8ebe, 0x11ce, 0x81, 0x83, 0x00, 0xaa, 0x00, 0x57, 0x7d, 0xa1 );
Step 3: Add functions such as registration
First, modify the entry function and add the registration and anti-registration functions. The operation is as follows:
// Register
Stdapi dllregisterserver ()
{
Return amoviedllregisterserver2 (true );
}
// Anti-registration
Stdapi dllunregisterserver ()
{
Return amoviedllregisterserver2 (false );
}
// Filter entry function
Extern "C" bool winapi dllentrypoint (hinstance, ulong, lpvoid );
Bool apientry dllmain (handle hmodule,
DWORD dwreason,
Lpvoid lpreserved)
{
Return dllentrypoint (hinstance) (hmodule), dwreason, lpreserved );
}
At this time, there will be errors such as class cfactorytemplate not implemented. We will implement it below.
Add the following code. I have added a general description for each place:
/************** Start to fill in registration information ***************/
// Media type
Const amoviesetup_mediatype sudoppintypes =
{
& Mediatype_video, // main type of major type
& Mediasubtype_null // minor type sub type, which can be mediasubtype_null
};
// PIN information
Const amoviesetup_pin sudoppin =
{
L "output", // pin string name pin name
False, // is it rendered. The input pin is useful. The output pin is generally false.
True, // is it an output true indicates that the output pin is used; otherwise, the input pin is used.
False, // can we have none can not be instantiated
False, // can we have possible to create multiple pins of the same type
& Clsid_null, // filter class connected by connects to filter
Null, // connects to pin the class of the pin to be connected
1, // number of types supported by the pin
& Sudoppintypes // pin details media type description of the pin
};
Const amoviesetup_filter sudballax =
{
& Clsid_pushtest, // filter CLSID class flag of the filter
L "push_test", // string name: the name of the filter.
Merit_do_not_use, // filter merit the merit value of the filter
1, // number pins the number of the filter pin
& Sudoppin // pin details the filter pin description
};
// Used to create an instance, including required information such as classes and names
Cfactorytemplate g_templates [] = {
{
L "push_test" // Filter Name
, & Clsid_pushtest // class ID of the object
, Pushtestfilter: createinstance // function used to create an instance
, Null //
, & Sudballax // filter Registration Information
}
};
Int g_ctemplates = sizeof (g_templates)/sizeof (g_templates [0]);
Through the comment above, we can see that the filter has an output pin that supports video type and other information.
Pushtestfilter: createinstance // function used to create an instance
Please note !! Pushtestfilter is our filter class !! Implement it below.
Step 4: implement the filter class
Add the new pushtestfilter class to inherit from csource. This is our filter class. There are no too many operations in this class, so there are only two functions:
// The primary class of the filter, inherited from csource
Class pushtestfilter: Public csource
{
Public:
// Unique interface for creating this type of instance
Static cunknown * winapi createinstance (lpunknown lpunk, hresult * phr );
PRIVATE:
// You can only create an instance by calling createinstance ().
Pushtestfilter (lpunknown lpunk, hresult * phr );
};
Note the following two points:
The constructor pushtestfilter () is private, not public !!!!!!!!!!!
The createinstance () function is static because it cannot be called through objects !!!!
The specific implementation of the two functions is as follows:
// Constructor. Note that the private attribute is not public,
// The instance to be created can only be created through the createinstance () function.
Pushtestfilter: pushtestfilter (lpunknown lpunk, hresult * phr ):
Csource (name ("pushtest"), lpunk, clsid_pushtest)
{
Assert (PHR );
Cautolock (& m_cstatelock );
// M_pastreams is a pointer array inherited from the csource base class. Because of this demo, we only
// One pin exists, so one space is allocated.
M_pastreams = (csourcestream **) New pushtesipin * [1];
If (m_pastreams = NULL)
{
If (PHR)
* Phr = e_outofmemory;
Return;
}
// Pay the value for the space you just allocated, which automatically adds a pin to the filter.
// The instance is automatically released.
M_pastreams [0] = new pushtesipin (phr, this, l "push_test ");
If (m_pastreams [0] = NULL)
{
If (PHR)
* Phr = e_outofmemory;
Return;
}
}
// Createinstance () this function is static because it cannot be called through an object
Cunknown * winapi pushtestfilter: createinstance (lpunknown lpunk, hresult * phr)
{
Assert (PHR );
// The constructor of the private attribute is called here.
Cunknown * punk = new pushtestfilter (lpunk, PHR );
If (punk = NULL)
{
If (PHR)
* Phr = e_outofmemory;
}
Return punk;
}
The pushtesipin class here is our pin class, which will be implemented later !! In fact, the main operation is in the pin class pushtesipin.
Step 5: Implementation of the pin class
Add pushtesipin to inherit from csourcestream. Here, you need to reload a little more functions! It does not matter! I will
.
This is mainly the three:
// Because our filter is a media type, the getmediatype (cmediatype * pmediatype) is overloaded)
// If there are multiple types, you should overload the other two functions. For details, refer to the base class csourcestream.
Hresult getmediatype (cmediatype * pmediatype );
// This function is used to set the sample size. It will be called after the pin connection is successful.
Hresult decidebuffersize (imemallocator * pimemalloc, allocator_properties * pproperties );
// Fill in sample data
Hresult fillbuffer (imediasample * PMS );
I have made more detailed comments in the source code, which can be easily understood by referring to the source code.
In fact, this filter does not do anything, it is equivalent to writing the pushsource example under the SDK again, mainly to illustrate this process,
I believe you should have a general concept here. Congratulations!