38 value = QString::fromUtf16(
reinterpret_cast<
const char16_t *>(var.pwszVal));
41 value =
int(var.lVal);
44 value = uint(var.ulVal);
47 value = qulonglong(var.uhVal.QuadPart);
50 value =
bool(var.boolVal);
54 if (!FileTimeToSystemTime(&var.filetime, &t))
57 value = QDateTime(QDate(t.wYear, t.wMonth, t.wDay),
58 QTime(t.wHour, t.wMinute, t.wSecond, t.wMilliseconds),
59 QTimeZone(QTimeZone::UTC));
64 if (FAILED(var.pStream->Stat(&stat, STATFLAG_NONAME)))
66 void *data = malloc(stat.cbSize.QuadPart);
68 if (FAILED(var.pStream->Read(data, stat.cbSize.QuadPart, &read))) {
72 value = QImage::fromData((
const uchar*)data, read);
76 case VT_VECTOR | VT_LPWSTR:
78 for (ULONG i = 0; i < var.calpwstr.cElems; ++i)
79 vList.append(QString::fromUtf16(
reinterpret_cast<
const char16_t *>(var.calpwstr.pElems[i])));
91 QtMultimediaPrivate::ScopedPropVariant pv;
92 if (FAILED(content->GetValue(key, pv.get())))
95 QVariant value = convertValue(pv.var);
100 if (key == PKEY_Media_ClassPrimaryID ) {
101 QString v = value.toString();
102 if (v == QLatin1String(
"{D1607DBC-E323-4BE2-86A1-48A42A28441E}"))
103 value = QStringLiteral(
"Music");
104 else if (v == QLatin1String(
"{DB9830BD-3AB3-4FAB-8A37-1A995F7FF74B}"))
105 value = QStringLiteral(
"Video");
106 else if (v == QLatin1String(
"{01CD0F29-DA4E-4157-897B-6275D50C4F11}"))
107 value = QStringLiteral(
"Audio");
108 else if (v == QLatin1String(
"{FCF24A76-9A57-4036-990D-E35DD8B244E1}"))
109 value = QStringLiteral(
"Other");
110 }
else if (key == PKEY_Media_Duration) {
112 value = (value.toLongLong() + 10000) / 10000;
113 }
else if (key == PKEY_Video_Compression) {
114 value =
int(QWindowsMultimediaUtils::codecForVideoFormat(value.toUuid()));
115 }
else if (key == PKEY_Audio_Format) {
116 value =
int(QWindowsMultimediaUtils::codecForAudioFormat(value.toUuid()));
117 }
else if (key == PKEY_Video_FrameHeight ) {
119 res.setHeight(value.toUInt());
120 if (SUCCEEDED(content->GetValue(PKEY_Video_FrameWidth, pv.get())))
121 res.setWidth(convertValue(pv.var).toUInt());
123 }
else if (key == PKEY_Video_Orientation) {
124 uint orientation = 0;
125 if (SUCCEEDED(content->GetValue(PKEY_Video_Orientation, pv.get())))
126 orientation = convertValue(pv.var).toUInt();
128 }
else if (key == PKEY_Video_FrameRate) {
129 value = value.toReal() / 1000.f;
135QMediaMetaData
MFMetaData::fromNative(IMFMediaSource* mediaSource)
142 ComPtr<IPropertyStore> content;
143 if (SUCCEEDED(MFGetService(mediaSource, MF_PROPERTY_HANDLER_SERVICE, IID_PPV_ARGS(&content))))
144 metaData = fromNative(content.Get());
149 ComPtr<IMFMetadataProvider> provider;
150 if (SUCCEEDED(MFGetService(mediaSource, MF_METADATA_PROVIDER_SERVICE, IID_PPV_ARGS(&provider)))) {
151 ComPtr<IMFPresentationDescriptor> pd;
152 if (SUCCEEDED(mediaSource->CreatePresentationDescriptor(&pd))) {
153 ComPtr<IMFMetadata> metadata;
154 if (SUCCEEDED(provider->GetMFMetadata(pd.Get(), 0, 0, &metadata))) {
155 const QMediaMetaData mfData = fromNative(metadata.Get());
156 for (
const auto &[key, value] : mfData.asKeyValueRange()) {
157 if (!metaData.value(key).isValid())
158 metaData.insert(key, value);
200 QtMultimediaPrivate::ScopedPropVariant names;
201 if (FAILED(metadata->GetAllPropertyNames(names.get())))
209 static const QVarLengthFlatMap<QStringView, QMediaMetaData::Key, 12> nameToKey({
210 { u"Title", QMediaMetaData::Title },
211 { u"Author", QMediaMetaData::ContributingArtist },
212 { u"WM/AlbumTitle", QMediaMetaData::AlbumTitle },
213 { u"WM/AlbumArtist", QMediaMetaData::AlbumArtist },
214 { u"WM/Composer", QMediaMetaData::Composer },
215 { u"WM/Genre", QMediaMetaData::Genre },
216 { u"WM/TrackNumber", QMediaMetaData::TrackNumber },
217 { u"Description", QMediaMetaData::Description },
218 { u"Copyright", QMediaMetaData::Copyright },
219 { u"WM/Publisher", QMediaMetaData::Publisher },
220 { u"WM/Language", QMediaMetaData::Language },
221 { u"WM/AuthorURL", QMediaMetaData::Url },
224 if (names->vt == (VT_VECTOR | VT_LPWSTR)) {
225 for (ULONG i = 0; i < names->calpwstr.cElems; ++i) {
226 const QStringView name(names->calpwstr.pElems[i]);
230 if (name == u"WM/Picture") {
231 QtMultimediaPrivate::ScopedPropVariant value;
232 if (SUCCEEDED(metadata->GetProperty(names->calpwstr.pElems[i], value.get()))
233 && value->vt == VT_BLOB) {
234 QImage img = imageFromAsfFlatPicture(value->blob);
236 metaData.insert(QMediaMetaData::CoverArtImage, img);
241 auto it = nameToKey.find(name);
242 if (it == nameToKey.end())
245 QtMultimediaPrivate::ScopedPropVariant value;
246 if (SUCCEEDED(metadata->GetProperty(names->calpwstr.pElems[i], value.get()))) {
247 QVariant v = convertValue(value.var);
249 metaData.insert(it.value(), v);
257QMediaMetaData
MFMetaData::fromNative(IPropertyStore *content)
265 if (SUCCEEDED(content->GetCount(&cProps))) {
266 for (DWORD i = 0; i < cProps; i++)
269 if (FAILED(content->GetAt(i, &key)))
271 QMediaMetaData::Key mediaKey;
272 if (key == PKEY_Author) {
273 mediaKey = QMediaMetaData::Author;
274 }
else if (key == PKEY_Title) {
275 mediaKey = QMediaMetaData::Title;
280 }
else if (key == PKEY_Media_EncodingSettings) {
281 mediaKey = QMediaMetaData::Description;
282 }
else if (key == PKEY_Copyright) {
283 mediaKey = QMediaMetaData::Copyright;
284 }
else if (key == PKEY_Comment) {
285 mediaKey = QMediaMetaData::Comment;
286 }
else if (key == PKEY_Media_ProviderStyle) {
287 mediaKey = QMediaMetaData::Genre;
288 }
else if (key == PKEY_Media_DateEncoded) {
289 mediaKey = QMediaMetaData::Date;
294 }
else if (key == PKEY_Language) {
295 mediaKey = QMediaMetaData::Language;
296 }
else if (key == PKEY_Media_Publisher) {
297 mediaKey = QMediaMetaData::Publisher;
298 }
else if (key == PKEY_Media_ClassPrimaryID) {
299 mediaKey = QMediaMetaData::MediaType;
300 }
else if (key == PKEY_Media_Duration) {
301 mediaKey = QMediaMetaData::Duration;
302 }
else if (key == PKEY_Audio_EncodingBitrate) {
303 mediaKey = QMediaMetaData::AudioBitRate;
304 }
else if (key == PKEY_Audio_Format) {
305 mediaKey = QMediaMetaData::AudioCodec;
314 }
else if (key == PKEY_Music_AlbumTitle) {
315 mediaKey = QMediaMetaData::AlbumTitle;
316 }
else if (key == PKEY_Music_AlbumArtist) {
317 mediaKey = QMediaMetaData::AlbumArtist;
318 }
else if (key == PKEY_Music_Artist) {
319 mediaKey = QMediaMetaData::ContributingArtist;
320 }
else if (key == PKEY_Music_Composer) {
321 mediaKey = QMediaMetaData::Composer;
328 }
else if (key == PKEY_Music_TrackNumber) {
329 mediaKey = QMediaMetaData::TrackNumber;
330 }
else if (key == PKEY_Music_Genre) {
331 mediaKey = QMediaMetaData::Genre;
332 }
else if (key == PKEY_ThumbnailStream) {
333 QVariant val = metaDataValue(content, key);
334 if (val.canConvert<QImage>())
335 QtMultimediaPrivate::setCoverArtImage(metaData, val.value<QImage>());
337 }
else if (key == PKEY_Video_FrameHeight) {
338 mediaKey = QMediaMetaData::Resolution;
339 }
else if (key == PKEY_Video_Orientation) {
340 mediaKey = QMediaMetaData::Orientation;
341 }
else if (key == PKEY_Video_FrameRate) {
342 mediaKey = QMediaMetaData::VideoFrameRate;
343 }
else if (key == PKEY_Video_EncodingBitrate) {
344 mediaKey = QMediaMetaData::VideoBitRate;
345 }
else if (key == PKEY_Video_Compression) {
346 mediaKey = QMediaMetaData::VideoCodec;
354 metaData.insert(mediaKey, metaDataValue(content, key));
364 case QMediaMetaData::Key::Title:
366 case QMediaMetaData::Key::Author:
368 case QMediaMetaData::Key::Comment:
370 case QMediaMetaData::Key::Genre:
371 return PKEY_Music_Genre;
372 case QMediaMetaData::Key::Copyright:
373 return PKEY_Copyright;
374 case QMediaMetaData::Key::Publisher:
375 return PKEY_Media_Publisher;
376 case QMediaMetaData::Key::Url:
377 return PKEY_Media_AuthorUrl;
378 case QMediaMetaData::Key::AlbumTitle:
379 return PKEY_Music_AlbumTitle;
380 case QMediaMetaData::Key::AlbumArtist:
381 return PKEY_Music_AlbumArtist;
382 case QMediaMetaData::Key::TrackNumber:
383 return PKEY_Music_TrackNumber;
384 case QMediaMetaData::Key::Date:
385 return PKEY_Media_DateEncoded;
386 case QMediaMetaData::Key::Composer:
387 return PKEY_Music_Composer;
388 case QMediaMetaData::Key::Duration:
389 return PKEY_Media_Duration;
390 case QMediaMetaData::Key::Language:
391 return PKEY_Language;
392 case QMediaMetaData::Key::Description:
393 return PKEY_Media_EncodingSettings;
394 case QMediaMetaData::Key::AudioBitRate:
395 return PKEY_Audio_EncodingBitrate;
396 case QMediaMetaData::Key::ContributingArtist:
397 return PKEY_Music_Artist;
398#if QT_DEPRECATED_SINCE(6
, 12
)
399 case QtMultimediaPrivate::deprecatedThumbnailImage:
401 case QMediaMetaData::Key::CoverArtImage:
402 return PKEY_ThumbnailStream;
403 case QMediaMetaData::Key::Orientation:
404 return PKEY_Video_Orientation;
405 case QMediaMetaData::Key::VideoFrameRate:
406 return PKEY_Video_FrameRate;
407 case QMediaMetaData::Key::VideoBitRate:
408 return PKEY_Video_EncodingBitrate;
409 case QMediaMetaData::MediaType:
410 return PKEY_Media_ClassPrimaryID;
412 return PROP_KEY_NULL;
452void MFMetaData::toNative(
const QMediaMetaData &metaData, IPropertyStore *content)
456 for (
const auto &key : metaData.keys()) {
458 QVariant value = metaData.value(key);
460 if (key == QMediaMetaData::Key::MediaType) {
462 QString strValue = metaData.stringValue(key);
467 if (strValue == QLatin1String(
"Music"))
468 v = QLatin1String(
"{D1607DBC-E323-4BE2-86A1-48A42A28441E}");
469 else if (strValue == QLatin1String(
"Video"))
470 v = QLatin1String(
"{DB9830BD-3AB3-4FAB-8A37-1A995F7FF74B}");
471 else if (strValue == QLatin1String(
"Audio"))
472 v = QLatin1String(
"{01CD0F29-DA4E-4157-897B-6275D50C4F11}");
474 v = QLatin1String(
"{FCF24A76-9A57-4036-990D-E35DD8B244E1}");
476 setStringProperty(content, PKEY_Media_ClassPrimaryID, v);
478 }
else if (key == QMediaMetaData::Key::Duration) {
480 setUInt64Property(content, PKEY_Media_Duration, value.toULongLong() * 10000);
482 }
else if (key == QMediaMetaData::Key::Resolution) {
484 QSize res = value.toSize();
485 setUInt32Property(content, PKEY_Video_FrameWidth, quint32(res.width()));
486 setUInt32Property(content, PKEY_Video_FrameHeight, quint32(res.height()));
488 }
else if (key == QMediaMetaData::Key::Orientation) {
490 setUInt32Property(content, PKEY_Video_Orientation, value.toUInt());
492 }
else if (key == QMediaMetaData::Key::VideoFrameRate) {
494 qreal fps = value.toReal();
495 setUInt32Property(content, PKEY_Video_FrameRate, quint32(fps * 1000));
497 }
else if (key == QMediaMetaData::Key::TrackNumber) {
499 setUInt32Property(content, PKEY_Music_TrackNumber, value.toUInt());
501 }
else if (key == QMediaMetaData::Key::AudioBitRate) {
503 setUInt32Property(content, PKEY_Audio_EncodingBitrate, value.toUInt());
505 }
else if (key == QMediaMetaData::Key::VideoBitRate) {
507 setUInt32Property(content, PKEY_Video_EncodingBitrate, value.toUInt());
509 }
else if (key == QMediaMetaData::Key::Date) {
513 ULARGE_INTEGER t = {};
514 t.QuadPart = ULONGLONG(value.toDateTime().toUTC().toMSecsSinceEpoch() * 10000
515 + 116444736000000000LL);
518 ft.dwHighDateTime = t.HighPart;
519 ft.dwLowDateTime = t.LowPart;
521 setFileTimeProperty(content, PKEY_Media_DateEncoded, &ft);
527 REFPROPERTYKEY propKey = propertyKeyForMetaDataKey(key);
529 if (propKey != PROP_KEY_NULL) {
530 QString strValue = metaData.stringValue(key);
531 if (!strValue.isEmpty())
532 setStringProperty(content, propKey, strValue);