Metadata Providers in Windows Vista

In Windows Vista, Microsoft Media Foundation exposes metadata through the IMFMetadata interface.

Reading Metadata

To read metadata from a media source, perform the following steps:

  1. Get a pointer to the IMFMediaSource interface of the media source. You can use the IMFSourceResolver interface to get an IMFMediaSource pointer.
  2. Call IMFMediaSource::CreatePresentationDescriptor to get the media source's presentation descriptor.
  3. Call MFGetService on the media source to get a pointer to the IMFMetadataProvider interface. In the guidService parameter of MFGetService, specify the value MF_METADATA_PROVIDER_SERVICE. If the source does not support the IMFMetadataProvider interface, MFGetService returns MF_E_UNSUPPORTED_SERVICE.
  4. Call IMFMetadataProvider::GetMFMetadata and pass in a pointer to the presentation descriptor. This method returns a pointer to the IMFMetadata interface.
    • To get stream-level metadata first call IMFStreamDescriptor::GetStreamIdentifier to get the stream identifier. Then pass the stream identifier in the dwStreamIdentifier parameter of GetMFMetadata.
    • To get presentation-level metadata, set dwStreamIdentifier to zero.
  5. [Optional] Call IMFMetadata::GetAllLanguages to get a list of the languages in which metadata is available. Languages are identified using RFC 1766-compliant language tags.
  6. [Optional] Call IMFMetadata::SetLanguage to select the language.
  7. [Optional] Call IMFMetadata::GetAllPropertyNames to get a list of the names of all the metadata properties for this stream or presentation.
  8. Call IMFMetadata::GetProperty to get a specific metadata property value, passing in the name of the property.

The following code shows steps 2–4:

HRESULT GetMetadata(
    IMFMediaSource *pSource, IMFMetadata **ppMetadata, DWORD dwStream = 0)
{
    IMFPresentationDescriptor *pPD = NULL;
    IMFMetadataProvider *pProvider = NULL;

    HRESULT hr = pSource->CreatePresentationDescriptor(&pPD);
    if (FAILED(hr))
    {
        goto done;
    }

    hr = MFGetService(
        pSource, MF_METADATA_PROVIDER_SERVICE, IID_PPV_ARGS(&pProvider));

    if (FAILED(hr))
    {
        goto done;
    }

    hr = pProvider->GetMFMetadata(pPD, dwStream, 0, ppMetadata);

done:
    SafeRelease(&pPD);
    SafeRelease(&pProvider);
    return hr;
}

The following code shows steps 7–8. Assume that DisplayProperty is a function that displays a PROPVARIANT value.

HRESULT DisplayMetadata(IMFMetadata *pMetadata)
{
    PROPVARIANT varNames;
    HRESULT hr = pMetadata->GetAllPropertyNames(&varNames);
    if (FAILED(hr))
    {
        return hr;
    }

    for (ULONG i = 0; i < varNames.calpwstr.cElems; i++)
    {
        wprintf(L"%s\n", varNames.calpwstr.pElems[i]);

        PROPVARIANT varValue;
        hr = pMetadata->GetProperty( varNames.calpwstr.pElems[i], &varValue );
        if (SUCCEEDED(hr))
        {
            DisplayProperty(varValue);
            PropVariantClear(&varValue);
        }
    }

    PropVariantClear(&varNames);
    return hr;
}

Media Metadata

Shell Metadata Providers