Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qffmpegmediametadata.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5#include <QDebug>
6#include <QtCore/qdatetime.h>
7#include <qstringlist.h>
8#include <qurl.h>
9#include <qlocale.h>
10
11#include <qloggingcategory.h>
12
14
15static Q_LOGGING_CATEGORY(qLcMetaData, "qt.multimedia.ffmpeg.metadata")
16
17namespace {
18
19struct {
20 const char *tag;
22} ffmpegTagToMetaDataKey[] = {
23 { "title", QMediaMetaData::Title },
24 { "comment", QMediaMetaData::Comment },
25 { "description", QMediaMetaData::Description },
26 { "genre", QMediaMetaData::Genre },
27 { "date", QMediaMetaData::Date },
28 { "year", QMediaMetaData::Date },
29 { "creation_time", QMediaMetaData::Date },
30
31 { "language", QMediaMetaData::Language },
32
33 { "copyright", QMediaMetaData::Copyright },
34
35 // Music
36 { "album", QMediaMetaData::AlbumTitle },
37 { "album_artist", QMediaMetaData::AlbumArtist },
39 { "track", QMediaMetaData::TrackNumber },
40
41 // Movie
42 { "performer", QMediaMetaData::LeadPerformer },
43
44 { nullptr, QMediaMetaData::Title }
45};
46
47}
48
49static QMediaMetaData::Key tagToKey(const char *tag)
50{
51 auto *map = ffmpegTagToMetaDataKey;
52 while (map->tag) {
53 if (!strcmp(map->tag, tag))
54 return map->key;
55 ++map;
56 }
57 return QMediaMetaData::Key(-1);
58}
59
60static const char *keyToTag(QMediaMetaData::Key key)
61{
62 auto *map = ffmpegTagToMetaDataKey;
63 while (map->tag) {
64 if (map->key == key)
65 return map->tag;
66 ++map;
67 }
68 return nullptr;
69}
70
71//internal
72void QFFmpegMetaData::addEntry(QMediaMetaData &metaData, AVDictionaryEntry *entry)
73{
74 qCDebug(qLcMetaData) << " checking:" << entry->key << entry->value;
75 QByteArray tag(entry->key);
77 if (key == QMediaMetaData::Key(-1))
78 return;
79 qCDebug(qLcMetaData) << " adding" << key;
80
81 auto *map = &metaData;
82
83 int metaTypeId = keyType(key).id();
84 switch (metaTypeId) {
85 case qMetaTypeId<QString>():
87 return;
88 case qMetaTypeId<QStringList>():
90 return;
91 case qMetaTypeId<QDateTime>(): {
93 if (!qstrcmp(entry->key, "year")) {
95 return;
96 date = QDateTime(QDate(QByteArray(entry->value).toInt(), 1, 1), QTime(0, 0, 0));
97 } else {
98 date = QDateTime::fromString(QString::fromUtf8(entry->value), Qt::ISODate);
99 }
100 map->insert(key, date);
101 return;
102 }
103 case qMetaTypeId<QUrl>():
105 return;
106 case qMetaTypeId<qint64>():
108 return;
109 case qMetaTypeId<int>():
110 map->insert(key, QByteArray(entry->value).toInt());
111 return;
112 case qMetaTypeId<qreal>():
114 return;
115 default:
116 break;
117 }
118 if (metaTypeId == qMetaTypeId<QLocale::Language>()) {
120 }
121}
122
123
125{
126 QMediaMetaData metaData;
127 AVDictionaryEntry *entry = nullptr;
128 while ((entry = av_dict_get(tags, "", entry, AV_DICT_IGNORE_SUFFIX)))
129 addEntry(metaData, entry);
130
131 return metaData;
132}
133
135{
136 const int metaTypeId = keyType(key).id();
137 const QVariant val = metaData.value(key);
138 switch (metaTypeId) {
139 case qMetaTypeId<QString>():
140 return val.toString().toUtf8();
141 case qMetaTypeId<QStringList>():
142 return val.toStringList().join(u",").toUtf8();
143 case qMetaTypeId<QDateTime>():
144 return val.toDateTime().toString(Qt::ISODate).toUtf8();
145 case qMetaTypeId<QUrl>():
146 return val.toUrl().toEncoded();
147 case qMetaTypeId<qint64>():
148 case qMetaTypeId<int>():
149 return QByteArray::number(val.toLongLong());
150 case qMetaTypeId<qreal>():
151 return QByteArray::number(val.toDouble());
152 default:
153 break;
154 }
155 if (metaTypeId == qMetaTypeId<QLocale::Language>())
157 return {};
158}
159
160
161AVDictionary *QFFmpegMetaData::toAVMetaData(const QMediaMetaData &metaData)
162{
163 const QList<Key> keys = metaData.keys();
164 AVDictionary *dict = nullptr;
165 for (const auto &k : keys) {
166 const char *key = ::keyToTag(k);
167 if (!key)
168 continue;
169 QByteArray val = value(metaData, k);
170 if (val.isEmpty())
171 continue;
172 av_dict_set(&dict, key, val.constData(), 0);
173 }
174 return dict;
175}
176
177
178
\inmodule QtCore
Definition qbytearray.h:57
qlonglong toLongLong(bool *ok=nullptr, int base=10) const
Returns the byte array converted to a {long long} using base base, which is ten by default.
int toInt(bool *ok=nullptr, int base=10) const
Returns the byte array converted to an int using base base, which is ten by default.
double toDouble(bool *ok=nullptr) const
Returns the byte array converted to a double value.
static QByteArray number(int, int base=10)
Returns a byte-array representing the whole number n as text.
\inmodule QtCore\reentrant
Definition qdatetime.h:257
\inmodule QtCore \reentrant
Definition qdatetime.h:27
static QByteArray value(const QMediaMetaData &metaData, QMediaMetaData::Key key)
static AVDictionary * toAVMetaData(const QMediaMetaData &metaData)
static QMediaMetaData fromAVMetaData(const AVDictionary *tags)
static void addEntry(QMediaMetaData &metaData, AVDictionaryEntry *entry)
Definition qlist.h:74
static QString languageToCode(Language language, LanguageCodeTypes codeTypes=AnyLanguageCode)
Returns the two- or three-letter language code for language, as defined in the ISO 639 standards.
Definition qlocale.cpp:1420
@ ISO639Part2
Definition qlocale.h:1066
static Language codeToLanguage(QStringView languageCode, LanguageCodeTypes codeTypes=AnyLanguageCode) noexcept
Returns the QLocale::Language enum corresponding to the two- or three-letter languageCode,...
Definition qlocale.cpp:1440
iterator insert(const Key &key, const T &value)
Definition qmap.h:687
QList< Key > keys() const
Definition qmap.h:382
Key key(const T &value, const Key &defaultKey=Key()) const
Definition qmap.h:348
\inmodule QtMultimedia
Q_INVOKABLE QVariant value(Key k) const
\variable QMediaMetaData::NumMetaData
Q_INVOKABLE QList< Key > keys() const
\qmlmethod list<Key> QtMultimedia::mediaMetaData::keys() Returns a list of MediaMetaData....
static QMetaType keyType(Key key)
Returns the meta type used to store data for Key key.
int id(int=0) const
Definition qmetatype.h:454
QStringList split(const QString &sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the string into substrings wherever sep occurs, and returns the list of those strings.
Definition qstring.cpp:7956
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5857
QByteArray toUtf8() const &
Definition qstring.h:563
\inmodule QtCore \reentrant
Definition qdatetime.h:189
static QUrl fromEncoded(QByteArrayView input, ParsingMode mode=TolerantMode)
Parses input and returns the corresponding QUrl.
Definition qurl.cpp:2985
\inmodule QtCore
Definition qvariant.h:64
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
Definition qvariant.h:531
QMap< QString, QString > map
[6]
QDate date
[1]
Combined button and popup list for selecting options.
@ ISODate
Q_CORE_EXPORT int qstrcmp(const char *str1, const char *str2)
AudioChannelLayoutTag tag
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
static QMediaMetaData::Key tagToKey(const char *tag)
static const char * keyToTag(QMediaMetaData::Key key)
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
GLuint64 key
GLuint GLfloat * val
GLuint entry
long long qint64
Definition qtypes.h:55
double qreal
Definition qtypes.h:92
\inmodule QtCore \reentrant
Definition qchar.h:17
bool contains(const AT &t) const noexcept
Definition qlist.h:44