|
hmm. I installed both sdk's (sdk WinCE4.2 and sdk WinCE 5)but platform builder refuses to install stating WinCE5 not found. Are you also using WinCE sdk or you are using WinCE as host OS for development along with platform builder? Because in this case I am suspecting platform builder is asking for WinCE as host OS.My apologies for bugging on this issue, but you said you are doing a fresh install of the entire system. My build environment is XP home edition, visual studio .Net 2009, latest windows sdk and windows mobile 5 and 6 sdk.
Thanks,
Mrunal
|
|
|
|
|
thank you for the excellent work.
but please can you post a C# client that capture the video from the camera using the grabber you developed
|
|
|
|
|
Hello all.
I tried to follow the article, but I cannot manage to build a c# client.
Can any body help!!! If you have an example project of a c# client please contact me
Bests.
|
|
|
|
|
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
|
|
|
|
|
is platform builder a mandatory thing to get this code working?
|
|
|
|
|
|
Hi, when i run the application i get unresolved error.
i also need the mulmedia based application can ucontact me for detials.
have a prize for doing some tasks of direct show in windows mobile 6....
contact m_adnan_tariq@hotmail.com
|
|
|
|
|
After compile the sample,i got the error message
SampleGrabber.obj : error LNK2001: unresolved external symbol "public: virtual unsigned long __cdecl CBaseFilter::NonDelegatingRelease(void)" (?NonDelegatingRelease@CBaseFilter@@UAAKXZ)
1>Windows Mobile 5.0 Pocket PC SDK (ARMV4I)\Debug/SampleGrabberFilter.dll : fatal error LNK1120: one unresolved external symbol
could anyone tell me how to solve this problem
|
|
|
|
|
You need to implement this function under windows mobile 5.
|
|
|
|
|
Thanks for your reply.
I don't really understand how "CBaseFilter::NonDelegatingRelease(void)"
work.
Could you please show me an example how to implement the "NonDelegatingRelease" function.
Thanks a lot
|
|
|
|
|
Hi,
NonDelegatingRelease only exists in "Debug"... If you switch to "Release" that problem should dissapear.
Greets
|
|
|
|
|
Dear Mr. Angel Kafazov.
With your great help, finally I got callback~~.
Thank you very very much!!
Still but, I have some problem.
I modified your code as following, because my MPEG4 video clip works properly with RGB555 format only.
HRESULT CSampleGrabber::CheckInputType(const CMediaType *pmt)
{
if( (pmt->majortype == MEDIATYPE_Video) &&
(pmt->subtype == MEDIASUBTYPE_RGB555) &&
(pmt->formattype == FORMAT_VideoInfo) )
{
Report(L"CSampleGrabber::CheckInputType return S_OK\0");
return S_OK;
}
else
{
Report(L"CSampleGrabber::CheckInputType return E_FAIL\0");
return E_FAIL;
}
}
HRESULT CSampleGrabber::SetMediaType(PIN_DIRECTION direction, const CMediaType *pmt)
{
HRESULT hr = S_OK;
VIDEOINFOHEADER* vih = (VIDEOINFOHEADER *) pmt->pbFormat;
TCHAR szInfo[MAX_PATH] = L"\0";
if( (pmt->majortype == MEDIATYPE_Video) &&
(pmt->subtype == MEDIASUBTYPE_RGB555) &&
(pmt->formattype == FORMAT_VideoInfo) &&
(pmt->cbFormat >= sizeof(VIDEOINFOHEADER)) &&
(pmt->pbFormat != NULL) )
{
Report(L"SetMediaType - All conditions are valid.");
DWORD dwStride = (vih->bmiHeader.biWidth * (vih->bmiHeader.biBitCount / 8) + 3) & ~3;
wsprintf(szInfo, L"SetMediaType - biBitCount=%d, dwStride=%d",
vih->bmiHeader.biBitCount, dwStride);
Report(szInfo);
m_Width = vih->bmiHeader.biWidth;
m_Height = vih->bmiHeader.biHeight;
m_SampleSize = pmt->lSampleSize;
m_Stride = (long)dwStride;
wsprintf(szInfo, L"SetMediaType - m_Width=%d, m_Height=%d, mSampleSize=%d, m_Stride=%d",
m_Width, m_Height, m_SampleSize, m_Stride);
Report(szInfo);
}
else
{
fTest = (pmt->subtype == MEDIASUBTYPE_RGB555) ? 1 : 0;
wsprintf(szInfo, L"Invalid - subtype = %d", fTest);
Report(szInfo);
hr = E_FAIL;
}
return hr;
}
And I got the log message as following;
0000: CSampleGrabber::RegisterCallback
0001: CSampleGrabber::CheckInputType return E_FAIL
0002: CSampleGrabber::CheckInputType return E_FAIL
0003: CSampleGrabber::CheckInputType return E_FAIL
0004: CSampleGrabber::CheckInputType return S_OK
0005: CSampleGrabber::CheckInputType return S_OK
0006: SetMediaType - All conditions are valid.
0007: SetMediaType - biBitCount=16, dwStride=352
0008: SetMediaType - m_Width=176, m_Height=144, mSampleSize=50688, m_Stride=352
0009: CSampleGrabber::CheckInputType return S_OK
0010: SetMediaType - All conditions are valid.
0011: SetMediaType - biBitCount=16, dwStride=352
0012: SetMediaType - m_Width=176, m_Height=144, mSampleSize=50688, m_Stride=352
0013: CSampleGrabber::CheckInputType return S_OK
0014: CSampleGrabber::CheckInputType return S_OK
0015: SetMediaType - All conditions are valid.
0016: SetMediaType - biBitCount=16, dwStride=352
0017: SetMediaType - m_Width=176, m_Height=144, mSampleSize=50688, m_Stride=352
When this DLL is worked, the screen on my WindowsMobile 6 device display "There is an error. Divided by 0".
And the callback function is never called.
I think the "Divided by 0 error" is invoked when the "CSampleGrabber::Transform" is called.
But I am not sure.
Sorry for bothering you but, would you give me some advice or help regarding to this error?
Thank you and best regards.
|
|
|
|
|
It looks like the filter negotiated 3 datatypes. This is OK. However, check to see if the filtergraph is running at all and if not, you can check for the error. Did you get the filtergraph running before changing the code?
|
|
|
|
|
Dear Mr. Angel Kafazov.
Thank you so much for your kind reply.
Yes. The filtergraph is running on the test application.
The test application is very simple and following is the code.
It starts in the WinMain() and when it got the callback, simply save the data to the file "Image.dat".
Is there anything I made mistake?
Thank you and best regards.
static void CALLBACK ManagedCallbackProc(BYTE* pData, long len)
{
HANDLE hFile;
DWORD dwWritten;
TCHAR szFileName[MAX_PATH];
wsprintf(szFileName, L"Image.dat");
hFile = ::CreateFile(szFileName, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, 0, NULL);
::WriteFile(hFile, pData, len, &dwWritten, NULL);
::CloseHandle(hFile);
}
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
IGraphBuilder *pGraph = NULL;
ISampleGrabber *pSampleGrabber = NULL;
IMediaControl *pControl = NULL;
IMediaEvent *pEvent = NULL;
LPTSTR szFile = L"\\My Documents\\00475D33819.mp4";
HRESULT hr;
CHK( CoInitializeEx(NULL, COINIT_MULTITHREADED) );
CHK( CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGraph) );
CHK( CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (void **)&pSampleGrabber) );
CHK( pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl) );
CHK( pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent) );
CHK( pGraph->AddFilter((IBaseFilter*)pSampleGrabber, L"SampleGrabber Filter") );
pSampleGrabber->QueryInterface(IID_ISampleGrabber, (void **)&m_pISampleGrabber);
if(m_pISampleGrabber)
{
m_pISampleGrabber->RegisterCallback(&ManagedCallbackProc);
}
CHK( pGraph->RenderFile(szFile, NULL) );
CHK( pControl->Run() );
Sleep(3000);
CHK( pControl->Pause() );
Sleep(1500);
Cleanup:
if(pControl)
pControl->Release();
if(pEvent)
pEvent->Release();
if(pGraph)
pGraph->Release();
if(pSampleGrabber)
pSampleGrabber->Release();
CoUninitialize();
if(FAILED(hr))
{
MessageBox(NULL, L"There are some problems..", L"Info", MB_OK);
return 10;
}
return 0;
}
|
|
|
|
|
Dear Mr. Angel Kafazov.
With adding a line of code ((CMediaType*)(pmt))->ResetFormatBuffer(); to the "CSampleGrabber::SetMediaType", there is no "divided by 0" error.
But, there is no callback call, too.
Would you give me some advice?
I modified it as below;
Thank you and best regards.
HRESULT CSampleGrabber::SetMediaType(PIN_DIRECTION direction, const CMediaType *pmt)
{
HRESULT hr = S_OK;
VIDEOINFOHEADER* vih = (VIDEOINFOHEADER *) pmt->pbFormat;
TCHAR szInfo[MAX_PATH] = L"\0";
if( (pmt->majortype == MEDIATYPE_Video) &&
(pmt->subtype == MEDIASUBTYPE_RGB555) &&
(pmt->cbFormat >= sizeof(VIDEOINFOHEADER)) &&
(pmt->pbFormat != NULL) )
{
VIDEOINFOHEADER* vih = (VIDEOINFOHEADER *) pmt->pbFormat;
Report(L"SetMediaType - All conditions are valid.");
DWORD dwStride = (vih->bmiHeader.biWidth * (vih->bmiHeader.biBitCount / 8) + 3) & ~3;
wsprintf(szInfo, L"SetMediaType - biBitCount=%d, dwStride=%d",
vih->bmiHeader.biBitCount, dwStride);
Report(szInfo);
m_Width = vih->bmiHeader.biWidth;
m_Height = vih->bmiHeader.biHeight;
m_SampleSize = pmt->lSampleSize;
m_Stride = (long)dwStride;
wsprintf(szInfo, L"SetMediaType - m_Width=%d, m_Height=%d, mSampleSize=%d, m_Stride=%d",
m_Width, m_Height, m_SampleSize, m_Stride);
Report(szInfo);
((CMediaType*)(pmt))->ResetFormatBuffer();
}
else
{
hr = E_FAIL;
}
return hr;
}
|
|
|
|
|
Remove the SampleGrabber filter from the graph and test to see if it's running fine.
|
|
|
|
|
Dear Mr. Angel Kafazov.
Yes, of course, if the SampleGrabber is removed, the MPEG4 video clip is played fine.
Thank you for your reply.
|
|
|
|
|
Try removing
((CMediaType*)(pmt))->ResetFormatBuffer();
a set a breakpoint in ::Transform() to see what causes the division by 0.
|
|
|
|
|
Yes. I already made some breakpoints in the "Transform()", but the "Transform()" is never called.
Please let me summarize.
1. When I run following codes;
(a) Video clip is worked fine. There is NO "divide by 0" error.
(b) The "Transform()" and callback function is successfully called.
(c) But the data size which reported by "Size = pMediaSample->GetSize();" in the "Transform()" is much smaller.
(Because of a video clip frame shoud be have the size 176(w)x144(h)x16bit = 50,688bytes. But the "Size" says "1,519"
CSampleGrabber::CheckInputType(const CMediaType *pmt)
{
if (pmt->majortype == MEDIATYPE_Video &&
pmt->formattype == FORMAT_VideoInfo)
return S_OK;
2. When I run following codes;
(a) The "divided by 0" error is occurred.
(b) The "Transform()" and callback function is never called.
(c) But the actual data size which is reported by "m_SampleSize = pmt->lSampleSize;" in the "CSampleGrabber::SetMediaType(PIN_DIRECTION direction, const CMediaType *pmt)" is correct (50,688bytes)
CSampleGrabber::CheckInputType(const CMediaType *pmt)
{
if (pmt->majortype == MEDIATYPE_Video &&
(pmt->subtype == MEDIASUBTYPE_RGB555) &&
pmt->formattype == FORMAT_VideoInfo)
return S_OK;
.....
CSampleGrabber::SetMediaType(PIN_DIRECTION direction, const CMediaType *pmt)
{
HRESULT hr = S_OK;
VIDEOINFOHEADER* vih = (VIDEOINFOHEADER *) pmt->pbFormat;
if(pmt->majortype == MEDIATYPE_Video &&
(pmt->subtype == MEDIASUBTYPE_RGB555) &&
pmt->formattype == FORMAT_VideoInfo &&
pmt->cbFormat >= sizeof(VIDEOINFOHEADER) &&
pmt->pbFormat != NULL)
{
DWORD dwStride = (vih->bmiHeader.biWidth * (vih->bmiHeader.biBitCount / 8) + 3) & ~3;
m_Width = vih->bmiHeader.biWidth;
m_Height = vih->bmiHeader.biHeight;
m_SampleSize = pmt->lSampleSize;
.....
Sorry for bothering you but, your reply will be highly appreciated.
Thank you and best regards.
|
|
|
|
|
Try to find out where does division by 0 occur in the second case.
|
|
|
|
|
Thank you Mr. Angel Kafazov.
As you advise me, now I'm doing my best to find out the point where the "divided by 0" is issued.
But until now, I cannot find out.
I wonder this issue is caused in the DirectShow internal.
But I will keep investigate the cause, and if you have any idea for this, please let me know.
Thank you and best regards.
|
|
|
|
|
|
Hi, akafazov
Thanks for your great post, it gives me a lot of help.
I want to know how did you register the filter on wm6 device?
by code or other way?
BTW, i want to implement a transform filter, but i didn't have wince 5.0 builder platform, that means whether i can't finish this work if i just used windows mobile 6 SDK?
Waiting for your reply!
|
|
|
|
|
I have implemented a transform filter by Windows mobile 6 SDK, but i tried it out on many devices, but no one can work, i wonder the wince platform builder is mandatory?
|
|
|
|
|
Dear akafazov.
First of all, I appreciate your great post.
I made a simple test application using your SampleGrabber.
But there is problem that this simple application cannot get the "callback".
Sorry for bothering you but, would you give some advice for this problem?
And if you possible, may I ask you sample application?
<configurations>
1. Compiler: Microsoft Visual Studio 2005.
2. Target: WindowsMobile 6.
3. Platform builder is installed.
4. "SampleGrabberFilter.dll" has been installed on WindowsMobile 6 device and it was registered using "regsvrce.exe".
5. The "callback" registration is done successfully.
6. The callback function (MyCallbackHandler) never been called.
My main source code is as bellow;
#include "stdafx.h"
#include "SimplePlayer.h"
#include "SimplePlayerDoc.h"
#include "SimplePlayerView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#ifndef CLSID_SampleGrabber
DEFINE_GUID(CLSID_SampleGrabber,
0xad5db5b4, 0xd1ab, 0x4f37, 0xa6, 0xd, 0x21, 0x51, 0x54, 0xb4, 0xec, 0xc1);
DEFINE_GUID(IID_ISampleGrabber,
0x4951bff, 0x696a, 0x4ade, 0x82, 0x8d, 0x42, 0xa5, 0xf1, 0xed, 0xb6, 0x31);
#define SAMPLEGRABBER_NAME L"SampleGrabberFilter"
#undef INTERFACE
#define INTERFACE ISampleGrabber
DECLARE_INTERFACE_(ISampleGrabber, IUnknown) {
STDMETHOD(RegisterCallback)(LPVOID callback) PURE;
};
#endif
ISampleGrabber* m_pSampleGrabber;
IMPLEMENT_DYNCREATE(CSimplePlayerView, CFormView)
BEGIN_MESSAGE_MAP(CSimplePlayerView, CFormView)
ON_COMMAND(ID_MEDIA_SAMPLEGRABBING, &CSimplePlayerView::OnMediaSamplegrabbing)
END_MESSAGE_MAP()
CSimplePlayerView::CSimplePlayerView()
: CFormView(CSimplePlayerView::IDD)
{
if(FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
{
return;
}
}
CSimplePlayerView::~CSimplePlayerView()
{
CoUninitialize();
}
void CSimplePlayerView::DoDataExchange(CDataExchange* pDX)
{
CFormView::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDITREPORT, m_editReport);
}
BOOL CSimplePlayerView::PreCreateWindow(CREATESTRUCT& cs)
{
return CFormView::PreCreateWindow(cs);
}
void CSimplePlayerView::OnInitialUpdate()
{
CFormView::OnInitialUpdate();
}
#ifdef _DEBUG
void CSimplePlayerView::AssertValid() const
{
CFormView::AssertValid();
}
CSimplePlayerDoc* CSimplePlayerView::GetDocument() const
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSimplePlayerDoc)));
return (CSimplePlayerDoc*)m_pDocument;
}
#endif //_DEBUG
void CSimplePlayerView::MyCallbackHandler(BYTE* pData, long len)
{
::MessageBox(NULL, L"Wow!! in the MyCallbackHandler!\r\n",
L"Info", MB_OK | MB_ICONINFORMATION);
}
void CSimplePlayerView::OnMediaSamplegrabbing()
{
HRESULT hr;
TCHAR szFile[MAX_PATH] = L"\0";
OPENFILENAME openFile = {0};
CString strInfo;
openFile.lStructSize = sizeof(OPENFILENAME);
openFile.hwndOwner = GetSafeHwnd();
openFile.lpstrFilter = L"All files\0*.*\0\0";
openFile.nMaxFile = MAX_PATH;
openFile.lpstrFile = szFile;
if(!::GetOpenFileName(&openFile))
{
return;
}
ISampleGrabber* pSampleGrabber = NULL;;
IMediaControl* pMControl = NULL;
IVideoWindow *pVidWin = NULL;
CoCreateInstance(CLSID_FilterGraph,
NULL,
CLSCTX_INPROC,
IID_IGraphBuilder,
(LPVOID *)&m_pGraphicBuilder);
CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC,
IID_IBaseFilter, (void**)&pSampleGrabber);
m_pGraphicBuilder->AddFilter((IBaseFilter*)pSampleGrabber, SAMPLEGRABBER_NAME);
m_pSampleGrabber = NULL;
pSampleGrabber->QueryInterface(IID_ISampleGrabber, (void**)&m_pSampleGrabber);
if(m_pSampleGrabber)
{
m_pSampleGrabber->RegisterCallback(reinterpret_cast<lpvoid>(&CSimplePlayerView::MyCallbackHandler));
MessageBox(L"CALLBACK is successfully installed.\r\n", L"Info",
MB_OK);
}
m_pGraphicBuilder->RenderFile(szFile, NULL);
Sleep(20000);
}
</lpvoid>
modified on Monday, September 8, 2008 9:39 AM
|
|
|
|
|