summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Blechmann <tim@klingt.org>2024-02-29 12:37:30 +0800
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2024-03-08 09:21:01 +0000
commite3a250d53454ae65cc55c384502e063dcd87ac09 (patch)
tree461c83c0dd00e81389a4a2dd5c4bc1ad30e370cc
parent83122d3a8ada9786467bbc2d4867e155779e4d8e (diff)
GStreamer: introduce GList range adaptor
Remove boilerplate code when iterating GLists. Pick-to: 6.5 Change-Id: I66603585e51b27f2302d83a08e03ba104871232a Reviewed-by: Artem Dyomin <artem.dyomin@qt.io> (cherry picked from commit 40bb9be18b0e249dee430eb72539309331fb35f0) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> (cherry picked from commit 1ef7349ccefa27e68b5e18322872e38c9c4b0eb6)
-rw-r--r--src/plugins/multimedia/gstreamer/common/qglist_helper_p.h82
-rw-r--r--src/plugins/multimedia/gstreamer/common/qgstreamervideooverlay.cpp7
-rw-r--r--src/plugins/multimedia/gstreamer/qgstreamerformatinfo.cpp55
-rw-r--r--src/plugins/multimedia/gstreamer/qgstreamervideodevices.cpp7
4 files changed, 111 insertions, 40 deletions
diff --git a/src/plugins/multimedia/gstreamer/common/qglist_helper_p.h b/src/plugins/multimedia/gstreamer/common/qglist_helper_p.h
new file mode 100644
index 000000000..54108e1c3
--- /dev/null
+++ b/src/plugins/multimedia/gstreamer/common/qglist_helper_p.h
@@ -0,0 +1,82 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QGLIST_HELPER_P_H
+#define QGLIST_HELPER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qtconfigmacros.h>
+
+#include <glib.h>
+#include <iterator>
+
+QT_BEGIN_NAMESPACE
+
+namespace QGstUtils {
+
+template <typename ListType>
+struct GListIterator
+{
+ explicit GListIterator(const GList *element = nullptr) : element(element) { }
+
+ const ListType &operator*() const noexcept { return *operator->(); }
+ const ListType *operator->() const noexcept
+ {
+ return reinterpret_cast<const ListType *>(&element->data);
+ }
+
+ GListIterator &operator++() noexcept
+ {
+ if (element)
+ element = element->next;
+
+ return *this;
+ }
+ GListIterator operator++(int n) noexcept
+ {
+ for (int i = 0; i != n; ++i)
+ operator++();
+
+ return *this;
+ }
+
+ bool operator==(const GListIterator &r) const noexcept { return element == r.element; }
+ bool operator!=(const GListIterator &r) const noexcept { return element != r.element; }
+
+ using difference_type = std::ptrdiff_t;
+ using value_type = ListType;
+ using pointer = value_type *;
+ using reference = value_type &;
+ using iterator_category = std::input_iterator_tag;
+
+ const GList *element = nullptr;
+};
+
+template <typename ListType>
+struct GListRangeAdaptor
+{
+ static_assert(std::is_pointer_v<ListType>);
+
+ explicit GListRangeAdaptor(const GList *list) : head(list) { }
+
+ auto begin() { return GListIterator<ListType>(head); }
+ auto end() { return GListIterator<ListType>(nullptr); }
+
+ const GList *head;
+};
+
+} // namespace QGstUtils
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/multimedia/gstreamer/common/qgstreamervideooverlay.cpp b/src/plugins/multimedia/gstreamer/common/qgstreamervideooverlay.cpp
index b6d0de876..3def5f515 100644
--- a/src/plugins/multimedia/gstreamer/common/qgstreamervideooverlay.cpp
+++ b/src/plugins/multimedia/gstreamer/common/qgstreamervideooverlay.cpp
@@ -4,10 +4,11 @@
#include "qgstreamervideooverlay_p.h"
#include <QtGui/qguiapplication.h>
-#include "qgstutils_p.h"
+#include "qglist_helper_p.h"
#include "qgst_p.h"
#include "qgstreamermessage_p.h"
#include "qgstreamervideosink_p.h"
+#include "qgstutils_p.h"
#include <gst/video/videooverlay.h>
@@ -67,9 +68,7 @@ static QGstElement findBestVideoSink()
// If none of the known video sinks are available, try to find one that implements the
// GstVideoOverlay interface and has autoplugging rank.
GList *list = qt_gst_video_sinks();
- for (GList *item = list; item != nullptr; item = item->next) {
- GstElementFactory *f = GST_ELEMENT_FACTORY(item->data);
-
+ for (GstElementFactory *f : QGstUtils::GListRangeAdaptor<GstElementFactory *>(list)) {
if (!gst_element_factory_has_interface(f, "GstVideoOverlay"))
continue;
diff --git a/src/plugins/multimedia/gstreamer/qgstreamerformatinfo.cpp b/src/plugins/multimedia/gstreamer/qgstreamerformatinfo.cpp
index 70a824c8b..45291b7a6 100644
--- a/src/plugins/multimedia/gstreamer/qgstreamerformatinfo.cpp
+++ b/src/plugins/multimedia/gstreamer/qgstreamerformatinfo.cpp
@@ -1,6 +1,7 @@
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#include "qglist_helper_p.h"
#include "qgstreamerformatinfo_p.h"
QT_BEGIN_NAMESPACE
@@ -143,16 +144,11 @@ static QPair<QList<QMediaFormat::AudioCodec>, QList<QMediaFormat::VideoCodec>> g
GList *elementList = gst_element_factory_list_get_elements(decode ? GST_ELEMENT_FACTORY_TYPE_DECODER : GST_ELEMENT_FACTORY_TYPE_ENCODER,
GST_RANK_MARGINAL);
- GList *element = elementList;
- while (element) {
- GstElementFactory *factory = (GstElementFactory *)element->data;
- element = element->next;
-
- const GList *padTemplates = gst_element_factory_get_static_pad_templates(factory);
- while (padTemplates) {
- GstStaticPadTemplate *padTemplate = (GstStaticPadTemplate *)padTemplates->data;
- padTemplates = padTemplates->next;
-
+ for (GstElementFactory *factory :
+ QGstUtils::GListRangeAdaptor<GstElementFactory *>(elementList)) {
+ for (GstStaticPadTemplate *padTemplate :
+ QGstUtils::GListRangeAdaptor<GstStaticPadTemplate *>(
+ gst_element_factory_get_static_pad_templates(factory))) {
if (padTemplate->direction == padDirection) {
auto caps = QGstCaps(gst_static_caps_get(&padTemplate->static_caps), QGstCaps::HasRef);
@@ -181,19 +177,17 @@ QList<QGstreamerFormatInfo::CodecMap> QGstreamerFormatInfo::getMuxerList(bool de
GstPadDirection padDirection = demuxer ? GST_PAD_SINK : GST_PAD_SRC;
- GList *elementList = gst_element_factory_list_get_elements(demuxer ? GST_ELEMENT_FACTORY_TYPE_DEMUXER : GST_ELEMENT_FACTORY_TYPE_MUXER,
- GST_RANK_MARGINAL);
- GList *element = elementList;
- while (element) {
- GstElementFactory *factory = (GstElementFactory *)element->data;
- element = element->next;
+ GList *elementList = gst_element_factory_list_get_elements(
+ demuxer ? GST_ELEMENT_FACTORY_TYPE_DEMUXER : GST_ELEMENT_FACTORY_TYPE_MUXER,
+ GST_RANK_MARGINAL);
+ for (GstElementFactory *factory :
+ QGstUtils::GListRangeAdaptor<GstElementFactory *>(elementList)) {
QList<QMediaFormat::FileFormat> fileFormats;
- const GList *padTemplates = gst_element_factory_get_static_pad_templates(factory);
- while (padTemplates) {
- GstStaticPadTemplate *padTemplate = (GstStaticPadTemplate *)padTemplates->data;
- padTemplates = padTemplates->next;
+ for (GstStaticPadTemplate *padTemplate :
+ QGstUtils::GListRangeAdaptor<GstStaticPadTemplate *>(
+ gst_element_factory_get_static_pad_templates(factory))) {
if (padTemplate->direction == padDirection) {
auto caps = QGstCaps(gst_static_caps_get(&padTemplate->static_caps), QGstCaps::HasRef);
@@ -212,10 +206,9 @@ QList<QGstreamerFormatInfo::CodecMap> QGstreamerFormatInfo::getMuxerList(bool de
QList<QMediaFormat::AudioCodec> audioCodecs;
QList<QMediaFormat::VideoCodec> videoCodecs;
- padTemplates = gst_element_factory_get_static_pad_templates(factory);
- while (padTemplates) {
- GstStaticPadTemplate *padTemplate = (GstStaticPadTemplate *)padTemplates->data;
- padTemplates = padTemplates->next;
+ for (GstStaticPadTemplate *padTemplate :
+ QGstUtils::GListRangeAdaptor<GstStaticPadTemplate *>(
+ gst_element_factory_get_static_pad_templates(factory))) {
// check the other side for supported inputs/outputs
if (padTemplate->direction != padDirection) {
@@ -275,16 +268,12 @@ static QList<QImageCapture::FileFormat> getImageFormatList()
GList *elementList = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_ENCODER,
GST_RANK_MARGINAL);
- GList *element = elementList;
- while (element) {
- GstElementFactory *factory = (GstElementFactory *)element->data;
- element = element->next;
-
- const GList *padTemplates = gst_element_factory_get_static_pad_templates(factory);
- while (padTemplates) {
- GstStaticPadTemplate *padTemplate = (GstStaticPadTemplate *)padTemplates->data;
- padTemplates = padTemplates->next;
+ for (GstElementFactory *factory :
+ QGstUtils::GListRangeAdaptor<GstElementFactory *>(elementList)) {
+ for (GstStaticPadTemplate *padTemplate :
+ QGstUtils::GListRangeAdaptor<GstStaticPadTemplate *>(
+ gst_element_factory_get_static_pad_templates(factory))) {
if (padTemplate->direction == GST_PAD_SRC) {
QGstCaps caps = QGstCaps(gst_static_caps_get(&padTemplate->static_caps), QGstCaps::HasRef);
diff --git a/src/plugins/multimedia/gstreamer/qgstreamervideodevices.cpp b/src/plugins/multimedia/gstreamer/qgstreamervideodevices.cpp
index 799fa8792..ddb5fe605 100644
--- a/src/plugins/multimedia/gstreamer/qgstreamervideodevices.cpp
+++ b/src/plugins/multimedia/gstreamer/qgstreamervideodevices.cpp
@@ -6,6 +6,7 @@
#include "private/qcameradevice_p.h"
#include "qgstutils_p.h"
+#include "qglist_helper_p.h"
QT_BEGIN_NAMESPACE
@@ -46,14 +47,14 @@ QGstreamerVideoDevices::QGstreamerVideoDevices(QPlatformMediaIntegration *integr
GList *devices = gst_device_monitor_get_devices(m_deviceMonitor.get());
- while (devices) {
- GstDevice *device = static_cast<GstDevice *>(devices->data);
+ for (GstDevice *device : QGstUtils::GListRangeAdaptor<GstDevice *>(devices)) {
addDevice(QGstDeviceHandle{
device,
QGstDeviceHandle::HasRef,
});
- devices = g_list_delete_link(devices, devices);
}
+
+ g_list_free(devices);
}
QGstreamerVideoDevices::~QGstreamerVideoDevices()