title: How to get a list of all Microsoft Media Foundation Transforms (MFTs) available on a system
body: <p>I'm a newbie to native development on Windows, but I've been tasked with creating a small app that will list out all the transformers for various video+audio codecs.</p>
  
  <p>Looking at the MSDN documentation, there doesn't seem to be much direct documentation on doing this.  Docs that I've found indicate that this information is stored in the registry (not sure where) so that could be a vector.</p>
  
  <ol>
  <li>Is this possible?</li>
  <li>Generally how should I do it?</li>
  </ol>
  
  <p>Thanks</p>
  
  <p><strong>EDIT:</strong></p>
  
  <p>It does seem that a call to  MFTEnumEx with the parameters of type MFT_REGISTER_TYPE_INFO set to NULL returns a count of 8  </p>
  
  <pre><code>MFTEnumEx(MFT_CATEGORY_VIDEO_DECODER,MFT_ENUM_FLAG_ALL,NULL, NULL, &amp;ppActivate, &amp;count);
  assert(count &gt; 0);
  </code></pre>
  
  <p>Still have to get the actual values though.  But the passed ppActivate param should contain an enumeration of them.</p>
  
  <p><strong>EDIT:</strong>
  It's surprising, but while the count above == 8, there are no video or audio attributes(the video/audio IMFAttributes object is NULL)</p>
  
  <pre><code> IMFAttributes* videoAttributes = NULL;    
          if(SUCCEEDED(hr)){
              hr = pProfile-&gt;GetVideoAttributes(&amp;videoAttributes);
              //If there are no container attributes set in the transcode profile, the GetVideoAttributes method succeeds and videoAttributes receives NULL.
  
          }
  assert(videoAttributes != NULL);  //FAILS!
  </code></pre>
  
  <p><strong>EDIT:</strong></p>
  
  <p>This is a method that pulls all the IMFMediaTypes from the machine(modified call from the book <a href="https://rads.stackoverflow.com/amzn/click/com/B005WZ0SJ6" rel="nofollow noreferrer" rel="nofollow noreferrer">Developing Microsoft® Media Foundation Applications</a>); I then enumerate over them in the caller:</p>
  
  <pre><code>HRESULT CTranscoder::GetVideoOutputAvailableTypes(
      DWORD flags, 
      CComPtr&lt;IMFCollection&gt;&amp; pTypeCollection)
  {
      HRESULT hr = S_OK;
      IMFActivate** pActivateArray = NULL;
      MFT_REGISTER_TYPE_INFO outputType;
      UINT32 nMftsFound = 0;
  
      do
      {
          // create the collection in which we will return the types found
          hr = MFCreateCollection(&amp;pTypeCollection);
          BREAK_ON_FAIL(hr);
  
          // initialize the structure that describes the output streams that the encoders must
          // be able to produce.  In this case we want video encoders - so major type is video, 
          // and we want the specified subtype
          outputType.guidMajorType = MFMediaType_Video;
          outputType.guidSubtype = MFVideoFormat_WMV3;
  
          // get a collection of MFTs that fit the requested pattern - video encoders,
          // with the specified subtype, and using the specified search flags
          hr = MFTEnumEx(
              MFT_CATEGORY_VIDEO_ENCODER,         // type of object to find - video encoders
              flags,                              // search flags
              NULL,                               // match all input types for an encoder
              &amp;outputType,                        // get encoders with specified output type
              &amp;pActivateArray,
              &amp;nMftsFound);
          BREAK_ON_FAIL(hr);
  
          // now that we have an array of activation objects for matching MFTs, loop through 
          // each of those MFTs, extracting all possible and available formats from each of them
          for(UINT32 x = 0; x &lt; nMftsFound; x++)
          {
              CComPtr&lt;IMFTransform&gt; pEncoder;
              UINT32 typeIndex = 0;
  
              // activate the encoder that corresponds to the activation object
              hr = pActivateArray[x]-&gt;ActivateObject(IID_IMFTransform, 
                  (void**)&amp;pEncoder);
  
              // while we don't have a failure, get each available output type for the MFT 
              // encoder we keep looping until there are no more available types.  If there 
              // are no more types for the encoder, IMFTransform::GetOutputAvailableTypes[] 
              // will return MF_E_NO_MORE_TYPES
              while(SUCCEEDED(hr))
              {
                  IMFMediaType* pType;
  
                  // get the avilable type for the type index, and increment the typeIndex 
                  // counter
                  hr = pEncoder-&gt;GetOutputAvailableType(0, typeIndex++, &amp;pType);
                  if(SUCCEEDED(hr))
                  {
                      // store the type in the IMFCollection
                      hr = pTypeCollection-&gt;AddElement(pType);
                  }
              }
          }
      } while(false);
  
      // possible valid errors that may be returned after the previous for loop is done
      if(hr == MF_E_NO_MORE_TYPES  ||  hr == MF_E_TRANSFORM_TYPE_NOT_SET)
          hr = S_OK;
  
      // if we successfully used MFTEnumEx() to allocate an array of the MFT activation 
      // objects, then it is our responsibility to release each one and free up the memory 
      // used by the array
      if(pActivateArray != NULL)
      {
          // release the individual activation objects
          for(UINT32 x = 0; x &lt; nMftsFound; x++)
          {
              if(pActivateArray[x] != NULL)
                  pActivateArray[x]-&gt;Release();
          }
  
          // free the memory used by the array
          CoTaskMemFree(pActivateArray);
          pActivateArray = NULL;
      }
  
      return hr;
  }
  </code></pre>
  
  <p>Caller:</p>
  
  <pre><code>    hr=transcoder.GetVideoOutputAvailableTypes( MFT_ENUM_FLAG_ALL, availableTypes);
      if (FAILED(hr)){
          wprintf_s(L"didn't like the printVideoProfiles method");
      }
  
      DWORD availableInputTypeCount =0;
      if(SUCCEEDED(hr)){
          hr= availableTypes-&gt;GetElementCount(&amp;availableInputTypeCount);
      }
      for(DWORD i = 0; i&lt; availableInputTypeCount  &amp;&amp; SUCCEEDED(hr); i++)
      {
  
          //really a IMFMediaType*
          IMFAttributes* mediaInterface = NULL;
              if(SUCCEEDED(hr)){
                  hr = availableTypes-&gt;GetElement(i, (IUnknown**)&amp;mediaInterface) ;}
  
              if(SUCCEEDED(hr)){ 
                  //see http://msdn.microsoft.com/en-us/library/aa376629(v=VS.85).aspx for a list of attributes to pull off the media interface.
  
                  GUID majorType;
                  hr = mediaInterface-&gt;GetGUID(MF_MT_MAJOR_TYPE, &amp;majorType);
                  LPOLESTR majorGuidString = NULL;
                  hr = StringFromCLSID(majorType,&amp;majorGuidString);
                  wprintf_s(L"major type: %s \n", majorGuidString);
                  wprintf_s(L"is a video? %i \n", IsEqualGUID(MFMediaType_Video,majorType));
  
                  GUID subType;
                  if(SUCCEEDED(mediaInterface-&gt;GetGUID(MF_MT_SUBTYPE, &amp;subType))){
                      LPOLESTR minorGuidString = NULL;
                      if(SUCCEEDED(StringFromCLSID(subType,&amp;minorGuidString)))
                          wprintf_s(L"subtype: %s \n", minorGuidString);
                  }
  
                  //Contains a DirectShow format GUID for a media type: http://msdn.microsoft.com/en-us/library/dd373477(v=VS.85).aspx
                  GUID formatType;
                  if(SUCCEEDED(mediaInterface-&gt;GetGUID(MF_MT_AM_FORMAT_TYPE, &amp;formatType))){
                      LPOLESTR formatTypeString = NULL;
                      if(SUCCEEDED(StringFromCLSID(formatType,&amp;formatTypeString)))
                          wprintf_s(L"format type: %s \n", formatTypeString);
                  }
  
                  UINT32 numeratorFrameRate = 0;
                  UINT32 denominatorFrameRate = 0;
                  if(SUCCEEDED(MFGetAttributeRatio(mediaInterface, MF_MT_FRAME_RATE, &amp;numeratorFrameRate, &amp;denominatorFrameRate)))
                      wprintf_s(L"framerate: %i/%i \n", numeratorFrameRate, denominatorFrameRate);
  
                  UINT32 widthOfFrame = 0;
                  UINT32 heightOfFrame = 0;
                  if(SUCCEEDED(MFGetAttributeSize(mediaInterface, MF_MT_FRAME_SIZE, &amp;widthOfFrame, &amp;heightOfFrame)))
                      wprintf_s(L"height of frame: %i width of frame: %i \n", heightOfFrame, widthOfFrame);
  
                  UINT32 isCompressedP = 0;
                  if(SUCCEEDED(mediaInterface-&gt;GetUINT32(MF_MT_COMPRESSED, &amp;isCompressedP)))
                      wprintf_s(L"is media compressed? %iu \n", (BOOL)isCompressedP);
  
                  BOOL isCompressedP2 = 0;
                  if(SUCCEEDED((((IMFMediaType*)mediaInterface)-&gt;IsCompressedFormat(&amp;isCompressedP2))))
                      wprintf_s(L"is media compressed2? %i \n", isCompressedP2);
  
                  UINT32 fixedSampleSizeP = 0;
                  if(SUCCEEDED(mediaInterface-&gt;GetUINT32(MF_MT_FIXED_SIZE_SAMPLES, &amp;fixedSampleSizeP)))
                      wprintf_s(L"is fixed sample size? %iu \n", fixedSampleSizeP);
  
                  UINT32 sampleSize = 0;
                  if(SUCCEEDED(mediaInterface-&gt;GetUINT32(MF_MT_SAMPLE_SIZE, &amp;sampleSize)))
                      wprintf_s(L"sample size: %iu \n", sampleSize);
  
                  UINT32 averateBitrate = 0;
                  if(SUCCEEDED(mediaInterface-&gt;GetUINT32(MF_MT_AVG_BITRATE, &amp;averateBitrate)))
                      wprintf_s(L"average bitrate: %iu \n", averateBitrate);
  
                  UINT32 aspectRatio = 0;
                  if(SUCCEEDED(mediaInterface-&gt;GetUINT32(MF_MT_PAD_CONTROL_FLAGS, &amp;aspectRatio)))
                      wprintf_s(L"4 by 3? %i  16 by 9? %i None? %i \n", aspectRatio == MFVideoPadFlag_PAD_TO_4x3, MFVideoPadFlag_PAD_TO_16x9 == aspectRatio, MFVideoPadFlag_PAD_TO_None == aspectRatio);
  
                  UINT32 drmFlag = 0;
                  if(SUCCEEDED(mediaInterface-&gt;GetUINT32(MF_MT_DRM_FLAGS, &amp;drmFlag)))
                      wprintf_s(L"requires digital drm: %i requires analog drm: %i  requires no drm: %i", drmFlag == MFVideoDRMFlag_DigitallyProtected, drmFlag == MFVideoDRMFlag_AnalogProtected, MFVideoDRMFlag_None == drmFlag);
  
                  UINT32 panScanEnabled = 0;
                  if(SUCCEEDED(mediaInterface-&gt;GetUINT32(MF_MT_PAN_SCAN_ENABLED, &amp;panScanEnabled)))
                      wprintf_s(L"pan/scan enabled? %i", panScanEnabled);
  
                  UINT32 maxFrameRateNumerator = 0;
                  UINT32 maxFrameRateDenominator = 0;
                  if(SUCCEEDED(MFGetAttributeRatio(mediaInterface, MF_MT_FRAME_RATE_RANGE_MAX, &amp;maxFrameRateNumerator, &amp;maxFrameRateDenominator)))
                      wprintf_s(L"max framerate range: %i/%i \n", maxFrameRateNumerator, maxFrameRateDenominator);
  
              }
  
      }
  </code></pre>
  
  <p>It's getting some attributes from the IMFMediaInterface, but not many attributes are set and 
   the call to <code>mediaInterface-&gt;GetUINT32(MF_MT_COMPRESSED, &amp;isCompressedP)</code> isn't successful but the call to <code>(IMFMediaType*)mediaInterface)-&gt;IsCompressedFormat(&amp;isCompressedP2)</code> is, which makes me wonder if I'm doing it wrong.</p>