sipsorcery's blog

Occassional posts about VoIP, SIP, WebRTC and Bitcoin.

sipsorcery.com response times SIP Sorcery Last 3 Hours
daily weekly
sipsorcery.com status

Building a video softphone part II

Got the video device enumeration code working, at least well enough for it to tell me my webcam is a Logitech QuickCam Pro 9000. The working code is below.

#include "stdafx.h"
#include <mfapi.h>
#include <mfplay.h>
#include "common.h"

HRESULT CreateVideoDeviceSource(IMFMediaSource **ppSource);

int _tmain(int argc, _TCHAR* argv[])
{
  printf("Get webcam properties test console.n");

  CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);

  IMFMediaSource *ppSource = NULL;

  CreateVideoDeviceSource(&ppSource);

  getchar();

  return 0;
}

HRESULT CreateVideoDeviceSource(IMFMediaSource **ppSource)
{
  *ppSource = NULL;

  UINT32 count = 0;

  IMFAttributes *pConfig = NULL;
  IMFActivate **ppDevices = NULL;

  // Create an attribute store to hold the search criteria.
  HRESULT hr = MFCreateAttributes(&pConfig, 1);

  // Request video capture devices.
  if (SUCCEEDED(hr))
  {
    hr = pConfig->SetGUID(
      MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
      MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
    );
  }

  // Enumerate the devices,
  if (SUCCEEDED(hr))
  {
    hr = MFEnumDeviceSources(pConfig, &ppDevices, &count);
  }

  printf("Device Count: %i.n", count);

  // Create a media source for the first device in the list.
  if (SUCCEEDED(hr))
  {
    if (count > 0)
    {
      hr = ppDevices[0]->ActivateObject(IID_PPV_ARGS(ppSource));

      if (SUCCEEDED(hr))
      {
        WCHAR *szFriendlyName = NULL;

        // Try to get the display name.
        UINT32 cchName;
        hr = ppDevices[0]->GetAllocatedString(
          MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME,
          &szFriendlyName, &cchName);

        if (SUCCEEDED(hr))
        {
          wprintf(L"Device Name: %s.n", szFriendlyName);
        }
        else
        {
          printf("Error getting device attribute.");
        }

        CoTaskMemFree(szFriendlyName);
      }
    }
    else
    {
      hr = MF_E_NOT_FOUND;
    }
  }

  for (DWORD i = 0; i < count; i++)
  {
    ppDevices[i]->Release();
  }
  CoTaskMemFree(ppDevices);
  return hr;
}

The problem I had previously was a missing call to CoInitializeEx. It seems it’s needed to initialise things to allow the user of COM libraries.

The next step is now to work out how to get a sample from the webcam.