Media FoundationでMetadataを読み込むには、下表の2つの方法があります。
IPropertyStore (Shell metadata) |
IMFMetadata (Media Foundation v1 Metadata) |
|
---|---|---|
対応OS | Windows 7以降 | Windows Vista以降 |
シェル プロパティ システムとの互換性 | ○ | × |
ファイル レベルのプロパティ | ○ | ○ |
ストリーム レベルのプロパティ | × | ○ |
多言語のプロパティ | × | ○ |
プロパティのキーの指定方法 | PROPERTYKEYの値 | ワイド文字の文字列 |
プロパティの値 | PROPVARIANTの値 | PROPVARIANTの値 |
指定パスの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);
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
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) |
存在しないPROPERTYKEYを指定した場合にはS_OKが返され、引数のpvのvtメンバーはVT_EMPTYとなります。Remarks - IPropertyStore::GetValue (propsys.h) - Win32 apps | Microsoft Learn
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
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
この方法では拡張子とは無関係に情報を取得できます。ただし書き換えには失敗します。
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);