ファイルにメタデータを設定する
メタデータは、デバイスに書き込む前に ( IWMDMStorageControl3::Insert3 を使用する場合)、または既存のストレージ ( IWMDMStorage3::SetMetadata を呼び出すことによって) に設定できます。 属性は、既存のストレージでのみ設定できます ( IWMDMStorage::SetAttributes または IWMDMStorage2::SetAttributes2 を呼び出します)。
メタデータの設定は、IWMDMStorageControl3::Insert3 に渡される IWMDMMetaData インターフェイスを作成して入力することによって行われます。 ただし、このメソッドは、ファイル名やサイズなど、ファイル システム自体に格納されているハードコーディングされたメタデータ以外の、ファイル上のすべての既存のメタデータをクリアできます。 したがって、保持する既存のメタデータをすべて、送信する IWMDMMetaData インターフェイスにコピーする必要があります。 Windows Media デバイス マネージャーを使用してローカル ファイルからメタデータを取得することはできないため、このようなメタデータを取得するには、Windows Media Format SDK (またはその他のツール) を使用する必要があります。
Windows Media Format SDK を使用して ASF ファイルのプロパティを取得するには、次の手順に従います。
- WMCreateEditor を呼び出し、IWMMetadataEditor インターフェイスを要求して、メタデータ エディター オブジェクトを作成します。
- IWMMetadataEditor::Open を呼び出して、メタデータの読み取り用にファイルを開きます。
- ファイルが有効な ASF ファイルであり、開くことができる場合は、 エディターに対して IWMHeaderInfo インターフェイスのクエリを実行します。
- IWMHeaderInfo::GetAttributeByName を呼び出し、目的の Windows Media Format SDK プロパティ定数を渡して、ファイル のプロパティを取得します。 次の表に、同等の Windows Media デバイス マネージャー SDK 定数を含む FORMAT SDK 定数の一覧を示します。
Windows Media Format SDK 定数 | Windows Media デバイス マネージャー SDK 定数 |
---|---|
g_wszWMTitle | g_wszWMDMTitle |
g_wszWMAuthor | g_wszWMDMAuthor |
g_wszWMAlbumTitle | g_wszWMDMAlbumTitle |
g_wszWMGenre | g_wszWMDMGenre |
g_wszWMYear | g_wszWMDMYear |
g_wszWMTrackNumberまたはg_wszWMTrack | g_wszWMDMTrack |
g_wszWMComposer | g_wszWMDMComposer |
g_wszWMDuration | g_wszWMDMDuration |
g_wszWMCopyright | g_wszWMDMProviderCopyright |
g_wszWMDescription | g_wszWMDMDescription |
g_wszWMBitrate | g_wszWMDMBitrate |
g_wszWMRating | g_wszWMDMUserRating |
g_wszWMAlbumArtist | g_wszWMDMAlbumArtist |
g_wszWMParentalRating | g_wszWMDMParentalRating |
g_wszWMRadioStationName | g_wszWMDMMediaStationName |
g_wszWMSubTitle | g_wszWMDMSubTitle |
g_wszWMVideoWidth | g_wszWMDMWidth |
g_wszWMVideoHeight | g_wszWMDMHeight |
g_wszWMMood | g_wszWMDMTrackMood |
g_wszWMCodec | g_wszAudioWAVECodecまたはg_wszVideoFourCCCodec |
次の C++ コード例は、Windows Media Format SDK を使用して ASF ファイルから多数のメタデータ プロパティを取得し、それらを同等の Windows Media デバイス マネージャー値に変換する方法を示しています。
// Structure and array to hold equivalent Windows Media Format SDK
// and Windows Media Device Manager SDK metadata property names.
struct EquivalentProperty
{
LPCWSTR FormatSDKConst;
LPCWSTR WMDMSDKConst;
};
EquivalentProperty EquivalentProperties []=
{
{g_wszWMTitle, g_wszWMDMTitle},
{g_wszWMAuthor, g_wszWMDMAuthor},
{g_wszWMAlbumTitle, g_wszWMDMAlbumTitle},
{g_wszWMGenre, g_wszWMDMGenre},
{g_wszWMYear, g_wszWMDMYear},
{g_wszWMTrackNumber, g_wszWMDMTrack},
{g_wszWMTrack, g_wszWMDMTrack},
{g_wszWMComposer, g_wszWMDMComposer},
{g_wszWMBitrate, g_wszWMDMBitrate},
{g_wszWMDuration, g_wszWMDMDuration},
{g_wszWMCopyright, g_wszWMDMProviderCopyright},
{g_wszWMDescription, g_wszWMDMDescription},
{g_wszWMRating, g_wszWMDMUserRating},
{g_wszWMAlbumArtist, g_wszWMDMAlbumArtist},
{g_wszWMParentalRating, g_wszWMDMParentalRating},
{g_wszWMRadioStationName, g_wszWMDMMediaStationName},
{g_wszWMSubTitle, g_wszWMDMSubTitle},
{g_wszWMVideoWidth, g_wszWMDMWidth},
{g_wszWMVideoHeight, g_wszWMDMHeight},
{g_wszWMMood, g_wszWMDMTrackMood},
{g_wszWMCodec, g_wszAudioWAVECodec},
{g_wszWMCodec, g_wszVideoFourCCCodec}
};
// Function that tries to get metadata by using the Format SDK.
// If it cannot open the file, it returns E_FAIL.
HRESULT GetFileMetadataFromFormatSDK(IWMDMMetaData* pMetadata, LPCWSTR file)
{
if ((pMetaData == NULL) || (file == NULL)) return E_INVALIDPARAM;
HRESULT hr = S_OK;
CComPtr<IWMMetadataEditor> pEditor;
// Do loop to allow easy error trapping. Even if there are no errors,
// the loop executes only once.
do {
hr = WMCreateEditor(&pEditor);
if (FAILED(hr))
break;
// Open the file.
hr = pEditor->Open(file);
if (FAILED(hr))
break;
CComPtr<IWMHeaderInfo>pHeaderInfo;
hr = pEditor->QueryInterface(__uuidof(IWMHeaderInfo), (void**)&pHeaderInfo);
if (FAILED(hr))
break;
// Copy values from Format SDK to equivalent WMDM SDK metadata values.
// Loop through all known values
WORD stream = 0;
WMT_ATTR_DATATYPE wmfType;
WORD len = 0;
BYTE* value = NULL;
WMDM_TAG_DATATYPE wmdmType;
for (int i = 0; i < sizeof(EquivalentProperties) / sizeof(EquivalentProperties[0]); i++)
{
// Request each value from our equivalency list by name.
// The function is called twice: once to get the buffer size,
// and once to get the value in the allocated buffer.
if (FAILED(pHeaderInfo->GetAttributeByName(
&stream, EquivalentProperties[i].FormatSDKConst, &wmfType, NULL, &len)))
{
continue;
}
value = new BYTE[len];
if (value == NULL) continue;
if (FAILED(pHeaderInfo->GetAttributeByName(&stream, EquivalentProperties[i].FormatSDKConst, &wmfType, value, &len)))
{
delete[] value;
continue;
}
// Send the data to the equivalent WMDM metadata value.
// First, find the equivalent WMDM type for the WMF type.
switch(wmfType)
{
case WMT_TYPE_BINARY:
wmdmType = WMDM_TYPE_BINARY;
break;
case WMT_TYPE_DWORD:
wmdmType = WMDM_TYPE_DWORD;
break;
case WMT_TYPE_STRING:
wmdmType = WMDM_TYPE_STRING;
break;
case WMT_TYPE_BOOL:
wmdmType = WMDM_TYPE_BOOL;
break;
case WMT_TYPE_QWORD:
wmdmType = WMDM_TYPE_QWORD;
break;
case WMT_TYPE_WORD:
wmdmType = WMDM_TYPE_WORD;
break;
case WMT_TYPE_GUID:
wmdmType = WMDM_TYPE_GUID;
break;
default:
wmdmType = WMDM_TYPE_BINARY;
break;
}
// Don't worry about trapping errors, because there's nothing
// we can do about it.
pMetadata->AddItem(wmdmType,
EquivalentProperties[i].WMDMSDKConst, value, len);
delete[] value;
} // Add next value.
} while (FALSE); // End Do loop error trap.
// Close the file opened with IWMMetadataEditor.
pEditor->Close();
return hr;
}
次の C++ 関数の例は、DirectShow を使用してファイル情報を取得し、メタデータに追加する方法を示しています。
// For IMediaDet, you must link to strmiids.lib. Also include the following:
//#include <Qedit.h> // for IMediaDet declaration.
//#include <Dshow.h> // for VIDEOINFOHEADER declaration.
HRESULT GetFileMetadataFromDShow(IWMDMMetaData* pMetadata, LPCWSTR file)
{
HRESULT hr = S_OK;
// Add file metadata properties from DirectShow.
// This is good for non-ASF files, or to add any information
// that the Format SDK didn't get.
// Do loop to allow easy error trapping. Even if there are no errors,
// the loop executes only once.
do
{
// Create the Media Detector object.
CComPtr<IMediaDet> pIMediaDet;
hr = pIMediaDet.CoCreateInstance(CLSID_MediaDet, NULL);
if (FAILED(hr))
break;
// Open the file.
hr = pIMediaDet->put_Filename(BSTR(file));
if (FAILED(hr))
break;
// Get the media type for the default stream.
AM_MEDIA_TYPE mediaType;
hr = pIMediaDet->get_StreamMediaType(&mediaType);
if (FAILED(hr))
break;
// We have the file open, so start requesting information from the
// Media Detector and adding it to the metadata. When adding
// individual metadata values, ignore the HRESULT, because failure
// to add these metadata values is not a breaking issue.
// Get major and minor types.
WCHAR strMediaType[64];
ZeroMemory(strMediaType, 64);
//Change the major type to a string, then add to IWMDMMetaData.
StringFromGUID2(reinterpret_cast<GUID&>(mediaType.majortype),
(LPOLESTR)strMediaType, 64);
hr = pMetadata->AddItem(WMDM_TYPE_STRING,
g_wszWMDMediaClassPrimaryID,
(BYTE*) strMediaType,
sizeof(strMediaType) / sizeof(strMediaType[0]));
// Clear local string, then retrieve subtype the same way.
ZeroMemory(strMediaType, 64);
StringFromGUID2(reinterpret_cast<GUID&>(mediaType.subtype),
(LPOLESTR)strMediaType, 64);
hr = pMetadata->AddItem(WMDM_TYPE_STRING,
g_wszWMDMMediaClassSecondaryID, (BYTE*) strMediaType,
sizeof(strMediaType) / sizeof(strMediaType[0]));
// Get the duration. Duration is retrieved in seconds, but set
// in 100-nanosecond units.
double duration = 0;
hr = pIMediaDet->get_StreamLength(&duration);
if (duration > 0)
{
duration *= 10E7;
hr = pMetadata->AddItem(WMDM_TYPE_DWORD, g_wszWMDMDuration, (BYTE*) &duration, sizeof(duration));
}
// Get the frame rate.
double frameRate = 0;
hr = pIMediaDet->get_FrameRate(&frameRate);
if (frameRate > 0)
{
hr = pMetadata->AddItem(WMDM_TYPE_DWORD, g_wszWMDMFrameRate,
(BYTE*) &frameRate,
sizeof(frameRate));
}
// Get the structure for the default stream's major type and
// fill in additional information.
if (IsEqualGUID(mediaType.formattype, FORMAT_VideoInfo))
{
VIDEOINFOHEADER* data = (VIDEOINFOHEADER*) mediaType.pbFormat;
hr = pMetadata->AddItem(WMDM_TYPE_DWORD, g_wszWMDMVideoBitrate,
(BYTE*) &data->dwBitRate, sizeof(DWORD));
hr = pMetadata->AddItem(WMDM_TYPE_DWORD, g_wszWMDMHeight,
(BYTE*) &data->bmiHeader.biHeight, sizeof(LONG));
hr = pMetadata->AddItem(WMDM_TYPE_DWORD, g_wszWMDMWidth,
(BYTE*) &data->bmiHeader.biWidth, sizeof(LONG));
}
if (IsEqualGUID(mediaType.formattype, FORMAT_WaveFormatEx))
{
WAVEFORMATEX* data = (WAVEFORMATEX*) mediaType.pbFormat;
hr = pMetadata->AddItem(WMDM_TYPE_WORD, g_wszWMDMBlockAlignment,
(BYTE*) &data->nBlockAlign, sizeof(WORD));
hr = pMetadata->AddItem(WMDM_TYPE_WORD, g_wszWMDMNumChannels,
(BYTE*) &data->nChannels, sizeof(WORD));
}
} while (FALSE); // End of error loop.
return hr;
}
関連トピック