Friday, March 30, 2007

Desktop screen capture source filter…

Desktop screen capture filter…


HWND hwndDesktop = GetDesktopWindow();
HDC hdcDesktop = GetDC(hwndDesktop);

//BitBlt(m_hdcPaint,0,0,300,300,hdcDesktop,0,0,SRCCOPY);
StretchBlt(m_hdcPaint,0,0,300,300,hdcDesktop,0,0,720,480,SRCCOPY) ;
CopyMemory(pBuffer,m_pPaintBuffer,pSample->GetSize());
ReleaseDC(hwndDesktop,hdcDesktop);

HRESULT CMySourceStream::FillBuffer(IMediaSample *pSample)
{

try
{
CAutoLock lock(m_pFilter->pStateLock());
HRESULT hr = S_OK;
BYTE* pBuffer;
char szDisplay[MAX_PATH];
OutputDebugString("\n CMySourceStream::FillBuffer() fn");
hr = pSample->GetPointer(&pBuffer);

if(SUCCEEDED(hr))
{
sprintf(szDisplay,"%d", m_lFrameCount++);
TextOut(m_hdcPaint,100,100,szDisplay,strlen(szDisplay));
HWND hwndDesktop = GetDesktopWindow();
HDC hdcDesktop = GetDC(hwndDesktop);
// BitBlt(m_hdcPaint,0,0,300,300,hdcDesktop,0,0,SRCCOPY);
StretchBlt(m_hdcPaint,0,0,300,300,hdcDesktop,0,0,720,480,SRCCOPY);
CopyMemory(pBuffer,m_pPaintBuffer,pSample->GetSize());
ReleaseDC(hwndDesktop,hdcDesktop);
}

return hr;
}
catch(...)
{
OutputDebugString("\n Error in CMySourceStream::FillBuffer() fn");
return E_FAIL;
}
}

S.No

Tasks completed


1

sample application for loading JPEG,BMP images using Windows SDK

VC++

2

Source Filter for displaying numbers on the screen…

completed

3

Source filter for displaying the image file Source

completed



30 –March-2007….


Problems faced …


Directshow Source Filter development :


While developing the filter I got The error as the


I developed the source filter for displaying numbers on the screen...


The code related to this ...


But I faced the following problem...


---------------------------

GraphEdit

---------------------------

Sorry, the Filter Graph cannot render this pin.


Class not registered (Return code: 0x80040154)

---------------------------

OK

---------------------------




HRESULT CMySourceStream::GetMediaType(CMediaType* pMediaType)

{

try

{


HRESULT hr = S_OK;


CheckPointer(pMediaType,E_POINTER);

OutputDebugString("n CMySourceStream::GetMediaType() fn");

ZeroMemory(pMediaType,sizeof(CMediaType));


VIDEOINFO *pvi = (VIDEOINFO*)pMediaType->AllocFormatBuffer(sizeof(VIDEOINFO));


pvi->bmiHeader.biCompression = BI_RGB;

pvi->bmiHeader.biBitCount = 24;

pvi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);

pvi->bmiHeader.biWidth = 300;

pvi->bmiHeader.biHeight = 300;


pvi->bmiHeader.biPlanes = 1;

pvi->bmiHeader.biSizeImage = pvi->bmiHeader.biWidth * pvi->bmiHeader.biHeight * (pvi->bmiHeader.biBitCount/8);

pvi->bmiHeader.biClrImportant = 0;


SetRectEmpty(&(pvi->rcSource));

SetRectEmpty(&(pvi->rcTarget));

pMediaType->SetType(&MEDIATYPE_Video);

pMediaType->SetFormatType(&FORMAT_VideoInfo);

pMediaType->SetTemporalCompression(FALSE);


//pMediaType->SetSubtype(&MEDIASUBTYPE_Vi)

const GUID SubTypeGUID = GetBitmapSubtype(&pvi->bmiHeader);

pMediaType->SetSubtype(&SubTypeGUID);

pMediaType->SetSampleSize(pvi->bmiHeader.biSizeImage);


m_bmpInfo.bmiHeader = pvi->bmiHeader;


return hr;

}

catch(...)

{

OutputDebugString("n Errror in CMySourceStream::GetMediaType() fn");

return E_FAIL;


}

}





Solution :

--------------

1.I added the checkMediaType() fn as follows...


CheckMediaType() is an important Function for any filter....


without it, the filter will not work...


HRESULT CMySourceStream::CheckMediaType(const CMediaType *pMediaType)

{

CheckPointer(pMediaType,E_POINTER);

try

{

OutputDebugString("n CheckMediaType fn...");

if((*(pMediaType->Type()) != MEDIATYPE_Video) || // we only output video

!(pMediaType->IsFixedSize())) // in fixed size samples

{

return E_INVALIDARG;

}


// Check for the subtypes we support

const GUID *SubType = pMediaType->Subtype();

if (SubType == NULL)

return E_INVALIDARG;


if(*SubType != MEDIASUBTYPE_RGB24)

{

return E_INVALIDARG;

}


// Get the format area of the media type

VIDEOINFO *pvi = (VIDEOINFO *) pMediaType->Format();


if(pvi == NULL)

return E_INVALIDARG;


if(pvi->bmiHeader.biBitCount==24)

return NOERROR;

else

return E_INVALIDARG;

}

catch(...)

{

OutputDebugString("n Exception in CheckMediaType() fn...");

return E_INVALIDARG;

}



}






S.No

Tasks To be Done Next


1

Identify the time taken for filter's processing per frame…


2

look at WMINTF


3

Prepare Class diagram and Architecture Diagram for Ur Directshow filters

4

Prepare DFD for ur directshow filters


5

Prepare Documentation


6

Directshow source filter for screen capturing


7

Add File Dialog to Directshow Image File source filter


8

Add histogram and property dialog to the filter


1

Sample application for displaying numbers on the screen

D:samplesSDKBitmapTest

2

Sample application for source filter

SnakeSource filter on Desktop…

3

Directshow source filter

D:samplesSourceFilter



S.No

Puzzle





1

There are 3 glasses. The biggest one can hold 24 ounces. The medium one can hold 11 ounces and the smallest one can hold 5 ounces. Now you have 24 ounces of soft drink in the largest glass. Can you use just these 3 glasses to make the largest glass contain 12 ounces of soft drink by pouring soft drink from one glass to another?












Ans

24ounce

11 ounce

5 ounce


24ounce is filled

24

0

0

Initial State



13

11

0

From 24 ounce, Fill the 11 ounce



18

6

0




18

1

5




23

1

0




23

0

1




12

11

1

Target state


Directshow Image File Source Filter problem

Directshow source filter problem :
while developing the filter, I got confusion in the following....


pvi->bmiHeader.biCompression = BI_RGB; //This is the compression format

while using JPEG we have to use BI_JPEG and for PNG we have to change it as BI_PNG...

But I didnt do anything... if I made it like this for JPEG i got an error...

So what I have done is whatever may be the file format, I simply used the BI_RGB to represent all the types of file formats

regardless of the JPEG or pNg image.. BI_RGB may be acceptable due to OpenCV...

OpenCV may give the decompressed data as bytes from the file.. For Example if the JPEG is a compressed file..

if we are loading the JPEG image with cvLoadImage() fn ,openCV will loads the decompressed buffer of the JPEg file...

So we need not specify the things in pvi->bmiHeader.biCompression.






HRESULT CMySourceStream::GetMediaType(CMediaType* pMediaType)
{
try
{

HRESULT hr = S_OK;

CheckPointer(pMediaType,E_POINTER);
OutputDebugString("\n CMySourceStream::GetMediaType() fn");
ZeroMemory(pMediaType,sizeof(CMediaType));

VIDEOINFO *pvi = (VIDEOINFO*)pMediaType->AllocFormatBuffer(sizeof(VIDEOINFO));

if(m_pSrcImage == NULL)
{
m_pSrcImage = cvLoadImage("D:\\cartoon.png");
cvFlip(m_pSrcImage);
}

//check the file extension...
//if JPEG or jpg extension - BI_JPEG
//if BMP extension - BI_RGB
//if PNG extension - BI_PNG...

pvi->bmiHeader.biCompression = BI_RGB;
pvi->bmiHeader.biBitCount = (m_pSrcImage->nChannels * 8 );
pvi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pvi->bmiHeader.biWidth = m_pSrcImage->width;
pvi->bmiHeader.biHeight = m_pSrcImage->height;

pvi->bmiHeader.biPlanes = 1;
pvi->bmiHeader.biSizeImage = m_pSrcImage->imageSize;
pvi->bmiHeader.biClrImportant = 0;

SetRectEmpty(&(pvi->rcSource));
SetRectEmpty(&(pvi->rcTarget));
pMediaType->SetType(&MEDIATYPE_Video);
pMediaType->SetFormatType(&FORMAT_VideoInfo);
pMediaType->SetTemporalCompression(FALSE);

//pMediaType->SetSubtype(&MEDIASUBTYPE_Vi)
const GUID SubTypeGUID = GetBitmapSubtype(&pvi->bmiHeader);
pMediaType->SetSubtype(&SubTypeGUID);
pMediaType->SetSampleSize(pvi->bmiHeader.biSizeImage);

m_bmpInfo.bmiHeader = pvi->bmiHeader;

return hr;
}
catch(...)
{
OutputDebugString("\n Errror in CMySourceStream::GetMediaType() fn");
return E_FAIL;

}
}

Directshow source filter Error

I developed the source filter for displaying numbers on the screen...

The code related to this ...


HRESULT CMySourceStream::GetMediaType(CMediaType* pMediaType)
{
try
{

HRESULT hr = S_OK;

CheckPointer(pMediaType,E_POINTER);
OutputDebugString("\n CMySourceStream::GetMediaType() fn");
ZeroMemory(pMediaType,sizeof(CMediaType));

VIDEOINFO *pvi = (VIDEOINFO*)pMediaType->AllocFormatBuffer(sizeof(VIDEOINFO));

pvi->bmiHeader.biCompression = BI_RGB;
pvi->bmiHeader.biBitCount = 24;
pvi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pvi->bmiHeader.biWidth = 300;
pvi->bmiHeader.biHeight = 300;

pvi->bmiHeader.biPlanes = 1;
pvi->bmiHeader.biSizeImage = pvi->bmiHeader.biWidth * pvi->bmiHeader.biHeight * (pvi->bmiHeader.biBitCount/8);
pvi->bmiHeader.biClrImportant = 0;

SetRectEmpty(&(pvi->rcSource));
SetRectEmpty(&(pvi->rcTarget));
pMediaType->SetType(&MEDIATYPE_Video);
pMediaType->SetFormatType(&FORMAT_VideoInfo);
pMediaType->SetTemporalCompression(FALSE);

//pMediaType->SetSubtype(&MEDIASUBTYPE_Vi)
const GUID SubTypeGUID = GetBitmapSubtype(&pvi->bmiHeader);
pMediaType->SetSubtype(&SubTypeGUID);
pMediaType->SetSampleSize(pvi->bmiHeader.biSizeImage);

m_bmpInfo.bmiHeader = pvi->bmiHeader;

return hr;
}
catch(...)
{
OutputDebugString("\n Errror in CMySourceStream::GetMediaType() fn");
return E_FAIL;

}
}



But I faced the following problem...

---------------------------
GraphEdit
---------------------------
Sorry, the Filter Graph cannot render this pin.

Class not registered (Return code: 0x80040154)
---------------------------
OK
---------------------------

Solution :
--------------
1.I added the checkMediaType() fn as follows...

CheckMediaType() is an important Function for any filter....

without it, the filter will not work...


HRESULT CMySourceStream::CheckMediaType(const CMediaType *pMediaType)
{
CheckPointer(pMediaType,E_POINTER);
try
{

OutputDebugString("\n CheckMediaType fn...");
if((*(pMediaType->Type()) != MEDIATYPE_Video) || // we only output video
!(pMediaType->IsFixedSize())) // in fixed size samples
{
return E_INVALIDARG;
}

// Check for the subtypes we support
const GUID *SubType = pMediaType->Subtype();
if (SubType == NULL)
return E_INVALIDARG;

if(*SubType != MEDIASUBTYPE_RGB24)
{
return E_INVALIDARG;
}

// Get the format area of the media type
VIDEOINFO *pvi = (VIDEOINFO *) pMediaType->Format();

if(pvi == NULL)
return E_INVALIDARG;

if(pvi->bmiHeader.biBitCount==24)
return NOERROR;
else
return E_INVALIDARG;
}
catch(...)
{
OutputDebugString("\n Exception in CheckMediaType() fn...");
return E_INVALIDARG;
}


}

Thursday, March 29, 2007

Load JPEG,GIF files in VC++ :

Once again it is only for VC++ guys... To load JPEG in VC++ is a headache problem...

Now we can use this function to load JPEG,GIF and all picture file formats...
Header files to be included :
#include <olectl.h>
#include <ole2.h>
All u need is to pass the device context and the filename to it....
This is the function to load the JPEG images
// Function LoadAnImage: accepts a file name
void LoadAnImage(HDC hdc,char* FileName)
{
// Use IPicture stuff to use JPG / GIF files
IPicture* p;
IStream* s;
IPersistStream* ps;
HGLOBAL hG;
void* pp;
FILE* fp;


// Read file in memory
fp = fopen(FileName,"rb");
if (!fp)
return;

fseek(fp,0,SEEK_END);
int fs = ftell(fp);
fseek(fp,0,SEEK_SET);
hG = GlobalAlloc(GPTR,fs);


if (!hG)
{
fclose(fp);
return;
}


pp = (void*)hG;
fread(pp,1,fs,fp);
fclose(fp);

// Create an IStream so IPicture can
// CreateStreamOnHGlobal(hG,false,&s);
CreateStreamOnHGlobal(hG,false,&s);
if (!s)
{
GlobalFree(hG);
return;
}

OleLoadPicture(s,0,false,IID_IPicture,(void**)&p);

if (!p)
{
s->Release();
GlobalFree(hG);
return;
}

s->Release();
GlobalFree(hG);


long hmHeight;
long hmWidth;

HBITMAP hB = 0;


p->get_Handle((unsigned int*)&hB);
p->get_Height(&hmHeight);
p->get_Width(&hmWidth);


p->Render(hdc,0,0,300,300,0,hmHeight,hmWidth,-hmHeight,NULL);
p->Release();

}
How can we use it ?....
From windows SDK ...
HDC hdc = GetDC(hwnd);
LoadAnImage(hdc,"D:\Test.jpg");
ReleaseDC(hdc );
if u are using MFC ,
CClientDC dc(this );
LoadAnImage(dc->m_hDC,"D:test.jpg");
we may pass the control's (command buttons...) device context, which in turn draws the picture over the control.....

List of Filters Completed....

1 BDL AbsDiff filter
2 BDL Bitmap Overlay Filter
3 BDL Blur Filter
4 BDL Brightness filter
5 BDL ChannelBlur filter
6 BDL ColorBalanceRGB filter
7 BDL ColorToGray filter
8 BDL Contrast filter
9 BDL Crop Filter
10 BDL Dyadic Arithmetic filter
11 BDL Dyadic Logic Filter
12 BDL Emboss Filter
13 BDL GammaCorrection filter
14 BDL Hue filter
15 BDL Inverse Filter
16 BDL Luminance filter
17 BDL Mask Filter
18 BDL Mirror Filter
19 BDL Morphology Filter
20 BDL Overlay Transform Filter
21 BDL Pixellate filter
22 BDL Posterize Filter
23 BDL RandomJitter filter
24 BDL RGBScaling Filter
25 BDL Rotate90 filter
26 BDL Rotation Filter
27 BDL Saturation Filter
28 BDL Sepia Filter
29 BDL ShiftChannels filter
30 BDL Solarize Filter
31 BDL Sphere Filter
32 BDL Swirl Filter
33 BDL Threshold filter
34 BDL Tiles Filter
35 BDL Timecode Burning filter
36 BDL Timewarp Filter
37 BDL VideoOverlay Filter
38 BDL Vortex Filter
39 BDL Water Filter
40 BDL Zoom Filter

Wednesday, March 28, 2007

Shared memory in Windows...

Shared memory Server

#include <stdio.h>
#include <conio.h>
#include <windows.h>

int main(int argc, char* argv[])
{

HANDLE hMemMapFile;
LPSTR lpMsg;

hMemMapFile = CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,
PAGE_READWRITE,0,0x1000,"SharedMemory");


if(hMemMapFile == NULL)
{
printf("n Failed to allocate Shared memory...");
exit(1);
}
lpMsg = (LPSTR)MapViewOfFile(hMemMapFile,FILE_MAP_WRITE,0,0,0);

if(lpMsg == NULL)
{
printf("n Failed to map shared memory ...");
exit(1);

}
lpMsg[0] = NULL;

while(lpMsg[0] == NULL) Sleep(1000);

printf("n Message Received : %s",lpMsg);

UnmapViewOfFile(lpMsg);


getch();
return 0;
}

Shared memory Client :

#include <stdio.h>
#include <conio.h>
#include <windows.h>

int main(int argc, char* argv[])
{

HANDLE hMemMapFile;
LPSTR lpMsg;

hMemMapFile = CreateFileMapping((HANDLE)0xffffffff,NULL,PAGE_READWRITE,0,0x1000,"SharedMemory");

if(hMemMapFile == NULL)
{
printf("n Failed to allocate Shared memory...");
exit(1);
}
lpMsg = (LPSTR)MapViewOfFile(hMemMapFile,FILE_MAP_WRITE,0,0,0);

if(lpMsg == NULL)
{
printf("n Failed to map shared memory ...");
exit(1);
}


strcpy(lpMsg,"Hello from client");
printf("n Message sent from client :%s",lpMsg);
UnmapViewOfFile(lpMsg);
getch();
return 0;
}


Object Construction and destruction in a single function :

IplImage* m_pSrcImage = NULL;

int ObjectLifeTime( bool bConstruct)

{

if( m_pSrcImage)

{

cvReleaseImage(&m_pSrcImage);

m_pSrcImage = NULL;

}

if( bConstruct)

{

m_pSrcImage = cvCreateImage(cvSize(300,300),IPL_DEPTH_8U, 3);

}

return 0;

}

we can use the ObjectLifeTime() fn to construct as well as destruct the object...

ObjectLifeTime( true) to construct the object...

ObjectLifeTime(false) to destruct the object....

Exact code for registering and unregistering the filter to the custom category.....

Before using CLSID_BDLImageProcessing we have to create a category for it...

we have to assign the CLSID to the custom category....



//My code registering a filter...

STDAPI
MyEliminateSubKey( HKEY hkey, LPTSTR strSubKey )
{
HKEY hk;
if (0 == lstrlen(strSubKey) ) {
// defensive approach
return E_FAIL;
}

LONG lreturn = RegOpenKeyEx( hkey
, strSubKey
, 0
, MAXIMUM_ALLOWED
, &hk );

ASSERT( lreturn == ERROR_SUCCESS
|| lreturn == ERROR_FILE_NOT_FOUND
|| lreturn == ERROR_INVALID_HANDLE );

if( ERROR_SUCCESS == lreturn )
{
// Keep on enumerating the first (zero-th)
// key and deleting that

for( ; ; )
{
TCHAR Buffer[MAX_KEY_LEN];
DWORD dw = MAX_KEY_LEN;
FILETIME ft;

lreturn = RegEnumKeyEx( hk
, 0
, Buffer
, &dw
, NULL
, NULL
, NULL
, &ft);

ASSERT( lreturn == ERROR_SUCCESS
|| lreturn == ERROR_NO_MORE_ITEMS );

if( ERROR_SUCCESS == lreturn )
{
MyEliminateSubKey(hk, Buffer);
}
else
{
break;
}
}

RegCloseKey(hk);
RegDeleteKey(hkey, strSubKey);
}

return NOERROR;
}



//---------------------------------------------------------------------------
//
// MyAMovieSetupRegisterServer()
//
// registers specfied file "szFileName" as server for
// CLSID "clsServer". A description is also required.
// The ThreadingModel and ServerType are optional, as
// they default to InprocServer32 (i.e. dll) and Both.
//
//---------------------------------------------------------------------------

STDAPI
MyAMovieSetupRegisterServer( CLSID clsServer
, LPCWSTR szDescription
, LPCWSTR szFileName
, LPCWSTR szThreadingModel = L"Both"
, LPCWSTR szServerType = L"InprocServer32" )
{
// temp buffer
//
TCHAR achTemp[MAX_PATH];

// convert CLSID uuid to string and write
// out subkey as string - CLSID\{}
//
OLECHAR szCLSID[CHARS_IN_GUID];
HRESULT hr = StringFromGUID2( clsServer
, szCLSID
, CHARS_IN_GUID );
ASSERT( SUCCEEDED(hr) );

// create key
//
HKEY hkey;
wsprintf( achTemp, TEXT("CLSID\\%ls"), szCLSID );
LONG lreturn = RegCreateKey( HKEY_CLASSES_ROOT
, (LPCTSTR)achTemp
, &hkey );
if( ERROR_SUCCESS != lreturn )
{
return AmHresultFromWin32(lreturn);
}

// set description string
//

wsprintf( achTemp, TEXT("%ls"), szDescription );
lreturn = RegSetValue( hkey
, (LPCTSTR)NULL
, REG_SZ
, achTemp
, sizeof(achTemp) );
if( ERROR_SUCCESS != lreturn )
{
RegCloseKey( hkey );
return AmHresultFromWin32(lreturn);
}

// create CLSID\\{"CLSID"}\\"ServerType" key,
// using key to CLSID\\{"CLSID"} passed back by
// last call to RegCreateKey().
//
HKEY hsubkey;

wsprintf( achTemp, TEXT("%ls"), szServerType );
lreturn = RegCreateKey( hkey
, achTemp
, &hsubkey );
if( ERROR_SUCCESS != lreturn )
{
RegCloseKey( hkey );
return AmHresultFromWin32(lreturn);
}

// set Server string
//
wsprintf( achTemp, TEXT("%ls"), szFileName );
lreturn = RegSetValue( hsubkey
, (LPCTSTR)NULL
, REG_SZ
, (LPCTSTR)achTemp
, sizeof(TCHAR) * (lstrlen(achTemp)+1) );
if( ERROR_SUCCESS != lreturn )
{
RegCloseKey( hkey );
RegCloseKey( hsubkey );
return AmHresultFromWin32(lreturn);
}

wsprintf( achTemp, TEXT("%ls"), szThreadingModel );
lreturn = RegSetValueEx( hsubkey
, TEXT("ThreadingModel")
, 0L
, REG_SZ
, (CONST BYTE *)achTemp
, sizeof(TCHAR) * (lstrlen(achTemp)+1) );

// close hkeys
//
RegCloseKey( hkey );
RegCloseKey( hsubkey );

// and return
//
return HRESULT_FROM_WIN32(lreturn);

}

//---------------------------------------------------------------------------
//
// MyAMovieSetupUnregisterServer()
//
// default ActiveMovie dll setup function
// - to use must be called from an exported
// function named DllRegisterServer()
//
//---------------------------------------------------------------------------

STDAPI
MyAMovieSetupUnregisterServer( CLSID clsServer )
{
// convert CLSID uuid to string and write
// out subkey CLSID\{}
//
OLECHAR szCLSID[CHARS_IN_GUID];
HRESULT hr = StringFromGUID2( clsServer
, szCLSID
, CHARS_IN_GUID );
ASSERT( SUCCEEDED(hr) );

TCHAR achBuffer[MAX_KEY_LEN];
wsprintf( achBuffer, TEXT("CLSID\\%ls"), szCLSID );

// delete subkey
//

hr = MyEliminateSubKey( HKEY_CLASSES_ROOT, achBuffer );
ASSERT( SUCCEEDED(hr) );

// return
//
return NOERROR;
}


STDAPI
MyRegisterAllServers( LPCWSTR szFileName, BOOL bRegister )
{
HRESULT hr = NOERROR;

for( int i = 0; i < g_cTemplates; i++ )
{
// get i'th template
//
const CFactoryTemplate *pT = &g_Templates[i];

DbgLog((LOG_TRACE, 2, TEXT("- - register %ls"),
(LPCWSTR)pT->m_Name ));

// register CLSID and InprocServer32
//
if( bRegister )
{
hr = MyAMovieSetupRegisterServer( *(pT->m_ClsID)
, (LPCWSTR)pT->m_Name
, szFileName );
}
else
{
hr = MyAMovieSetupUnregisterServer( *(pT->m_ClsID) );
}

// check final error for this pass
// and break loop if we failed
//
if( FAILED(hr) )
break;
}

return hr;
}


STDAPI
MyAMovieSetupRegisterFilter2( const AMOVIESETUP_FILTER * const psetupdata
, IFilterMapper2 * pIFM2
, BOOL bRegister )
{
DbgLog((LOG_TRACE, 3, TEXT("= AMovieSetupRegisterFilter")));

// check we've got data
//
if(NULL == psetupdata) return S_FALSE;


// unregister filter
// (as pins are subkeys of filter's CLSID key
// they do not need to be removed separately).
//
DbgLog((LOG_TRACE, 3, TEXT("= = unregister filter")));
HRESULT hr = pIFM2->UnregisterFilter(
&CLSID_BDLImageProcessing, // default category
0, // default instance name
*psetupdata->clsID);


if(bRegister)
{
REGFILTER2 rf2;
rf2.dwVersion = 1;
rf2.dwMerit = psetupdata->dwMerit;
rf2.cPins = psetupdata->nPins;
rf2.rgPins = psetupdata->lpPin;

// register filter
//
DbgLog((LOG_TRACE, 3, TEXT("= = register filter")));
hr = pIFM2->RegisterFilter(*psetupdata->clsID
, psetupdata->strName
, 0 // moniker
, &CLSID_BDLImageProcessing // category
, NULL // instance
, &rf2);
}

// handle one acceptable "error" - that
// of filter not being registered!
// (couldn't find a suitable #define'd
// name for the error!)
//
if(0x80070002 == hr)
return NOERROR;
else
return hr;
}


STDAPI MyAMovieDllRegisterServer2( BOOL bRegister )
{
HRESULT hr = NOERROR;

DbgLog((LOG_TRACE, 2, TEXT("AMovieDllRegisterServer2()")));

// get file name (where g_hInst is the
// instance handle of the filter dll)
//
WCHAR achFileName[MAX_PATH];

// WIN95 doesn't support GetModuleFileNameW
//
{
char achTemp[MAX_PATH];

DbgLog((LOG_TRACE, 2, TEXT("- get module file name")));

// g_hInst handle is set in our dll entry point. Make sure
// DllEntryPoint in dllentry.cpp is called
ASSERT(g_hInst != 0);

if( 0 == GetModuleFileNameA( g_hInst
, achTemp
, sizeof(achTemp) ) )
{
// we've failed!
DWORD dwerr = GetLastError();
return AmHresultFromWin32(dwerr);
}

MultiByteToWideChar( CP_ACP
, 0L
, achTemp
, lstrlenA(achTemp) + 1
, achFileName
, NUMELMS(achFileName) );
}

//
// first registering, register all OLE servers
//
if( bRegister )
{
DbgLog((LOG_TRACE, 2, TEXT("- register OLE Servers")));
hr = MyRegisterAllServers( achFileName, TRUE );
}

//
// next, register/unregister all filters
//

if( SUCCEEDED(hr) )
{
// init is ref counted so call just in case
// we're being called cold.
//
DbgLog((LOG_TRACE, 2, TEXT("- CoInitialize")));
hr = CoInitialize( (LPVOID)NULL );
ASSERT( SUCCEEDED(hr) );

// get hold of IFilterMapper2
//
DbgLog((LOG_TRACE, 2, TEXT("- obtain IFilterMapper2")));
IFilterMapper2 *pIFM2 = 0;
IFilterMapper *pIFM = 0;
hr = CoCreateInstance( CLSID_FilterMapper2
, NULL
, CLSCTX_INPROC_SERVER
, IID_IFilterMapper2
, (void **)&pIFM2 );
if(FAILED(hr))
{
DbgLog((LOG_TRACE, 2, TEXT("- trying IFilterMapper instead")));

hr = CoCreateInstance(
CLSID_FilterMapper,
NULL,
CLSCTX_INPROC_SERVER,
IID_IFilterMapper,
(void **)&pIFM);
}
if( SUCCEEDED(hr) )
{
// scan through array of CFactoryTemplates
// registering servers and filters.
//
DbgLog((LOG_TRACE, 2, TEXT("- register Filters")));
for( int i = 0; i < g_cTemplates; i++ )
{
// get i'th template
//
const CFactoryTemplate *pT = &g_Templates[i];

if( NULL != pT->m_pAMovieSetup_Filter )
{
DbgLog((LOG_TRACE, 2, TEXT("- - register %ls"), (LPCWSTR)pT->m_Name ));

if(pIFM2)
{
hr = MyAMovieSetupRegisterFilter2( pT->m_pAMovieSetup_Filter, pIFM2, bRegister );
}
else
{
hr = AMovieSetupRegisterFilter( pT->m_pAMovieSetup_Filter, pIFM, bRegister );
}
}

// check final error for this pass
// and break loop if we failed
//
if( FAILED(hr) )
break;
}

// release interface
//
if(pIFM2)
pIFM2->Release();
else
pIFM->Release();

}

// and clear up
//
CoFreeUnusedLibraries();
CoUninitialize();
}

//
// if unregistering, unregister all OLE servers
//
if( SUCCEEDED(hr) && !bRegister )
{
DbgLog((LOG_TRACE, 2, TEXT("- register OLE Servers")));
hr = MyRegisterAllServers( achFileName, FALSE );
}

DbgLog((LOG_TRACE, 2, TEXT("- return %0x"), hr));
return hr;
}


//End of the code for registering/Unregistering a filter


//
// DllRegisterServer
//
// Handle registration of this filter
//
STDAPI DllRegisterServer()
{
OutputDebugString("\n DllRegisterServer() fn");
HRESULT hr = NOERROR;

hr = MyAMovieDllRegisterServer2( TRUE );

/*
if(FAILED(hr))
{
return hr;
}


IFilterMapper2* pFM2 = NULL;
hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
IID_IFilterMapper2, (void **)&pFM2);

if (SUCCEEDED(hr))
{
// Declare filter information
const REGFILTER2 rf2AbsDiffReg =
{
1, // Version number
MERIT_DO_NOT_USE+1, // Filter merit
2, // Number of pins
sudpPins // Pin information
};

hr = pFM2->RegisterFilter(
CLSID_AbsDiff, // Filter CLSID.
TRANSFORM_NAME, // Filter name.
NULL, // Device moniker.
&CLSID_BDLImageProcessing, // DirectShow filter
TRANSFORM_NAME, // Instance data.
// This instance data is an essential thing...
&rf2AbsDiffReg // Filter information.
);
pFM2->Release();
}
*/
return hr;

} // DllRegisterServer

//
// DllUnregisterServer
//
STDAPI DllUnregisterServer()
{
OutputDebugString("\n DllUnRegisterServer fn" );
HRESULT hr = NOERROR;


hr = MyAMovieDllRegisterServer2( FALSE );

/*
if(FAILED(hr))
{
return hr;
}


IFilterMapper2* pFM2 = NULL;
hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
IID_IFilterMapper2, (void **)&pFM2);

if (SUCCEEDED(hr))
{
hr = pFM2->UnregisterFilter(
&CLSID_BDLImageProcessing, // Filter CLSID.
TRANSFORM_NAME, // Filter name.
CLSID_AbsDiff // Device moniker.
);
if(SUCCEEDED(hr))
{
OutputDebugString("\n Sucessfully Unregistered ");
}
else
{
OutputDebugString("\n UnRegistration failed...");
}
pFM2->Release();
}
else
{
OutputDebugString("\n Error in IFilterMapper2 Interface problems>>>");
}

*/
return hr;

} // DllUnregisterS

Completed :

1.Created the sample application for adding a new category in GraphEdit...

2. I added the code to register the filter

3. while unregistering the filter, it also done successfully...

4. The filter is registered and unregistered successfully on the BDL image processing filters category...

registering and Unregistering a filter in a specified category....

STDAPI DllRegisterServer()
{
OutputDebugString("\n DllRegisterServer() fn");
HRESULT hr = NOERROR;

hr = AMovieDllRegisterServer2( TRUE );

if(FAILED(hr))
{
return hr;
}


IFilterMapper2* pFM2 = NULL;
hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
IID_IFilterMapper2, (void **)&pFM2);

if (SUCCEEDED(hr))
{
// Declare filter information
const REGFILTER2 rf2AbsDiffReg =
{
1, // Version number
MERIT_DO_NOT_USE+1, // Filter merit
2, // Number of pins
sudpPins // Pin information
};

hr = pFM2->RegisterFilter(
CLSID_AbsDiff, // Filter CLSID.
TRANSFORM_NAME, // Filter name.
NULL, // Device moniker.
&CLSID_BDLImageProcessing, // DirectShow filter
TRANSFORM_NAME, // Instance data.
// This instance data is an essential thing...
&rf2AbsDiffReg // Filter information.
);
pFM2->Release();
}

return hr;

} // DllRegisterServer

//
// DllUnregisterServer
//
STDAPI DllUnregisterServer()
{
OutputDebugString("\n DllUnRegisterServer fn" );
HRESULT hr = NOERROR;


hr = AMovieDllRegisterServer2( FALSE );

if(FAILED(hr))
{
return hr;
}


IFilterMapper2* pFM2 = NULL;
hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
IID_IFilterMapper2, (void **)&pFM2);

if (SUCCEEDED(hr))
{
hr = pFM2->UnregisterFilter(
&CLSID_BDLImageProcessing, // Filter CLSID.
TRANSFORM_NAME, // Filter name.
CLSID_AbsDiff // Device moniker.
);
if(SUCCEEDED(hr))
{
OutputDebugString("\n Sucessfully Unregistered ");
}
else
{
OutputDebugString("\n UnRegistration failed...");
}
pFM2->Release();
}
else
{
OutputDebugString("\n Error in IFilterMapper2 Interface problems>>>");
}


return hr;

} // DllUnregisterServer

Registering our filter in a specified category...

IFilterMapper2* pFM2 = NULL;
hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
IID_IFilterMapper2, (void **)&pFM2);

if (SUCCEEDED(hr))
{
// Declare filter information
const REGFILTER2 rf2AbsDiffReg =
{
1, // Version number
MERIT_DO_NOT_USE+1, // Filter merit
2, // Number of pins
sudpPins // Pin information
};

hr = pFM2->RegisterFilter(
CLSID_AbsDiff, // Filter CLSID.
TRANSFORM_NAME, // Filter name.
NULL, // Device moniker.
&CLSID_BDLImageProcessing, // DirectShow filter
TRANSFORM_NAME, // Instance data.
// This instance data is an essential thing...
&rf2AbsDiffReg // Filter information.
);
pFM2->Release();
}





Today I faced the problem I am not able to unregister the filter....


the reason is
For UnregisterFilter(), i passed the NULL as an instance data... (check the documentation) even though I have given valid class ID...




following code for unregistering the filter:



IFilterMapper2* pFM2 = NULL;
hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
IID_IFilterMapper2, (void **)&pFM2);

if (SUCCEEDED(hr))
{
hr = pFM2->UnregisterFilter(
&CLSID_BDLImageProcessing, // Filter CLSID.
TRANSFORM_NAME,
// I passed this value as NULL So i got a problem // Filter name.
CLSID_AbsDiff // Device moniker.
);
if(SUCCEEDED(hr))
{
OutputDebugString("\n Sucessfully Unregistered ");
}
else
{
OutputDebugString("\n UnRegistration failed...");
}
pFM2->Release();
}
else
{
OutputDebugString("\n Error in IFilterMapper2 Interface problems>>>");
}



So it failed...

Sample application for creating a filter category in GraphEdit

#include
#include

#pragma comment(lib,"strmiids") //Load the Directshow IIDs...


// {6C93F1D6-45B7-4d28-A1D9-992D71E7150D}
DEFINE_GUID(CLSID_BDLImageProcessing,
0x6c93f1d6, 0x45b7, 0x4d28, 0xa1, 0xd9, 0x99, 0x2d, 0x71, 0xe7, 0x15, 0xd);


int main(int argc, char* argv[])
{
CoInitialize(NULL); //Initialize COM Runtime

HRESULT hr = NOERROR;

IFilterMapper2 *pMapper2= NULL;

hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
IID_IFilterMapper2, (void **)&pMapper2);

if(SUCCEEDED(hr))
{
hr =pMapper2->CreateCategory(CLSID_BDLImageProcessing,MERIT_DO_NOT_USE,L"BDL Image Processing Filters");

if(SUCCEEDED(hr))
{
printf("\n Sucesssfully created the BDL category");
}
}



CoUninitialize(); //Uninitialize COM runtime
return 0;
}

Tuesday, March 27, 2007

Bottom up DIB and Top down DIB

The origin for a bottom-up DIB is the lower-left corner of the bitmap; the origin for a top-down DIB is the upper-left corner.

I faced the problem like this
I have drawn the image using DrawText() fn... it succeeds... But it didnt work well...
I used the hBackDC to DrawText()... On hBackDC I selected the hBackBitmap object.
hBackBitmap holds the image size as 320 * 240 bitmap...
using DrawText() I displayed the image in out of region in hBackBitmap...
it wont get any error.
Even though the x,y values exceeds, DrawText( ) fails...

I must start the basics in CSource filter...

Directshow source filter developement_Abstraction

class CSnakeFilter : public CSource
{
friend class CSnakeStream;

public:
CSnakeFilter(LPUNKNOWN pUnk, HRESULT *phr);
virtual ~CSnakeFilter(void);

// static
public:
static CUnknown * WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);

// Attributes
public:

// Operations
public:

// Overrides
protected:

// Implementations
protected:
// IUnknown interface
DECLARE_IUNKNOWN;
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
return CSource::NonDelegatingQueryInterface(riid, ppv);
}


// member variables
private:
};

CSnakeFilter::CSnakeFilter(LPUNKNOWN pUnk, HRESULT *phr)
: CSource(NAME("CSnakeFilter"), pUnk, CLSID_Snake)
{
CAutoLock cAutoLock(&m_cStateLock);

//
// CSource::AddPin() is automatically called
// by creating a source stream (CSourceStream)
//

// Add one source stream (output pin)!
new CSnakeStream(phr, this, L"Out");

// TODO: add source stream here
}


//
// Destructor
//
CSnakeFilter::~CSnakeFilter()
{
}







// CSourceStream derived class....

class CSnakeStream : public CSourceStream
{
public:
CSnakeStream(HRESULT *phr, CSnakeFilter *pParent, LPCWSTR pPinName);
virtual ~CSnakeStream(void);

// Attributes
public:

// Operations
public:
LONGLONG m_llFrameCount;

BITMAPINFO m_bmpInfo;
void *m_pPaintBuffer;
HDC m_dcPaint;
int m_nLastX;
int m_nLastY;
int m_nScoreBoardHeight;
int m_nSnakeBlockHeight;
int m_nSnakeBlockWidth;
int m_nNumberSnakeBlocks;
int m_nSpaceBetweenBlock;

// Overrides
protected:
///////////////////////////
// Media Type support

// media types filter have
virtual HRESULT GetMediaType(CMediaType *pMediaType);

///////////////////////////
// Buffer Negotiation support

// buffer size
virtual HRESULT DecideBufferSize(IMemAllocator *pMemAlloc, ALLOCATOR_PROPERTIES *pProperties);

///////////////////////////
// Data Source support

// media sample
virtual HRESULT FillBuffer(IMediaSample *pSample);

// signal
virtual HRESULT OnThreadCreate(void);
virtual HRESULT OnThreadDestroy(void);
virtual HRESULT OnThreadStartPlay(void);

// Overrides
protected:

// Implementations
protected:

// member variables
private:

};


CSnakeStream::CSnakeStream(HRESULT *phr, CSnakeFilter *pParent, LPCWSTR pPinName)
: CSourceStream(NAME("CSnakeStream"), phr, pParent, pPinName)
, m_llFrameCount(0)

{
CAutoLock cAutoLock(m_pFilter->pStateLock());

}


//
// Destructor
//
CSnakeStream::~CSnakeStream()
{
}


//
// GetMediaType
//
HRESULT CSnakeStream::GetMediaType(CMediaType *pMediaType)
{
CAutoLock lock(m_pFilter->pStateLock());

ZeroMemory(pMediaType, sizeof(CMediaType));

// TODO: modify this option
{
VIDEOINFO *pvi = (VIDEOINFO *)pMediaType->AllocFormatBuffer(sizeof(VIDEOINFO));
if (NULL == pvi)
return E_OUTOFMEMORY;

ZeroMemory(pvi, sizeof(VIDEOINFO));

pvi->bmiHeader.biCompression = BI_RGB;
pvi->bmiHeader.biBitCount = 24;
pvi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pvi->bmiHeader.biWidth = 320;
pvi->bmiHeader.biHeight = 240;
pvi->bmiHeader.biPlanes = 1;
pvi->bmiHeader.biSizeImage = GetBitmapSize(&pvi->bmiHeader);
pvi->bmiHeader.biClrImportant = 0;

SetRectEmpty(&(pvi->rcSource)); // we want the whole image area rendered.
SetRectEmpty(&(pvi->rcTarget)); // no particular destination rectangle

pMediaType->SetType(&MEDIATYPE_Video);
pMediaType->SetFormatType(&FORMAT_VideoInfo);
pMediaType->SetTemporalCompression(FALSE);

const GUID SubTypeGUID = GetBitmapSubtype(&pvi->bmiHeader);
pMediaType->SetSubtype(&SubTypeGUID);
pMediaType->SetSampleSize(pvi->bmiHeader.biSizeImage);

m_bmpInfo.bmiHeader = pvi->bmiHeader;
}

return S_OK;
}


//
// DecideBufferSize
//
HRESULT CSnakeStream::DecideBufferSize(IMemAllocator *pMemAlloc, ALLOCATOR_PROPERTIES *pProperties)
{
CAutoLock cAutoLock(m_pFilter->pStateLock());
ASSERT(pMemAlloc);
ASSERT(pProperties);

HRESULT hr;

// TODO: set the properties
{
VIDEOINFO *pvi = (VIDEOINFO *)m_mt.Format();
pProperties->cBuffers = 3;
pProperties->cbBuffer = pvi->bmiHeader.biSizeImage;
}

// Ask the allocator to reserve us some sample memory, NOTE the function
// can succeed (that is return NOERROR) but still not have allocated the
// memory that we requested, so we must check we got whatever we wanted

ALLOCATOR_PROPERTIES Actual;
hr = pMemAlloc->SetProperties(pProperties, &Actual);
if (FAILED(hr))
{
return hr;
}

// Is this allocator unsuitable
if (Actual.cbBuffer < pProperties->cbBuffer)
{
return E_FAIL;
}

return S_OK;
}

int nFrameRate = 0;




// FillBuffer
//
HRESULT CSnakeStream::FillBuffer(IMediaSample *pSample)
{
CAutoLock lock(m_pFilter->pStateLock());

HRESULT hr;
BYTE *pBuffer;
long lSize;

hr = pSample->GetPointer(&pBuffer);
if (SUCCEEDED(hr))
{
lSize = pSample->GetSize();

//write the TExt to BackDC or MemDc
sprintf(str,"%ld",count++ );
DrawText(hMemDC,str,strlen(str),DT_CENTER);
CopyMemory(pBuffer,m_pPaintBuffer,lSize);
}

return S_OK;
}


//
// OnThreadCreate
//
HRESULT CSnakeStream::OnThreadCreate(void)
{
HBITMAP hDibSection = CreateDIBSection(NULL, (BITMAPINFO *) &m_bmpInfo, DIB_RGB_COLORS,&m_pPaintBuffer, NULL, 0);

HDC hDC = GetDC(NULL);
m_dcPaint = CreateCompatibleDC(hDC);
SetMapMode(m_dcPaint, GetMapMode(hDC));

HGDIOBJ OldObject = SelectObject(m_dcPaint,hDibSection);

m_nScoreBoardHeight = m_bmpInfo.bmiHeader.biHeight/8;
m_nSnakeBlockHeight = 4, m_nSnakeBlockWidth = 6;
m_nNumberSnakeBlocks = 6;
m_nSpaceBetweenBlock = 1;


m_nLastX = 0;//(m_bmpInfo.bmiHeader.biWidth/2) - (m_nSnakeBlockWidth+m_nSpaceBetweenBlock)*m_nNumberSnakeBlocks;
m_nLastY = 0;//(m_bmpInfo.bmiHeader.biHeight/2);


return CSourceStream::OnThreadCreate();
}


//
// OnThreadDestroy
//
HRESULT CSnakeStream::OnThreadDestroy(void)
{
return CSourceStream::OnThreadDestroy();
}


//
// OnThreadStartPlay
//
HRESULT CSnakeStream::OnThreadStartPlay(void)
{
return CSourceStream::OnThreadStartPlay();
}




/// Another file


// {92E9BF2A-4385-4a08-8236-397478EB34B8}
DEFINE_GUID(CLSID_Snake,
0x92e9bf2a, 0x4385, 0x4a08, 0x82, 0x36, 0x39, 0x74, 0x78, 0xeb, 0x34, 0xb8);


#include
#include "Snake.h"


//
// Setup data for filter registration
//
const AMOVIESETUP_MEDIATYPE sudPinTypes =
{ &MEDIATYPE_NULL, // Major CLSID
&MEDIASUBTYPE_NULL // Minor type
};

const AMOVIESETUP_PIN psudPins[] =
{
{
L"Output", // Pin's string name
FALSE, // Is it rendered
TRUE, // Is it an output
FALSE, // Allowed none
FALSE, // Allowed many
&CLSID_NULL, // Connects to filter
L"Input", // Connects to pin
1, // Number of types
&sudPinTypes // Pin type information
},
};

const AMOVIESETUP_FILTER sudSnake =
{
&CLSID_Snake, // CLSID of filter
L"Snake Filter", // Filter's name
MERIT_DO_NOT_USE, // Filter merit
1, // Number of pins
psudPins // Pin information
};


//
// Object creation template
//
CFactoryTemplate g_Templates[] =
{
{
L"Snake Filter",
&CLSID_Snake,
CSnakeFilter::CreateInstance,
NULL,
&sudSnake
},
};

int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);


//
// Filter registration functions
//
HRESULT DllRegisterServer()
{
return AMovieDllRegisterServer2(TRUE);
}

HRESULT DllUnregisterServer()
{
return AMovieDllRegisterServer2(FALSE);
}


//
// Create a new instance of this class
//
CUnknown *CSnakeFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *phr)
{
// DLLEntry does the right thing with the return code and
// returned value on failure
CUnknown *pUnknown = new CSnakeFilter(pUnk, phr);
if (pUnknown == NULL)
{
*phr = E_OUTOFMEMORY;
}

return pUnknown;
}

How to find the width and height of the text with specified font ?

How to find the width and height of the text with specified font :

LOGFONT logFont... which holds information about the selected font...
HFONT hFont = CreateFontIndirect(&logfont);

SelectObject(graphics->GetHdc(),(HGDIOBJ)hFont);
GetTextExtentPoint32 () ... returns the width and height of the text
we can get width here...

we may get Height From the following :

TextMetrics tm;
GetTextMetrics(&tm);
tm.Height - Height of the text....


The GetTextExtentPoint32 function computes the width and height of the specified string of text. the GetTextExtentPoint32 function initializes the members of a SIZE structure with the length and height of the specified string. The GetTextMetrics function retrieves the overhang for the current font. Because the overhang is zero if the font is a TrueType font, the overhang value does not change the string placement. For raster fonts, however, it is important to use the overhang value.

Monday, March 26, 2007

Display video after Pause the video...

After closing or paused the video in graphedit, I just only got the video as a still without moving...

that means the existing image kept as it is. My code which cause this problem...

void CAbsDiffFilter::Run()
{

for (i=0;i< m_nInputPinsCount;i++)
{
if (m_ip[i]->IsConnected() == FALSE)
{
NotConnected=true;
break;
}
}
if (NotConnected)
{
for (i=0;i m_ip[i]->EndOfStream();
}
hr = CBaseFilter::Run(tStart);

return hr;
}

Modified code :...
void CAbsDiffFilter::Run()
{

hr = CBaseFilter::Run(tStart);
for (i=0;i< m_nInputPinsCount;i++)
{
if (m_ip[i]->IsConnected() == FALSE) // if input pins are not connected
//m_ip[i] are input pins...
{
NotConnected=true;
break;
}
}
if (NotConnected)
{
for (i=0;i m_ip[i]->EndOfStream();
}


return hr;
}

Simple MFC application

//Simple MFC application program

// Define a window class derived from CWnd
class CHelloWindow : public CWnd
{
public:
CHelloWindow()
{
CreateEx(WS_EX_CLIENTEDGE,
AfxRegisterWndClass(0, ::LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_WINDOW+1)),
_T("Hello World!"), WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, 0);
}
};


// Define an application class derived from CWinApp
class CHelloApp : public CWinApp
{
public:
virtual BOOL InitInstance()
{
m_pMainWnd = new CHelloWindow();
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
};

CHelloApp HelloApp; // HelloApp's constructor initializes and runs the app

26-March-2007 works done

Completed Today :

1..Convert OpenCV coordinates to Windows Coordinates... Completed...
1.1. Copy the Background image as the srcInput Pin1.... Completed
1.2.Add histogram Support to Second Input Pin - completed
1.3. cvAbsDiff() gives an error...I thought that it is due to ROI...

I thought that cvAbsDiff() didnt support ROI... But the fact is cvAbsDiff() input images are set in the ROI as 0,0,0,0...

So I changed it ... Now it is working properly...

1.4.1.while Connecting with filter it must display the output width and height - Completed...

I loaded the width and height paramaeters within the Input Pin's CheckMediaType()... This will checks the

media type of the pin connected to the input pin...

I Set the values from here....

To be completed :

1. Generate the IMediasample interface .....
.

Sunday, March 25, 2007

CMutex with CSingleLock application

1.CSingleLock with CMutex.... MFC...

One thread incremented the counter , another one thread displays the value in the dialog box....

I have to synchronize the things...


Description :

1. CMutex object is available as a member in dialog application...

2. we developed the CCounterThread(increment the value) and CDisplayThread

used to update the value to the dialog box...

CCounterThread and CDisplayThread classes are derived from CWinThread...


The Dialog box have the string value for the counter (displayed in Text Box)...

within the counter thread, we incremented the counter and displayed the value in DisplayThread...

class CCounterThread : public CWinThread
{
public:
BOOL m_bDone;
CCounterThread() { m_bDone = FALSE; }
virtual BOOL InitInstance () { return TRUE; }
virtual int Run();
CMutexDlg* dlg; //Set this dialog at runtime...
};

int CCounterThread ::Run ()
{
int i =0;
CSingleLock sLock(&dlg->m_MutexObject);

while(!m_bDone)
{

sLock.Lock();
dlg->m_Number = i; // m_Number is mapped to the dialog's Edit box...
sLock.UnLock();

}

SendMessage(dlg,WM_CLOSE,0,0);

}
CMutexDlg has CCounterThread and CDisplayThread object, CMutex object...
CCounterThread and CDisplayThread must have the Dialog (CMutexDlg) object..


I derived the CWinThread class...

The CWinThread derived class has overriding Run() fn...

MSDN sample applications to learn

ATL samples - 22
MFC samples - 104
COM samples - 13
OLE DB sample - 2
application wizard sample - 3
ADDINS samples - 13
SDK samples - - 347
dotNET samples - - 81
Directshow samples - 87


672 samples...- This will takes 3 years...

Directshow source filter (sample Bouncing Ball)

CSourceStream derived class
CSource derived class....

//CSource is derived from cBaseFilter
//CSourceStream is derived from CBaseOutputPin and CAmThread

CSource filter has "CSourceStream m_paStreams" member...

This is used to define the output pins of the source filter...

what I have done in BOuncing Ball filter... ?


code for one output pin :

m_paStreams = (CSourceStream**)new CBallStream*[1];
m_paStreams[0] = new CBallStream(phr, this, L"A Bouncing Ball!");

I changed it as follows ...

m_paStreams = (CSourceStream**)new CBallStream*[2];
m_paStreams[0] = new CBallStream(phr, this, L"A Bouncing Ball!");
m_paStreams[1] = new CBallStream(phr, this, L"Bouncer"); //Second output pin

Friday, March 23, 2007

AbsDiff() filter error

AbsDiff filter Error :

we can add the filter in two ways...

1. First we render two media files and insert the AbsDiff filter(two

input pin filter...). In this way, the filter works well...

2.Second way, we insert the filter first and then render the two media

files, it will automatically connect to the AbsDiff Filter( Two Input Pin

filter...)

In the second way, i got the error...

I am not able to identify the error where it is...

Solution :

I previously have the input and output pin's CheckMediaType() as follows..

HRESULT CheckMediaType(const CMediaType* pmt)
{
// Check this is a VIDEOINFO type

if (*pmt->FormatType() != FORMAT_VideoInfo)
{
return E_INVALIDARG;
}


VIDEOINFO* vi = (VIDEOINFO*)pmt->Format();
if(vi->bmiHeader.biBitCount != 24)
{
return E_INVALIDARG;
}

return NOERROR;
}


I changed the input and output pin's CheckMediaType as follows...


HRESULT cvSyncOutputPin::CheckMediaType(const CMediaType* pMediaType)
{
// Check this is a VIDEOINFO type

// we accept the following image type: (RGB24, ARGB32 or RGB32)
if (IsEqualGUID(*pMediaType->Type(), MEDIATYPE_Video))
{
if (IsEqualGUID(*pMediaType->Subtype(), MEDIASUBTYPE_RGB24))
{
VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *) pMediaType->Format();
if(pvi->bmiHeader.biBitCount == 24)
{
return NOERROR;
}
}

}

return E_INVALIDARG;


}

So the Problem lies in while we check the media type,

we checked the FormatType() of the input media type...

I changed it as only checking MEDIATYPE (Type())and MEDIASUBTYPE (SubType())

of the input media type...

This is the excellent problem solving ... I didnt met before like this...

(vennai Olungaa program pannuda...)








I solved the problem of Intelligent Connect ... The problem is due to the CheckMediaType() conditions.....

I changed the CheckMediaType() fn conditions as like as TransformFilter....

Now It is working...

The problem is CheckMediaType() fn...

Thursday, March 22, 2007

File Change Notifications

File Change Notifications

HANDLE parameter passed to ::WaitForSingleObject can be a "file change notification handle." The Win32 API includes a
function named ::FindFirstChangeNotification that returns a handle you can use to wake a blocked thread whenever a change
occurs in a specified directory or its subdirectories—for example, when a file is renamed or deleted or a new directory is
created.

Changes to the file system are instantly reflected in the left or right pane. The most efficient way to do it is to start a
background thread and have it block on one or more file change notification handles. Here's what the thread function for a
thread that monitors drive C: might look like:

UINT ThreadFunc (LPVOID pParam)
{
HWND hwnd = (HWND) pParam; // Window to notify
HANDLE hChange = ::FindFirstChangeNotification (_T ("C:\\"),
TRUE, FILE_NOTIFY_CHANGE_FILE_NAME ¦ FILE_NOTIFY_CHANGE_DIR_NAME);

if (hChange == INVALID_HANDLE_VALUE) {
TRACE (_T ("Error: FindFirstChangeNotification failed\n"));
return (UINT) -1;
}

while (...) {
::WaitForSingleObject (hChange, INFINITE);
::PostMessage (hwnd, WM_USER_CHANGE_NOTIFY, 0, 2);
::FindNextChangeNotification (hChange); // Reset
}
::FindCloseChangeNotification (hChange);
return 0;
}




The first parameter passed to ::FindFirstChangeNotification identifies the directory you want to monitor, the second
specifies whether you want to monitor just that directory (FALSE) or that directory and all its subdirectories (TRUE), and
the third specifies the kinds of changes that the thread should be notified of. In this example, the thread will be awakened
when a file is created, renamed, or deleted anywhere on the C: drive (FILE_NOTIFY_CHANGE_FILE_NAME) or when a directory is
created, renamed, or deleted (FILE_NOTIFY_CHANGE_DIR_NAME). When the thread is awakened, it posts a user-defined message to
the window whose handle was passed in pParam. The message's lParam holds a drive number (2 for drive C:). The window that
receives the message—presumably the application's top-level frame window—can respond to the message by updating its views.
Keep in mind that a thread awakened by a file change notification doesn't receive any information about the nature of the
change or about where in the directory tree the change occurred, so it must scan the file system if it wants to determine
what caused the file change notification.

It's also possible to structure the thread so that it monitors not just one drive, but several. All you would have to do is
call ::FindFirstChangeNotification once per drive to acquire a separate file change notification handle for each drive and
use ::WaitForMultipleObjects to block on all the file change notifications simultaneously. ::WaitForMultipleObjects is the
Win32 API equivalent of CMultiLock::Lock. Passing FALSE in the third parameter to a call to ::WaitForMultipleObjects tells
the system to wake the thread when any one of the objects that the thread is blocking on becomes signaled.

AlphaBlend() fn notes

In VC98, AlphaBlend() fn is not added to CDC class..we can make use of

AlphaBlend() fn with msimg32.lib . msimg32.lib contains AlphaBlend() fn..

#define AC_SRC_OVER 0x0
#define AC_SRC_ALPHA 0x1

How can we access the HDC from CDC class ?...

CDC class has m_hDC member which is a type of HDC for CDC...

Dialog as a MainWnd in Windows programming

BOOL CALLBACK DlgProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
switch( uMsg )
{
case WM_INITDIALOG:
InitDlgBox(hwndDlg); // initialize some variables
return true;
break;
case WM_CLOSE:
DestroyWindow(hwndDlg);
PostQuitMessage(0);
return true;
break;
case WM_COMMAND:
if(LOWORD(wParam==IDC_ABBRECHEN)) { // cancel button pressed ?
DestroyWindow(hwndDlg);
PostQuitMessage(0);
status=false; // Dialog is canceled
return true;
}
if(LOWORD(wParam==IDC_START)) { // start button pressed ?
SaveOptions(hwndDlg);
DestroyWindow(hwndDlg);
PostQuitMessage(0);
status=true; // Dialog is accepted
return true;
}


break;


}
return false;



}


bool DlgBox(HINSTANCE hInstance)
{
HWND hwndDlg;
hwndDlg=CreateDialog(hInstance,MAKEINTRESOURCE(IDD_DLG),NULL,
(DLGPROC)DlgProc) ;
ShowWindow(hwndDlg, SW_NORMAL);
UpdateWindow(hwndDlg);

while( GetMessage( &DlgMsg, NULL, 0, 0) )
{
TranslateMessage(&DlgMsg);
DispatchMessage(&DlgMsg);
}
return status; // should return true if Dlg is accepted otherwise false



}


int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{

.....
.....
if(DlgBox(hInstance)==false) {
return false; // <= seems to cause the problem (should exit
WinMain)
}
.....
.....
.....



}

Debug Assertion Failed! _ OpenCV _VC++_Directshow

---------------------------
Microsoft Visual C++ Debug Library
---------------------------
Debug Assertion Failed!

Program: C:\DXSDK\Bin\DXUtils\graphedt.exe
File: dbgheap.c
Line: 1138

Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.

(Press Retry to debug the application)
---------------------------
Abort Retry Ignore
---------------------------

Solution :
---------------

I got this error... I released the image using delete operator... this is caused this error...

So I deleted the image using cvReleaseImage() fn...

Regards
Sundara rajan.A

Tuesday, March 13, 2007

AtlWinModuleInit Error

while working with 2003 ,
I got an error in Directshow filters as follows
PsiParser error LNK2001: unresolved external symbol "class ATL::CAtlBaseModule ATL::_AtlBaseModule" (?_AtlBaseModule@ATL@@3VCAtlBaseModule@1@A)
PsiParser error LNK2019: unresolved external symbol "long __stdcall ATL::AtlWinModuleInit(struct ATL::_ATL_WIN_MODULE70 *)" (?AtlWinModuleInit@ATL@@YGJPAU_ATL_WIN_MODULE70@1@@Z) referenced in function "public: __thiscall ATL::CAtlWinModule::CAtlWinModule(void)" (??0CAtlWinModule@ATL@@QAE@XZ)


Solution :
You need to do one of two things.
Link with atls(d).lib OR remove atlbase.h and replace it with atlconv.h
atls.lib (release) and atlsd.lib (debug) appear to be the atl run time
libraries.
If you are only use atl conversion macros you can use the include file
atlconv.h in place of atlbase.h.
atl based com objects and executables need _Module defined in order to run
(alessandro is going to beat me up for being too simplistic [and maybe
wrong here!]). In VS2003 it appears that the run time has been put in a
library. If you are only using the conversion functions, you don't need
it.

Monday, March 12, 2007

placement form new

#include
int main(int argc, char* argv[])
{
char *pTest = new char[10];

char* pStr = new(pTest) char[10];

strcpy(pTest,"Rammohan");
strcpy(pTest,"Sundar");

printf("%s",pStr);

if(pStr)
{
delete pStr;
}
getch();
return 0;
}

output is : Sundar
Only one pointer is used...

Sunday, March 11, 2007

Tips and Tricks...

why we need to know about some tricks in any(C++) language ?

we may use tips and tricks in our program .another one reason to learn the tips and tricks is

mostly we develope program based on sample code from the net...

at that time we need to understand what they have done in their program, for that reason alone

we need to know about the tips and tricks in any language...


1. x i = 10;


what is x ?can u make this bit of code as a meaningful one ?

How can we do it ? Think about it if u cant get an idea... see the results below.
.
.
.
.
.
.
.
.


1. typedef int x;
x i = 10;


2. x may be a class with parameterized constructor...


class x
{

int i;

public:
x(int a)
{
i = a;
}

};


2.

Is it possible to make use of this code in C or C++ ? replace() is an user defined function..

replace(5) = 'X';

try....



answer is ....





char s[80] = "Hello world";

char & replace(int i);

int main()
{
replace(5) = 'X'; // this will inserts the X value at space
// the content of s will be
// HelloXWorld
}

char& replace(int i)
{
return s[i];
}



3.Simple reference example in C++


void neg(int &i)
{
i = -i;
}

int main( )
{
int x = 10;
neg(x);

cout << x; // Here the output value is -10
//can't believe it test it with sample programs
}

Saturday, March 10, 2007

MFC Array Classes

Type-Specific MFC Array Classes

Class Name Data Type
CByteArray 8-bit bytes (BYTEs)
CWordArray 16-bit words (WORDs)
CDWordArray 32-bit double words (DWORDs)
CUIntArray Unsigned integers (UINTs)
CStringArray CStrings
CPtrArray void pointers
CObArray CObject pointers


Once you learn to use one of these array classes, you can use the others too, because all share a common set of member functions. The following example declares an array of 10 UINTs and initializes it with the numbers 1 through 10:

CUIntArray array;
array.SetSize (10);
for (int i=0; i<10; i++)
array[i] = i + 1;




You can use the same approach to declare an array of CStrings and initialize it with textual representations of the integers 1 through 10:

CStringArray array;
array.SetSize (10);
for (int i=0; i<10; i++) {
CString string;
string.Format (_T ("%d"), i);
array[i] = string;
}




In both cases, SetSize sizes the array to hold 10 elements. In both cases, the overloaded [] operator calls the array's SetAt function, which copies a value to an element at a specified location in the array. And in both cases, the code asserts if the array's bounds are violated. The bounds check is built into the code for SetAt:

ASSERT(nIndex >= 0 && nIndex < m_nSize);




You can see this code for yourself in the MFC source code file Afxcoll.inl.

You can insert items into an array without overwriting the items that are already there by using the InsertAt function. Unlike SetAt, which simply assigns a value to an existing array element, InsertAt makes room for the new element by moving elements above the insertion point upward in the array. The following statements initialize an array with the numbers 1 through 4 and 6 through 10, and then insert a 5 between the 4 and the 6:

CUIntArray array;
array.SetSize (9);
for (int i=0; i<4; i++)
array[i] = i + 1;
for (i=4; i<9; i++)
array[i] = i + 2;
array.InsertAt (4, 5); // Insert a 5 at index 4.




You can also pass a third parameter to InsertAt specifying the number of times the item should be inserted or pass a pointer to another array object in parameter 2 to insert an entire array. Note that this example sets the array size to 9, not 10, yet no assertion occurs when InsertAt is called. That's because InsertAt is one of a handful of array functions that automatically grow the array as new items are added. Dynamically sized arrays are discussed in the next section.

Values can be retrieved from an MFC array using standard array addressing syntax. The following example reads back the UINTs written to the CUIntArray in the previous example:

for (int i=0; i<10; i++)
UINT nVal = array[i];




Used this way, the [] operator calls the array's GetAt function, which retrieves a value from a specified position in the array—with bounds checking, of course. If you'd prefer, you can call GetAt directly rather than use the [] operator.

To find out how many elements an array contains, call the array's GetSize function. You can also call GetUpperBound, which returns the 0-based index of the array's upper bound—the number of elements in the array minus 1.

MFC's array classes provide two functions for removing elements from an array: RemoveAt and RemoveAll. RemoveAt removes one or more items from the array and shifts down any items above the ones that were removed. RemoveAll empties the array. Both functions adjust the array's upper bounds to reflect the number of items that were removed, as the following example demonstrates:

// Add 10 items.
CUIntArray array;
array.SetSize (10);
for (int i=0; i<10; i++)
array[i] = i + 1;

// Remove the item at index 0.
array.RemoveAt (0);
TRACE (_T ("Count = %d\n"), array.GetSize ()); // 9 left.

// Remove items 0, 1, and 2.
array.RemoveAt (0, 3);
TRACE (_T ("Count = %d\n"), array.GetSize ()); // 6 left.

// Empty the array.
array.RemoveAll ();
TRACE (_T ("Count = %d\n"), array.GetSize ()); // 0 left.




The Remove functions delete elements, but they don't delete the objects that the elements point to if the elements are pointers. If array is a CPtrArray or a CObArray and you want to empty the array and delete the objects referenced by the deleted pointers, rather than write

array.RemoveAll ();




you should write this:

int nSize = array.GetSize ();
for (int i=0; i delete array[i];
array.RemoveAll ();




Failure to delete the objects whose addresses are stored in a pointer array will result in memory leaks. The same is true of MFC lists and maps that store pointers.

Dynamic Array Sizing
Besides being bounds-checked, the MFC array classes also support dynamic sizing. You don't have to predict ahead of time how many elements a dynamically sized array should have because the memory set aside to store array elements can be grown as elements are added and shrunk as elements are removed.

One way to dynamically grow an MFC array is to call SetSize. You can call SetSize as often as needed to allocate additional memory for storage. Suppose you initially size an array to hold 10 items but later find that it needs to hold 20. Simply call SetSize a second time to make room for the additional items:

// Add 10 items.
CUIntArray array;
array.SetSize (10);
for (int i=0; i<10; i++)
array[i] = i + 1;

// Add 10 more.
array.SetSize (20);
for (i=10; i<20; i++)
array[i] = i + 1;




When an array is resized this way, the original items retain their values. Thus, only the new items require explicit initialization following a call to SetSize.

Another way to grow an array is to use SetAtGrow instead of SetAt to add items. For example, the following code attempts to use SetAt to add 10 items to an array of UINTs:

CUIntArray array;
for (int i=0; i<10; i++)
array.SetAt (i, i + 1);




This code will assert the first time SetAt is called. Why? Because the array's size is 0 (note the absence of a call to SetSize), and SetAt doesn't automatically grow the array to accommodate new elements. Change SetAt to SetAtGrow, however, and the code works just fine:

CUIntArray array;
for (int i=0; i<10; i++)
array.SetAtGrow (i, i + 1);




Unlike SetAt, SetAtGrow automatically grows the array's memory allocation if necessary. So does Add, which adds an item to the end of the array. The next example is functionally identical to the previous one, but it uses Add instead of SetAtGrow to add elements to the array:

CUIntArray array;
for (int i=0; i<10; i++)
array.Add (i + 1);




Other functions that automatically grow an array to accommodate new items include InsertAt, Append (which appends one array to another), and Copy, which, as the name implies, copies one array to another.

MFC grows an array by allocating a new memory buffer and copying items from the old buffer to the new one. If a grow operation fails because of insufficient memory, MFC throws an exception. To trap such errors when they occur, wrap calls that grow an array in a try block accompanied by a catch handler for CMemoryExceptions:

try {
CUIntArray array;
array.SetSize (1000); // Might throw a CMemoryException.

}
catch (CMemoryException* e) {
AfxMessageBox (_T ("Error: Insufficient memory"));
e->Delete (); // Delete the exception object.
}




This catch handler displays an error message warning the user that the system is low on memory. In real life, more extensive measures might be required to recover gracefully from out-of-memory situations.

Because a new memory allocation is performed every time an array's size is increased, growing an array too frequently can adversely impact performance and can also lead to memory fragmentation. Consider the following code fragment:

CUIntArray array;
for (int i=0; i<100000; i++)
array.Add (i + 1);




These statements look innocent enough, but they're inefficient because they require thousands of separate memory allocations. That's why MFC lets you specify a grow size in SetSize's optional second parameter. The following code initializes the array more efficiently because it tells MFC to allocate space for 10,000 new UINTs whenever more memory is required:

CUIntArray array;
array.SetSize (0, 10000);
for (int i=0; i<100000; i++)
array.Add (i + 1);