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;
639 void dumpPipelineGraph(
const char *filename)
const;
642template <
typename... Ts>
643std::enable_if_t<(std::is_base_of_v<QGstElement, Ts> && ...),
void>
646 bool link_success = [&] {
647 if constexpr (
sizeof...(Ts) == 2)
648 return gst_element_link(ts.element()...);
650 return gst_element_link_many(ts.element()...,
nullptr);
654 qWarning() <<
"qLinkGstElements: could not link elements: "
655 << std::initializer_list<const char *>{
656 (GST_ELEMENT_NAME(ts.element()))...,
661template <
typename... Ts>
662std::enable_if_t<(std::is_base_of_v<QGstElement, Ts> && ...),
void>
665 if constexpr (
sizeof...(Ts) == 2)
666 gst_element_unlink(ts.element()...);
668 gst_element_unlink_many(ts.element()...,
nullptr);
683 static
QGstBin createFromPipelineDescription(const
QByteArray &pipelineDescription,
684 const
char *
name =
nullptr,
685 bool ghostUnlinkedPads =
false);
686 static
QGstBin createFromPipelineDescription(const
char *pipelineDescription,
687 const
char *
name =
nullptr,
688 bool ghostUnlinkedPads =
false);
690 template <typename... Ts>
693 if constexpr (
sizeof...(Ts) == 1)
694 gst_bin_add(bin(), ts.element()...);
696 gst_bin_add_many(bin(), ts.element()...,
nullptr);
699 template <
typename... Ts>
700 std::enable_if_t<(std::is_base_of_v<QGstElement, Ts> && ...),
void>
remove(
const Ts &...ts)
702 if constexpr (
sizeof...(Ts) == 1)
703 gst_bin_remove(bin(), ts.element()...);
705 gst_bin_remove_many(bin(), ts.element()...,
nullptr);
708 template <
typename... Ts>
709 std::enable_if_t<(std::is_base_of_v<QGstElement, Ts> && ...),
void>
712 bool stateChangeSuccessful = (ts.setStateSync(GST_STATE_NULL) && ...);
720 void addGhostPad(
const char *
name,
const QGstPad &pad);
722 bool syncChildrenState();
724 void dumpGraph(
const char *fileNamePrefix);
743 GstBaseSink *baseSink() const;
758 GstBaseSrc *baseSrc() const;
761#if QT_CONFIG(gstreamer_app)
767 explicit QGstAppSink(GstAppSink *, RefMode);
769 QGstAppSink(
const QGstAppSink &) =
default;
770 QGstAppSink(QGstAppSink &&)
noexcept =
default;
771 QGstAppSink &operator=(
const QGstAppSink &) =
default;
772 QGstAppSink &operator=(QGstAppSink &&)
noexcept =
default;
776 GstAppSink *appSink()
const;
778 void setMaxBuffers(
int);
779# if GST_CHECK_VERSION(1, 24, 0)
780 void setMaxBufferTime(std::chrono::nanoseconds);
784 void setCallbacks(GstAppSinkCallbacks &
callbacks, gpointer
user_data, GDestroyNotify notify);
794 explicit QGstAppSrc(GstAppSrc *, RefMode);
796 QGstAppSrc(
const QGstAppSrc &) =
default;
797 QGstAppSrc(QGstAppSrc &&) noexcept = default;
798 QGstAppSrc &operator=(const QGstAppSrc &) = default;
799 QGstAppSrc &operator=(QGstAppSrc &&) noexcept = default;
803 GstAppSrc *appSrc() const;
805 void setCallbacks(GstAppSrcCallbacks &
callbacks, gpointer
user_data, GDestroyNotify notify);
807 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)
GstClockTime qGstClockTimeFromChrono(std::chrono::nanoseconds ns)
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