Mengatur Metadata pada File
Anda dapat mengatur metadata pada file sebelum menulisnya ke perangkat (saat menggunakan IWMDMStorageControl3::Insert3) atau pada penyimpanan yang ada (dengan memanggil IWMDMStorage3::SetMetadata). Anda hanya dapat mengatur atribut pada penyimpanan yang ada (dengan memanggil IWMDMStorage::SetAttributes atau IWMDMStorage2::SetAttributes2).
Mengatur metadata dilakukan dengan membuat dan mengisi antarmukaIWMDMMetaDatayang diteruskan ke IWMDMStorageControl3::Insert3. Namun, metode ini dapat menghapus semua metadata yang ada pada file, selain metadata yang dikodekan secara permanen yang disimpan dalam sistem file itu sendiri, seperti nama atau ukuran file. Oleh karena itu, Anda harus menyalin semua metadata yang ada yang ingin Anda pertahankan ke antarmuka IWMDMMetaData yang Anda kirimkan. Karena Windows Media Device Manager tidak dapat digunakan untuk mengambil metadata dari file lokal, Anda harus menggunakan Windows Media Format SDK (atau beberapa alat lain) untuk mengambil metadata tersebut.
Untuk menggunakan Windows Media Format SDK untuk mengambil properti file ASF, ikuti langkah-langkah berikut:
- Buat objek editor metadata dengan cara memanggil WMCreateEditor dan meminta antarmuka IWMMetadataEditor.
- Buka file untuk pembacaan metadata dengan memanggil IWMMetadataEditor::Buka.
- Jika file adalah file ASF yang valid dan dapat dibuka, tanyakan kepada editor untuk antarmuka IWMHeaderInfo .
- Ambil properti file dengan cara memanggil IWMHeaderInfo::GetAttributeByName, dengan melewatkan konstanta properti Windows Media Format SDK yang diinginkan. Daftar konstanta Format SDK dengan konstanta Windows Media Device Manager SDK yang setara diberikan dalam tabel berikut.
Konstanta Format Media Windows SDK | SDK Pengelola Perangkat Media Windows Konstanta |
---|---|
g_wszWMTitle | g_wszWMDMTitle |
g_wszWMAuthor | g_wszWMDMAuthor |
g_wszWMAlbumTitle | g_wszWMDMAlbumTitle |
g_wszWMGenre | g_wszWMDMGenre |
g_wszWMYear | g_wszWMDMYear |
g_wszWMTrackNumber atau 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 atau g_wszVideoFourCCCodec |
Kode contoh C++ berikut menunjukkan pengambilan sejumlah properti metadata dari file ASF menggunakan Windows Media Format SDK dan mengonversinya ke nilai Windows Media Device Manager yang setara.
// 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;
}
Fungsi contoh C++ berikut menunjukkan cara menggunakan DirectShow untuk mendapatkan beberapa informasi file dan menambahkannya ke metadata.
// 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;
}
Topik terkait
-
Menulis File ke Perangkat