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