|
Thanks for your feedback =D
[Status]
Problem solved. Silly mistake was that the PIN was set to preview instead of capture. After changing it to PIN_CATEGORY_CAPTURE the resolution size was able to be set. Reasons in detail I'm not too sure. However attempts to change the subtype failed, therefore the default YV12 was used.
"CHK( m_pCaptureGraphBuilder->RenderStream( &PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, m_pVideoCaptureFilter, pH263Transform, NULL ) );"
As for the distortion, it is still an issue. Let me explain abit more, as I did not use the callback function. The process of saving the bmp file was done in CSampleGrabber::Transform function. The code I had added is as follows:
"HANDLE fh = CreateFile(filePath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, NULL, NULL);
BITMAPFILEHEADER bfh;
memset(&bfh, 0, sizeof(bfh));
bfh.bfType = 'MB';
bfh.bfSize = sizeof(bfh) + sizeof(BITMAPINFOHEADER) + lSize;
bfh.bfOffBits = sizeof(bfh) + sizeof(BITMAPINFOHEADER);
DWORD nWritten = 0;
WriteFile(fh, &bfh, sizeof(bfh), &nWritten, NULL);
BITMAPINFOHEADER bih;
memset(&bih, 0, sizeof(bih));
bih.biSize = sizeof(bih);
bih.biWidth = m_Width;
bih.biHeight = m_Height;
bih.biPlanes = 1;
bih.biClrImportant = 0;
bih.biClrUsed = 0;
bih.biBitCount = (WORD)m_Bit;
nWritten = 0;
WriteFile(fh, &bih, sizeof(bih), &nWritten, NULL);
nWritten = 0;
WriteFile(fh, pCurrentBits, lSize, &nWritten, NULL);
CloseHandle(fh);"
The values for m_Width, m_Height and m_Bit are derived when the function CSampleGrabber::SetMediaType is called. Currently subtype MEDIASUBTYPE_RGB565 is used instead of MEDIASUBTYPE_YV12. In RGB565 the video preview is perfect, but when YV12 is used the video window merely appears as a black box.
Once again, any comments and advice is greatly appreciated.
|
|
|
|
|
Renderstream automatically inserts a color converter filter after your video capture filter. That will automatically convert your YV12 to RGB565 format. No other possible conversion are available for YV12 format except RGB565.
|
|
|
|
|
[Question]
Does that mean in the given scenario below:
"RenderStream( &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pVideoCaptureFilter, pH263Transform, NULL )"
A color filter is inserted after m_pVideoCaptureFilter?
[Status]
I tried checking and permitting MEDIASUBTYPE_YV12 in functions
CSampleGrabber::CheckInputType and CSampleGrabber::SetMediaType, but the application will crash when capturing is started. I am able to capture a couple of files before it crashes, and with the use of a yuv viewer, I discovered that the UV properties were inverted causing color distortion. Given the same scenario, and MEDIASUBTYPE_RGB565 is used, the preview and application is fine. However, the file captured is badly distorted.
I suspect that CSampleGrabber might be recieving RGB565 and I am not saving it properly into a bmp file.
Please advice me on an approach to capture the frame.
Sincerely appreciate your prompt response.
|
|
|
|
|
Yes using
RenderStream( &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pVideoCaptureFilter, pH263Transform, NULL )
will automatically insert a color converter filter inside. You only need to check for RGB565 images. The color converter filter will be inserted between the videocapturefilter and the samplegrabber.
|
|
|
|
|
Thanks for the info.
[Status]
Could not figure out how to set to a format needed, thus stayed with RGB565 16bit. Managed to save the frame to bmp file format.
And thats a WRAP! =D
Thanks once again for your assistance.
|
|
|
|
|
To say the truth, most phones only have 1 available format. E.g if your phone doesn't have RGB24, it is not possible for you to set it at all.
If you do not wish to stick to RGB565, you can try to connect the pins between the filters without RenderStream. It will allow you to use the YV12 format. Only drawback of this is that, you have to specifically obtain the pins of the rendering filter to get a preview.
|
|
|
|
|
Hi there,
I am trying to use the FrameGrabber in my own Project, however I have stumbled upon a problem.
I am using RenderStream() to connect the videoCaptureFilter with the SampleGrabber filter like so:
hr=_captureGraphBuilder->RenderStream(&PIN_CATEGORY_PREVIEW,&MEDIATYPE_Video,_videoCaptureFilter,pSampleGrabber, NULL);
Running this on a Windows Mobile Emulator works just fine. On an actual device however(HTC HD2 for example) this does not work and returns E_FAIL.
Does anyone have any ideas as to the reason for this behaviour?
Thanks for your help!
|
|
|
|
|
The RenderStream function should be working fine, unless your HTC HD2 does not have a preview pin, which is not very possible. It is best for you to post the whole section of your code where you initialized your samplegrabber before we can help to analyze the problem for you. It might be also possible that your samplegrabber is not initialized, but then the same problem will happen to the emulator as well.
|
|
|
|
|
Hi,
Encountered the same problem initially, but have been reading through the posts and got it to preview on the actual device (HTC HD2).
Modifications made were just to the RGB type. Can't remember where the modifications are so you might need to do a find for [PixelFormat.Format24bppRgb].
"PixelFormat.Format24bppRgb -> PixelFormat.Format16bppRgb565"
Hope this helps.
|
|
|
|
|
hi,
at first, thanks a lot for your work, I can now grab frame data on my HTC HD2!
But the problem is that the dll is only using the smallest possible resolution. I saw that in CGraphManager::StartCaptureFramesInternal() there are already these lines of code, which seem to be the beginning of a resolution-changing algorithm:
CComPtr<IAMStreamConfig> pConfig;
int iCount = 0;
int iSize = 0;
int dwId = 0;
If added the following code after that:
dwId = 7;
hr = m_pCaptureGraphBuilder->FindInterface(NULL, &MEDIATYPE_Video,
m_pVideoCaptureFilter, IID_IAMStreamConfig, (void**)&pConfig);
hr = pConfig->GetNumberOfCapabilities(&iCount, &iSize);
if (SUCCEEDED(hr) && (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS)) && (dwId < iCount))
{
VIDEO_STREAM_CONFIG_CAPS scc;
AM_MEDIA_TYPE *pmtConfig;
hr = pConfig->GetStreamCaps(dwId, &pmtConfig, (BYTE*)&scc);
if (SUCCEEDED(hr))
{
hr = pConfig->SetFormat(pmtConfig);
DeleteMediaType(pmtConfig);
}
}
Everything seems to be alright, and when I go through that part in debugging, I get for example a resolution of 320x240 in scc for dwId = 7, which should be ok. The only problem is that the resolution of my output image stays the same tiny one, no matter what I do!
Do you know what I am doing wrong?
|
|
|
|
|
Nothing is wrong with your code. I think the problem in your case lies in the fact that you did not resize your picturebox or panel, which might be why the resolution remains at 176x144.
Further possible problems is that you tried to change your resolution while your graph is running. Ensure that your graph is stopped before you change resolution.
modified on Sunday, October 24, 2010 2:44 AM
|
|
|
|
|
Hi All,
Firstly, Thanks to the author for the sample code !!!
I am having the following error while trying to compile this code:
unresolved external symbol "public: virtual unsigned long __cdecl CBaseFilter::NonDelegatingRelease(void)"
Angel has mentioned that version "26.08.2008 v1.1 Created. " has the NonDelegatingRelease added, but am unable to locate the source. Any help would be useful.
Best,
Surya
|
|
|
|
|
I am also having this same problem. Any help would be great.
Linda
|
|
|
|
|
add the following code to your CSampleGrabber public method declaration.
ULONG CBaseFilter::NonDelegatingRelease(void)
{
return 1;
}
|
|
|
|
|
hi everybody,
this is my sample code
IGraphBuilder *pGraph;
IBaseFilter *pGrabberF;
ISampleGrabber *pGrabber;
// create the Sample Grabber filter.
1) hr = CoCreateInstance( CLSID_GrabberSample, NULL, CLSCTX_INPROC,
IID_IBaseFilter, (void**)&pGrabberF);
if(FAILED(hr))
goto done;
2) hr = pGraph->AddFilter(pGrabberF, L"Sample Grabber");
if(FAILED(hr))
goto done;
//get a point to the interface
hr = pGrabberF->QueryInterface(IID_IGrabberSample, (void **)&pGrabber);
if(FAILED(hr))
goto done;
i just want to instantiate pGrabberF. the fact is that it always fails in step 1 in
debug modle.does anyone know how to solve the problem?
thanks a lot!
|
|
|
|
|
If it hangs at step 1, most likely its the way you defined your CLSID_GrabberSample. Check your code and make sure you don't call "initguid.h" more than 2 times. If you already included "initguid.h" in your grabbersample's .h or .cpp file, then make sure you don't call it again in your main program.
|
|
|
|
|
it still doesn't work. the architecture of files like this
grabber.h inclues initguid.h file and CLSID_GrabberSample is only defined in it.
the code
hr = CoCreateInstance( CLSID_GrabberSample, NULL,
CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pGrabberF);
if(FAILED(hr))
goto done;
is written in framegrabber.cpp file. grabber.h is inclued in framegrabber.h.
i am a beginner in directshow, could you give me some details suggestion about
the problem if you know.
thank you!
|
|
|
|
|
Ok, try this combination instead:
in grabber.h, define your GUID (CLSID_GrabberSample)
in grabber.cpp, include the "initguid.h" then follow by the grabber.h
in framegrabber.h, include grabber.h
|
|
|
|
|
hi, i did as what you said and it didn't work.
i gonna be crazy. is there any reasons that can cause
this problem?
modified on Monday, May 3, 2010 4:37 AM
|
|
|
|
|
It's a clear case of the filter not being able to initialize properly. The CLSID should be registered, but the relevant constructor for the filter is not setup properly. In my case, I turned on MFC support. Go to Project Properties->Configuration Properties->General->Project Defaults->Use of MFC. Set to Use MFC in Static Library.
If it still doesnt work, change your filters to CComPtr like this with MFC still turn on:
CComPtr<IBaseFilter> GrabberFilter;
CComPtr<ISampleGrabber> I_SampleGrabber;
GrabberFilter.CoCreateInstance(CLSID_SampleGrabber);
m_pFilterGraph->AddFilter( GrabberFilter, L"Sample Grabber" );
GrabberFilter->QueryInterface( IID_ISampleGrabber, (void**)&I_SampleGrabber );
|
|
|
|
|
that's very kind of you. but i have some confusion.
register CLSID?
i don't know how to register. there are these function and relevant
resource information in program.
STDAPI DllRegisterServer()
{
return AMovieDllRegisterServer2(TRUE);
}
STDAPI DllUnregisterServer()
{
return AMovieDllRegisterServer2(FALSE);
}
extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
BOOL APIENTRY DllMain(HANDLE hModule,
DWORD dwReason,
LPVOID lpReserved)
{
return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved);
}
......
i wonder whether the filter will be registed dynamicly or should i call
some function to register.
and i have already set project properties->configuration properties->deployment->register out to yes.
|
|
|
|
|
Well, DllRegisterServer and DllUnregisterServer are steps for you to register your filter into a DLL. As for the steps to register a filter into a DLL, you can read it up in MSDN, cause it will be too long for me to explain it here. But nevertheless, those aren't really neccessary if your filter is only used within your project scope.
For now, I would just recommend you to set the MFC setting as recommended in my previous post and see if you can create your filter. I used to have problems initializing new filters when I did not turn on MFC support.
|
|
|
|
|
i know what cause failure.
after executing the statement
hr = CoCreateInstance(CLSID_GrabberSample, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (void**)&pGrabberF);
hr=-2147221164 and it means class not registered.
should i register SampleGrabber filter and CLSID_GrabberSample by hand?
|
|
|
|
|
If you don't intend to export your samplegrabber to other applications or projects, then you do not need to register them into a DLL, but you also cannot use CoCreateInstance like what you have written. If you are using the original SampleGrabber produced by Angel Kafazov, it will have the factory and pin settings already written for you to compile it to a DLL. But most importantly, I do hope you did include a export.def which specifies methods for loading the DLL. In addition to that, you need to declare methods like :
STDAPI DllRegisterServer(void)
{
HRESULT hr = AMovieDllRegisterServer2( TRUE );
return hr;
}
STDAPI DllUnregisterServer()
{
return AMovieDllRegisterServer2( FALSE );
}
BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
It will be best for you to read it up on MSDN http://msdn.microsoft.com/en-us/library/dd389096%28v=VS.85%29.aspx[^]
If you think the steps for creating a Filter Dll is too difficult. You can choose not to register the filter. You won't be able to initialize the filter using CoCreateInstance but you can initialize it using other means:
IBaseFilter* SampleGrabber;
HRESULT hr;
SampleGrabber = new CSampleGrabber(Null, &hr, FALSE);
m_pFilterGraph->AddFilter(SampleGrabber, L"Grabber Filter");
|
|
|
|
|
IBaseFilter* SampleGrabber;
HRESULT hr;
SampleGrabber = new CSampleGrabber(Null, &hr, FALSE);
m_pFilterGraph->AddFilter(SampleGrabber, L"Grabber Filter");
this method i did before. but my callback function wasn't called
,so i couldn't get data and save it to disk.
|
|
|
|
|