diff options
author | Tim Blechmann <tim@klingt.org> | 2024-02-29 12:37:30 +0800 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2024-03-08 09:21:01 +0000 |
commit | e3a250d53454ae65cc55c384502e063dcd87ac09 (patch) | |
tree | 461c83c0dd00e81389a4a2dd5c4bc1ad30e370cc | |
parent | 83122d3a8ada9786467bbc2d4867e155779e4d8e (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)
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() |