1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "camerabinmetadata.h"
41
42#include <QtMultimedia/qmediametadata.h>
43
44#include <gst/gst.h>
45#include <gst/gstversion.h>
46#include <private/qgstutils_p.h>
47
48#include <QDebug>
49
50QT_BEGIN_NAMESPACE
51
52namespace {
53 struct QGStreamerMetaDataKey
54 {
55 QString qtName;
56 const char *gstName;
57 QVariant::Type type;
58
59 QGStreamerMetaDataKey(const QString &qtn, const char *gstn, QVariant::Type t)
60 : qtName(qtn)
61 , gstName(gstn)
62 , type(t)
63 { }
64 };
65}
66
67typedef QList<QGStreamerMetaDataKey> QGStreamerMetaDataKeys;
68Q_GLOBAL_STATIC(QGStreamerMetaDataKeys, metadataKeys)
69
70static const QGStreamerMetaDataKeys *qt_gstreamerMetaDataKeys()
71{
72 if (metadataKeys->isEmpty()) {
73 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::Title, GST_TAG_TITLE, QVariant::String));
74 //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::SubTitle, 0, QVariant::String));
75 //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Author, 0, QVariant::String));
76 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::Comment, GST_TAG_COMMENT, QVariant::String));
77#if GST_CHECK_VERSION(0,10,31)
78 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::Date, GST_TAG_DATE_TIME, QVariant::DateTime));
79#endif
80 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::Description, GST_TAG_DESCRIPTION, QVariant::String));
81 //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Category, 0, QVariant::String));
82 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::Genre, GST_TAG_GENRE, QVariant::String));
83 //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Year, 0, QVariant::Int));
84 //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::UserRating, , QVariant::Int));
85
86 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::Language, GST_TAG_LANGUAGE_CODE, QVariant::String));
87
88 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::Publisher, GST_TAG_ORGANIZATION, QVariant::String));
89 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::Copyright, GST_TAG_COPYRIGHT, QVariant::String));
90 //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::ParentalRating, 0, QVariant::String));
91 //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::RatingOrganisation, 0, QVariant::String));
92
93 // Media
94 //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Size, 0, QVariant::Int));
95 //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::MediaType, 0, QVariant::String));
96 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::Duration, GST_TAG_DURATION, QVariant::Int));
97
98 // Audio
99 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::AudioBitRate, GST_TAG_BITRATE, QVariant::Int));
100 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::AudioCodec, GST_TAG_AUDIO_CODEC, QVariant::String));
101 //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::ChannelCount, 0, QVariant::Int));
102 //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::SampleRate, 0, QVariant::Int));
103
104 // Music
105 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::AlbumTitle, GST_TAG_ALBUM, QVariant::String));
106 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::AlbumArtist, GST_TAG_ARTIST, QVariant::String));
107 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::ContributingArtist, GST_TAG_PERFORMER, QVariant::String));
108#if GST_CHECK_VERSION(0,10,19)
109 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::Composer, GST_TAG_COMPOSER, QVariant::String));
110#endif
111 //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Conductor, 0, QVariant::String));
112 //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Lyrics, 0, QVariant::String));
113 //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Mood, 0, QVariant::String));
114 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::TrackNumber, GST_TAG_TRACK_NUMBER, QVariant::Int));
115
116 //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::CoverArtUrlSmall, 0, QVariant::String));
117 //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::CoverArtUrlLarge, 0, QVariant::String));
118
119 // Image/Video
120 //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Resolution, 0, QVariant::Size));
121 //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::PixelAspectRatio, 0, QVariant::Size));
122
123 // Video
124 //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::VideoFrameRate, 0, QVariant::String));
125 //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::VideoBitRate, 0, QVariant::Double));
126 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::VideoCodec, GST_TAG_VIDEO_CODEC, QVariant::String));
127
128 //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::PosterUrl, 0, QVariant::String));
129
130 // Movie
131 //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::ChapterNumber, 0, QVariant::Int));
132 //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Director, 0, QVariant::String));
133 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::LeadPerformer, GST_TAG_PERFORMER, QVariant::String));
134 //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Writer, 0, QVariant::String));
135#if GST_CHECK_VERSION(0,10,30)
136 // Photos
137 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::CameraManufacturer, GST_TAG_DEVICE_MANUFACTURER, QVariant::String));
138 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::CameraModel, GST_TAG_DEVICE_MODEL, QVariant::String));
139 //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Event, 0, QVariant::String));
140 //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Subject, 0, QVariant::String));
141
142 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::Orientation, GST_TAG_IMAGE_ORIENTATION, QVariant::String));
143
144 // GPS
145 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::GPSLatitude, GST_TAG_GEO_LOCATION_LATITUDE, QVariant::Double));
146 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::GPSLongitude, GST_TAG_GEO_LOCATION_LONGITUDE, QVariant::Double));
147 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::GPSAltitude, GST_TAG_GEO_LOCATION_ELEVATION, QVariant::Double));
148 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::GPSTrack, GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, QVariant::Double));
149 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::GPSSpeed, GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, QVariant::Double));
150 metadataKeys->append(t: QGStreamerMetaDataKey(QMediaMetaData::GPSImgDirection, GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, QVariant::Double));
151#endif
152 }
153
154 return metadataKeys;
155}
156
157CameraBinMetaData::CameraBinMetaData(QObject *parent)
158 :QMetaDataWriterControl(parent)
159{
160}
161
162QVariant CameraBinMetaData::metaData(const QString &key) const
163{
164#if GST_CHECK_VERSION(0,10,30)
165 if (key == QMediaMetaData::Orientation) {
166 return QGstUtils::fromGStreamerOrientation(value: m_values.value(akey: QByteArray(GST_TAG_IMAGE_ORIENTATION)));
167 } else if (key == QMediaMetaData::GPSSpeed) {
168 const double metersPerSec = m_values.value(akey: QByteArray(GST_TAG_GEO_LOCATION_MOVEMENT_SPEED)).toDouble();
169 return (metersPerSec * 3600) / 1000;
170 }
171#endif
172
173 const auto keys = *qt_gstreamerMetaDataKeys();
174 for (const QGStreamerMetaDataKey &metadataKey : keys) {
175 if (metadataKey.qtName == key)
176 return m_values.value(akey: QByteArray::fromRawData(metadataKey.gstName, size: qstrlen(str: metadataKey.gstName)));
177 }
178 return QVariant();
179}
180
181void CameraBinMetaData::setMetaData(const QString &key, const QVariant &value)
182{
183 QVariant correctedValue = value;
184#if GST_CHECK_VERSION(0,10,30)
185 if (value.isValid()) {
186 if (key == QMediaMetaData::Orientation) {
187 correctedValue = QGstUtils::toGStreamerOrientation(value);
188 } else if (key == QMediaMetaData::GPSSpeed) {
189 // kilometers per hour to meters per second.
190 correctedValue = (value.toDouble() * 1000) / 3600;
191 }
192 }
193#endif
194
195 const auto keys = *qt_gstreamerMetaDataKeys();
196 for (const QGStreamerMetaDataKey &metadataKey : keys) {
197 if (metadataKey.qtName == key) {
198 const char *name = metadataKey.gstName;
199
200 if (correctedValue.isValid()) {
201 correctedValue.convert(targetTypeId: metadataKey.type);
202 m_values.insert(akey: QByteArray::fromRawData(name, size: qstrlen(str: name)), avalue: correctedValue);
203 } else {
204 m_values.remove(akey: QByteArray::fromRawData(name, size: qstrlen(str: name)));
205 }
206
207 emit QMetaDataWriterControl::metaDataChanged();
208 emit metaDataChanged(m_values);
209
210 return;
211 }
212 }
213}
214
215QStringList CameraBinMetaData::availableMetaData() const
216{
217 static QMap<QByteArray, QString> keysMap;
218 if (keysMap.isEmpty()) {
219 const auto keys = *qt_gstreamerMetaDataKeys();
220 for (const QGStreamerMetaDataKey &metadataKey : keys)
221 keysMap[QByteArray(metadataKey.gstName)] = metadataKey.qtName;
222 }
223
224 QStringList res;
225 for (auto it = m_values.keyBegin(), end = m_values.keyEnd(); it != end; ++it) {
226 QString tag = keysMap.value(akey: *it);
227 if (!tag.isEmpty())
228 res.append(t: tag);
229 }
230
231 return res;
232}
233
234QT_END_NAMESPACE
235

source code of qtmultimedia/src/plugins/gstreamer/camerabin/camerabinmetadata.cpp