Click here to Skip to main content
15,867,308 members
Articles / Desktop Programming / ATL

A Brief Tutorial On How To Develop DirectShow Source Filter For Beginners

Rate me:
Please Sign up or sign in to vote.
4.96/5 (19 votes)
22 Feb 2010CPOL2 min read 75.2K   5.2K   57   17
The article will give you an idea on how to design a source filter.The source filter creates samples and outputs it from its output pin.
ds2.JPG

Introduction

The article is a brief tutorial on how to design a directshow's source filter. Most of them reference the SDK's example. Download the demo and have a test using GraphEdit. It creates a video stream, add the "My Source Filter" to the GraphEdit, right click the "My Source OutPin" and select render pin. Okay, now it works! Press play and you'll see my photo floating on the video screen.

Image 2

Principle of the Code

Before our development, be sure that the SDK is installed on your computer and configure it well in your VC or VS. After finishing the jobs, now going on:

Step 1

Build a project, for example we select the "Win32 Dynamic-Link Library" .

Step 2

Add the following libraries for your project: strmbasd.lib msvcrtd.lib quartz.lib vfw32.lib winmm.lib.

Include the header files we need:

C++
#include <streams.h>
#include <olectl.h>
#include <initguid.h>
#include "MyStream.h" //This file is not system's ,its a class's header that we create.

Step 3

Find the tool "GUIDGEN.EXE" on your computer. (If you failed, look on the internet.) Start the tool, click the "New GUID" button, a new GUID will be created. Now, go to select the second option, in other words we want to "DEFINE_GUID(...)" format, after that click "copy" button and paste it in your project.

Step 4

Set data types, major type and minor type.

C++
const AMOVIESETUP_MEDIATYPE sudOpPinTypes =
{
    &MEDIATYPE_Video,       // Major type
    &MEDIASUBTYPE_NULL      // Minor type
};

For our filter, we need an output pin. Do as follows. Get to set the pin's properties.

C++
const AMOVIESETUP_PIN sudOpPin =
{
    L"Output",              // Pin string name
    FALSE,                  // Is it rendered
    TRUE,                   // Is it an output
    FALSE,                  // Can we have none
    FALSE,                  // Can we have many
    &CLSID_NULL,            // Connects to filter
    NULL,                   // Connects to pin
    1,                      // Number of types
    &sudOpPinTypes };       // Pin details

Setup the filter's properties:

C++
const AMOVIESETUP_FILTER sudMyax =
{
    &CLSID_MySourceFilter,  	// Filter CLSID
    L"My Source Filter",    	// String name
    MERIT_DO_NOT_USE,       	// Filter merit
    1,                      	// Number pins
    &sudOpPin               	// Pin details
};

Step 5

Create a class that inherits from CSource. Why do we choose this class? Because we are going to develop a source filter. So, we must choose reasonable base classes.

C++
class CMySourceFilter:public CSource
{
public:
 // The only allowed way to create Bouncing balls!
    static CUnknown * WINAPI CreateInstance(LPUNKNOWN lpunk, HRESULT *phr);
private:
 CMySourceFilter(LPUNKNOWN lpunk, HRESULT *phr);
};
CMySourceFilter::CMySourceFilter(LPUNKNOWN lpunk, HRESULT *phr):
CSource(NAME("MySource"),lpunk,CLSID_MySourceFilter)
{
    CAutoLock cAutoLock(&m_cStateLock);
 
    m_paStreams    = (CSourceStream **) new CMyStream*[1];
    if (m_paStreams == NULL) {
        *phr = E_OUTOFMEMORY;
 return;
    }
m_paStreams[0] = new CMyStream(phr, this, L"My Source OutPin");
    if (m_paStreams[0] == NULL) {
        *phr = E_OUTOFMEMORY;
 return;
    }
}
CUnknown * WINAPI CMySourceFilter::CreateInstance(LPUNKNOWN lpunk, HRESULT *phr)
{
    CUnknown *punk = new CMySourceFilter(lpunk, phr);
    if (punk == NULL) {
        *phr = E_OUTOFMEMORY;
    }
    return punk;
} // CreateInstance

Having finished our source filter class, how could we create our new instances. Perhaps an array, please look at the following snippets:

C++
CFactoryTemplate g_Templates[] = {
  { L"My Source Filter"
  , &CLSID_MySourceFilter
  , CMySourceFilter::CreateInstance 
  , NULL
  , &sudMyax }
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);

Step 6

Add the two functions for register and unregister:

C++
STDAPI DllRegisterServer()
{
    return AMovieDllRegisterServer2( TRUE );
} // DllRegisterServer
//
// DllUnregisterServer
//
STDAPI DllUnregisterServer()
{
    return AMovieDllRegisterServer2( FALSE );
} // DllUnregisterServer

Step 7

For creating our filter in a DLL, we also need to export some functions. Create a new DEF file:

LIBRARY MySourceFilter.ax
EXPORTS
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE

Okay, so far. Our filter has finished without pins. Of course, you could test it in the GraphEdit.exe. You only look at its information, it can do nothing now. We want to add an output pin, the pin output video we want. Moving on...

Step 8

Now we need insert a new class inherited from CSourceStream. It could generate samples and push it to the next filters.

C++
class CMyStream  : public CSourceStream
{
public:
 STDMETHOD(Notify)(IBaseFilter * pSender, Quality q);
 HRESULT CheckMediaType(const CMediaType *pMediaType);
 HRESULT GetMediaType(int iPosition,CMediaType *pMediaType);
 HRESULT DecideBufferSize(IMemAllocator *pAlloc,ALLOCATOR_PROPERTIES *pProperties);
 HRESULT FillBuffer(IMediaSample *pms);
 CMyStream(HRESULT *phr,CSource *pms,LPCWSTR pName);
 virtual ~CMyStream();
private:
  CRefTime m_rtSampleTime;         // The time stamp for each sample
     int m_iRepeatTime;            // Time in msec between frames
 
  BITMAPFILEHEADER * pbfh;
  int xPos,yPos;
  BOOL xLock,yLock;
  HBITMAP hBmp;
};

How does the pin work? Look for more on MSDN for more details, click here!

The streaming thread runs a loop with the following structure:

until (stopped)
1. Get a media sample from the allocator.
2. Fill the sample with data.
3. Time stamp the sample. 
4. Deliver the sample downstream.

Okay, want more details? Download the resource. Tired!

Points of Interest

I am so tired after writing the article, but I'm very glad. Hope it will be useful to you.

History

  • 22nd February, 2010: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Engineer
China China
Secret..

Comments and Discussions

 
Questioncan u give me your email address? i'm just beginning to learn DS, maybe u can give me some help. Pin
Mr Pei4-Feb-14 22:05
Mr Pei4-Feb-14 22:05 
AnswerRe: can u give me your email address? i'm just beginning to learn DS, maybe u can give me some help. Pin
Aric Wang12-Apr-14 21:20
Aric Wang12-Apr-14 21:20 
QuestionCan you guide me on this:- Pin
Robert Clove5-Mar-13 23:09
Robert Clove5-Mar-13 23:09 
GeneralMy vote of 5 Pin
toann18-Dec-12 5:11
toann18-Dec-12 5:11 
QuestionMeaning of: "Time stamp the sample" Pin
Huy Vo Quang5-Oct-12 16:12
Huy Vo Quang5-Oct-12 16:12 
BugError Pin
vaadim8-Nov-11 6:35
vaadim8-Nov-11 6:35 
GeneralRe: Error Pin
Aric Wang28-Mar-12 16:53
Aric Wang28-Mar-12 16:53 
Generalproblem with lib files Pin
itaybo10-Apr-11 3:58
itaybo10-Apr-11 3:58 
GeneralRe: problem with lib files Pin
Aric Wang28-Mar-12 16:50
Aric Wang28-Mar-12 16:50 
GeneralIncluded filter does not work Pin
MikeVersteegDotCom11-Jan-11 5:44
MikeVersteegDotCom11-Jan-11 5:44 
GeneralRe: Included filter does not work Pin
Aric Wang28-Mar-12 16:45
Aric Wang28-Mar-12 16:45 
QuestionFilter don't work Pin
andrey_zhuravlev26-Feb-10 4:52
andrey_zhuravlev26-Feb-10 4:52 
AnswerRe: Filter don't work Pin
Aric Wang26-Feb-10 16:10
Aric Wang26-Feb-10 16:10 
AnswerRe: Filter don't work Pin
Aric Wang26-Feb-10 16:13
Aric Wang26-Feb-10 16:13 
AnswerRe: Filter don't work Pin
andrey_zhuravlev27-Feb-10 2:26
andrey_zhuravlev27-Feb-10 2:26 
GeneralRe: Filter don't work Pin
Aric Wang27-Feb-10 2:58
Aric Wang27-Feb-10 2:58 
GeneralRe: Filter don't work Pin
Aric Wang27-Feb-10 3:00
Aric Wang27-Feb-10 3:00 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.