Metadata

Media FoundationでMetadataを読み込むには、下表の2つの方法があります。

  IPropertyStore
(Shell metadata)
IMFMetadata
(Media Foundation v1 Metadata)
対応OS Windows 7以降 Windows Vista以降
シェル プロパティ システムとの互換性 ×
ファイル レベルのプロパティ
ストリーム レベルのプロパティ ×
多言語のプロパティ ×
プロパティのキーの指定方法 PROPERTYKEYの値 ワイド文字の文字列
プロパティの値 PROPVARIANTの値 PROPVARIANTの値
Media Metadata - Win32 apps | Microsoft Learn

IPropertyStoreインターフェイス

SHGetPropertyStoreFromParsingName()

指定パスのIPropertyStoreを取得できます。

SHSTDAPI SHGetPropertyStoreFromParsingName(
  PCWSTR                pszPath, // パス
  IBindCtx              *pbc,    // bind contextへのアクセスを提供するIBindCtxへのポインタ。NULLでも可
  GETPROPERTYSTOREFLAGS flags,   // 1つ以上のGETPROPERTYSTOREFLAGS列挙型の値
  REFIID                riid,    // 
  void                  **ppv    // 
);
SHGetPropertyStoreFromParsingName function (shobjidl_core.h) | Microsoft Learn

Metadataを読み込むだけならば、flagsをGPS_DEFAULTとします。書き込めないファイル形式にGPS_READWRITEを指定すると、0x80030005「アクセスが拒否されました。」として失敗します。

ファイルの拡張子が不適切だと、情報の取得に失敗します。

PCWSTR pszPath = L"sample.mp3";

IPropertyStore* pPropertyStore = NULL;
HRESULT hr = SHGetPropertyStoreFromParsingName(
    pszPath,
    NULL,
    GPS_READWRITE, // 読み込み・書き込み
    __uuidof(IPropertyStore),
    (void**)&pPropertyStore);


PROPVARIANT var;
PropVariantInit(&var);

// Title の取得
hr = pPropertyStore->GetValue(PKEY_Title, &var);
LPWSTR title = var.pwszVal;
hr = PropVariantClear(&var);

// Artist の取得
hr = pPropertyStore->GetValue(PKEY_Music_Artist, &var);
LPWSTR artist0 = var.calpwstr.pElems[0];
LPWSTR artist1 = var.calpwstr.pElems[1];
hr = PropVariantClear(&var);

// TrackNumber の取得
hr = pPropertyStore->GetValue(PKEY_Music_TrackNumber, &var);
INT number = var.intVal;
hr = PropVariantClear(&var);


// Title の書き換え
hr = InitPropVariantFromString(L"ABC", &var);
hr = pPropertyStore->SetValue(PKEY_Title, var);
hr = pPropertyStore->Commit();
hr = PropVariantClear(&var);


hr = pPropertyStore->Release();
How do I use IPropertyStore to access mp3 metadata in Windows with C++? - Stack Overflow

プロパティから値を除去するには、値の型 (PROPVARIANT.vt) をVT_EMPTYとして書き込みます。Remarks - IPropertyStore::SetValue (propsys.h) - Win32 apps | Microsoft Learn

PROPVARIANT var = { VT_EMPTY };
hr = pPropertyStore->SetValue(PKEY_Title, var);

SHGetPropertyStoreFromIDList()

IPropertyStoreをPIDL (pointer to an item ID list) から取得するには、次のようにします。

PIDLIST_ABSOLUTE pidl = ILCreateFromPath(pszPath);
HRESULT hr = SHGetPropertyStoreFromIDList(
    pidl,
    GPS_DEFAULT,
    __uuidof(IPropertyStore),
    (void**)&pPropertyStore);
SHGetPropertyStoreFromIDList function (shobjidl_core.h) | Microsoft Learn

GetValue()

HRESULT GetValue(
  REFPROPERTYKEY key,
  PROPVARIANT    *pv
);
IPropertyStore::GetValue (propsys.h) - Win32 apps | Microsoft Learn

keyには、下表のような値を指定します。

PROPERTYKEY Shell Name Description Data Type
PKEY_Title System.Title Title. String (VT_LPWSTR)
PKEY_Comment System.Comment A comment attached to a file, typically added by a user. String (VT_LPWSTR)
PKEY_Copyright System.Copyright Copyright information. String (VT_LPWSTR)
PKEY_Media_Year System.Media.Year Year the content was published. UInt32 (VT_UI4)
PKEY_Media_EncodingSettings System.Media.EncodingSettings Description of the settings used to encode the content. String (VT_LPWSTR)
PKEY_Music_Artist System.Music.Artist Artist. Multivalue String (VT_VECTOR | VT_LPWSTR)
PKEY_Music_AlbumArtist System.Music.AlbumArtist Primary artist for the album. This attribute can be used to distinguish the primary artist for an album from an artist who collaborated on a particular track. String (VT_LPWSTR)
PKEY_Music_AlbumTitle System.Music.AlbumTitle Album title. String (VT_LPWSTR)
PKEY_Music_Genre System.Music.Genre Genre. Multivalue String (VT_VECTOR | VT_LPWSTR)
PKEY_Music_Composer System.Music.Composer Composer. Multivalue String (VT_VECTOR | VT_LPWSTR)
PKEY_Music_TrackNumber System.Music.TrackNumber Track number. UInt32 (VT_UI4)
Metadata Properties for Media Files - Win32 apps | Microsoft Learn

存在しないPROPERTYKEYを指定した場合にはS_OKが返され、引数のpvのvtメンバーはVT_EMPTYとなります。Remarks - IPropertyStore::GetValue (propsys.h) - Win32 apps | Microsoft Learn

SetValue()

HRESULT SetValue(
  REFPROPERTYKEY key,
  REFPROPVARIANT propvar
);
IPropertyStore::SetValue (propsys.h) - Win32 apps | Microsoft Learn

IPropertyStoreのインスタンスの取得時にGPS_READWRITEを指定していないと、0x80030005「アクセスが拒否されました。」として値の設定に失敗します。

propvarに渡す値は、InitPropVariantFromString()などで指定します。

HRESULT InitPropVariantFromString(
  PCWSTR      psz,
  PROPVARIANT *ppropvar
);
InitPropVariantFromString function (propvarutil.h) - Win32 apps | Microsoft Learn
  • InitPropVariantFromInt32() … LONG (long)
  • InitPropVariantFromDouble() … DOUBLE (double)

IMFPMediaItem::GetMetadata()

IPropertyStoreのインスタンスはIMFPMediaItem::GetMetadataからも取得できますが、この方法は非推奨となっているMFPlayに依存します。

LPCWSTR pwszURL = L"sample.mp3";

IMFPMediaPlayer* pMediaPlayer;
HRESULT hr = MFPCreateMediaPlayer(NULL, FALSE, 0, NULL, NULL, &pMediaPlayer);

IMFPMediaItem* pMediaItem = NULL;
hr = pMediaPlayer->CreateMediaItemFromURL(pwszURL, TRUE, NULL, &pMediaItem);

IPropertyStore* pPropertyStore = NULL;
hr = pMediaItem->GetMetadata(&pPropertyStore);

// 以降は上の例に同じ
MFPlayer2 Sample - Win32 apps | Microsoft Learn

この方法では拡張子とは無関係に情報を取得できます。ただし書き換えには失敗します。

IMFMetadataインターフェイス

void Func(IMFMediaSource* pMediaSource)
{
    IMFPresentationDescriptor* pPD = NULL;
    HRESULT hr = pMediaSource->CreatePresentationDescriptor(&pPD);

    IMFMetadataProvider* pMetadataProvider = NULL;
    hr = MFGetService(pMediaSource, MF_METADATA_PROVIDER_SERVICE, IID_PPV_ARGS(&pMetadataProvider));


    // IMFMetadataを取得する
    DWORD dwStreamIdentifier = 0;
    IMFMetadata* pMetadata = NULL;
    hr = pMetadataProvider->GetMFMetadata(pPD, dwStreamIdentifier, 0, &pMetadata);


    PROPVARIANT var;
    PropVariantInit(&var);

    // Title の取得
    hr = pMetadata->GetProperty(L"Title", &var);
    LPWSTR title = var.pwszVal;
    hr = PropVariantClear(&var);

    // Author の取得
    hr = pMetadata->GetProperty(L"Author", &var);
    LPWSTR author = var.pwszVal;
    hr = PropVariantClear(&var);

    // Title の書き換え
    hr = InitPropVariantFromString(L"ABC", &var);
    hr = pMetadata->SetProperty(L"Title", &var); // E_NOTIMPL (0x80004001) Not implemented.
    hr = PropVariantClear(&var);

    pPD->Release();
    pMetadataProvider->Release();
    pMetadata->Release();
}
Metadata Providers in Windows Vista - Win32 apps | Microsoft Learn

IMFMetadata::GetProperty()で指定するプロパティ名は、IMFMetadata::GetAllPropertyNames()で取得できます。IMFMetadata::GetAllPropertyNames (mfidl.h) | Microsoft Learn

PROPVARIANT varNames;
PropVariantInit(&varNames);

hr = pMetadata->GetAllPropertyNames(&varNames);
LPWSTR elem0 = varNames.calpwstr.pElems[0]; // "Title" など
LPWSTR elem1 = varNames.calpwstr.pElems[1]; //

hr = PropVariantClear(&varNames);
Microsoft Learnから検索