Click here to Skip to main content
15,923,789 members
Articles / Mobile Apps / Windows Mobile

Creating Custom DirectShow SampleGrabber Filter for Windows Mobile

Rate me:
Please Sign up or sign in to vote.
4.73/5 (22 votes)
29 Nov 2008CPOL4 min read 608K   4.7K   57   280
This article explains how to write your custom DirectShow SampleGrabber filter for Windows Mobile.

Introduction

This article explains how to write your custom DirectShow SampleGrabber filter for Windows Mobile.

Background

In a recent project of mine, I needed to do some real-time video analysis in .NET CF. However the .NET API only allows for taking still images or recording videos, but it offers no way to access the video frame buffer so that I could parse the frames from the camera on the fly. So I decided to use the DirectShow API, which offers much better control of the video stream flow, but it still lacks the ISampleGrabber interface which is available under the complete DirectShow library for Windows. The remaining option was to write a custom DirectShow filter, which implements the ISampleGrabber interface and allows the developer to get access to the video buffer data. In this article, I will try to explain what I learned in the process.

You could use the sample code as a starting point to write your own filter or take the ready SampleGrabber filter and use it in your project. There are multiple references online which I used in the project, but as far as I am aware there is no complete "How to" on how to solve this problem.

Setting Up Your Visual Studio Project

Before your set up your Visual Studio project, you will need to install Windows Mobile SDK, Windows CE 5.0 and Windows CE 5.0 Platform builder which contains the BaseClasses library. In general, you don't necessarily use the BaseClasses, but it definitely makes your job a lot easier so I took advantage.

First create a Smart Devices DLL project with ATL support. You also need to add the header files from the Windows Mobile SDK and Platform Builder to your include path.

Writing the Filter

In this example, we will use a TransInPlaceFilter, which is a simplified version of the TransformFilter. We don't need to alter the data in any way, just to pass it to the client application. So we create a CSampleGrabber class, which also implements our custom interface with any additional functions. I added just the RegisterCallback function, which passes a function pointer from the client app. This function will be called whenever a MediaSample (a video frame) is passed through the filter, so the client can copy the data and do some processing.

C++
// define the filter class
class CSampleGrabber : 
public CTransInPlaceFilter, public ISampleGrabber
{
  private:
  MANAGEDCALLBACKPROC callback;
  long m_Width;
  long m_Height;
  long m_SampleSize;
  long m_Stride;

  public:
  // instantiation
  CSampleGrabber( IUnknown * pOuter, HRESULT * phr, BOOL ModifiesData );
  ~CSampleGrabber();
  static CUnknown *WINAPI CreateInstance(LPUNKNOWN punk, HRESULT *phr);

  // IUnknown
  DECLARE_IUNKNOWN;
  STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);

  // CTransInPlaceFilter
  HRESULT CheckInputType(const CMediaType *pmt);
  HRESULT SetMediaType(PIN_DIRECTION direction, const CMediaType *pmt);
  HRESULT Transform(IMediaSample *pMediaSample);
  HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProperties);
  HRESULT GetMediaType(int iPosition, CMediaType *pMediaType);
  HRESULT CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut) {
    return NOERROR; 
    }

  // ISampleGrabber
  STDMETHODIMP RegisterCallback(MANAGEDCALLBACKPROC mdelegate);
};

You could implement all interfaces like any other filter. The interesting parts are the Transform and RegisterCallback functions:

C++
// Set the client callback
STDMETHODIMP
CSampleGrabber::RegisterCallback( MANAGEDCALLBACKPROC mdelegate ) 
{
    // Set pointer to managed delegate
    callback = mdelegate;
    return S_OK;
}

// Get the pointer to the raw data and pass it to the applications
HRESULT 
CSampleGrabber::Transform(IMediaSample *pMediaSample)
{
    long Size = 0;
    BYTE *pData;

    if ( !pMediaSample )
        return E_FAIL;

    // Get pointer to the video buffer data
    if( FAILED(pMediaSample->GetPointer(&pData)) ) 
        return E_FAIL;
    Size = pMediaSample->GetSize();

    // invoke managed delegate
    if ( callback )
        callback(pData,Size);

    return S_OK;
}

Using the Code

You can use the SampleGrabber filter directly in your DirectShow applications exactly like any other filter. It is important to register the DLL before trying to instantiate it.

C++
// Create and initialize the SampleGrabber filter
CoCreateInstance( CLSID_SampleGrabber, NULL, CLSCTX_INPROC, 
		IID_IBaseFilter, (void**)&pSampleGrabber );
m_pFilterGraph->AddFilter( pSampleGrabber, FILTERNAME );

// Get a pointer to the ISampleGrabber interface
pSampleGrabber->QueryInterface( IID_ISampleGrabber, (void**)&m_pISampleGrabber );

// Register the client callback
if ( m_pISampleGrabber )
  m_pISampleGrabber->RegisterCallback( &CGraphBuilder::OnSampleProcessed );

When the client receives the frame sample, it should copy it to local buffer as soon as possible and return. This allows the filter to carry on and not wait for the client to process the data, which will considerably slow down the whole graph.

You could also make a C++ DLL which creates the filter graph and manages it and calls it through P/Invoke from your .NET CF applications. Creating filter graphs in .NET CF directly should be a bit trickier, as the .NET CF lacks C++. NET support, but maybe possible.

Online References

History

  • 23.08.2008 Article created
  • 26.08.2008 v1.1 Created.
    Fixes:
    • Release now builds OK, definition of NonDelegatingRelease added
    • Included C++ and C# client applications which show how to use the filter
    • The sample code now compiles under WM SDK 5
  • 28.11.2008
    • Added more sample code: CameraCaptureDLL project includes the CameraCapture sample and the builtin SampleGrabber filter. The TestCameraCapture project is a sample C# application that uses the filter to get the real-time frame data.
    • Note: The sample code demonstrates the basic concepts, but there are a couple of issues with it. For example, it might get stuck when trying to stop the filter graph. This is due to the fact that the filter is processing data while you try to do that (sorry but I didn't have time to fix that). Although buggy, you should be able to get the camera data.

License

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


Written By
Chief Technology Officer CST
Bulgaria Bulgaria
I am software engineering working for CST. My interests cover areas of Big Data, Cloud and Kubernetes.

For further information please contact me at akafazov@cst-bg.net

Comments and Discussions

 
GeneralRe: Unresolved external __cdecl CBaseFilter::NonDelegatingRelease(void)" Pin
mrunalgawade1-Nov-08 19:24
mrunalgawade1-Nov-08 19:24 
AnswerRe: Unresolved external __cdecl CBaseFilter::NonDelegatingRelease(void)" Pin
Angel Kafazov1-Nov-08 22:19
Angel Kafazov1-Nov-08 22:19 
GeneralRe: Unresolved external __cdecl CBaseFilter::NonDelegatingRelease(void)" Pin
mrunalgawade1-Nov-08 22:32
mrunalgawade1-Nov-08 22:32 
AnswerRe: Unresolved external __cdecl CBaseFilter::NonDelegatingRelease(void)" Pin
Angel Kafazov1-Nov-08 23:24
Angel Kafazov1-Nov-08 23:24 
GeneralRe: Unresolved external __cdecl CBaseFilter::NonDelegatingRelease(void)" Pin
mrunalgawade2-Nov-08 20:13
mrunalgawade2-Nov-08 20:13 
GeneralC# Client Pin
Tommy.T24-Oct-08 1:32
Tommy.T24-Oct-08 1:32 
QuestionSOS Pin
tigertop8916-Oct-08 6:54
tigertop8916-Oct-08 6:54 
GeneralCreating custom sample grabber filter on windows mobile 5(smartphone,vs2008) Pin
sreejit P16-Oct-08 5:28
sreejit P16-Oct-08 5:28 
Things I have tried till now


Scenario 1:Creating a custom sample grabber filter with out registering it as a COM.(windows mobile 5)

-Followed the steps mentioned in the link https://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=3699824&SiteID=1.
We were able to compile the project successfully.But when we tried to add the custom sample grabber filter to the filter graph,the smart phone device project exited with exception.

CSampleGrabber* pFilter=new CSampleGrabber(NULL,&hr); // CSampleGrabber is the custom sample grabber filter

pFilterGraph->AddFilter(pFilter, L"Grabber"); // pFilterGraph is CComPtr<igraphbuilder> pFilterGraph;

'Locals' window shows the value of pFilter as

- pFilter 0x00184e60 {callback=0x00000000 m_Width=0 m_Height=0 ...} CSampleGrabber*
+ [CTransInPlaceFilter] 0x00184e60 {m_idTransInPlace=0} CTransInPlaceFilter*
+ [ISampleGrabber] 0x00184f10 {ISampleGrabber*} ISampleGrabber*
callback 0 void (unsigned char*, long int)*
m_Width 0 long int
m_Height 0 long int
m_SampleSize 0 long int
m_Stride 0 long int
format_BitsPerSample 0 unsigned int
format_SamplesPerSecond 0 unsigned int
format_BytesPerSecond 0 unsigned int

After exiting the application the output window shows

Data Abort: Thread=96c2240c Proc=80fc7010 'ClientApp.exe'

AKY=00008001 PC=0001453c(ClientApp.exe+0x0000453c) RA=0001452c(ClientApp.exe+0x0000452c) BVA=20000000 FSR=00000407

The program '[0xD6D27642] ClientApp.exe' has exited with code 278 (0x116).

-Can I create a custom sample grabber filter with out registering it as a COM ?





Scenario 2: -Creating a custom sample grabber filter by registering it as a COM.(windows mobile 5)


-There are many articles including msdn explaining different steps to create a custom filter as a COM and then registering it( for desktop applications)
-I have got an example from the Direct Show sdk to create a custom sample grabber(example - Grabber).But this is not applicable to mobile platform.However I have got an example from the site "http://www.codeproject.com/KB/mobile/samplegrabberfilter-wm6.aspx" which explains how to create a Sample Grabber filter for windows mobile 6.But they are giving references to base classes include directories and device sdk directories.I downloaded the project and tried to build the project after giving reference to the device sdk include directories and lib files only.But it resulted in one error " error PRJ0050: Failed to register output. Please ensure you have the appropriate permissions to modify the registry ".Also after reading the respones for this code project I understood that it is only for windows mobile 6.But my project is a smart phone MFC dialog based application for windows mobile 5.I got the DLL after building this project.My main question is "how to register a custom direct show filter in windows mobile 5 ?"
-Is it a mandatory to give references to the direct show base classes while creating a custom filter?


Basically my application is a smart phone MFC dialog based application(windows mobile 5-smartphone).I am trying to capture video from mobile camera and try to grab each samples.But sample grabber is not available in mobile platform.So I am planning to create a custom sample grabber filter and add it to the filter graph.Please advice me on how to create a sample grabber in mobile platform(not in desktop application) and add it to the filter graph like other filters.

Please help me
Questionplatform builder Pin
krishnanand9-Oct-08 1:06
krishnanand9-Oct-08 1:06 
AnswerRe: platform builder Pin
Angel Kafazov4-Nov-08 2:46
Angel Kafazov4-Nov-08 2:46 
Questionunresolved linker error Pin
Member 125807325-Sep-08 18:25
Member 125807325-Sep-08 18:25 
Generalerror LNK2001: unresolved external symbol Pin
laloka21-Sep-08 17:19
laloka21-Sep-08 17:19 
AnswerRe: error LNK2001: unresolved external symbol Pin
Angel Kafazov22-Sep-08 11:05
Angel Kafazov22-Sep-08 11:05 
GeneralRe: error LNK2001: unresolved external symbol Pin
laloka22-Sep-08 17:00
laloka22-Sep-08 17:00 
GeneralRe: error LNK2001: unresolved external symbol Pin
KaLu1024-Sep-08 4:26
KaLu1024-Sep-08 4:26 
GeneralDivided by 0 error Pin
VAIOnian Anold17-Sep-08 1:40
VAIOnian Anold17-Sep-08 1:40 
GeneralRe: Divided by 0 error Pin
Angel Kafazov17-Sep-08 2:20
Angel Kafazov17-Sep-08 2:20 
GeneralRe: Divided by 0 error Pin
VAIOnian Anold17-Sep-08 4:31
VAIOnian Anold17-Sep-08 4:31 
QuestionRe: Divided by 0 error Pin
VAIOnian Anold18-Sep-08 3:48
VAIOnian Anold18-Sep-08 3:48 
AnswerRe: Divided by 0 error Pin
Angel Kafazov18-Sep-08 5:58
Angel Kafazov18-Sep-08 5:58 
GeneralRe: Divided by 0 error Pin
VAIOnian Anold18-Sep-08 6:06
VAIOnian Anold18-Sep-08 6:06 
AnswerRe: Divided by 0 error Pin
Angel Kafazov18-Sep-08 6:25
Angel Kafazov18-Sep-08 6:25 
GeneralRe: Divided by 0 error Pin
VAIOnian Anold18-Sep-08 7:13
VAIOnian Anold18-Sep-08 7:13 
AnswerRe: Divided by 0 error Pin
Angel Kafazov18-Sep-08 7:31
Angel Kafazov18-Sep-08 7:31 
GeneralRe: Divided by 0 error Pin
VAIOnian Anold18-Sep-08 7:52
VAIOnian Anold18-Sep-08 7:52 

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.