|
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
|
|
|
|
|
Dear akafazov:
1.CoCreateInstance
2.pGraphBuilder->AddFilter
3.pSampleGrabber->QueryInterface
4.m_pISampleGrabber->RegisterCallback
compile ok ,too.
.exe run ok,too.
but ,how i get data byte,where?
thanks!
my msn wmbarcode at live.cn
|
|
|
|
|
Hello, CH001.
May I ask you to post or send the email your sample client application to me (anold54@chol.com)?
I try to use this greate SampleGrabber, but I cannot compile until now, and I cannot find why.
I am looking forward your reply.
Thank you.
|
|
|
|
|
The data arrives at your callback function, the one that you register using RegisterCallback, when the graph is running.
|
|
|
|
|
I'm using VS 2008, targeting WM5, and trying to instantiate the SampleGrabber filter directly (that is, not going through the registry).
I find the CUnknown (from strmbase.lib provided w/ VS2008) does not set the "outer unknown" pointer in construction, so the first call to QueryInterface on my instance, as defined in the DECLARE_IUNKNOWN macro fails, because the implementation ( return GetOwner()->QueryInterface(riid,ppv); ) fails when GetOwner returns NULL.
I've tried endless ways to hack around this, with no luck.
Has anybody gotten this to work on WM5?
I'm also going to try get the "Platform Builder" in hopes of finding source to CUnknown to see if I can spot (and fix?) a bug.
Thanks
JM
|
|
|
|
|
I think you need Platform Builder to resolve this error. The code really doesn't work without it.
|
|
|
|
|
thx for the reply. Can you be more specific?
I'm getting strmbase.lib and the .h from the VS2008 installation.
I've been working to install platform builder; have installed "Windows CE" but the platform buidler included didn't have the dshow base classes. My goal was to inspect the CUnknown source.
Pls advise what you mean by "doesn't work without it," I'm getting successful compile/link, what would be different for me w/ the PB?
Thanks
|
|
|
|
|
Use the strmbase.lib from the platform builder. E.g.
E:\WINCE500\PUBLIC\DIRECTX\SDK\LIB\ARMV4I\DEBUG\strmbase.lib
if Platform Builder is installed in E:\WINCE500
|
|
|
|
|
OK, thanks. I finally got that stuff downloaded and installed... took a few steps, got "Armv4I not installed" even after I installed WinCE, had to augment the WinCE installation to select Arm, etc... I won't bore you further with that.
I'll try that alternative lib, assuming I can coerce VS9 to use it, and see if it makes a diff. After that, I'll probably see about confirming/fixing the problem I suspect in CUnknown source.
I think a lot of people would be happy to be able to build this filter in their App and use it directly, without suffering the CoCreateInstance stuff. I have a MS link suggesting that... use 'new' or (really, the equivalent) CSampleGrabber::CreateInstance, then QueryInterface to IBaseFilter, and (if there is a merciful God) plugging it into the filter graph between camera capture and preview/render...
From postings I've seen, I'm not the only guy who wants to snarf something out of mobile video images.
thx again. will report back in a few hours; if you're in Deutschland, you'll probably see it late or tomorrow.
|
|
|
|
|
I've got an error at this line
SUCCEEDED(hr=CoCreateInstance( CLSID_SampleGrabber, NULL, CLSCTX_INPROC, IID_IBaseFilter, (LPVOID *)&m_pSampleGraber)
Can you post me the demo application(galenpee@hotmail.com)?
Thanks a lot~
|
|
|
|
|