diff options
author | Tim Blechmann <tim@klingt.org> | 2024-05-01 21:00:24 +0800 |
---|---|---|
committer | Tim Blechmann <tim@klingt.org> | 2024-05-07 08:35:32 +0800 |
commit | 32c77267af32a82da040811d4b6d2274b34fa577 (patch) | |
tree | ae2045bd3e8ca6706cd5a60a3fbb4ff5c828ea68 | |
parent | c599e85c50858d57de92ba4316011ea3872b95a3 (diff) |
GStreamer: fix access to duration metadata
Fixes: QTBUG-124544
Pick-to: 6.5 6.7
Change-Id: I6cf975fab3644a7c5d51908f30441a22e6321573
Reviewed-by: Jøger Hansegård <joger.hansegard@qt.io>
3 files changed, 63 insertions, 3 deletions
diff --git a/src/plugins/multimedia/gstreamer/common/qgst_handle_types_p.h b/src/plugins/multimedia/gstreamer/common/qgst_handle_types_p.h index c37ac5971..5cbbfaf19 100644 --- a/src/plugins/multimedia/gstreamer/common/qgst_handle_types_p.h +++ b/src/plugins/multimedia/gstreamer/common/qgst_handle_types_p.h @@ -163,6 +163,18 @@ struct QUniqueGErrorHandleTraits } }; + +struct QUniqueGstDateTimeHandleTraits +{ + using Type = GstDateTime *; + static constexpr Type invalidValue() noexcept { return nullptr; } + static bool close(Type handle) noexcept + { + gst_date_time_unref(handle); + return true; + } +}; + struct QFileDescriptorHandleTraits { using Type = int; @@ -237,6 +249,7 @@ using QGstSampleHandle = QGstImpl::QSharedHandle<QGstImpl::QGstSampleHandleTrait using QUniqueGstStructureHandle = QUniqueHandle<QGstImpl::QUniqueGstStructureHandleTraits>; using QUniqueGStringHandle = QUniqueHandle<QGstImpl::QUniqueGStringHandleTraits>; using QUniqueGErrorHandle = QUniqueHandle<QGstImpl::QUniqueGErrorHandleTraits>; +using QUniqueGstDateTimeHandle = QUniqueHandle<QGstImpl::QUniqueGstDateTimeHandleTraits>; using QFileDescriptorHandle = QUniqueHandle<QGstImpl::QFileDescriptorHandleTraits>; using QGstBufferHandle = QGstImpl::QGstMiniObjectHandleHelper<GstBuffer>::SharedHandle; using QGstContextHandle = QGstImpl::QGstMiniObjectHandleHelper<GstContext>::UniqueHandle; diff --git a/src/plugins/multimedia/gstreamer/common/qgstreamermetadata.cpp b/src/plugins/multimedia/gstreamer/common/qgstreamermetadata.cpp index 3a229877d..fab4750f9 100644 --- a/src/plugins/multimedia/gstreamer/common/qgstreamermetadata.cpp +++ b/src/plugins/multimedia/gstreamer/common/qgstreamermetadata.cpp @@ -234,20 +234,68 @@ std::optional<double> parseFractionAsDouble(const GValue &val) return double(nom) / double(denom); } -// internal +constexpr std::string_view extendedComment{ GST_TAG_EXTENDED_COMMENT }; + +void addTagsFromExtendedComment(const GstTagList *list, const gchar *tag, QMediaMetaData &metadata) +{ + using namespace Qt::Literals; + assert(tag == extendedComment); + + int entryCount = gst_tag_list_get_tag_size(list, tag); + for (int i = 0; i != entryCount; ++i) { + const GValue *value = gst_tag_list_get_value_index(list, tag, i); + + const QLatin1StringView strValue{ g_value_get_string(value) }; + + auto equalIndex = strValue.indexOf(QLatin1StringView("=")); + if (equalIndex == -1) { + qDebug() << "Cannot parse GST_TAG_EXTENDED_COMMENT entry: " << value; + continue; + } + + const QLatin1StringView key = strValue.first(equalIndex); + const QLatin1StringView valueString = strValue.last(strValue.size() - equalIndex - 1); + + if (key == "DURATION"_L1) { + QUniqueGstDateTimeHandle duration{ + gst_date_time_new_from_iso8601_string(valueString.data()), + }; + + if (duration) { + using namespace std::chrono; + + auto chronoDuration = hours(gst_date_time_get_hour(duration.get())) + + minutes(gst_date_time_get_minute(duration.get())) + + seconds(gst_date_time_get_second(duration.get())) + + microseconds(gst_date_time_get_microsecond(duration.get())); + + metadata.insert(QMediaMetaData::Duration, + QVariant::fromValue(round<milliseconds>(chronoDuration).count())); + } + } + } +} + void addTagToMetaData(const GstTagList *list, const gchar *tag, void *userdata) { QMediaMetaData &metadata = *reinterpret_cast<QMediaMetaData *>(userdata); QMediaMetaData::Key key = tagToKey(tag); - if (key == QMediaMetaData::Key(-1)) + if (key == QMediaMetaData::Key(-1)) { + if (tag == extendedComment) + addTagsFromExtendedComment(list, tag, metadata); + return; + } GValue val{}; gst_tag_list_copy_value(&val, list, tag); GType type = G_VALUE_TYPE(&val); + if (auto entryCount = gst_tag_list_get_tag_size(list, tag) != 0; entryCount != 1) + qWarning() << "addTagToMetaData: invaled entry count for" << tag << "-" << entryCount; + if (type == G_TYPE_STRING) { const gchar *str_value = g_value_get_string(&val); diff --git a/tests/auto/unit/multimedia/gstreamer_backend/tst_gstreamer_backend.cpp b/tests/auto/unit/multimedia/gstreamer_backend/tst_gstreamer_backend.cpp index d51962076..d94d0831a 100644 --- a/tests/auto/unit/multimedia/gstreamer_backend/tst_gstreamer_backend.cpp +++ b/tests/auto/unit/multimedia/gstreamer_backend/tst_gstreamer_backend.cpp @@ -70,7 +70,6 @@ void tst_GStreamer::metadata_taglistToMetaData_extractsDuration() QMediaMetaData parsed = taglistToMetaData(tagList.get()); - QEXPECT_FAIL("", "duration in extended comment", Continue); QCOMPARE(parsed[QMediaMetaData::Duration].value<int>(), 400); } |