File indexing completed on 2024-05-19 09:23:11
0001 /* 0002 SPDX-FileCopyrightText: 2018-2020 Red Hat Inc 0003 SPDX-FileCopyrightText: 2020-2021 Aleix Pol Gonzalez <aleixpol@kde.org> 0004 SPDX-FileContributor: Jan Grulich <jgrulich@redhat.com> 0005 0006 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0007 */ 0008 0009 #pragma once 0010 0011 #include <QHash> 0012 #include <QImage> 0013 #include <QObject> 0014 #include <QPoint> 0015 #include <QSharedPointer> 0016 #include <QSize> 0017 #include <optional> 0018 0019 #include <pipewire/pipewire.h> 0020 #include <spa/param/format-utils.h> 0021 #include <spa/param/props.h> 0022 #include <spa/param/video/format-utils.h> 0023 0024 #undef Status 0025 0026 class PipeWireCore; 0027 struct gbm_device; 0028 0029 typedef void *EGLDisplay; 0030 0031 struct DmaBufPlane 0032 { 0033 int fd; ///< The dmabuf file descriptor 0034 uint32_t offset; ///< The offset from the start of buffer 0035 uint32_t stride; ///< The distance from the start of a row to the next row in bytes 0036 }; 0037 0038 struct DmaBufAttributes 0039 { 0040 int width = 0; 0041 int height = 0; 0042 uint32_t format = 0; 0043 uint64_t modifier = 0; ///< The layout modifier 0044 0045 QList<DmaBufPlane> planes; 0046 }; 0047 0048 struct PipeWireCursor 0049 { 0050 QPoint position; 0051 QPoint hotspot; 0052 QImage texture; 0053 bool operator!=(const PipeWireCursor &other) const 0054 { 0055 return !operator==(other); 0056 }; 0057 bool operator==(const PipeWireCursor &other) const 0058 { 0059 return position == other.position && hotspot == other.hotspot && texture == other.texture; 0060 } 0061 }; 0062 0063 struct PipeWireFrame 0064 { 0065 spa_video_format format; 0066 std::optional<int> sequential; 0067 std::optional<std::chrono::nanoseconds> presentationTimestamp; 0068 std::optional<DmaBufAttributes> dmabuf; 0069 std::optional<QImage> image; 0070 std::optional<QRegion> damage; 0071 std::optional<PipeWireCursor> cursor; 0072 }; 0073 0074 struct Fraction 0075 { 0076 bool operator==(const Fraction &other) const 0077 { 0078 return numerator == other.numerator && denominator == other.denominator; 0079 } 0080 explicit operator bool() const 0081 { 0082 return isValid(); 0083 } 0084 bool isValid() const 0085 { 0086 return denominator > 0; 0087 } 0088 quint32 numerator = 0; 0089 quint32 denominator = 0; 0090 }; 0091 0092 QImage::Format SpaToQImageFormat(quint32 /*spa_video_format*/ format); 0093 0094 struct PipeWireSourceStreamPrivate; 0095 0096 class PipeWireSourceStream : public QObject 0097 { 0098 Q_OBJECT 0099 public: 0100 explicit PipeWireSourceStream(QObject *parent = nullptr); 0101 ~PipeWireSourceStream(); 0102 0103 Fraction framerate() const; 0104 void setMaxFramerate(const Fraction &framerate); 0105 uint nodeId(); 0106 QString error() const; 0107 0108 QSize size() const; 0109 pw_stream_state state() const; 0110 bool createStream(uint nodeid, int fd); 0111 void setActive(bool active); 0112 void setDamageEnabled(bool withDamage); 0113 0114 void handleFrame(struct pw_buffer *buffer); 0115 void process(); 0116 void renegotiateModifierFailed(spa_video_format format, quint64 modifier); 0117 0118 std::optional<std::chrono::nanoseconds> currentPresentationTimestamp() const; 0119 0120 static uint32_t spaVideoFormatToDrmFormat(spa_video_format spa_format); 0121 0122 bool usingDmaBuf() const; 0123 bool allowDmaBuf() const; 0124 void setAllowDmaBuf(bool allowed); 0125 0126 Q_SIGNALS: 0127 void streamReady(); 0128 void startStreaming(); 0129 void stopStreaming(); 0130 void streamParametersChanged(); 0131 void frameReceived(const PipeWireFrame &frame); 0132 void stateChanged(pw_stream_state state, pw_stream_state oldState); 0133 0134 private: 0135 static void onStreamParamChanged(void *data, uint32_t id, const struct spa_pod *format); 0136 static void onStreamStateChanged(void *data, pw_stream_state old, pw_stream_state state, const char *error_message); 0137 static void onRenegotiate(void *data, uint64_t); 0138 QList<const spa_pod *> createFormatsParams(spa_pod_builder podBuilder); 0139 0140 void coreFailed(const QString &errorMessage); 0141 QScopedPointer<PipeWireSourceStreamPrivate> d; 0142 };