18#include <QtCore/qdebug.h>
19#include <QtCore/qlist.h>
20#include <QtCore/qsemaphore.h>
22#include <QtMultimedia/qaudioformat.h>
23#include <QtMultimedia/qvideoframe.h>
24#include <QtMultimedia/private/qtmultimediaglobal_p.h>
25#include <QtMultimedia/private/qmultimediautils_p.h>
28#include <gst/video/video-info.h>
34#if QT_CONFIG(gstreamer_photography)
35# define GST_USE_UNSTABLE_API
36# include <gst/interfaces/photography.h>
37# undef GST_USE_UNSTABLE_API
40#if QT_CONFIG(gstreamer_app)
41# include <gst/app/gstappsink.h>
42# include <gst/app/gstappsrc.h>
59#define QGST_DEFINE_CAST_TRAITS(ClassName, MACRO_LABEL) \
61 struct GstObjectTraits<ClassName> \
63 using Type = ClassName; \
64 template <typename U> \
65 static bool isObjectOfType(U *arg) \
67 return GST_IS_##MACRO_LABEL(arg); \
69 template <typename U> \
70 static Type *cast(U *arg) \
72 return GST_##MACRO_LABEL##_CAST(arg); \
74 template <typename U> \
75 static Type *checked_cast(U *arg) \
77 return GST_##MACRO_LABEL(arg); \
80 static_assert(true, "ensure semicolon")
82#define QGST_DEFINE_CAST_TRAITS_FOR_INTERFACE(ClassName, MACRO_LABEL) \
84 struct GstObjectTraits<ClassName> \
86 using Type = ClassName; \
87 template <typename U> \
88 static bool isObjectOfType(U *arg) \
90 return GST_IS_##MACRO_LABEL(arg); \
92 template <typename U> \
93 static Type *cast(U *arg) \
95 return checked_cast(arg); \
97 template <typename U> \
98 static Type *checked_cast(U *arg) \
100 return GST_##MACRO_LABEL(arg); \
103 static_assert(true, "ensure semicolon")
116#if QT_CONFIG(gstreamer_app)
125 template <
typename U>
128 return G_IS_OBJECT(
arg);
130 template <
typename U>
133 return G_OBJECT(
arg);
135 template <
typename U>
138 return G_OBJECT(
arg);
142#undef QGST_DEFINE_CAST_TRAITS
143#undef QGST_DEFINE_CAST_TRAITS_FOR_INTERFACE
147template <
typename DestinationType,
typename SourceType>
151 return arg && Traits::isObjectOfType(
arg);
154template <
typename DestinationType,
typename SourceType>
158 if (
arg && Traits::isObjectOfType(
arg))
159 return Traits::cast(
arg);
163template <
typename DestinationType,
typename SourceType>
169 return Traits::cast(
arg);
186 using QUniqueGStringHandle::QUniqueGStringHandle;
200 std::optional<bool>
toBool()
const;
201 std::optional<int>
toInt()
const;
202 std::optional<int>
toInt64()
const;
206 return value ?
static_cast<T *
>(g_value_get_pointer(
value)) :
nullptr;
212 std::optional<QGRange<int>>
toIntRange()
const;
226template <
typename RefcountedObject>
229template <
typename GstType>
232 using Adaptor = QGstRefcountingAdaptor<GstType>;
234 GstType *m_object =
nullptr;
244 Adaptor::ref(m_object);
250 Adaptor::ref(m_object);
256 Adaptor::unref(m_object);
260 : m_object(std::exchange(
other.m_object,
nullptr))
267 if (m_object !=
other.m_object) {
268 GstType *originalObject = m_object;
270 m_object =
other.m_object;
272 Adaptor::ref(m_object);
274 Adaptor::unref(originalObject);
281 if (
this != &
other) {
282 GstType *originalObject = m_object;
283 m_object = std::exchange(
other.m_object,
nullptr);
286 Adaptor::unref(originalObject);
293 return a.m_object ==
b.m_object;
297 return a.m_object !=
b.m_object;
300 explicit operator bool()
const {
return bool(m_object); }
301 bool isNull()
const {
return !m_object; }
302 GstType *
release() {
return std::exchange(m_object,
nullptr); }
305 GstType *
get()
const {
return m_object; }
338 static void ref(GstCaps *
arg)
noexcept { gst_caps_ref(
arg); }
347 using BaseClass::BaseClass;
357 GstCaps *
caps()
const;
362 void addPixelFormats(
const QList<QVideoFrameFormat::PixelFormat> &
formats,
const char *modifier =
nullptr);
375 static void ref(GstObject *
arg)
noexcept { gst_object_ref_sink(
arg); }
376 static void unref(GstObject *
arg)
noexcept { gst_object_unref(
arg); }
386 using BaseClass::BaseClass;
419 GstObject *
object() const;
420 const
char *
name() const;
437 static constexpr gulong invalidHandlerId = std::numeric_limits<gulong>::max();
440 gulong handlerId = invalidHandlerId;
481 bool isLinked() const;
484 bool unlinkPeer() const;
490 GstEvent *stickyEvent(GstEventType
type);
491 bool sendEvent(GstEvent *
event);
493 template<auto Member, typename T>
494 void addProbe(T *instance, GstPadProbeType
type) {
495 auto callback = [](GstPad *pad, GstPadProbeInfo *
info, gpointer userData) {
496 return (
static_cast<T *
>(userData)->*Member)(
QGstPad(pad, NeedsRef),
info);
499 gst_pad_add_probe(pad(),
type, callback, instance,
nullptr);
502 template <
typename Functor>
505 struct CallbackData {
512 .work = std::forward<Functor>(work),
515 auto callback= [](GstPad *, GstPadProbeInfo *, gpointer
p) {
516 auto cd =
reinterpret_cast<CallbackData*
>(
p);
519 return GST_PAD_PROBE_REMOVE;
522 gst_pad_add_probe(pad(), GST_PAD_PROBE_TYPE_IDLE, callback, &cd,
nullptr);
523 cd.waitDone.acquire();
526 template<auto Member,
typename T>
528 auto callback = [](GstPad *, GstPadProbeInfo *
info, gpointer userData) {
529 if (GST_EVENT_TYPE(GST_PAD_PROBE_INFO_DATA(
info)) != GST_EVENT_EOS)
530 return GST_PAD_PROBE_PASS;
531 (
static_cast<T *
>(userData)->*Member)();
532 return GST_PAD_PROBE_REMOVE;
535 gst_pad_add_probe(pad(), GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, callback, instance,
nullptr);
546 GstClock *clock()
const;
547 GstClockTime
time()
const;
564 static
QGstElement createFromFactory(GstElementFactory *, const
char *
name =
nullptr);
566 const
char *
name =
nullptr);
568 static
QGstElement createFromDevice(GstDevice *, const
char *
name =
nullptr);
569 static
QGstElement createFromPipelineDescription(const
char *);
576 void releaseRequestPad(const
QGstPad &pad) const;
579 GstStateChangeReturn setState(GstState
state);
580 bool setStateSync(GstState
state,
std::chrono::nanoseconds
timeout =
std::chrono::seconds(1));
581 bool syncStateWithParent();
582 bool finishStateChange(
std::chrono::nanoseconds
timeout =
std::chrono::seconds(5));
584 void lockState(
bool locked);
585 bool isStateLocked() const;
587 void sendEvent(GstEvent *
event) const;
588 void sendEos() const;
590 template <auto Member, typename T>
595 static void callback(GstElement *e, GstPad *pad, gpointer userData)
597 (
static_cast<T *
>(userData)->*Member)(
QGstElement(e, NeedsRef),
602 return connect(
"pad-added", G_CALLBACK(Impl::callback), instance);
604 template <auto Member,
typename T>
609 static void callback(GstElement *e, GstPad *pad, gpointer userData)
611 (
static_cast<T *
>(userData)->*Member)(
QGstElement(e, NeedsRef),
616 return connect(
"pad-removed", G_CALLBACK(Impl::callback), instance);
618 template <auto Member,
typename T>
623 static void callback(GstElement *e, gpointer userData)
625 (
static_cast<T *
>(userData)->*Member)(
QGstElement(e, NeedsRef));
629 return connect(
"no-more-pads", G_CALLBACK(Impl::callback), instance);
633 void setBaseTime(GstClockTime
time)
const;
635 GstElement *element()
const;
641template <
typename... Ts>
642std::enable_if_t<(std::is_base_of_v<QGstElement, Ts> && ...),
void>
645 bool link_success = [&] {
646 if constexpr (
sizeof...(Ts) == 2)
647 return gst_element_link(ts.element()...);
649 return gst_element_link_many(ts.element()...,
nullptr);
653 qWarning() <<
"qLinkGstElements: could not link elements: "
654 << std::initializer_list<const char *>{
655 (GST_ELEMENT_NAME(ts.element()))...,
660template <
typename... Ts>
661std::enable_if_t<(std::is_base_of_v<QGstElement, Ts> && ...),
void>
664 if constexpr (
sizeof...(Ts) == 2)
665 gst_element_unlink(ts.element()...);
667 gst_element_unlink_many(ts.element()...,
nullptr);
682 static
QGstBin createFromPipelineDescription(const
QByteArray &pipelineDescription,
683 const
char *
name =
nullptr,
684 bool ghostUnlinkedPads =
false);
685 static
QGstBin createFromPipelineDescription(const
char *pipelineDescription,
686 const
char *
name =
nullptr,
687 bool ghostUnlinkedPads =
false);
689 template <typename... Ts>
692 if constexpr (
sizeof...(Ts) == 1)
693 gst_bin_add(bin(), ts.element()...);
695 gst_bin_add_many(bin(), ts.element()...,
nullptr);
698 template <
typename... Ts>
699 std::enable_if_t<(std::is_base_of_v<QGstElement, Ts> && ...),
void>
remove(
const Ts &...ts)
701 if constexpr (
sizeof...(Ts) == 1)
702 gst_bin_remove(bin(), ts.element()...);
704 gst_bin_remove_many(bin(), ts.element()...,
nullptr);
707 template <
typename... Ts>
708 std::enable_if_t<(std::is_base_of_v<QGstElement, Ts> && ...),
void>
711 bool stateChangeSuccessful = (ts.setStateSync(GST_STATE_NULL) && ...);
719 void addGhostPad(
const char *
name,
const QGstPad &pad);
721 bool syncChildrenState();
723 void dumpGraph(
const char *fileNamePrefix);
740 GstBaseSink *baseSink() const;
755 GstBaseSrc *baseSrc() const;
758#if QT_CONFIG(gstreamer_app)
764 explicit QGstAppSink(GstAppSink *, RefMode);
766 QGstAppSink(
const QGstAppSink &) =
default;
767 QGstAppSink(QGstAppSink &&)
noexcept =
default;
768 QGstAppSink &operator=(
const QGstAppSink &) =
default;
769 QGstAppSink &operator=(QGstAppSink &&)
noexcept =
default;
773 GstAppSink *appSink()
const;
776 void setCallbacks(GstAppSinkCallbacks &
callbacks, gpointer
user_data, GDestroyNotify notify);
786 explicit QGstAppSrc(GstAppSrc *, RefMode);
788 QGstAppSrc(
const QGstAppSrc &) =
default;
789 QGstAppSrc(QGstAppSrc &&) noexcept = default;
790 QGstAppSrc &operator=(const QGstAppSrc &) = default;
791 QGstAppSrc &operator=(QGstAppSrc &&) noexcept = default;
795 GstAppSrc *appSrc() const;
797 void setCallbacks(GstAppSrcCallbacks &
callbacks, gpointer
user_data, GDestroyNotify notify);
799 GstFlowReturn pushBuffer(GstBuffer *);
QGObjectHandlerConnection & operator=(const QGObjectHandlerConnection &)=default
QGObjectHandlerConnection & operator=(QGObjectHandlerConnection &&)=default
QGObjectHandlerConnection()=default
QGObjectHandlerConnection(const QGObjectHandlerConnection &)=default
QGObjectHandlerConnection(QGObjectHandlerConnection &&)=default
QGObjectHandlerScopedConnection(const QGObjectHandlerScopedConnection &)=delete
QGObjectHandlerScopedConnection & operator=(const QGObjectHandlerScopedConnection &)=delete
QGObjectHandlerScopedConnection(QGObjectHandlerScopedConnection &&)=default
QGObjectHandlerScopedConnection()=default
QGObjectHandlerScopedConnection & operator=(QGObjectHandlerScopedConnection &&)=default
std::optional< int > toInt64() const
std::optional< QGRange< int > > toIntRange() const
std::optional< int > toInt() const
QList< QAudioFormat::SampleFormat > getSampleFormats() const
std::optional< QGRange< float > > getFractionRange() const
const char * toString() const
QGstStructure toStructure() const
std::optional< float > getFraction() const
std::optional< bool > toBool() const
QGstBaseSink(GstBaseSink *, RefMode)
QGstBaseSink(const QGstBaseSink &)=default
QGstBaseSink(QGstBaseSink &&) noexcept=default
QGstBaseSrc(QGstBaseSrc &&) noexcept=default
QGstBaseSrc(const QGstBaseSrc &)=default
QGstBaseSrc(GstBaseSrc *, RefMode)
QGstBin(QGstBin &&) noexcept=default
std::enable_if_t<(std::is_base_of_v< QGstElement, Ts > &&...), void remove)(const Ts &...ts)
QGstBin(const QGstBin &)=default
std::enable_if_t<(std::is_base_of_v< QGstElement, Ts > &&...), void stopAndRemoveElements)(Ts... ts)
void addPixelFormats(const QList< QVideoFrameFormat::PixelFormat > &formats, const char *modifier=nullptr)
MemoryFormat memoryFormat() const
std::optional< std::pair< QVideoFrameFormat, GstVideoInfo > > formatAndVideoInfo() const
static QGstCaps fromCameraFormat(const QCameraFormat &format)
void setResolution(QSize)
QGstCaps(const QGstCaps &)=default
QGstCaps(QGstCaps &&) noexcept=default
QGObjectHandlerConnection onPadRemoved(T *instance)
QGstElement(const QGstElement &)=default
QGstElement(QGstElement &&) noexcept=default
QGObjectHandlerConnection onNoMorePads(T *instance)
QGstStructure getStructure(const char *property) const
QGObjectHandlerConnection connect(const char *name, GCallback callback, gpointer userData)
double getDouble(const char *property) const
int getInt(const char *property) const
QGString getString(const char *property) const
const char * typeName() const
QGstObject getObject(const char *property) const
bool getBool(const char *property) const
QGstObject(const QGstObject &)=default
quint64 getUInt64(const char *property) const
qint64 getInt64(const char *property) const
float getFloat(const char *property) const
QGstObject(QGstObject &&) noexcept=default
uint getUInt(const char *property) const
GstObject * object() const
QGstPad(const QGstPad &)=default
void doInIdleProbe(Functor &&work)
QGstPad(QGstPad &&) noexcept=default
void addEosProbe(T *instance)
QGstObjectWrapper(const QGstObjectWrapper &other)
friend bool operator==(const QGstObjectWrapper &a, const QGstObjectWrapper &b)
QGstObjectWrapper & operator=(const QGstObjectWrapper &other)
QGstObjectWrapper & operator=(QGstObjectWrapper &&other) noexcept
friend bool operator!=(const QGstObjectWrapper &a, const QGstObjectWrapper &b)
QGstObjectWrapper(GstType *object, RefMode mode)
constexpr QGstObjectWrapper()=default
QGstObjectWrapper(QGstObjectWrapper &&other) noexcept
QGstStructure copy() const
QGstreamerMessage getMessage()
const GstStructure * structure
QGRange< float > frameRateRange() const
std::optional< Fraction > pixelAspectRatio() const
QByteArrayView name() const
QGValue operator[](const char *name) const
QVideoFrameFormat::PixelFormat pixelFormat() const
void release(int n=1)
Releases n resources guarded by the semaphore.
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Type get() const noexcept
Combined button and popup list for selecting options.
std::optional< qint64 > baseTime
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void * user_data
DBusConnection * connection
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
std::enable_if_t<(std::is_base_of_v< QGstElement, Ts > &&...), void qLinkGstElements)(const Ts &...ts)
DestinationType * qGstCheckedCast(SourceType *arg)
#define QGST_DEFINE_CAST_TRAITS(ClassName, MACRO_LABEL)
QString errorMessageCannotFindElement(std::string_view element)
bool qIsGstObjectOfType(SourceType *arg)
DestinationType * qGstSafeCast(SourceType *arg)
std::enable_if_t<(std::is_base_of_v< QGstElement, Ts > &&...), void qUnlinkGstElements)(const Ts &...ts)
#define QGST_DEFINE_CAST_TRAITS_FOR_INTERFACE(ClassName, MACRO_LABEL)
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLbitfield GLuint64 timeout
[4]
GLint GLsizei GLsizei GLenum format
GLsizei GLenum GLboolean sink
static void add(QPainterPath &path, const QWingedEdge &list, int edge, QPathEdge::Traversal traversal)
PromiseCallbacks callbacks
#define QStringLiteral(str)
unsigned long long quint64
QFuture< QSet< QChar > > set
[10]
settings remove("monkey")
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)
myObject disconnect()
[26]
QItemEditorFactory * factory
QString toQString() const
QLatin1StringView asStringView() const
static Type * cast(U *arg)
static bool isObjectOfType(U *arg)
static Type * checked_cast(U *arg)
static void unref(GstCaps *arg) noexcept
static void ref(GstCaps *arg) noexcept
static void unref(GstObject *arg) noexcept
static void ref(GstObject *arg) noexcept