26 {
"title", QMediaMetaData::Title },
27 {
"comment", QMediaMetaData::Comment },
28 {
"description", QMediaMetaData::Description },
29 {
"genre", QMediaMetaData::Genre },
30 {
"date", QMediaMetaData::Date },
32 {
"language", QMediaMetaData::Language },
34 {
"copyright", QMediaMetaData::Copyright },
37 {
"album", QMediaMetaData::AlbumTitle },
38 {
"album_artist", QMediaMetaData::AlbumArtist },
39 {
"artist", QMediaMetaData::ContributingArtist },
40 {
"track", QMediaMetaData::TrackNumber },
43 {
"performer", QMediaMetaData::LeadPerformer },
45 {
nullptr, QMediaMetaData::Title }
74 constexpr std::array prioritizedDateTags = {
76 "com.apple.quicktime.creationdate",
81 AVDictionaryEntry *entry =
nullptr;
83 for (
const char *dateTag : prioritizedDateTags) {
84 using namespace std::string_view_literals;
85 entry = av_dict_get(tags, dateTag,
nullptr, 0);
88 else if (entry->key ==
"year"sv)
89 return QDateTime(QDate(QByteArray(entry->value).toInt(), 1, 1), QTime(0, 0, 0));
91 return QDateTime::fromString(QString::fromUtf8(entry->value), Qt::ISODate);
98void QFFmpegMetaData::addEntry(QMediaMetaData &metaData, AVDictionaryEntry *entry)
100 qCDebug(qLcMetaData) <<
" checking:" << entry->key << entry->value;
101 QByteArray tag(entry->key);
102 QMediaMetaData::Key key = tagToKey(tag.toLower());
103 if (key == QMediaMetaData::Key(-1))
105 qCDebug(qLcMetaData) <<
" adding" << key;
107 auto *map = &metaData;
109 int metaTypeId = keyType(key).id();
110 switch (metaTypeId) {
111 case qMetaTypeId<QString>():
112 map->insert(key, QString::fromUtf8(entry->value));
114 case qMetaTypeId<QStringList>():
115 map->insert(key, QString::fromUtf8(entry->value).split(QLatin1Char(
',')));
117 case qMetaTypeId<QDateTime>():
120 case qMetaTypeId<QUrl>():
121 map->insert(key, QUrl::fromEncoded(entry->value));
123 case qMetaTypeId<qint64>():
124 map->insert(key, (qint64)QByteArray(entry->value).toLongLong());
126 case qMetaTypeId<
int>():
127 map->insert(key, QByteArray(entry->value).toInt());
129 case qMetaTypeId<qreal>():
130 map->insert(key, (qreal)QByteArray(entry->value).toDouble());
135 if (metaTypeId == qMetaTypeId<QLocale::Language>()) {
136 map->insert(key, QVariant::fromValue(QLocale::codeToLanguage(QString::fromUtf8(entry->value), QLocale::ISO639Part2)));
141QMediaMetaData QFFmpegMetaData::fromAVMetaData(
const AVDictionary *tags)
143 QMediaMetaData metaData;
144 AVDictionaryEntry *entry =
nullptr;
145 while ((entry = av_dict_get(tags,
"", entry, AV_DICT_IGNORE_SUFFIX)))
146 addEntry(metaData, entry);
149 QDateTime date = getRecordingTime(tags);
151 metaData.insert(QMediaMetaData::Date, date);
156QByteArray QFFmpegMetaData::value(
const QMediaMetaData &metaData, QMediaMetaData::Key key)
158 const int metaTypeId = keyType(key).id();
159 const QVariant val = metaData.value(key);
160 switch (metaTypeId) {
161 case qMetaTypeId<QString>():
162 return val.toString().toUtf8();
163 case qMetaTypeId<QStringList>():
164 return val.toStringList().join(u",").toUtf8();
165 case qMetaTypeId<QDateTime>():
166 return val.toDateTime().toString(Qt::ISODate).toUtf8();
167 case qMetaTypeId<QUrl>():
168 return val.toUrl().toEncoded();
169 case qMetaTypeId<qint64>():
170 case qMetaTypeId<
int>():
171 return QByteArray::number(val.toLongLong());
172 case qMetaTypeId<qreal>():
173 return QByteArray::number(val.toDouble());
177 if (metaTypeId == qMetaTypeId<QLocale::Language>())
178 return QLocale::languageToCode(val.value<QLocale::Language>(), QLocale::ISO639Part2).toUtf8();
183AVDictionary *QFFmpegMetaData::toAVMetaData(
const QMediaMetaData &metaData)
185 AVDictionary *dict =
nullptr;
186 for (
const auto &&[k, v] : metaData.asKeyValueRange()) {
187 const char *key = ::keyToTag(k);
190 QByteArray val = value(metaData, k);
193 av_dict_set(&dict, key, val.constData(), 0);