diff options
-rw-r--r-- | src/multimedia/video/qvideoframe.cpp | 53 | ||||
-rw-r--r-- | src/multimedia/video/qvideoframe.h | 6 | ||||
-rw-r--r-- | tests/auto/unit/qvideoframe/tst_qvideoframe.cpp | 60 |
3 files changed, 103 insertions, 16 deletions
diff --git a/src/multimedia/video/qvideoframe.cpp b/src/multimedia/video/qvideoframe.cpp index 687716ac8..c58b6ebe8 100644 --- a/src/multimedia/video/qvideoframe.cpp +++ b/src/multimedia/video/qvideoframe.cpp @@ -115,6 +115,7 @@ public: QAbstractVideoBuffer *buffer; int mappedCount; QMutex mapMutex; + QVariantMap metadata; private: Q_DISABLE_COPY(QVideoFramePrivate) @@ -754,6 +755,45 @@ void QVideoFrame::setEndTime(qint64 time) } /*! + Returns any extra metadata associated with this frame. + */ +QVariantMap QVideoFrame::availableMetaData() const +{ + return d->metadata; +} + +/*! + Returns any metadata for this frame for the given \a key. + + This might include frame specific information from + a camera, or subtitles from a decoded video stream. + + See the documentation for the relevant video frame + producer for further information about available metadata. + */ +QVariant QVideoFrame::metaData(const QString &key) const +{ + return d->metadata.value(key); +} + +/*! + Sets the metadata for the given \a key to \a value. + + If \a value is a null variant, any metadata for this key will be removed. + + The producer of the video frame might use this to associate + certain data with this frame, or for an intermediate processor + to add information for a consumer of this frame. + */ +void QVideoFrame::setMetaData(const QString &key, const QVariant &value) +{ + if (!value.isNull()) + d->metadata.insert(key, value); + else + d->metadata.remove(key); +} + +/*! Returns a video pixel format equivalent to an image \a format. If there is no equivalent format QVideoFrame::InvalidType is returned instead. @@ -843,6 +883,9 @@ QImage::Format QVideoFrame::imageFormatFromPixelFormat(PixelFormat format) return QImage::Format_Invalid; } + + + #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug dbg, QVideoFrame::PixelFormat pf) { @@ -1005,12 +1048,16 @@ static QString qFormatTimeStamps(qint64 start, qint64 end) QDebug operator<<(QDebug dbg, const QVideoFrame& f) { - return dbg << "QVideoFrame(" << f.size() << "," + dbg.nospace() << "QVideoFrame(" << f.size() << "," << f.pixelFormat() << ", " << f.handleType() << ", " << f.mapMode() << ", " - << qFormatTimeStamps(f.startTime(), f.endTime()).toLatin1().constData() - << ")"; + << qFormatTimeStamps(f.startTime(), f.endTime()).toLatin1().constData(); + if (f.availableMetaData().count()) { + dbg.nospace() << ", metaData: "; + dbg.nospace() << f.availableMetaData(); + } + return dbg.nospace() << ")"; } #endif diff --git a/src/multimedia/video/qvideoframe.h b/src/multimedia/video/qvideoframe.h index 5c3558721..f6261625e 100644 --- a/src/multimedia/video/qvideoframe.h +++ b/src/multimedia/video/qvideoframe.h @@ -46,6 +46,7 @@ #include <QtCore/qshareddata.h> #include <QtGui/qimage.h> #include <qabstractvideobuffer.h> +#include <QtCore/qvariant.h> QT_BEGIN_HEADER @@ -54,7 +55,6 @@ QT_BEGIN_NAMESPACE QT_MODULE(Multimedia) class QSize; -class QVariant; class QVideoFramePrivate; @@ -156,6 +156,10 @@ public: qint64 endTime() const; void setEndTime(qint64 time); + QVariantMap availableMetaData() const; + QVariant metaData(const QString &key) const; + void setMetaData(const QString &key, const QVariant &value); + static PixelFormat pixelFormatFromImageFormat(QImage::Format format); static QImage::Format imageFormatFromPixelFormat(PixelFormat format); diff --git a/tests/auto/unit/qvideoframe/tst_qvideoframe.cpp b/tests/auto/unit/qvideoframe/tst_qvideoframe.cpp index e61fd81a1..810bd7372 100644 --- a/tests/auto/unit/qvideoframe/tst_qvideoframe.cpp +++ b/tests/auto/unit/qvideoframe/tst_qvideoframe.cpp @@ -91,6 +91,8 @@ private slots: void formatConversion_data(); void formatConversion(); + void metadata(); + void debugType_data(); void debugType(); @@ -903,6 +905,35 @@ void tst_QVideoFrame::formatConversion() pixelFormat != QVideoFrame::Format_Invalid); } +void tst_QVideoFrame::metadata() +{ + // Simple metadata test + QVideoFrame f; + + QCOMPARE(f.availableMetaData(), QVariantMap()); + f.setMetaData("frob", QVariant("string")); + f.setMetaData("bar", QVariant(42)); + QCOMPARE(f.metaData("frob"), QVariant("string")); + QCOMPARE(f.metaData("bar"), QVariant(42)); + + QVariantMap map; + map.insert("frob", QVariant("string")); + map.insert("bar", QVariant(42)); + + QCOMPARE(f.availableMetaData(), map); + + f.setMetaData("frob", QVariant(56)); + QCOMPARE(f.metaData("frob"), QVariant(56)); + + f.setMetaData("frob", QVariant()); + QCOMPARE(f.metaData("frob"), QVariant()); + + QCOMPARE(f.availableMetaData().count(), 1); + + f.setMetaData("frob", QVariant("")); // empty but not null + QCOMPARE(f.availableMetaData().count(), 2); +} + #define TEST_MAPPED(frame, mode) \ do { \ QVERIFY(frame.bits()); \ @@ -1023,56 +1054,61 @@ void tst_QVideoFrame::debug_data() QTest::addColumn<QString>("stringized"); QVideoFrame f; - QTest::newRow("default") << f << QString::fromLatin1("QVideoFrame( QSize(-1, -1) , Format_Invalid, NoHandle, NotMapped, [no timestamp])"); + QTest::newRow("default") << f << QString::fromLatin1("QVideoFrame(QSize(-1, -1) , Format_Invalid, NoHandle, NotMapped, [no timestamp])"); QVideoFrame f2; f2.setStartTime(12345); f2.setEndTime(8000000000LL); - QTest::newRow("times") << f2 << QString::fromLatin1("QVideoFrame( QSize(-1, -1) , Format_Invalid, NoHandle, NotMapped, 0:00:00.12345 - 2:13:20.00)"); + QTest::newRow("times") << f2 << QString::fromLatin1("QVideoFrame(QSize(-1, -1) , Format_Invalid, NoHandle, NotMapped, 0:00:00.12345 - 2:13:20.00)"); QVideoFrame f3; f3.setFieldType(QVideoFrame::ProgressiveFrame); - QTest::newRow("times prog") << f3 << QString::fromLatin1("QVideoFrame( QSize(-1, -1) , Format_Invalid, NoHandle, NotMapped, [no timestamp])"); + QTest::newRow("times prog") << f3 << QString::fromLatin1("QVideoFrame(QSize(-1, -1) , Format_Invalid, NoHandle, NotMapped, [no timestamp])"); QVideoFrame f4; f4.setFieldType(QVideoFrame::TopField); - QTest::newRow("times top") << f4 << QString::fromLatin1("QVideoFrame( QSize(-1, -1) , Format_Invalid, NoHandle, NotMapped, [no timestamp])"); + QTest::newRow("times top") << f4 << QString::fromLatin1("QVideoFrame(QSize(-1, -1) , Format_Invalid, NoHandle, NotMapped, [no timestamp])"); QVideoFrame f5; f5.setFieldType(QVideoFrame::TopField); f5.setEndTime(90000000000LL); - QTest::newRow("end but no start") << f5 << QString::fromLatin1("QVideoFrame( QSize(-1, -1) , Format_Invalid, NoHandle, NotMapped, [no timestamp])"); + QTest::newRow("end but no start") << f5 << QString::fromLatin1("QVideoFrame(QSize(-1, -1) , Format_Invalid, NoHandle, NotMapped, [no timestamp])"); QVideoFrame f6; f6.setStartTime(12345000000LL); f6.setEndTime(80000000000LL); - QTest::newRow("times big") << f6 << QString::fromLatin1("QVideoFrame( QSize(-1, -1) , Format_Invalid, NoHandle, NotMapped, 3:25:45.00 - 22:13:20.00)"); + QTest::newRow("times big") << f6 << QString::fromLatin1("QVideoFrame(QSize(-1, -1) , Format_Invalid, NoHandle, NotMapped, 3:25:45.00 - 22:13:20.00)"); QVideoFrame g(0, QSize(320,240), 640, QVideoFrame::Format_ARGB32); - QTest::newRow("more valid") << g << QString::fromLatin1("QVideoFrame( QSize(320, 240) , Format_ARGB32, NoHandle, NotMapped, [no timestamp])"); + QTest::newRow("more valid") << g << QString::fromLatin1("QVideoFrame(QSize(320, 240) , Format_ARGB32, NoHandle, NotMapped, [no timestamp])"); QVideoFrame g2(0, QSize(320,240), 640, QVideoFrame::Format_ARGB32); g2.setStartTime(9000000000LL); g2.setEndTime(9000000000LL); - QTest::newRow("more valid") << g2 << QString::fromLatin1("QVideoFrame( QSize(320, 240) , Format_ARGB32, NoHandle, NotMapped, @2:30:00.00)"); + QTest::newRow("more valid") << g2 << QString::fromLatin1("QVideoFrame(QSize(320, 240) , Format_ARGB32, NoHandle, NotMapped, @2:30:00.00)"); QVideoFrame g3(0, QSize(320,240), 640, QVideoFrame::Format_ARGB32); g3.setStartTime(900000LL); g3.setEndTime(900000LL); - QTest::newRow("more valid single timestamp") << g3 << QString::fromLatin1("QVideoFrame( QSize(320, 240) , Format_ARGB32, NoHandle, NotMapped, @00:00.900000)"); + QTest::newRow("more valid single timestamp") << g3 << QString::fromLatin1("QVideoFrame(QSize(320, 240) , Format_ARGB32, NoHandle, NotMapped, @00:00.900000)"); QVideoFrame g4(0, QSize(320,240), 640, QVideoFrame::Format_ARGB32); g4.setStartTime(200000000LL); g4.setEndTime(300000000LL); - QTest::newRow("more valid") << g4 << QString::fromLatin1("QVideoFrame( QSize(320, 240) , Format_ARGB32, NoHandle, NotMapped, 03:20.00 - 05:00.00)"); + QTest::newRow("more valid") << g4 << QString::fromLatin1("QVideoFrame(QSize(320, 240) , Format_ARGB32, NoHandle, NotMapped, 03:20.00 - 05:00.00)"); QVideoFrame g5(0, QSize(320,240), 640, QVideoFrame::Format_ARGB32); g5.setStartTime(200000000LL); - QTest::newRow("more valid until forever") << g5 << QString::fromLatin1("QVideoFrame( QSize(320, 240) , Format_ARGB32, NoHandle, NotMapped, 03:20.00 - forever)"); + QTest::newRow("more valid until forever") << g5 << QString::fromLatin1("QVideoFrame(QSize(320, 240) , Format_ARGB32, NoHandle, NotMapped, 03:20.00 - forever)"); QVideoFrame g6(0, QSize(320,240), 640, QVideoFrame::Format_ARGB32); g6.setStartTime(9000000000LL); - QTest::newRow("more valid for long forever") << g6 << QString::fromLatin1("QVideoFrame( QSize(320, 240) , Format_ARGB32, NoHandle, NotMapped, 2:30:00.00 - forever)"); + QTest::newRow("more valid for long forever") << g6 << QString::fromLatin1("QVideoFrame(QSize(320, 240) , Format_ARGB32, NoHandle, NotMapped, 2:30:00.00 - forever)"); + + QVideoFrame g7(0, QSize(320,240), 640, QVideoFrame::Format_ARGB32); + g7.setStartTime(9000000000LL); + g7.setMetaData("bar", 42); + QTest::newRow("more valid for long forever + metadata") << g7 << QString::fromLatin1("QVideoFrame(QSize(320, 240) , Format_ARGB32, NoHandle, NotMapped, 2:30:00.00 - forever, metaData: QMap((\"bar\", QVariant(int, 42) ) ) )"); } void tst_QVideoFrame::debug() |