I am new to this news group. I haven't programmed with DirectShow for about
7 years and I forgot everything.
So anyway, I need to capture an image on command. I actually got that much
working. However, the image is a default size of 352 x 240. It needs to be
640 x 480.
So I looked to see how I can change it and I found that I can modify the
CMediaType:
CMediaType *pmt = new CMediaType();
VIDEOINFO *pvi = (VIDEOINFO *)pmt->AllocFormatBuffer(sizeof(VIDEOINFO));
ZeroMemory(pvi, sizeof(VIDEOINFO));
pmt->SetType( &MEDIATYPE_Video );
pmt->SetSubtype(&MEDIASUBTYPE_RGB24);
pvi->bmiHeader.biBitCount = 24;
pvi->bmiHeader.biWidth = 640;
pvi->bmiHeader.biHeight = 480;
pvi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pvi->bmiHeader.biPlanes = 1;
pvi->bmiHeader.biSizeImage = GetBitmapSize(&pvi->bmiHeader);
pvi->bmiHeader.biClrImportant = 0;
hr = pGrabber->SetMediaType( pmt );
I must be missing something because later when I check the size:
AM_MEDIA_TYPE mt;
hr = pGrabber->GetConnectedMediaType( &mt );
VIDEOINFOHEADER * vih = (VIDEOINFOHEADER*) mt.pbFormat;
width = vih->bmiHeader.biWidth;
height = vih->bmiHeader.biHeight;
FreeMediaType( mt );
I find that it has not changed. And also, I can't end or kill the program
without rebooting which is a real time waster.
If I don't try to change the size it works fine. I am sure that I am missing
something somewhere.
Thanks,
Judie
> So anyway, I need to capture an image on command. I actually got that much
> working. However, the image is a default size of 352 x 240. It needs to be
> 640 x 480.
What does your graph look like?
If you are using a capture source like a web cam, you can set the capture
resolution with IAMStreamConfig.
--
Please read this before replying:
1. Dshow & posting help: http://tmhare.mvps.org/help.htm
2. Trim & respond inline (please don't top post or snip everything)
3. Benefit others: follow up if you are helped or you found a solution
Thanks,
Judie
Well, I have tried using the IAMCaptureConfig and still no luck. Here is my
entire code so you can see my obvious mistake! Also please note this is
prototyping code and I know the name of my capture device. LOL.
// CaptureGraph.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
int main(int argc, char* argv[])
{
variant_t nameToSave = "";
bool done = false;
IBaseFilter *pVCap = NULL;
int width = 0, height = 0;
IEnumMoniker *pEm = 0;
ICreateDevEnum *pCreateDevEnum = 0;
//step 1
//this requires preprocessors: _WIN32_DCOM,_WIN32_WINNT=0x0500
// and #include <objbase.h>
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
CComPtr<IGraphBuilder> pGraph = NULL;
HRESULT hr = pGraph.CoCreateInstance( CLSID_FilterGraph );
//Selecting a Capture Device
//Using the System Device Enumerator
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum, (void**)&pCreateDevEnum);
hr =
pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEm,
0);
if(hr != NOERROR)
exit(0);
//look for the device
pEm->Reset();
ULONG cFetched;
IMoniker *pM;
while((!done) && (hr = pEm->Next(1, &pM, &cFetched), hr==S_OK))
{
IPropertyBag *pBag=0;
hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
if(SUCCEEDED(hr))
{
VARIANT var;
var.vt = VT_BSTR;
hr = pBag->Read(L"FriendlyName", &var, NULL);
if(hr == NOERROR)
{
variant_t stringval = var.bstrVal;
CString test = stringval.bstrVal;
if(test.Find("Pinnacle", 0) != -1)
//if(test.Find("Web", 0) != -1)
{
nameToSave = var.bstrVal;
hr = pM->BindToObject(0, 0, IID_IBaseFilter, (void**)&pVCap);
done = true;
}
SysFreeString(var.bstrVal);
pM->AddRef();
}
pBag->Release();
}
pM->Release();
}
pEm->Release();
hr = pGraph->AddFilter(pVCap, nameToSave.bstrVal);
// create a sample grabber
//
CComPtr<ISampleGrabber>pGrabber;
hr = pGrabber.CoCreateInstance( CLSID_SampleGrabber );
if( !pGrabber )
{
}
CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabberF( pGrabber );
if( FAILED( hr ) )
{
exit(0);
}
hr = pGraph->AddFilter(pGrabberF, L"Sample Grabber");
if( FAILED( hr ) )
{
exit(0);
}
// build the graph
CComPtr<ICaptureGraphBuilder2> pBuilder;
hr = pBuilder.CoCreateInstance (CLSID_CaptureGraphBuilder2, NULL,
CLSCTX_INPROC);
if (FAILED( hr ))
{
}
hr = pBuilder->SetFiltergraph( pGraph );
if (FAILED( hr ))
{
}
// If there is a VP pin present on the video device, then put the
// renderer on CLSID_NullRenderer
CComPtr<IPin> pVPPin;
hr = pBuilder->FindPin(
pVCap,
PINDIR_OUTPUT,
&PIN_CATEGORY_VIDEOPORT,
NULL,
FALSE,
0,
&pVPPin);
// If there is a VP pin, put the renderer on NULL Renderer
CComPtr<IBaseFilter> pRenderer;
if (S_OK == hr)
{
hr = pRenderer.CoCreateInstance(CLSID_NullRenderer);
if (S_OK != hr)
{
}
hr = pGraph->AddFilter(pRenderer, L"NULL renderer");
if (FAILED (hr))
{
}
}
hr = pBuilder->RenderStream(
&PIN_CATEGORY_PREVIEW,
&MEDIATYPE_Interleaved,
pVCap,
pGrabberF,
pRenderer);
if (FAILED (hr))
{
// try to render preview pin
hr = pBuilder->RenderStream(
&PIN_CATEGORY_PREVIEW,
&MEDIATYPE_Video,
pVCap,
pGrabberF,
pRenderer);
// try to render capture pin
if( FAILED( hr ) )
{
hr = pBuilder->RenderStream(
&PIN_CATEGORY_CAPTURE,
&MEDIATYPE_Video,
pVCap,
pGrabberF,
pRenderer);
}
}
if( FAILED( hr ) )
{
exit(0);
}
IAMStreamConfig *pSC;
hr = pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,
&MEDIATYPE_Interleaved,
pVCap, IID_IAMStreamConfig, (void **)&pSC);
if(hr != S_OK)
hr = pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,
&MEDIATYPE_Video, pVCap, IID_IAMStreamConfig, (void **)&pSC);
if(hr != NOERROR)
{
}
if(pSC)
{
AM_MEDIA_TYPE *pmt;
hr = pSC->GetFormat(&pmt);
// DV capture does not use a VIDEOINFOHEADER
if(hr == NOERROR)
{
if(pmt->formattype == FORMAT_VideoInfo)
{
VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *)pmt->pbFormat;
pvi->bmiHeader.biBitCount = 24;
pvi->bmiHeader.biWidth = 640;
pvi->bmiHeader.biHeight = 480;
pvi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pvi->bmiHeader.biPlanes = 1;
pvi->bmiHeader.biSizeImage = GetBitmapSize(&pvi->bmiHeader);
pmt->majortype = MEDIATYPE_Video;
pmt->subtype = MEDIASUBTYPE_RGB24;
hr = pSC->SetFormat(pmt);
if(hr != S_OK)
{
//ErrMsg(TEXT("%x: Cannot set new frame rate"), hr);
}
DeleteMediaType(pmt);
}
}
}
// ask for the connection media type so we know how big
// it is, so we can write out bitmaps
//
AM_MEDIA_TYPE mt;
hr = pGrabber->GetConnectedMediaType( &mt );
if ( FAILED( hr) )
{
}
VIDEOINFOHEADER * vih = (VIDEOINFOHEADER*) mt.pbFormat;
width = vih->bmiHeader.biWidth;
height = vih->bmiHeader.biHeight;
FreeMediaType( mt );
// Set one-shot mode and buffering.
hr = pGrabber->SetOneShot(TRUE);
hr = pGrabber->SetBufferSamples(TRUE);
// run the graph
//
CComQIPtr< IMediaControl, &IID_IMediaControl > pControl = pGraph;
hr = pControl->Run( );
if( FAILED( hr ) )
{
exit(0);
}
IMediaEvent *pEvent;
LONG lEvCode = 0;
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **) &pEvent);
pEvent->WaitForCompletion(INFINITE, &lEvCode); // Wait till it's done.
// Find the required buffer size.
long cbBuffer = 0;
hr = pGrabber->GetCurrentBuffer(&cbBuffer, NULL);
//Allocate the array and call the method a second time to copy the buffer:
char *pBuffer = new char[cbBuffer];
if (!pBuffer)
{
// Out of memory. Return an error code.
}
hr = pGrabber->GetCurrentBuffer(&cbBuffer, (long*)pBuffer);
delete [] pBuffer;
//fail:
CoUninitialize();
return 0;
}
"The March Hare [MVP]" wrote:
> I have tried using the IAMCaptureConfig and still no luck. Here is my
> entire code so you can see my obvious mistake!
You're mixing smart pointers and regular ones which is not a good idea.
You're calling IAMStreamConfig after you have already rendered the streams.
I do not know if that will work.
You are not checking whether the capture resolution will work before
setting it.
> Also please note this is
> prototyping code and I know the name of my capture device.
But we don't, and it is potentially useful information. See the link
below.
"Judie Stanley" <JudieS...@discussions.microsoft.com> wrote in message
news:56C0F8FC-DD4F-444C...@microsoft.com...
> On Wed, 18 Jun 2008 13:48:02 -0700, Judie Stanley wrote:
>
> > I have tried using the IAMCaptureConfig and still no luck. Here is my
> > entire code so you can see my obvious mistake!
>
> You're mixing smart pointers and regular ones which is not a good idea.
I did not know I would be judged so harshly. I was cutting and pasting a lot
of sections from various places. It was an evolving process. But, yeah, I
made them all smart pointers now.
>
> You're calling IAMStreamConfig after you have already rendered the streams.
> I do not know if that will work.
I had already tried it before so that is why I tried it after.
>
> You are not checking whether the capture resolution will work before
> setting it.
You are right, that was the root of my issue. It does not support 640 x 480.
The webcam does so I will try that one.
>
> > Also please note this is
> > prototyping code and I know the name of my capture device.
>
> But we don't, and it is potentially useful information.
But I am writing a specific application for a specific hardware
configuration and there is no user interface to select the device so this
makes more sense to me. And I am only prototyping.
See the link
> below.
>
> --
> Please read this before replying:
> 1. Dshow & posting help: http://tmhare.mvps.org/help.htm
> 2. Trim & respond inline (please don't top post or snip everything)
> 3. Benefit others: follow up if you are helped or you found a solution
>
I appreciate your help.
Judie
"Shugo_Ishida" wrote:
> You might want to call IAMStreamConfig::SetFormat, Before RenderStream.
> Basically, when one pin connects to another one, format is fixed. You cannot change it.
I had it that way initially and I was just trying stuff. The fix was to
enumerate through the capabilities then I saw that the capture card could not
do 640 x 480 but the web cam could.
The S-Video card can to 720 x 480. So I will write an algorithm to convert
it to 640 x 480.
Judie
>> You're mixing smart pointers and regular ones which is not a good idea.
>
> I did not know I would be judged so harshly. I was cutting and pasting a lot
> of sections from various places. It was an evolving process. But, yeah, I
> made them all smart pointers now.
That's harshly.. I thought that was just plain good advice.
>> You're calling IAMStreamConfig after you have already rendered the streams.
>> I do not know if that will work.
>
> I had already tried it before so that is why I tried it after.
Again, useful information to put in your post.
>> You are not checking whether the capture resolution will work before
>> setting it.
>
> You are right, that was the root of my issue. It does not support 640 x 480.
> The webcam does so I will try that one.
Thank you for following up.
>>> Also please note this is
>>> prototyping code and I know the name of my capture device.
>>
>> But we don't, and it is potentially useful information.
>
> But I am writing a specific application for a specific hardware
> configuration and there is no user interface to select the device so this
> makes more sense to me. And I am only prototyping.
But, if it is a device someone else here has used, by telling us what it
is, that person might have been able to tell you it didn't support 640x480.
Do you see a pattern here? :)
>
> But, if it is a device someone else here has used, by telling us what it
> is, that person might have been able to tell you it didn't support 640x480.
> Do you see a pattern here? :)
>
I can change the resolution, and it is leading me to believe that I am
changing the bit depth as well, but when I query the actual video info, the
bit depth is not what it should be.
Here is the story:
1) I enumerate the video formats and see which one I like. Then I copy that
to my own VIDEOINFOHEADER.
2) Then I get the IAMStreamConfig and I get the AM_MEDIA_TYPE and I set the
VIDEOINFOHEADER. The HRESULT says OK.
3) Later when I have conntected the ISampleGrabber, I check the
AM_MEDIA_TYPE. I see that the resolution has indeed been changed (so
something happened) however, it set the bit depth to 16 instead of 24!
The device friendly name is "Pinnacle DV/AV Capture"
The resolution I am selecting is 720 x 480 x 24 (initally it is 352 x 240 x
16)
The resolution I see after is 720 x 480 x 16.
If anybody has had a similar experience with this device, I would like to
know.
Thanks,
Judie