What is the recommended way to set the resolution of a webcam using DirectShow?

Q. Why does my DirectShow based video capture application fail to set resolution for the LifeCam VX-6000/VX-3000 webcam when LifeCam software is installed in the system? Is there any way to resolve this issue programmatically?

Here is the code snippet that I am using to set webcam resolution:

 IAMStreamConfig *pConfig = NULL;
 IPin       *pPin = NULL;
 HRESULT hr = 0;
  
 …
 hr = pPin->QueryInterface(IID_IAMStreamConfig, (void**)&pConfig);
 …
  
 if (pConfig != NULL) {
  
     AM_MEDIA_TYPE *mT;
     pConfig->GetFormat(&mT);
  
     if (mT->formattype == FORMAT_VideoInfo) {
         VIDEOINFOHEADER *info = (VIDEOINFOHEADER *)mT->pbFormat;
         info->bmiHeader.biBitCount = 24;
         info->bmiHeader.biWidth = 320;
         info->bmiHeader.biHeight = 240;
     }
  
     hr = pConfig->SetFormat(mT);
 }

A. Here is the proper way to set the webcam resolution that will work regardless of LifeCam software (or any other webcam software) being installed:

 IAMStreamConfig *pConfig = NULL;
 IPin       *pPin = NULL;
 HRESULT hr = 0;
 …
 hr = pPin->QueryInterface(IID_IAMStreamConfig, (void**)&pConfig);
 …
 bool isFormatSet = false;
  
 if (pConfig != NULL) {
     int count, size;
     hr = pConfig->GetNumberOfCapabilities(&count, &size);
     if (FAILED(hr)) return -1;
     BYTE* pSCC = new BYTE[size]; // this we don't care about
     AM_MEDIA_TYPE *mT;
  
     for (int pos = 0; pos < count && !isFormatSet; pos++) {
         hr = pConfig->GetStreamCaps(pos, &mT, pSCC);
         if (FAILED(hr)) return -1;
  
         if (mT->formattype == FORMAT_VideoInfo) {
             VIDEOINFOHEADER *info = (VIDEOINFOHEADER *)mT->pbFormat;
             if (mT->subtype == MEDIASUBTYPE_RGB24 &&
                 info->bmiHeader.biWidth == 320 &&    
                 info->bmiHeader.biHeight == 240) { // you may want to ensure that it's RGB24 too 
             
                 hr = pConfig->SetFormat(mT);
                 if (FAILED(hr)) return -1;
                 isFormatSet = true;
             }
         }
         DeleteMediaType(mT);    // include dshowutil.h
     }
 }

The issue here is that setting the VIH’s width and height is not good enough. There is a bunch of values in the AM_MEDIA_TYPE that would need to be changed to make the original code work.

In the new code, now we are not forcing any format but checking capabilities for different formats of the webcam calling IAMStreamConfig::GetNumberOfCapabilities and then if our required format is supported by the webcam, then switching to the new format using AM_MEDIA_TYPE we got from IAMStreamConfig::GetStreamCaps.