Skip to content

Commit 71db6e0

Browse files
committed
[GStreamer] add Rialto quirk
https://bugs.webkit.org/show_bug.cgi?id=273812 Reviewed by Philippe Normand. Original patch by Eugene Mutavchi <Ievgen_Mutavchi@comcast.com>. * Source/WebCore/platform/SourcesGStreamer.txt: * Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp: (WebCore::MediaPlayerPrivateGStreamer::createAudioSink): (WebCore::MediaPlayerPrivateGStreamer::createVideoSink): * Source/WebCore/platform/gstreamer/GStreamerHolePunchQuirkRialto.cpp: Added. (WebCore::GStreamerHolePunchQuirkRialto::createHolePunchVideoSink): (WebCore::GStreamerHolePunchQuirkRialto::setHolePunchVideoRectangle): * Source/WebCore/platform/gstreamer/GStreamerHolePunchQuirkRialto.h: Added. * Source/WebCore/platform/gstreamer/GStreamerQuirkRialto.cpp: Added. (WebCore::GStreamerQuirkRialto::GStreamerQuirkRialto): (WebCore::GStreamerQuirkRialto::configureElement): (WebCore::GStreamerQuirkRialto::createAudioSink): (WebCore::GStreamerQuirkRialto::createWebAudioSink): (WebCore::GStreamerQuirkRialto::isHardwareAccelerated): * Source/WebCore/platform/gstreamer/GStreamerQuirkRialto.h: Added. * Source/WebCore/platform/gstreamer/GStreamerQuirks.cpp: (WebCore::GStreamerQuirksManager::GStreamerQuirksManager): (WebCore::GStreamerQuirksManager::createAudioSink): * Source/WebCore/platform/gstreamer/GStreamerQuirks.h: (WebCore::GStreamerQuirk::createAudioSink): Canonical link: https://commits.webkit.org/278452@main
1 parent 33365d6 commit 71db6e0

8 files changed

Lines changed: 300 additions & 3 deletions

File tree

Source/WebCore/platform/GStreamer.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,13 @@ if (ENABLE_VIDEO OR ENABLE_WEB_AUDIO)
6868

6969
platform/gstreamer/GStreamerCodecUtilities.cpp
7070
platform/gstreamer/GStreamerHolePunchQuirkBcmNexus.cpp
71+
platform/gstreamer/GStreamerHolePunchQuirkRialto.cpp
7172
platform/gstreamer/GStreamerHolePunchQuirkWesteros.cpp
7273
platform/gstreamer/GStreamerQuirkAmLogic.cpp
7374
platform/gstreamer/GStreamerQuirkBcmNexus.cpp
7475
platform/gstreamer/GStreamerQuirkBroadcom.cpp
7576
platform/gstreamer/GStreamerQuirkRealtek.cpp
77+
platform/gstreamer/GStreamerQuirkRialto.cpp
7678
platform/gstreamer/GStreamerQuirkWesteros.cpp
7779
platform/gstreamer/GStreamerQuirks.cpp
7880
platform/gstreamer/VideoEncoderPrivateGStreamer.cpp

Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1317,7 +1317,7 @@ GstElement* MediaPlayerPrivateGStreamer::createAudioSink()
13171317
// If audio is being controlled by an another pipeline, creating sink here may interfere with
13181318
// audio playback. Instead, check if an audio sink was setup in handleMessage and use it.
13191319
if (quirksManager.isEnabled())
1320-
return nullptr;
1320+
return quirksManager.createAudioSink();
13211321

13221322
// For platform specific audio sinks, they need to be properly upranked so that they get properly autoplugged.
13231323

@@ -4121,8 +4121,14 @@ GstElement* MediaPlayerPrivateGStreamer::createVideoSink()
41214121
g_value_unset(&value);
41224122
}
41234123

4124-
uint64_t maxLateness = 100 * GST_MSECOND;
4125-
g_object_set(sink, "max-lateness", maxLateness, nullptr);
4124+
if (gstObjectHasProperty(sink, "max-lateness")) {
4125+
uint64_t maxLateness = 100 * GST_MSECOND;
4126+
g_object_set(sink, "max-lateness", maxLateness, nullptr);
4127+
} else {
4128+
GST_WARNING_OBJECT(pipeline(), "video sink does not have max-lateness property. This could result in A/V "
4129+
"desynchronization if it does not discard buffers that are arriving late (for example quality changes "
4130+
"decoding something again that has already been played)");
4131+
}
41264132
});
41274133

41284134
if (!m_player->isVideoPlayer()) {
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright 2024 RDK Management
3+
*
4+
* Redistribution and use in source and binary forms, with or without
5+
* modification, are permitted provided that the following conditions
6+
* are met:
7+
* 1. Redistributions of source code must retain the above copyright
8+
* notice, this list of conditions and the following disclaimer.
9+
* 2. Redistributions in binary form must reproduce the above copyright
10+
* notice, this list of conditions and the following disclaimer in the
11+
* documentation and/or other materials provided with the distribution.
12+
*
13+
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15+
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17+
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23+
* THE POSSIBILITY OF SUCH DAMAGE.
24+
*/
25+
26+
#include "config.h"
27+
#include "GStreamerHolePunchQuirkRialto.h"
28+
29+
#if USE(GSTREAMER)
30+
31+
#include "GStreamerCommon.h"
32+
#include "MediaPlayerPrivateGStreamer.h"
33+
34+
namespace WebCore {
35+
36+
GstElement* GStreamerHolePunchQuirkRialto::createHolePunchVideoSink(bool isLegacyPlaybin, const MediaPlayer* player)
37+
{
38+
AtomString value;
39+
bool isPIPRequested = player && player->doesHaveAttribute("pip"_s, &value) && equalLettersIgnoringASCIICase(value, "true"_s);
40+
if (isLegacyPlaybin && !isPIPRequested)
41+
return nullptr;
42+
43+
// Rialto using holepunch.
44+
GstElement* videoSink = makeGStreamerElement("rialtomsevideosink", nullptr);
45+
if (isPIPRequested)
46+
g_object_set(G_OBJECT(videoSink), "maxVideoWidth", 640, "maxVideoHeight", 480, "has-drm", FALSE, nullptr);
47+
return videoSink;
48+
}
49+
50+
bool GStreamerHolePunchQuirkRialto::setHolePunchVideoRectangle(GstElement* videoSink, const IntRect& rect)
51+
{
52+
if (UNLIKELY(!gstObjectHasProperty(videoSink, "rectangle")))
53+
return false;
54+
55+
auto rectString = makeString(rect.x(), ',', rect.y(), ',', rect.width(), ',', rect.height());
56+
g_object_set(videoSink, "rectangle", rectString.ascii().data(), nullptr);
57+
return true;
58+
}
59+
60+
#undef GST_CAT_DEFAULT
61+
62+
} // namespace WebCore
63+
64+
#endif // USE(GSTREAMER)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2024 RDK Management
3+
*
4+
* Redistribution and use in source and binary forms, with or without
5+
* modification, are permitted provided that the following conditions
6+
* are met:
7+
* 1. Redistributions of source code must retain the above copyright
8+
* notice, this list of conditions and the following disclaimer.
9+
* 2. Redistributions in binary form must reproduce the above copyright
10+
* notice, this list of conditions and the following disclaimer in the
11+
* documentation and/or other materials provided with the distribution.
12+
*
13+
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15+
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17+
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23+
* THE POSSIBILITY OF SUCH DAMAGE.
24+
*/
25+
26+
#pragma once
27+
28+
#if USE(GSTREAMER)
29+
30+
#include "GStreamerQuirks.h"
31+
32+
namespace WebCore {
33+
34+
class GStreamerHolePunchQuirkRialto final : public GStreamerHolePunchQuirk {
35+
public:
36+
const char* identifier() final { return "RialtoHolePunch"; }
37+
38+
GstElement* createHolePunchVideoSink(bool, const MediaPlayer*) final;
39+
bool setHolePunchVideoRectangle(GstElement*, const IntRect&) final;
40+
bool requiresClockSynchronization() const final { return false; }
41+
};
42+
43+
} // namespace WebCore
44+
45+
#endif // USE(GSTREAMER)
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Copyright 2024 RDK Management
3+
*
4+
* Redistribution and use in source and binary forms, with or without
5+
* modification, are permitted provided that the following conditions
6+
* are met:
7+
* 1. Redistributions of source code must retain the above copyright
8+
* notice, this list of conditions and the following disclaimer.
9+
* 2. Redistributions in binary form must reproduce the above copyright
10+
* notice, this list of conditions and the following disclaimer in the
11+
* documentation and/or other materials provided with the distribution.
12+
*
13+
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15+
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17+
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23+
* THE POSSIBILITY OF SUCH DAMAGE.
24+
*/
25+
26+
#include "config.h"
27+
#include "GStreamerQuirkRialto.h"
28+
29+
#if USE(GSTREAMER)
30+
31+
#include "GStreamerCommon.h"
32+
#include <wtf/OptionSet.h>
33+
34+
namespace WebCore {
35+
36+
GST_DEBUG_CATEGORY_STATIC(webkit_rialto_quirks_debug);
37+
#define GST_CAT_DEFAULT webkit_rialto_quirks_debug
38+
39+
GStreamerQuirkRialto::GStreamerQuirkRialto()
40+
{
41+
GST_DEBUG_CATEGORY_INIT(webkit_rialto_quirks_debug, "webkitquirksrialto", 0, "WebKit Rialto Quirks");
42+
43+
std::array<const char *, 2> rialtoSinks = { "rialtomsevideosink", "rialtomseaudiosink" };
44+
45+
for (const auto* sink : rialtoSinks) {
46+
auto sinkFactory = adoptGRef(gst_element_factory_find(sink));
47+
if (UNLIKELY(!sinkFactory))
48+
continue;
49+
50+
gst_object_unref(gst_plugin_feature_load(GST_PLUGIN_FEATURE(sinkFactory.get())));
51+
for (auto* padTemplateListElement = gst_element_factory_get_static_pad_templates(sinkFactory.get());
52+
padTemplateListElement; padTemplateListElement = g_list_next(padTemplateListElement)) {
53+
54+
auto* padTemplate = static_cast<GstStaticPadTemplate*>(padTemplateListElement->data);
55+
if (padTemplate->direction != GST_PAD_SINK)
56+
continue;
57+
GRefPtr<GstCaps> templateCaps = adoptGRef(gst_static_caps_get(&padTemplate->static_caps));
58+
if (!templateCaps)
59+
continue;
60+
if (gst_caps_is_empty(templateCaps.get()) || gst_caps_is_any(templateCaps.get()))
61+
continue;
62+
if (m_sinkCaps)
63+
m_sinkCaps = adoptGRef(gst_caps_merge(m_sinkCaps.leakRef(), templateCaps.leakRef()));
64+
else
65+
m_sinkCaps = WTFMove(templateCaps);
66+
}
67+
}
68+
}
69+
70+
void GStreamerQuirkRialto::configureElement(GstElement* element, const OptionSet<ElementRuntimeCharacteristics>&)
71+
{
72+
if (!g_strcmp0(G_OBJECT_TYPE_NAME(G_OBJECT(element)), "GstURIDecodeBin3")) {
73+
GRefPtr<GstCaps> defaultCaps;
74+
g_object_get(element, "caps", &defaultCaps.outPtr(), nullptr);
75+
defaultCaps = adoptGRef(gst_caps_merge(gst_caps_ref(m_sinkCaps.get()), defaultCaps.leakRef()));
76+
GST_INFO("Setting stop caps to %" GST_PTR_FORMAT, defaultCaps.get());
77+
g_object_set(element, "caps", defaultCaps.get(), nullptr);
78+
}
79+
}
80+
81+
GstElement* GStreamerQuirkRialto::createAudioSink()
82+
{
83+
auto sink = makeGStreamerElement("rialtomseaudiosink", nullptr);
84+
RELEASE_ASSERT_WITH_MESSAGE(sink, "rialtomseaudiosink should be available in the system but it is not");
85+
return sink;
86+
}
87+
88+
GstElement* GStreamerQuirkRialto::createWebAudioSink()
89+
{
90+
auto sink = makeGStreamerElement("rialtowebaudiosink", nullptr);
91+
RELEASE_ASSERT_WITH_MESSAGE(sink, "rialtowebaudiosink should be available in the system but it is not");
92+
return sink;
93+
}
94+
95+
std::optional<bool> GStreamerQuirkRialto::isHardwareAccelerated(GstElementFactory* factory)
96+
{
97+
if (g_str_has_prefix(GST_OBJECT_NAME(factory), "rialto"))
98+
return true;
99+
100+
return std::nullopt;
101+
}
102+
103+
#undef GST_CAT_DEFAULT
104+
105+
} // namespace WebCore
106+
107+
#endif // USE(GSTREAMER)
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright 2024 RDK Management
3+
*
4+
* Redistribution and use in source and binary forms, with or without
5+
* modification, are permitted provided that the following conditions
6+
* are met:
7+
* 1. Redistributions of source code must retain the above copyright
8+
* notice, this list of conditions and the following disclaimer.
9+
* 2. Redistributions in binary form must reproduce the above copyright
10+
* notice, this list of conditions and the following disclaimer in the
11+
* documentation and/or other materials provided with the distribution.
12+
*
13+
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15+
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17+
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23+
* THE POSSIBILITY OF SUCH DAMAGE.
24+
*/
25+
26+
#pragma once
27+
28+
#if USE(GSTREAMER)
29+
30+
#include "GStreamerQuirks.h"
31+
32+
namespace WebCore {
33+
34+
class GStreamerQuirkRialto final : public GStreamerQuirk {
35+
public:
36+
GStreamerQuirkRialto();
37+
const char* identifier() final { return "Rialto"; }
38+
39+
void configureElement(GstElement*, const OptionSet<ElementRuntimeCharacteristics>&) final;
40+
GstElement* createAudioSink() final;
41+
GstElement* createWebAudioSink() final;
42+
std::optional<bool> isHardwareAccelerated(GstElementFactory*) final;
43+
bool shouldParseIncomingLibWebRTCBitStream() const final { return false; }
44+
unsigned getAdditionalPlaybinFlags() const { return getGstPlayFlag("text") | getGstPlayFlag("native-audio") | getGstPlayFlag("native-video"); }
45+
46+
private:
47+
GRefPtr<GstCaps> m_sinkCaps;
48+
};
49+
50+
} // namespace WebCore
51+
52+
#endif // USE(GSTREAMER)

Source/WebCore/platform/gstreamer/GStreamerQuirks.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@
2626
#include "GStreamerCommon.h"
2727
#include "GStreamerHolePunchQuirkBcmNexus.h"
2828
#include "GStreamerHolePunchQuirkFake.h"
29+
#include "GStreamerHolePunchQuirkRialto.h"
2930
#include "GStreamerHolePunchQuirkWesteros.h"
3031
#include "GStreamerQuirkAmLogic.h"
3132
#include "GStreamerQuirkBcmNexus.h"
3233
#include "GStreamerQuirkBroadcom.h"
3334
#include "GStreamerQuirkRealtek.h"
35+
#include "GStreamerQuirkRialto.h"
3436
#include "GStreamerQuirkWesteros.h"
3537
#include <wtf/NeverDestroyed.h>
3638
#include <wtf/OptionSet.h>
@@ -104,6 +106,8 @@ GStreamerQuirksManager::GStreamerQuirksManager(bool isForTesting, bool loadQuirk
104106
quirk = WTF::makeUnique<GStreamerQuirkBcmNexus>();
105107
else if (WTF::equalLettersIgnoringASCIICase(identifier, "realtek"_s))
106108
quirk = WTF::makeUnique<GStreamerQuirkRealtek>();
109+
else if (WTF::equalLettersIgnoringASCIICase(identifier, "rialto"_s))
110+
quirk = WTF::makeUnique<GStreamerQuirkRialto>();
107111
else if (WTF::equalLettersIgnoringASCIICase(identifier, "westeros"_s))
108112
quirk = WTF::makeUnique<GStreamerQuirkWesteros>();
109113
else {
@@ -142,6 +146,8 @@ GStreamerQuirksManager::GStreamerQuirksManager(bool isForTesting, bool loadQuirk
142146
// TODO: Maybe check this is coherent (somehow) with the quirk(s) selected above.
143147
if (WTF::equalLettersIgnoringASCIICase(holePunchQuirk, "bcmnexus"_s))
144148
m_holePunchQuirk = WTF::makeUnique<GStreamerHolePunchQuirkBcmNexus>();
149+
else if (WTF::equalLettersIgnoringASCIICase(holePunchQuirk, "rialto"_s))
150+
m_holePunchQuirk = WTF::makeUnique<GStreamerHolePunchQuirkRialto>();
145151
else if (WTF::equalLettersIgnoringASCIICase(holePunchQuirk, "westeros"_s))
146152
m_holePunchQuirk = WTF::makeUnique<GStreamerHolePunchQuirkWesteros>();
147153
else if (WTF::equalLettersIgnoringASCIICase(holePunchQuirk, "fake"_s))
@@ -155,6 +161,19 @@ bool GStreamerQuirksManager::isEnabled() const
155161
return !m_quirks.isEmpty();
156162
}
157163

164+
GstElement* GStreamerQuirksManager::createAudioSink()
165+
{
166+
for (const auto& quirk : m_quirks) {
167+
auto* sink = quirk->createAudioSink();
168+
if (sink) {
169+
GST_DEBUG("Using AudioSink from quirk %s : %" GST_PTR_FORMAT, quirk->identifier(), sink);
170+
return sink;
171+
}
172+
}
173+
174+
return nullptr;
175+
}
176+
158177
GstElement* GStreamerQuirksManager::createWebAudioSink()
159178
{
160179
for (const auto& quirk : m_quirks) {

Source/WebCore/platform/gstreamer/GStreamerQuirks.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ class GStreamerQuirk : public GStreamerQuirkBase {
5454
virtual ~GStreamerQuirk() = default;
5555

5656
virtual bool isPlatformSupported() const { return true; }
57+
virtual GstElement* createAudioSink() { return nullptr; }
5758
virtual GstElement* createWebAudioSink() { return nullptr; }
5859
virtual void configureElement(GstElement*, const OptionSet<ElementRuntimeCharacteristics>&) { }
5960
virtual std::optional<bool> isHardwareAccelerated(GstElementFactory*) { return std::nullopt; }
@@ -88,6 +89,7 @@ class GStreamerQuirksManager : public RefCounted<GStreamerQuirksManager> {
8889

8990
bool isEnabled() const;
9091

92+
GstElement* createAudioSink();
9193
GstElement* createWebAudioSink();
9294
void configureElement(GstElement*, OptionSet<ElementRuntimeCharacteristics>&&);
9395
std::optional<bool> isHardwareAccelerated(GstElementFactory*) const;

0 commit comments

Comments
 (0)