Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

DirectShow live capture - how to change width/height

327 views
Skip to first unread message

Stanley@discussions.microsoft.com Judie Stanley

unread,
Jun 18, 2008, 12:52:01 PM6/18/08
to
Hi Everybody!

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

The March Hare [MVP]

unread,
Jun 18, 2008, 1:03:06 PM6/18/08
to
On Wed, 18 Jun 2008 09:52:01 -0700, Judie Stanley wrote:

> 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

Judie Stanley

unread,
Jun 18, 2008, 1:19:01 PM6/18/08
to
OK, I will try that and let you know.

Thanks,

Judie

Judie Stanley

unread,
Jun 18, 2008, 4:48:02 PM6/18/08
to
Hi again,

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:

The March Hare [MVP]

unread,
Jun 18, 2008, 5:09:24 PM6/18/08
to
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.

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.

Shugo_Ishida

unread,
Jun 19, 2008, 7:18:43 AM6/19/08
to
You might want to call IAMStreamConfig::SetFormat, Before RenderStream.
Basically, when one pin connects to another one, format is fixed. You cannot change it.

"Judie Stanley" <JudieS...@discussions.microsoft.com> wrote in message
news:56C0F8FC-DD4F-444C...@microsoft.com...

Judie Stanley

unread,
Jun 19, 2008, 3:34:00 PM6/19/08
to
"The March Hare [MVP]" wrote:

> 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

Judie Stanley

unread,
Jun 19, 2008, 3:37:00 PM6/19/08
to

"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

The March Hare [MVP]

unread,
Jun 23, 2008, 1:46:43 PM6/23/08
to
On Thu, 19 Jun 2008 12:34:00 -0700, Judie Stanley wrote:

>> 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? :)

Judie Stanley

unread,
Jun 24, 2008, 5:24:00 PM6/24/08
to
"The March Hare [MVP]" wrote:

>
> 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

0 new messages