Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qgst.cpp
Go to the documentation of this file.
1// Copyright (C) 2024 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <common/qgst_p.h>
5#include <common/qgst_debug_p.h>
6#include <common/qgstpipeline_p.h>
7#include <common/qgstreamermessage_p.h>
8
9#include <QtCore/qdebug.h>
10#include <QtMultimedia/qcameradevice.h>
11
12#include <array>
13#include <thread>
14
15QT_BEGIN_NAMESPACE
16
17namespace {
18
24
25constexpr std::array<VideoFormat, 19> qt_videoFormatLookup{ {
26 { QVideoFrameFormat::Format_YUV420P, GST_VIDEO_FORMAT_I420 },
27 { QVideoFrameFormat::Format_YUV422P, GST_VIDEO_FORMAT_Y42B },
28 { QVideoFrameFormat::Format_YV12, GST_VIDEO_FORMAT_YV12 },
29 { QVideoFrameFormat::Format_UYVY, GST_VIDEO_FORMAT_UYVY },
30 { QVideoFrameFormat::Format_YUYV, GST_VIDEO_FORMAT_YUY2 },
31 { QVideoFrameFormat::Format_NV12, GST_VIDEO_FORMAT_NV12 },
32 { QVideoFrameFormat::Format_NV21, GST_VIDEO_FORMAT_NV21 },
33 { QVideoFrameFormat::Format_AYUV, GST_VIDEO_FORMAT_AYUV },
34 { QVideoFrameFormat::Format_Y8, GST_VIDEO_FORMAT_GRAY8 },
35 { QVideoFrameFormat::Format_XRGB8888, GST_VIDEO_FORMAT_xRGB },
36 { QVideoFrameFormat::Format_XBGR8888, GST_VIDEO_FORMAT_xBGR },
37 { QVideoFrameFormat::Format_RGBX8888, GST_VIDEO_FORMAT_RGBx },
38 { QVideoFrameFormat::Format_BGRX8888, GST_VIDEO_FORMAT_BGRx },
39 { QVideoFrameFormat::Format_ARGB8888, GST_VIDEO_FORMAT_ARGB },
40 { QVideoFrameFormat::Format_ABGR8888, GST_VIDEO_FORMAT_ABGR },
41 { QVideoFrameFormat::Format_RGBA8888, GST_VIDEO_FORMAT_RGBA },
42 { QVideoFrameFormat::Format_BGRA8888, GST_VIDEO_FORMAT_BGRA },
43#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
44 { QVideoFrameFormat::Format_Y16, GST_VIDEO_FORMAT_GRAY16_LE },
45 { QVideoFrameFormat::Format_P010, GST_VIDEO_FORMAT_P010_10LE },
46#else
47 { QVideoFrameFormat::Format_Y16, GST_VIDEO_FORMAT_GRAY16_BE },
48 { QVideoFrameFormat::Format_P010, GST_VIDEO_FORMAT_P010_10BE },
49#endif
50} };
51
52int indexOfVideoFormat(QVideoFrameFormat::PixelFormat format)
53{
54 for (size_t i = 0; i < qt_videoFormatLookup.size(); ++i)
55 if (qt_videoFormatLookup[i].pixelFormat == format)
56 return int(i);
57
58 return -1;
59}
60
61int indexOfVideoFormat(GstVideoFormat format)
62{
63 for (size_t i = 0; i < qt_videoFormatLookup.size(); ++i)
64 if (qt_videoFormatLookup[i].gstFormat == format)
65 return int(i);
66
67 return -1;
68}
69
70} // namespace
71
72// QGValue
73
74QGValue::QGValue(const GValue *v) : value(v) { }
75
76bool QGValue::isNull() const
77{
78 return !value;
79}
80
81std::optional<bool> QGValue::toBool() const
82{
83 if (!G_VALUE_HOLDS_BOOLEAN(value))
84 return std::nullopt;
85 return g_value_get_boolean(value);
86}
87
88std::optional<int> QGValue::toInt() const
89{
90 if (!G_VALUE_HOLDS_INT(value))
91 return std::nullopt;
92 return g_value_get_int(value);
93}
94
95std::optional<int> QGValue::toInt64() const
96{
97 if (!G_VALUE_HOLDS_INT64(value))
98 return std::nullopt;
99 return g_value_get_int64(value);
100}
101
102const char *QGValue::toString() const
103{
104 return value ? g_value_get_string(value) : nullptr;
105}
106
107std::optional<float> QGValue::getFraction() const
108{
109 if (!GST_VALUE_HOLDS_FRACTION(value))
110 return std::nullopt;
111 return (float)gst_value_get_fraction_numerator(value)
112 / (float)gst_value_get_fraction_denominator(value);
113}
114
115std::optional<QGRange<float>> QGValue::getFractionRange() const
116{
117 if (!GST_VALUE_HOLDS_FRACTION_RANGE(value))
118 return std::nullopt;
119 QGValue min = QGValue{ gst_value_get_fraction_range_min(value) };
120 QGValue max = QGValue{ gst_value_get_fraction_range_max(value) };
121 return QGRange<float>{ *min.getFraction(), *max.getFraction() };
122}
123
124std::optional<QGRange<int>> QGValue::toIntRange() const
125{
126 if (!GST_VALUE_HOLDS_INT_RANGE(value))
127 return std::nullopt;
128 return QGRange<int>{ gst_value_get_int_range_min(value), gst_value_get_int_range_max(value) };
129}
130
132{
133 if (!value || !GST_VALUE_HOLDS_STRUCTURE(value))
134 return QGstStructureView(nullptr);
135 return QGstStructureView(gst_value_get_structure(value));
136}
137
139{
140 if (!value || !GST_VALUE_HOLDS_CAPS(value))
141 return {};
142 return QGstCaps(gst_caps_copy(gst_value_get_caps(value)), QGstCaps::HasRef);
143}
144
145bool QGValue::isList() const
146{
147 return value && GST_VALUE_HOLDS_LIST(value);
148}
149
150int QGValue::listSize() const
151{
152 return gst_value_list_get_size(value);
153}
154
155QGValue QGValue::at(int index) const
156{
157 return QGValue{ gst_value_list_get_value(value, index) };
158}
159
160// QGstStructureView
161
162QGstStructureView::QGstStructureView(const GstStructure *s) : structure(s) { }
163
164QGstStructureView::QGstStructureView(const QUniqueGstStructureHandle &handle)
165 : QGstStructureView{ handle.get() }
166{
167}
168
170{
171 return QUniqueGstStructureHandle{ gst_structure_copy(structure) };
172}
173
175{
176 return !structure;
177}
178
180{
181 return gst_structure_get_name(structure);
182}
183
184QGValue QGstStructureView::operator[](const char *fieldname) const
185{
186 return QGValue{ gst_structure_get_value(structure, fieldname) };
187}
188
190{
191 return operator[]("caps").toCaps();
192}
193
194QGstTagListHandle QGstStructureView::tags() const
195{
196 QGValue tags = operator[]("tags");
197 if (tags.isNull())
198 return {};
199
200 QGstTagListHandle tagList;
201 gst_structure_get(structure, "tags", GST_TYPE_TAG_LIST, &tagList, nullptr);
202 return tagList;
203}
204
206{
207 QSize size;
208
209 int w, h;
210 if (structure && gst_structure_get_int(structure, "width", &w)
211 && gst_structure_get_int(structure, "height", &h)) {
212 size.rwidth() = w;
213 size.rheight() = h;
214 }
215
216 return size;
217}
218
220{
221 QVideoFrameFormat::PixelFormat pixelFormat = QVideoFrameFormat::Format_Invalid;
222
223 if (!structure)
224 return pixelFormat;
225
226 if (gst_structure_has_name(structure, "video/x-raw")) {
227 const gchar *s = gst_structure_get_string(structure, "format");
228 if (s) {
229 GstVideoFormat format = gst_video_format_from_string(s);
230 int index = indexOfVideoFormat(format);
231
232 if (index != -1)
233 pixelFormat = qt_videoFormatLookup[index].pixelFormat;
234 }
235 } else if (gst_structure_has_name(structure, "image/jpeg")) {
236 pixelFormat = QVideoFrameFormat::Format_Jpeg;
237 }
238
239 return pixelFormat;
240}
241
243{
244 if (!structure)
245 return { 0.f, 0.f };
246
247 std::optional<float> minRate;
248 std::optional<float> maxRate;
249
250 auto extractFraction = [](const GValue *v) -> float {
251 return (float)gst_value_get_fraction_numerator(v)
252 / (float)gst_value_get_fraction_denominator(v);
253 };
254 auto extractFrameRate = [&](const GValue *v) {
255 auto insert = [&](float min, float max) {
256 if (!maxRate || max > maxRate)
257 maxRate = max;
258 if (!minRate || min < minRate)
259 minRate = min;
260 };
261
262 if (GST_VALUE_HOLDS_FRACTION(v)) {
263 float rate = extractFraction(v);
264 insert(rate, rate);
265 } else if (GST_VALUE_HOLDS_FRACTION_RANGE(v)) {
266 const GValue *min = gst_value_get_fraction_range_min(v);
267 const GValue *max = gst_value_get_fraction_range_max(v);
268 insert(extractFraction(min), extractFraction(max));
269 }
270 };
271
272 const GValue *gstFrameRates = gst_structure_get_value(structure, "framerate");
273 if (gstFrameRates) {
274 if (GST_VALUE_HOLDS_LIST(gstFrameRates)) {
275 guint nFrameRates = gst_value_list_get_size(gstFrameRates);
276 for (guint f = 0; f < nFrameRates; ++f) {
277 extractFrameRate(gst_value_list_get_value(gstFrameRates, f));
278 }
279 } else {
280 extractFrameRate(gstFrameRates);
281 }
282 } else {
283 const GValue *min = gst_structure_get_value(structure, "min-framerate");
284 const GValue *max = gst_structure_get_value(structure, "max-framerate");
285 if (min && max) {
286 minRate = extractFraction(min);
287 maxRate = extractFraction(max);
288 }
289 }
290
291 if (!minRate || !maxRate)
292 return { 0.f, 0.f };
293
294 return {
295 minRate.value_or(*maxRate),
296 maxRate.value_or(*minRate),
297 };
298}
299
301{
302 if (!structure)
303 return std::nullopt;
304
305 const GValue *width = gst_structure_get_value(structure, "width");
306 const GValue *height = gst_structure_get_value(structure, "height");
307
308 if (!width || !height)
309 return std::nullopt;
310
311 for (const GValue *v : { width, height })
312 if (!GST_VALUE_HOLDS_INT_RANGE(v))
313 return std::nullopt;
314
315 int minWidth = gst_value_get_int_range_min(width);
316 int maxWidth = gst_value_get_int_range_max(width);
317 int minHeight = gst_value_get_int_range_min(height);
318 int maxHeight = gst_value_get_int_range_max(height);
319
320 return QGRange<QSize>{
321 QSize(minWidth, minHeight),
322 QSize(maxWidth, maxHeight),
323 };
324}
325
327{
328 GstMessage *message = nullptr;
329 gst_structure_get(structure, "message", GST_TYPE_MESSAGE, &message, nullptr);
330 return QGstreamerMessage(message, QGstreamerMessage::HasRef);
331}
332
334{
335 gint numerator;
336 gint denominator;
337 if (gst_structure_get_fraction(structure, "pixel-aspect-ratio", &numerator, &denominator)) {
338 return Fraction{
339 numerator,
340 denominator,
341 };
342 }
343
344 return std::nullopt;
345}
346
347// QTBUG-125249: gstreamer tries "to keep the input height (because of interlacing)". Can we align
348// the behavior between gstreamer and ffmpeg?
349static QSize qCalculateFrameSizeGStreamer(QSize resolution, Fraction par)
350{
351 if (par.numerator == par.denominator || par.numerator < 1 || par.denominator < 1)
352 return resolution;
353
354 return QSize{
355 resolution.width() * par.numerator / par.denominator,
356 resolution.height(),
357 };
358}
359
361{
362 QSize size = resolution();
363 if (!size.isValid()) {
364 qWarning() << Q_FUNC_INFO << "invalid resolution when querying nativeSize";
365 return size;
366 }
367
368 std::optional<Fraction> par = pixelAspectRatio();
369 if (par)
370 size = qCalculateFrameSizeGStreamer(size, *par);
371 return size;
372}
373
374// QGstCaps
375
376std::optional<std::pair<QVideoFrameFormat, GstVideoInfo>> QGstCaps::formatAndVideoInfo() const
377{
378 GstVideoInfo vidInfo;
379
380 bool success = gst_video_info_from_caps(&vidInfo, get());
381 if (!success)
382 return std::nullopt;
383
384 int index = indexOfVideoFormat(vidInfo.finfo->format);
385 if (index == -1)
386 return std::nullopt;
387
388 QVideoFrameFormat format(QSize(vidInfo.width, vidInfo.height),
389 qt_videoFormatLookup[index].pixelFormat);
390
391 if (vidInfo.fps_d > 0)
392 format.setStreamFrameRate(qreal(vidInfo.fps_n) / vidInfo.fps_d);
393
394 QVideoFrameFormat::ColorRange range = QVideoFrameFormat::ColorRange_Unknown;
395 switch (vidInfo.colorimetry.range) {
396 case GST_VIDEO_COLOR_RANGE_UNKNOWN:
397 break;
398 case GST_VIDEO_COLOR_RANGE_0_255:
399 range = QVideoFrameFormat::ColorRange_Full;
400 break;
401 case GST_VIDEO_COLOR_RANGE_16_235:
402 range = QVideoFrameFormat::ColorRange_Video;
403 break;
404 }
405 format.setColorRange(range);
406
407 QVideoFrameFormat::ColorSpace colorSpace = QVideoFrameFormat::ColorSpace_Undefined;
408 switch (vidInfo.colorimetry.matrix) {
409 case GST_VIDEO_COLOR_MATRIX_UNKNOWN:
410 case GST_VIDEO_COLOR_MATRIX_RGB:
411 case GST_VIDEO_COLOR_MATRIX_FCC:
412 break;
413 case GST_VIDEO_COLOR_MATRIX_BT709:
414 colorSpace = QVideoFrameFormat::ColorSpace_BT709;
415 break;
416 case GST_VIDEO_COLOR_MATRIX_BT601:
417 colorSpace = QVideoFrameFormat::ColorSpace_BT601;
418 break;
419 case GST_VIDEO_COLOR_MATRIX_SMPTE240M:
420 colorSpace = QVideoFrameFormat::ColorSpace_AdobeRgb;
421 break;
422 case GST_VIDEO_COLOR_MATRIX_BT2020:
423 colorSpace = QVideoFrameFormat::ColorSpace_BT2020;
424 break;
425 }
426 format.setColorSpace(colorSpace);
427
428 QVideoFrameFormat::ColorTransfer transfer = QVideoFrameFormat::ColorTransfer_Unknown;
429 switch (vidInfo.colorimetry.transfer) {
430 case GST_VIDEO_TRANSFER_UNKNOWN:
431 break;
432 case GST_VIDEO_TRANSFER_GAMMA10:
433 transfer = QVideoFrameFormat::ColorTransfer_Linear;
434 break;
435 case GST_VIDEO_TRANSFER_GAMMA22:
436 case GST_VIDEO_TRANSFER_SMPTE240M:
437 case GST_VIDEO_TRANSFER_SRGB:
438 case GST_VIDEO_TRANSFER_ADOBERGB:
439 transfer = QVideoFrameFormat::ColorTransfer_Gamma22;
440 break;
441 case GST_VIDEO_TRANSFER_GAMMA18:
442 case GST_VIDEO_TRANSFER_GAMMA20:
443 // not quite, but best fit
444 case GST_VIDEO_TRANSFER_BT709:
445 case GST_VIDEO_TRANSFER_BT2020_12:
446 transfer = QVideoFrameFormat::ColorTransfer_BT709;
447 break;
448 case GST_VIDEO_TRANSFER_GAMMA28:
449 transfer = QVideoFrameFormat::ColorTransfer_Gamma28;
450 break;
451 case GST_VIDEO_TRANSFER_LOG100:
452 case GST_VIDEO_TRANSFER_LOG316:
453 break;
454 case GST_VIDEO_TRANSFER_SMPTE2084:
455 transfer = QVideoFrameFormat::ColorTransfer_ST2084;
456 break;
457 case GST_VIDEO_TRANSFER_ARIB_STD_B67:
458 transfer = QVideoFrameFormat::ColorTransfer_STD_B67;
459 break;
460 case GST_VIDEO_TRANSFER_BT2020_10:
461 transfer = QVideoFrameFormat::ColorTransfer_BT709;
462 break;
463 case GST_VIDEO_TRANSFER_BT601:
464 transfer = QVideoFrameFormat::ColorTransfer_BT601;
465 break;
466 }
467 format.setColorTransfer(transfer);
468
469 return std::pair{
470 std::move(format),
471 vidInfo,
472 };
473}
474
475void QGstCaps::addPixelFormats(const QList<QVideoFrameFormat::PixelFormat> &formats,
476 const char *modifier)
477{
478 if (!gst_caps_is_writable(get()))
479 *this = QGstCaps(gst_caps_make_writable(release()), QGstCaps::RefMode::HasRef);
480
481 GValue list = {};
482 g_value_init(&list, GST_TYPE_LIST);
483
484 for (QVideoFrameFormat::PixelFormat format : formats) {
485 int index = indexOfVideoFormat(format);
486 if (index == -1)
487 continue;
488 GValue item = {};
489
490 g_value_init(&item, G_TYPE_STRING);
491 g_value_set_string(&item,
492 gst_video_format_to_string(qt_videoFormatLookup[index].gstFormat));
493 gst_value_list_append_value(&list, &item);
494 g_value_unset(&item);
495 }
496
497 auto *structure = gst_structure_new("video/x-raw", "framerate", GST_TYPE_FRACTION_RANGE, 0, 1,
498 INT_MAX, 1, "width", GST_TYPE_INT_RANGE, 1, INT_MAX,
499 "height", GST_TYPE_INT_RANGE, 1, INT_MAX, nullptr);
500 gst_structure_set_value(structure, "format", &list);
501 gst_caps_append_structure(get(), structure);
502 g_value_unset(&list);
503
504 if (modifier)
505 gst_caps_set_features(get(), size() - 1, gst_caps_features_from_string(modifier));
506}
507
508void QGstCaps::setResolution(QSize resolution)
509{
510 Q_ASSERT(resolution.isValid());
511 GValue width{};
512 g_value_init(&width, G_TYPE_INT);
513 g_value_set_int(&width, resolution.width());
514 GValue height{};
515 g_value_init(&height, G_TYPE_INT);
516 g_value_set_int(&height, resolution.height());
517
518 gst_caps_set_value(caps(), "width", &width);
519 gst_caps_set_value(caps(), "height", &height);
520}
521
522QGstCaps QGstCaps::fromCameraFormat(const QCameraFormat &format)
523{
524 QSize size = format.resolution();
525 GstStructure *structure = nullptr;
526 if (format.pixelFormat() == QVideoFrameFormat::Format_Jpeg) {
527 structure = gst_structure_new("image/jpeg", "width", G_TYPE_INT, size.width(), "height",
528 G_TYPE_INT, size.height(), nullptr);
529 } else {
530 int index = indexOfVideoFormat(format.pixelFormat());
531 if (index < 0)
532 return {};
533 auto gstFormat = qt_videoFormatLookup[index].gstFormat;
534 structure = gst_structure_new("video/x-raw", "format", G_TYPE_STRING,
535 gst_video_format_to_string(gstFormat), "width", G_TYPE_INT,
536 size.width(), "height", G_TYPE_INT, size.height(), nullptr);
537 }
538 auto caps = QGstCaps::create();
539 gst_caps_append_structure(caps.get(), structure);
540 return caps;
541}
542
544{
545 return QGstCaps{
546 gst_caps_copy(caps()),
547 QGstCaps::HasRef,
548 };
549}
550
552{
553 auto *features = gst_caps_get_features(get(), 0);
554 if (gst_caps_features_contains(features, "memory:GLMemory"))
555 return GLTexture;
556 if (gst_caps_features_contains(features, "memory:DMABuf"))
557 return DMABuf;
558 return CpuMemory;
559}
560
561int QGstCaps::size() const
562{
563 return int(gst_caps_get_size(get()));
564}
565
567{
568 return QGstStructureView{
569 gst_caps_get_structure(get(), index),
570 };
571}
572
574{
575 return get();
576}
577
579{
580 return QGstCaps(gst_caps_new_empty(), HasRef);
581}
582
583// QGstObject
584
585void QGstObject::set(const char *property, const char *str)
586{
587 g_object_set(get(), property, str, nullptr);
588}
589
590void QGstObject::set(const char *property, bool b)
591{
592 g_object_set(get(), property, gboolean(b), nullptr);
593}
594
595void QGstObject::set(const char *property, uint32_t i)
596{
597 g_object_set(get(), property, guint(i), nullptr);
598}
599
600void QGstObject::set(const char *property, int32_t i)
601{
602 g_object_set(get(), property, gint(i), nullptr);
603}
604
605void QGstObject::set(const char *property, int64_t i)
606{
607 g_object_set(get(), property, gint64(i), nullptr);
608}
609
610void QGstObject::set(const char *property, uint64_t i)
611{
612 g_object_set(get(), property, guint64(i), nullptr);
613}
614
615void QGstObject::set(const char *property, double d)
616{
617 g_object_set(get(), property, gdouble(d), nullptr);
618}
619
620void QGstObject::set(const char *property, const QGstObject &o)
621{
622 g_object_set(get(), property, o.object(), nullptr);
623}
624
625void QGstObject::set(const char *property, const QGstCaps &c)
626{
627 g_object_set(get(), property, c.caps(), nullptr);
628}
629
630void QGstObject::set(const char *property, void *object, GDestroyNotify destroyFunction)
631{
632 g_object_set_data_full(qGstCheckedCast<GObject>(get()), property, object, destroyFunction);
633}
634
635QGString QGstObject::getString(const char *property) const
636{
637 char *s = nullptr;
638 g_object_get(get(), property, &s, nullptr);
639 return QGString(s);
640}
641
642QGstStructureView QGstObject::getStructure(const char *property) const
643{
644 GstStructure *s = nullptr;
645 g_object_get(get(), property, &s, nullptr);
646 return QGstStructureView(s);
647}
648
649bool QGstObject::getBool(const char *property) const
650{
651 gboolean b = false;
652 g_object_get(get(), property, &b, nullptr);
653 return b;
654}
655
656uint QGstObject::getUInt(const char *property) const
657{
658 guint i = 0;
659 g_object_get(get(), property, &i, nullptr);
660 return i;
661}
662
663int QGstObject::getInt(const char *property) const
664{
665 gint i = 0;
666 g_object_get(get(), property, &i, nullptr);
667 return i;
668}
669
670quint64 QGstObject::getUInt64(const char *property) const
671{
672 guint64 i = 0;
673 g_object_get(get(), property, &i, nullptr);
674 return i;
675}
676
677qint64 QGstObject::getInt64(const char *property) const
678{
679 gint64 i = 0;
680 g_object_get(get(), property, &i, nullptr);
681 return i;
682}
683
684float QGstObject::getFloat(const char *property) const
685{
686 gfloat d = 0;
687 g_object_get(get(), property, &d, nullptr);
688 return d;
689}
690
691double QGstObject::getDouble(const char *property) const
692{
693 gdouble d = 0;
694 g_object_get(get(), property, &d, nullptr);
695 return d;
696}
697
698QGstObject QGstObject::getGstObject(const char *property) const
699{
700 GstObject *o = nullptr;
701 g_object_get(get(), property, &o, nullptr);
702 return QGstObject(o, HasRef);
703}
704
705void *QGstObject::getObject(const char *property) const
706{
707 return g_object_get_data(qGstCheckedCast<GObject>(get()), property);
708}
709
710QGObjectHandlerConnection QGstObject::connect(const char *name, GCallback callback,
711 gpointer userData)
712{
714 *this,
715 g_signal_connect(get(), name, callback, userData),
716 };
717}
718
719void QGstObject::disconnect(gulong handlerId)
720{
721 g_signal_handler_disconnect(get(), handlerId);
722}
723
725{
726 return G_OBJECT_TYPE(get());
727}
728
730{
731 return QLatin1StringView{
732 g_type_name(type()),
733 };
734}
735
737{
738 return get();
739}
740
742{
743 using namespace Qt::StringLiterals;
744
745 return get() ? QLatin1StringView{ GST_OBJECT_NAME(get()) } : "(null)"_L1;
746}
747
748// QGObjectHandlerConnection
749
751 : object{ std::move(object) }, handlerId{ handlerId }
752{
753}
754
756{
757 if (!object)
758 return;
759
760 object.disconnect(handlerId);
761 object = {};
762 handlerId = invalidHandlerId;
763}
764
765// QGObjectHandlerScopedConnection
766
774
776{
777 connection.disconnect();
778}
779
781{
782 connection.disconnect();
783}
784
785// QGstPad
786
788 : QGstPad{
791 }
792{
793}
794
795QGstPad::QGstPad(GstPad *pad, RefMode mode)
796 : QGstObject{
798 mode,
799 }
800{
801}
802
804{
805 return QGstCaps(gst_pad_get_current_caps(pad()), QGstCaps::HasRef);
806}
807
809{
810 return QGstCaps(gst_pad_query_caps(pad(), nullptr), QGstCaps::HasRef);
811}
812
813QGstTagListHandle QGstPad::tags() const
814{
815 QGstTagListHandle tagList;
816 g_object_get(object(), "tags", &tagList, nullptr);
817 return tagList;
818}
819
821{
822 return QGString{
823 gst_pad_get_stream_id(pad()),
824 };
825}
826
828{
829 using namespace Qt::Literals;
830 QLatin1StringView padName = name();
831
832 if (padName.startsWith("video_"_L1))
833 return QPlatformMediaPlayer::TrackType::VideoStream;
834 if (padName.startsWith("audio_"_L1))
835 return QPlatformMediaPlayer::TrackType::AudioStream;
836 if (padName.startsWith("text_"_L1))
837 return QPlatformMediaPlayer::TrackType::SubtitleStream;
838
839 return std::nullopt;
840}
841
842bool QGstPad::isLinked() const
843{
844 return gst_pad_is_linked(pad());
845}
846
847bool QGstPad::link(const QGstPad &sink) const
848{
849 return gst_pad_link(pad(), sink.pad()) == GST_PAD_LINK_OK;
850}
851
852bool QGstPad::unlink(const QGstPad &sink) const
853{
854 return gst_pad_unlink(pad(), sink.pad());
855}
856
857bool QGstPad::unlinkPeer() const
858{
859 QGstPad peerPad = peer();
860 if (peerPad)
861 return GST_PAD_IS_SRC(pad()) ? unlink(peerPad) : peerPad.unlink(*this);
862
863 return true;
864}
865
867{
868 return QGstPad(gst_pad_get_peer(pad()), HasRef);
869}
870
872{
873 return QGstElement(gst_pad_get_parent_element(pad()), HasRef);
874}
875
877{
878 return qGstCheckedCast<GstPad>(object());
879}
880
881GstEvent *QGstPad::stickyEvent(GstEventType type)
882{
883 return gst_pad_get_sticky_event(pad(), type, 0);
884}
885
886bool QGstPad::sendEvent(GstEvent *event)
887{
888 return gst_pad_send_event(pad(), event);
889}
890
891void QGstPad::sendFlushStartStop(bool resetTime)
892{
893 GstEvent *flushStart = gst_event_new_flush_start();
894 gboolean ret = sendEvent(flushStart);
895 if (!ret) {
896 qWarning("failed to send flush-start event");
897 return;
898 }
899
900 GstEvent *flushStop = gst_event_new_flush_stop(resetTime);
901 ret = sendEvent(flushStop);
902 if (!ret)
903 qWarning("failed to send flush-stop event");
904}
905
907{
908 using namespace std::chrono_literals;
909
910 GstState state = parent().state(1s);
911
912 if (state != GST_STATE_PAUSED)
913 return;
914
915 sendFlushStartStop(/*resetTime=*/true);
916}
917
918// QGstClock
919
921 : QGstClock{
924 }
925{
926}
927
928QGstClock::QGstClock(GstClock *clock, RefMode mode)
929 : QGstObject{
931 mode,
932 }
933{
934}
935
937{
938 return qGstCheckedCast<GstClock>(object());
939}
940
942{
943 return gst_clock_get_time(clock());
944}
946// QGstElement
947
948QGstElement::QGstElement(GstElement *element, RefMode mode)
949 : QGstObject{
951 mode,
952 }
953{
954}
955
956QGstElement QGstElement::createFromFactory(const char *factory, const char *name)
957{
958 GstElement *element = gst_element_factory_make(factory, name);
959
960#ifndef QT_NO_DEBUG
961 if (!element) {
962 qWarning() << "Failed to make element" << name << "from factory" << factory;
963 return QGstElement{};
964 }
965#endif
966
967 return QGstElement{
968 element,
969 NeedsRef,
970 };
971}
972
973QGstElement QGstElement::createFromFactory(GstElementFactory *factory, const char *name)
974{
975 return QGstElement{
976 gst_element_factory_create(factory, name),
977 NeedsRef,
978 };
979}
980
981QGstElement QGstElement::createFromFactory(const QGstElementFactoryHandle &factory,
982 const char *name)
983{
984 return createFromFactory(factory.get(), name);
985}
986
987QGstElement QGstElement::createFromDevice(const QGstDeviceHandle &device, const char *name)
988{
989 return createFromDevice(device.get(), name);
990}
991
992QGstElement QGstElement::createFromDevice(GstDevice *device, const char *name)
993{
994 return QGstElement{
995 gst_device_create_element(device, name),
996 QGstElement::NeedsRef,
997 };
998}
999
1001{
1002 QUniqueGErrorHandle error;
1003 QGstElement element{
1004 gst_parse_launch(str, &error),
1005 QGstElement::NeedsRef,
1006 };
1007
1008 if (error) // error does not mean that the element could not be constructed
1009 qWarning() << "gst_parse_launch error:" << error;
1010
1011 return element;
1012}
1013
1014QGstElement QGstElement::createFromPipelineDescription(const QByteArray &str)
1015{
1016 return createFromPipelineDescription(str.constData());
1017}
1018
1019QGstElementFactoryHandle QGstElement::findFactory(const char *name)
1020{
1021 return QGstElementFactoryHandle{
1022 gst_element_factory_find(name),
1023 QGstElementFactoryHandle::HasRef,
1024 };
1025}
1026
1027QGstElementFactoryHandle QGstElement::findFactory(const QByteArray &name)
1028{
1029 return findFactory(name.constData());
1030}
1031
1032QGstPad QGstElement::staticPad(const char *name) const
1033{
1034 return QGstPad(gst_element_get_static_pad(element(), name), HasRef);
1035}
1036
1038{
1039 return staticPad("src");
1040}
1041
1043{
1044 return staticPad("sink");
1045}
1046
1047QGstPad QGstElement::getRequestPad(const char *name) const
1048{
1049 return QGstPad(gst_element_request_pad_simple(element(), name), HasRef);
1050}
1051
1053{
1054 return gst_element_release_request_pad(element(), pad.pad());
1055}
1056
1057GstState QGstElement::state(std::chrono::nanoseconds timeout) const
1058{
1059 using namespace std::chrono_literals;
1060
1061 GstState state;
1062 GstStateChangeReturn change =
1063 gst_element_get_state(element(), &state, nullptr, timeout.count());
1064
1065 if (Q_UNLIKELY(change == GST_STATE_CHANGE_ASYNC))
1066 qWarning() << "QGstElement::state detected an asynchronous state change. Return value not "
1067 "reliable";
1068
1069 return state;
1070}
1071
1073{
1074 return gst_element_set_state(element(), state);
1075}
1076
1077bool QGstElement::setStateSync(GstState state, std::chrono::nanoseconds timeout)
1078{
1079 GstStateChangeReturn change = gst_element_set_state(element(), state);
1080 if (change == GST_STATE_CHANGE_ASYNC)
1081 change = gst_element_get_state(element(), nullptr, &state, timeout.count());
1082
1083 if (change != GST_STATE_CHANGE_SUCCESS && change != GST_STATE_CHANGE_NO_PREROLL) {
1084 qWarning() << "Could not change state of" << name() << "to" << state << change;
1085 dumpPipelineGraph("setStateSyncFailure");
1086 }
1087 return change == GST_STATE_CHANGE_SUCCESS || change == GST_STATE_CHANGE_NO_PREROLL;
1088}
1089
1091{
1092 Q_ASSERT(element());
1093 return gst_element_sync_state_with_parent(element()) == TRUE;
1094}
1095
1096bool QGstElement::finishStateChange(std::chrono::nanoseconds timeout)
1097{
1098 GstState state, pending;
1099 GstStateChangeReturn change =
1100 gst_element_get_state(element(), &state, &pending, timeout.count());
1101
1102 if (change != GST_STATE_CHANGE_SUCCESS && change != GST_STATE_CHANGE_NO_PREROLL) {
1103 qWarning() << "Could not finish change state of" << name() << change << state << pending;
1104 dumpPipelineGraph("finishStateChangeFailure");
1105 }
1106 return change == GST_STATE_CHANGE_SUCCESS;
1107}
1108
1109bool QGstElement::hasAsyncStateChange(std::chrono::nanoseconds timeout) const
1110{
1111 GstState state;
1112 GstStateChangeReturn change =
1113 gst_element_get_state(element(), &state, nullptr, timeout.count());
1114 return change == GST_STATE_CHANGE_ASYNC;
1115}
1116
1117bool QGstElement::waitForAsyncStateChangeComplete(std::chrono::nanoseconds timeout) const
1118{
1119 using namespace std::chrono_literals;
1120 for (;;) {
1121 if (!hasAsyncStateChange())
1122 return true;
1123 timeout -= 10ms;
1124 if (timeout < 0ms)
1125 return false;
1126 std::this_thread::sleep_for(10ms);
1127 }
1128}
1129
1130void QGstElement::lockState(bool locked)
1131{
1132 gst_element_set_locked_state(element(), locked);
1133}
1134
1136{
1137 return gst_element_is_locked_state(element());
1138}
1139
1140void QGstElement::sendEvent(GstEvent *event) const
1141{
1142 gst_element_send_event(element(), event);
1143}
1144
1146{
1147 sendEvent(gst_event_new_eos());
1148}
1149
1150std::optional<std::chrono::nanoseconds> QGstElement::duration() const
1151{
1152 gint64 d;
1153 if (!gst_element_query_duration(element(), GST_FORMAT_TIME, &d)) {
1154 qDebug() << "QGstElement: failed to query duration";
1155 return std::nullopt;
1156 }
1157 return std::chrono::nanoseconds{ d };
1158}
1159
1160std::optional<std::chrono::milliseconds> QGstElement::durationInMs() const
1161{
1162 using namespace std::chrono;
1163 auto dur = duration();
1164 if (dur)
1165 return round<milliseconds>(*dur);
1166 return std::nullopt;
1167}
1168
1169std::optional<std::chrono::nanoseconds> QGstElement::position() const
1170{
1171 QGstQueryHandle &query = positionQuery();
1172
1173 gint64 pos;
1174 if (gst_element_query(element(), query.get())) {
1175 gst_query_parse_position(query.get(), nullptr, &pos);
1176 return std::chrono::nanoseconds{ pos };
1177 }
1178
1179 qDebug() << "QGstElement: failed to query position";
1180 return std::nullopt;
1181}
1182
1183std::optional<std::chrono::milliseconds> QGstElement::positionInMs() const
1184{
1185 using namespace std::chrono;
1186 auto pos = position();
1187 if (pos)
1188 return round<milliseconds>(*pos);
1189 return std::nullopt;
1190}
1191
1192std::optional<bool> QGstElement::canSeek() const
1193{
1194 QGstQueryHandle query{
1195 gst_query_new_seeking(GST_FORMAT_TIME),
1196 QGstQueryHandle::HasRef,
1197 };
1198 gboolean canSeek = false;
1199 gst_query_parse_seeking(query.get(), nullptr, &canSeek, nullptr, nullptr);
1200
1201 if (gst_element_query(element(), query.get())) {
1202 gst_query_parse_seeking(query.get(), nullptr, &canSeek, nullptr, nullptr);
1203 return canSeek;
1204 }
1205 return std::nullopt;
1206}
1207
1209{
1210 return gst_element_get_base_time(element());
1211}
1212
1213void QGstElement::setBaseTime(GstClockTime time) const
1214{
1215 gst_element_set_base_time(element(), time);
1216}
1217
1219{
1220 return GST_ELEMENT_CAST(get());
1221}
1222
1224{
1225 return QGstElement{
1226 qGstCheckedCast<GstElement>(gst_element_get_parent(object())),
1227 QGstElement::HasRef,
1228 };
1229}
1230
1232{
1233 QGstElement ancestor = *this;
1234 for (;;) {
1235 QGstElement greatAncestor = ancestor.getParent();
1236 if (greatAncestor) {
1237 ancestor = std::move(greatAncestor);
1238 continue;
1239 }
1240
1241 return QGstPipeline{
1242 qGstSafeCast<GstPipeline>(ancestor.element()),
1243 QGstPipeline::NeedsRef,
1244 };
1245 }
1246}
1247
1248void QGstElement::dumpPipelineGraph(const char *filename) const
1249{
1250 static const bool dumpEnabled = qEnvironmentVariableIsSet("GST_DEBUG_DUMP_DOT_DIR");
1251 if (dumpEnabled) {
1252 QGstPipeline pipeline = getPipeline();
1253 if (pipeline)
1254 pipeline.dumpGraph(filename);
1255 }
1256}
1257
1258QGstQueryHandle &QGstElement::positionQuery() const
1259{
1260 if (Q_UNLIKELY(!m_positionQuery))
1261 m_positionQuery = QGstQueryHandle{
1262 gst_query_new_position(GST_FORMAT_TIME),
1263 QGstQueryHandle::HasRef,
1264 };
1265
1266 return m_positionQuery;
1267}
1268
1269// QGstBin
1270
1271QGstBin QGstBin::create(const char *name)
1272{
1273 return QGstBin(gst_bin_new(name), NeedsRef);
1274}
1275
1276QGstBin QGstBin::createFromFactory(const char *factory, const char *name)
1277{
1278 QGstElement element = QGstElement::createFromFactory(factory, name);
1279 Q_ASSERT(GST_IS_BIN(element.element()));
1280 return QGstBin{
1281 GST_BIN(element.release()),
1282 RefMode::HasRef,
1283 };
1284}
1285
1286QGstBin QGstBin::createFromPipelineDescription(const QByteArray &pipelineDescription,
1287 const char *name, bool ghostUnlinkedPads)
1288{
1289 return createFromPipelineDescription(pipelineDescription.constData(), name, ghostUnlinkedPads);
1290}
1291
1292QGstBin QGstBin::createFromPipelineDescription(const char *pipelineDescription, const char *name,
1293 bool ghostUnlinkedPads)
1294{
1295 QUniqueGErrorHandle error;
1296
1297 GstElement *element =
1298 gst_parse_bin_from_description_full(pipelineDescription, ghostUnlinkedPads,
1299 /*context=*/nullptr, GST_PARSE_FLAG_NONE, &error);
1300
1301 if (!element) {
1302 qWarning() << "Failed to make element from pipeline description" << pipelineDescription
1303 << error;
1304 return QGstBin{};
1305 }
1306
1307 if (name)
1308 gst_element_set_name(element, name);
1309
1310 return QGstBin{
1311 element,
1312 NeedsRef,
1313 };
1314}
1315
1316QGstBin::QGstBin(GstBin *bin, RefMode mode)
1317 : QGstElement{
1319 mode,
1320 }
1321{
1322}
1323
1325{
1326 return qGstCheckedCast<GstBin>(object());
1327}
1328
1329void QGstBin::addGhostPad(const QGstElement &child, const char *name)
1330{
1331 addGhostPad(name, child.staticPad(name));
1332}
1333
1334void QGstBin::addGhostPad(const char *name, const QGstPad &pad)
1335{
1336 gst_element_add_pad(element(), gst_ghost_pad_new(name, pad.pad()));
1337}
1338
1340{
1341 return gst_bin_sync_children_states(bin());
1342}
1343
1344void QGstBin::dumpGraph(const char *fileNamePrefix) const
1345{
1346 if (isNull())
1347 return;
1348
1349 GST_DEBUG_BIN_TO_DOT_FILE(bin(), GST_DEBUG_GRAPH_SHOW_VERBOSE, fileNamePrefix);
1350}
1351
1353{
1354 return QGstElement{
1355 gst_bin_get_by_name(bin(), name),
1356 QGstElement::NeedsRef,
1357 };
1358}
1359
1361{
1362 gst_bin_recalculate_latency(bin());
1363}
1364
1365// QGstBaseSink
1366
1367QGstBaseSink::QGstBaseSink(GstBaseSink *element, RefMode mode)
1368 : QGstElement{
1370 mode,
1371 }
1372{
1373}
1374
1375void QGstBaseSink::setSync(bool arg)
1376{
1377 gst_base_sink_set_sync(baseSink(), arg ? TRUE : FALSE);
1378}
1379
1381{
1382 return qGstCheckedCast<GstBaseSink>(element());
1383}
1384
1385// QGstBaseSrc
1386
1387QGstBaseSrc::QGstBaseSrc(GstBaseSrc *element, RefMode mode)
1388 : QGstElement{
1390 mode,
1391 }
1392{
1393}
1394
1396{
1397 return qGstCheckedCast<GstBaseSrc>(element());
1398}
1399
1400// QGstAppSink
1401
1402QGstAppSink::QGstAppSink(GstAppSink *element, RefMode mode)
1403 : QGstBaseSink{
1405 mode,
1406 }
1407{
1408}
1409
1411{
1412 QGstElement created = QGstElement::createFromFactory("appsink", name);
1413 return QGstAppSink{
1414 qGstCheckedCast<GstAppSink>(created.element()),
1415 QGstAppSink::NeedsRef,
1416 };
1417}
1418
1420{
1421 return qGstCheckedCast<GstAppSink>(element());
1422}
1423
1424# if GST_CHECK_VERSION(1, 24, 0)
1425void QGstAppSink::setMaxBufferTime(std::chrono::nanoseconds ns)
1426{
1427 gst_app_sink_set_max_time(appSink(), qGstClockTimeFromChrono(ns));
1428}
1429# endif
1430
1432{
1433 gst_app_sink_set_max_buffers(appSink(), n);
1434}
1435
1436void QGstAppSink::setCaps(const QGstCaps &caps)
1437{
1438 gst_app_sink_set_caps(appSink(), caps.caps());
1439}
1440
1441void QGstAppSink::setCallbacks(GstAppSinkCallbacks &callbacks, gpointer user_data,
1442 GDestroyNotify notify)
1443{
1444 gst_app_sink_set_callbacks(appSink(), &callbacks, user_data, notify);
1445}
1446
1447QGstSampleHandle QGstAppSink::pullSample()
1448{
1449 return QGstSampleHandle{
1450 gst_app_sink_pull_sample(appSink()),
1451 QGstSampleHandle::HasRef,
1452 };
1453}
1454
1455// QGstAppSrc
1456
1457QGstAppSrc::QGstAppSrc(GstAppSrc *element, RefMode mode)
1458 : QGstBaseSrc{
1460 mode,
1461 }
1462{
1463}
1464
1465QGstAppSrc QGstAppSrc::create(const char *name)
1466{
1467 QGstElement created = QGstElement::createFromFactory("appsrc", name);
1468 return QGstAppSrc{
1469 qGstCheckedCast<GstAppSrc>(created.element()),
1470 QGstAppSrc::NeedsRef,
1471 };
1472}
1473
1475{
1476 return qGstCheckedCast<GstAppSrc>(element());
1477}
1478
1479void QGstAppSrc::setCallbacks(GstAppSrcCallbacks &callbacks, gpointer user_data,
1480 GDestroyNotify notify)
1481{
1482 gst_app_src_set_callbacks(appSrc(), &callbacks, user_data, notify);
1483}
1484
1486{
1487 return gst_app_src_push_buffer(appSrc(), buffer);
1488}
1489
1490QString qGstErrorMessageCannotFindElement(std::string_view element)
1491{
1492 return QStringLiteral("Could not find the %1 GStreamer element")
1493 .arg(QLatin1StringView(element));
1494}
1495
1496QT_END_NAMESPACE
QGObjectHandlerConnection(QGstObject object, gulong handler)
Definition qgst.cpp:750
QGObjectHandlerScopedConnection(QGObjectHandlerConnection connection)
Definition qgst.cpp:767
std::optional< int > toInt64() const
Definition qgst.cpp:95
std::optional< QGRange< int > > toIntRange() const
Definition qgst.cpp:124
std::optional< int > toInt() const
Definition qgst.cpp:88
int listSize() const
Definition qgst.cpp:150
bool isList() const
Definition qgst.cpp:145
QGstStructureView toStructure() const
Definition qgst.cpp:131
std::optional< QGRange< float > > getFractionRange() const
Definition qgst.cpp:115
const char * toString() const
Definition qgst.cpp:102
std::optional< float > getFraction() const
Definition qgst.cpp:107
QGValue at(int index) const
Definition qgst.cpp:155
bool isNull() const
Definition qgst.cpp:76
QGstCaps toCaps() const
Definition qgst.cpp:138
std::optional< bool > toBool() const
Definition qgst.cpp:81
QGValue(const GValue *v)
Definition qgst.cpp:74
QGstSampleHandle pullSample()
Definition qgst.cpp:1447
void setCallbacks(GstAppSinkCallbacks &callbacks, gpointer user_data, GDestroyNotify notify)
Definition qgst.cpp:1441
GstAppSink * appSink() const
Definition qgst.cpp:1419
void setCaps(const QGstCaps &caps)
Definition qgst.cpp:1436
void setMaxBuffers(int)
Definition qgst.cpp:1431
static QGstAppSink create(const char *name)
Definition qgst.cpp:1410
QGstAppSink(GstAppSink *, RefMode)
Definition qgst.cpp:1402
static QGstAppSrc create(const char *name)
Definition qgst.cpp:1465
GstFlowReturn pushBuffer(GstBuffer *)
Definition qgst.cpp:1485
void setCallbacks(GstAppSrcCallbacks &callbacks, gpointer user_data, GDestroyNotify notify)
Definition qgst.cpp:1479
QGstAppSrc(GstAppSrc *, RefMode)
Definition qgst.cpp:1457
GstAppSrc * appSrc() const
Definition qgst.cpp:1474
void setSync(bool)
Definition qgst.cpp:1375
QGstBaseSink(GstBaseSink *, RefMode)
Definition qgst.cpp:1367
GstBaseSink * baseSink() const
Definition qgst.cpp:1380
QGstBaseSrc(GstBaseSrc *, RefMode)
Definition qgst.cpp:1387
GstBaseSrc * baseSrc() const
Definition qgst.cpp:1395
QGstElement findByName(const char *)
Definition qgst.cpp:1352
void dumpGraph(const char *fileNamePrefix) const
Definition qgst.cpp:1344
void recalculateLatency()
Definition qgst.cpp:1360
GstBin * bin() const
Definition qgst.cpp:1324
static QGstBin create(const char *name)
Definition qgst.cpp:1271
void addGhostPad(const QGstElement &child, const char *name)
Definition qgst.cpp:1329
static QGstBin createFromPipelineDescription(const char *pipelineDescription, const char *name=nullptr, bool ghostUnlinkedPads=false)
Definition qgst.cpp:1292
static QGstBin createFromFactory(const char *factory, const char *name)
Definition qgst.cpp:1276
void addGhostPad(const char *name, const QGstPad &pad)
Definition qgst.cpp:1334
bool syncChildrenState()
Definition qgst.cpp:1339
QGstBin(GstBin *bin, RefMode mode=NeedsRef)
Definition qgst.cpp:1316
void addPixelFormats(const QList< QVideoFrameFormat::PixelFormat > &formats, const char *modifier=nullptr)
Definition qgst.cpp:475
MemoryFormat memoryFormat() const
Definition qgst.cpp:551
int size() const
Definition qgst.cpp:561
static QGstCaps fromCameraFormat(const QCameraFormat &format)
Definition qgst.cpp:522
static QGstCaps create()
Definition qgst.cpp:578
GstCaps * caps() const
Definition qgst.cpp:573
void setResolution(QSize)
Definition qgst.cpp:508
MemoryFormat
Definition qgst_p.h:433
@ DMABuf
Definition qgst_p.h:433
@ CpuMemory
Definition qgst_p.h:433
@ GLTexture
Definition qgst_p.h:433
QGstCaps copy() const
Definition qgst.cpp:543
QGstStructureView at(int index) const
Definition qgst.cpp:566
QGstClock(GstClock *clock, RefMode mode)
Definition qgst.cpp:928
GstClockTime time() const
Definition qgst.cpp:941
GstClock * clock() const
Definition qgst.cpp:936
QGstClock(const QGstObject &o)
Definition qgst.cpp:920
void setBaseTime(GstClockTime time) const
Definition qgst.cpp:1213
GstStateChangeReturn setState(GstState state)
Definition qgst.cpp:1072
std::optional< std::chrono::nanoseconds > position() const
Definition qgst.cpp:1169
GstElement * element() const
Definition qgst.cpp:1218
QGstElement(GstElement *element, RefMode mode)
Definition qgst.cpp:948
void lockState(bool locked)
Definition qgst.cpp:1130
QGstPad getRequestPad(const char *name) const
Definition qgst.cpp:1047
std::optional< bool > canSeek() const
Definition qgst.cpp:1192
std::optional< std::chrono::nanoseconds > duration() const
Definition qgst.cpp:1150
bool isStateLocked() const
Definition qgst.cpp:1135
void sendEvent(GstEvent *event) const
Definition qgst.cpp:1140
void dumpPipelineGraph(const char *filename) const
Definition qgst.cpp:1248
GstClockTime baseTime() const
Definition qgst.cpp:1208
void releaseRequestPad(const QGstPad &pad) const
Definition qgst.cpp:1052
bool syncStateWithParent()
Definition qgst.cpp:1090
QGstPad sink() const
Definition qgst.cpp:1042
QGstPad staticPad(const char *name) const
Definition qgst.cpp:1032
void sendEos() const
Definition qgst.cpp:1145
std::optional< std::chrono::milliseconds > positionInMs() const
Definition qgst.cpp:1183
static QGstElement createFromFactory(const char *factory, const char *name=nullptr)
Definition qgst.cpp:956
QGstElement getParent() const
Definition qgst.cpp:1223
QGstPipeline getPipeline() const
Definition qgst.cpp:1231
static QGstElement createFromPipelineDescription(const char *)
Definition qgst.cpp:1000
QGstPad src() const
Definition qgst.cpp:1037
std::optional< std::chrono::milliseconds > durationInMs() const
Definition qgst.cpp:1160
void set(const char *property, double d)
Definition qgst.cpp:615
QGObjectHandlerConnection connect(const char *name, GCallback callback, gpointer userData)
Definition qgst.cpp:710
void * getObject(const char *property) const
Definition qgst.cpp:705
double getDouble(const char *property) const
Definition qgst.cpp:691
int getInt(const char *property) const
Definition qgst.cpp:663
void set(const char *property, int32_t i)
Definition qgst.cpp:600
QLatin1StringView name() const
Definition qgst.cpp:741
void set(const char *property, const QGstObject &o)
Definition qgst.cpp:620
QGString getString(const char *property) const
Definition qgst.cpp:635
void disconnect(gulong handlerId)
Definition qgst.cpp:719
QGstObject getGstObject(const char *property) const
Definition qgst.cpp:698
QLatin1StringView typeName() const
Definition qgst.cpp:729
void set(const char *property, const char *str)
Definition qgst.cpp:585
bool getBool(const char *property) const
Definition qgst.cpp:649
GType type() const
Definition qgst.cpp:724
QGstObject & operator=(QGstObject &&) noexcept=default
void set(const char *property, void *object, GDestroyNotify destroyFunction)
Definition qgst.cpp:630
void set(const char *property, bool b)
Definition qgst.cpp:590
quint64 getUInt64(const char *property) const
Definition qgst.cpp:670
QGstStructureView getStructure(const char *property) const
Definition qgst.cpp:642
qint64 getInt64(const char *property) const
Definition qgst.cpp:677
void set(const char *property, const QGstCaps &c)
Definition qgst.cpp:625
float getFloat(const char *property) const
Definition qgst.cpp:684
uint getUInt(const char *property) const
Definition qgst.cpp:656
GstObject * object() const
Definition qgst.cpp:736
bool link(const QGstPad &sink) const
Definition qgst.cpp:847
GstEvent * stickyEvent(GstEventType type)
Definition qgst.cpp:881
QGstTagListHandle tags() const
Definition qgst.cpp:813
QGstPad(const QGstObject &o)
Definition qgst.cpp:787
bool isLinked() const
Definition qgst.cpp:842
bool unlinkPeer() const
Definition qgst.cpp:857
QGstCaps queryCaps() const
Definition qgst.cpp:808
GstPad * pad() const
Definition qgst.cpp:876
QGstPad(GstPad *pad, RefMode mode)
Definition qgst.cpp:795
void sendFlushIfPaused()
Definition qgst.cpp:906
void sendFlushStartStop(bool resetTime)
Definition qgst.cpp:891
QGString streamId() const
Definition qgst.cpp:820
std::optional< QPlatformMediaPlayer::TrackType > inferTrackTypeFromName() const
Definition qgst.cpp:827
bool sendEvent(GstEvent *event)
Definition qgst.cpp:886
QGstCaps currentCaps() const
Definition qgst.cpp:803
QGstElement parent() const
Definition qgst.cpp:871
bool unlink(const QGstPad &sink) const
Definition qgst.cpp:852
QGstPad peer() const
Definition qgst.cpp:866
QGstStructureView(const QUniqueGstStructureHandle &)
Definition qgst.cpp:164
bool isNull() const
Definition qgst.cpp:174
QGRange< float > frameRateRange() const
Definition qgst.cpp:242
QSize nativeSize() const
Definition qgst.cpp:360
QGValue operator[](const char *fieldname) const
Definition qgst.cpp:184
QVideoFrameFormat::PixelFormat pixelFormat() const
Definition qgst.cpp:219
QUniqueGstStructureHandle clone() const
Definition qgst.cpp:169
std::optional< QGRange< QSize > > resolutionRange() const
Definition qgst.cpp:300
QGstreamerMessage getMessage()
Definition qgst.cpp:326
QGstCaps caps() const
Definition qgst.cpp:189
std::optional< Fraction > pixelAspectRatio() const
Definition qgst.cpp:333
QGstTagListHandle tags() const
Definition qgst.cpp:194
QSize resolution() const
Definition qgst.cpp:205
QByteArrayView name() const
Definition qgst.cpp:179
QGstStructureView(const GstStructure *)
Definition qgst.cpp:162
constexpr std::array< VideoFormat, 19 > qt_videoFormatLookup
Definition qgst.cpp:25
int indexOfVideoFormat(QVideoFrameFormat::PixelFormat format)
Definition qgst.cpp:52
static QSize qCalculateFrameSizeGStreamer(QSize resolution, Fraction par)
Definition qgst.cpp:349
QString qGstErrorMessageCannotFindElement(std::string_view element)
Definition qgst.cpp:1490
QVideoFrameFormat::PixelFormat pixelFormat
Definition qgst.cpp:21