Fix gstreamer crash when meta-data is of incorrect type.

GStreamer tags are typed and the correct type must be used when inserting
a value into a GstTagList or subsequent merges or data accesses can crash
because of invalid casts.

Found while adding additional mappings for GPS values.

Change-Id: I95ab40a480a4685bf4e69064315557faa9de288e
Reviewed-by: Yoann Lopes <yoann.lopes@digia.com>
This commit is contained in:
Andrew den Exter
2014-01-28 11:28:19 +10:00
committed by The Qt Project
parent 87b8b4489a
commit c949a98c42

View File

@@ -46,12 +46,15 @@
#include <gst/gst.h> #include <gst/gst.h>
#include <gst/gstversion.h> #include <gst/gstversion.h>
#include <QDebug>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
struct QGstreamerMetaDataKeyLookup struct QGstreamerMetaDataKeyLookup
{ {
QString key; QString key;
const char *token; const char *token;
QVariant::Type type;
}; };
static QVariant fromGStreamerOrientation(const QVariant &value) static QVariant fromGStreamerOrientation(const QVariant &value)
@@ -86,74 +89,77 @@ static QVariant toGStreamerOrientation(const QVariant &value)
static const QGstreamerMetaDataKeyLookup qt_gstreamerMetaDataKeys[] = static const QGstreamerMetaDataKeyLookup qt_gstreamerMetaDataKeys[] =
{ {
{ QMediaMetaData::Title, GST_TAG_TITLE }, { QMediaMetaData::Title, GST_TAG_TITLE, QVariant::String },
//{ QMediaMetaData::SubTitle, 0 }, //{ QMediaMetaData::SubTitle, 0, QVariant::String },
//{ QMediaMetaData::Author, 0 }, //{ QMediaMetaData::Author, 0, QVariant::String },
{ QMediaMetaData::Comment, GST_TAG_COMMENT }, { QMediaMetaData::Comment, GST_TAG_COMMENT, QVariant::String },
{ QMediaMetaData::Date, GST_TAG_DATE_TIME }, { QMediaMetaData::Date, GST_TAG_DATE_TIME, QVariant::DateTime },
{ QMediaMetaData::Description, GST_TAG_DESCRIPTION }, { QMediaMetaData::Description, GST_TAG_DESCRIPTION, QVariant::String },
//{ QMediaMetaData::Category, 0 }, //{ QMediaMetaData::Category, 0, QVariant::String },
{ QMediaMetaData::Genre, GST_TAG_GENRE }, { QMediaMetaData::Genre, GST_TAG_GENRE, QVariant::String },
//{ QMediaMetaData::Year, 0 }, //{ QMediaMetaData::Year, 0, QVariant::Int },
//{ QMediaMetaData::UserRating, 0 }, //{ QMediaMetaData::UserRating, , QVariant::Int },
{ QMediaMetaData::Language, GST_TAG_LANGUAGE_CODE }, { QMediaMetaData::Language, GST_TAG_LANGUAGE_CODE, QVariant::String },
{ QMediaMetaData::Publisher, GST_TAG_ORGANIZATION }, { QMediaMetaData::Publisher, GST_TAG_ORGANIZATION, QVariant::String },
{ QMediaMetaData::Copyright, GST_TAG_COPYRIGHT }, { QMediaMetaData::Copyright, GST_TAG_COPYRIGHT, QVariant::String },
//{ QMediaMetaData::ParentalRating, 0 }, //{ QMediaMetaData::ParentalRating, 0, QVariant::String },
//{ QMediaMetaData::RatingOrganisation, 0 }, //{ QMediaMetaData::RatingOrganisation, 0, QVariant::String },
// Media // Media
//{ QMediaMetaData::Size, 0 }, //{ QMediaMetaData::Size, 0, QVariant::Int },
//{ QMediaMetaData::MediaType, 0 }, //{ QMediaMetaData::MediaType, 0, QVariant::String },
{ QMediaMetaData::Duration, GST_TAG_DURATION }, { QMediaMetaData::Duration, GST_TAG_DURATION, QVariant::Int },
// Audio // Audio
{ QMediaMetaData::AudioBitRate, GST_TAG_BITRATE }, { QMediaMetaData::AudioBitRate, GST_TAG_BITRATE, QVariant::Int },
{ QMediaMetaData::AudioCodec, GST_TAG_AUDIO_CODEC }, { QMediaMetaData::AudioCodec, GST_TAG_AUDIO_CODEC, QVariant::String },
//{ QMediaMetaData::ChannelCount, 0 }, //{ QMediaMetaData::ChannelCount, 0, QVariant::Int },
//{ QMediaMetaData::SampleRate, 0 }, //{ QMediaMetaData::SampleRate, 0, QVariant::Int },
// Music // Music
{ QMediaMetaData::AlbumTitle, GST_TAG_ALBUM }, { QMediaMetaData::AlbumTitle, GST_TAG_ALBUM, QVariant::String },
{ QMediaMetaData::AlbumArtist, GST_TAG_ARTIST}, { QMediaMetaData::AlbumArtist, GST_TAG_ARTIST, QVariant::String},
{ QMediaMetaData::ContributingArtist, GST_TAG_PERFORMER }, { QMediaMetaData::ContributingArtist, GST_TAG_PERFORMER, QVariant::String },
#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19) #if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19)
{ QMediaMetaData::Composer, GST_TAG_COMPOSER }, { QMediaMetaData::Composer, GST_TAG_COMPOSER, QVariant::String },
#endif #endif
//{ QMediaMetaData::Conductor, 0 }, //{ QMediaMetaData::Conductor, 0, QVariant::String },
//{ QMediaMetaData::Lyrics, 0 }, //{ QMediaMetaData::Lyrics, 0, QVariant::String },
//{ QMediaMetaData::Mood, 0 }, //{ QMediaMetaData::Mood, 0, QVariant::String },
{ QMediaMetaData::TrackNumber, GST_TAG_TRACK_NUMBER }, { QMediaMetaData::TrackNumber, GST_TAG_TRACK_NUMBER, QVariant::Int },
//{ QMediaMetaData::CoverArtUrlSmall, 0 }, //{ QMediaMetaData::CoverArtUrlSmall, 0, QVariant::String },
//{ QMediaMetaData::CoverArtUrlLarge, 0 }, //{ QMediaMetaData::CoverArtUrlLarge, 0, QVariant::String },
// Image/Video // Image/Video
//{ QMediaMetaData::Resolution, 0 }, //{ QMediaMetaData::Resolution, 0, QVariant::Size },
//{ QMediaMetaData::PixelAspectRatio, 0 }, //{ QMediaMetaData::PixelAspectRatio, 0, QVariant::Size },
// Video // Video
//{ QMediaMetaData::VideoFrameRate, 0 }, //{ QMediaMetaData::VideoFrameRate, 0, QVariant::String },
//{ QMediaMetaData::VideoBitRate, 0 }, //{ QMediaMetaData::VideoBitRate, 0, QVariant::Double },
{ QMediaMetaData::VideoCodec, GST_TAG_VIDEO_CODEC }, { QMediaMetaData::VideoCodec, GST_TAG_VIDEO_CODEC, QVariant::String },
//{ QMediaMetaData::PosterUrl, 0 }, //{ QMediaMetaData::PosterUrl, 0, QVariant::String },
// Movie // Movie
//{ QMediaMetaData::ChapterNumber, 0 }, //{ QMediaMetaData::ChapterNumber, 0, QVariant::Int },
//{ QMediaMetaData::Director, 0 }, //{ QMediaMetaData::Director, 0, QVariant::String },
{ QMediaMetaData::LeadPerformer, GST_TAG_PERFORMER }, { QMediaMetaData::LeadPerformer, GST_TAG_PERFORMER, QVariant::String },
//{ QMediaMetaData::Writer, 0 }, //{ QMediaMetaData::Writer, 0, QVariant::String },
#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 30)
// Photos // Photos
//{ QMediaMetaData::CameraManufacturer, 0 }, { QMediaMetaData::CameraManufacturer, 0, QVariant::String },
//{ QMediaMetaData::CameraModel, 0 }, { QMediaMetaData::CameraModel, 0, QVariant::String },
//{ QMediaMetaData::Event, 0 }, //{ QMediaMetaData::Event, 0, QVariant::String },
//{ QMediaMetaData::Subject, 0 }, //{ QMediaMetaData::Subject, 0, QVariant::String },
{ QMediaMetaData::Orientation, GST_TAG_IMAGE_ORIENTATION } { QMediaMetaData::Orientation, GST_TAG_IMAGE_ORIENTATION, QVariant::String },
#endif
}; };
CameraBinMetaData::CameraBinMetaData(QObject *parent) CameraBinMetaData::CameraBinMetaData(QObject *parent)
@@ -165,6 +171,9 @@ QVariant CameraBinMetaData::metaData(const QString &key) const
{ {
if (key == QMediaMetaData::Orientation) { if (key == QMediaMetaData::Orientation) {
return fromGStreamerOrientation(m_values.value(QByteArray(GST_TAG_IMAGE_ORIENTATION))); return fromGStreamerOrientation(m_values.value(QByteArray(GST_TAG_IMAGE_ORIENTATION)));
} else if (key == QMediaMetaData::GPSSpeed) {
const double metersPerSec = m_values.value(QByteArray(GST_TAG_GEO_LOCATION_MOVEMENT_SPEED)).toDouble();
return (metersPerSec * 3600) / 1000;
} }
static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup); static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup);
@@ -181,13 +190,12 @@ QVariant CameraBinMetaData::metaData(const QString &key) const
void CameraBinMetaData::setMetaData(const QString &key, const QVariant &value) void CameraBinMetaData::setMetaData(const QString &key, const QVariant &value)
{ {
QVariant correctedValue = value;
if (key == QMediaMetaData::Orientation) { if (key == QMediaMetaData::Orientation) {
m_values.insert(QByteArray(GST_TAG_IMAGE_ORIENTATION), toGStreamerOrientation(value)); correctedValue = toGStreamerOrientation(value);
} else if (key == QMediaMetaData::GPSSpeed) {
emit QMetaDataWriterControl::metaDataChanged(); // kilometers per hour to meters per second.
emit metaDataChanged(m_values); correctedValue = (value.toDouble() * 1000) / 3600;
return;
} }
static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup); static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup);
@@ -196,7 +204,9 @@ void CameraBinMetaData::setMetaData(const QString &key, const QVariant &value)
if (qt_gstreamerMetaDataKeys[i].key == key) { if (qt_gstreamerMetaDataKeys[i].key == key) {
const char *name = qt_gstreamerMetaDataKeys[i].token; const char *name = qt_gstreamerMetaDataKeys[i].token;
m_values.insert(QByteArray::fromRawData(name, qstrlen(name)), value); correctedValue.convert(qt_gstreamerMetaDataKeys[i].type);
m_values.insert(QByteArray::fromRawData(name, qstrlen(name)), correctedValue);
emit QMetaDataWriterControl::metaDataChanged(); emit QMetaDataWriterControl::metaDataChanged();
emit metaDataChanged(m_values); emit metaDataChanged(m_values);