File indexing completed on 2024-05-05 05:30:19
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 <QDebug> 0012 #include <QHash> 0013 #include <QImage> 0014 #include <QObject> 0015 #include <QPoint> 0016 #include <QSharedPointer> 0017 #include <QSize> 0018 #include <optional> 0019 0020 #include <pipewire/pipewire.h> 0021 #include <spa/param/format-utils.h> 0022 #include <spa/param/props.h> 0023 #include <spa/param/video/format-utils.h> 0024 0025 #include <kpipewire_export.h> 0026 0027 #undef Status 0028 0029 class PipeWireFrameCleanupFunction; 0030 class PipeWireCore; 0031 struct gbm_device; 0032 0033 typedef void *EGLDisplay; 0034 0035 struct DmaBufPlane { 0036 int fd; ///< The dmabuf file descriptor 0037 uint32_t offset; ///< The offset from the start of buffer 0038 uint32_t stride; ///< The distance from the start of a row to the next row in bytes 0039 }; 0040 0041 struct DmaBufAttributes { 0042 int width = 0; 0043 int height = 0; 0044 uint32_t format = 0; 0045 uint64_t modifier = 0; ///< The layout modifier 0046 0047 QList<DmaBufPlane> planes; 0048 }; 0049 0050 struct PipeWireCursor { 0051 QPoint position; 0052 QPoint hotspot; 0053 QImage texture; 0054 bool operator!=(const PipeWireCursor &other) const 0055 { 0056 return !operator==(other); 0057 }; 0058 bool operator==(const PipeWireCursor &other) const 0059 { 0060 return position == other.position && hotspot == other.hotspot && texture == other.texture; 0061 } 0062 }; 0063 Q_DECLARE_METATYPE(PipeWireCursor); 0064 0065 class KPIPEWIRE_EXPORT PipeWireFrameData 0066 { 0067 Q_DISABLE_COPY(PipeWireFrameData) 0068 public: 0069 PipeWireFrameData(spa_video_format format, void *data, QSize size, qint32 stride, PipeWireFrameCleanupFunction *cleanup); 0070 ~PipeWireFrameData(); 0071 0072 QImage toImage() const; 0073 std::shared_ptr<PipeWireFrameData> copy() const; 0074 0075 const spa_video_format format; 0076 void *const data = nullptr; 0077 const QSize size; 0078 const qint32 stride = 0; 0079 PipeWireFrameCleanupFunction *const cleanup = nullptr; 0080 }; 0081 0082 struct KPIPEWIRE_EXPORT PipeWireFrame { 0083 spa_video_format format; 0084 std::optional<quint64> sequential; 0085 std::optional<std::chrono::nanoseconds> presentationTimestamp; 0086 std::optional<DmaBufAttributes> dmabuf; 0087 std::optional<QRegion> damage; 0088 std::optional<PipeWireCursor> cursor; 0089 std::shared_ptr<PipeWireFrameData> dataFrame; 0090 }; 0091 0092 struct Fraction { 0093 bool operator==(const Fraction &other) const 0094 { 0095 return numerator == other.numerator && denominator == other.denominator; 0096 } 0097 explicit operator bool() const 0098 { 0099 return isValid(); 0100 } 0101 bool isValid() const 0102 { 0103 return denominator > 0; 0104 } 0105 quint32 numerator = 0; 0106 quint32 denominator = 0; 0107 }; 0108 0109 struct PipeWireSourceStreamPrivate; 0110 0111 class KPIPEWIRE_EXPORT PipeWireSourceStream : public QObject 0112 { 0113 Q_OBJECT 0114 public: 0115 explicit PipeWireSourceStream(QObject *parent = nullptr); 0116 ~PipeWireSourceStream(); 0117 0118 Fraction framerate() const; 0119 void setMaxFramerate(const Fraction &framerate); 0120 uint nodeId(); 0121 QString error() const; 0122 0123 QSize size() const; 0124 pw_stream_state state() const; 0125 bool createStream(uint nodeid, int fd); 0126 void setActive(bool active); 0127 void setDamageEnabled(bool withDamage); 0128 0129 void handleFrame(struct pw_buffer *buffer); 0130 void process(); 0131 void renegotiateModifierFailed(spa_video_format format, quint64 modifier); 0132 0133 std::optional<std::chrono::nanoseconds> currentPresentationTimestamp() const; 0134 0135 static uint32_t spaVideoFormatToDrmFormat(spa_video_format spa_format); 0136 0137 bool usingDmaBuf() const; 0138 bool allowDmaBuf() const; 0139 void setAllowDmaBuf(bool allowed); 0140 0141 Q_SIGNALS: 0142 void streamReady(); 0143 void startStreaming(); 0144 void stopStreaming(); 0145 void streamParametersChanged(); 0146 void frameReceived(const PipeWireFrame &frame); 0147 void stateChanged(pw_stream_state state, pw_stream_state oldState); 0148 0149 private: 0150 static void onStreamParamChanged(void *data, uint32_t id, const struct spa_pod *format); 0151 static void onStreamStateChanged(void *data, pw_stream_state old, pw_stream_state state, const char *error_message); 0152 static void onRenegotiate(void *data, uint64_t); 0153 QList<const spa_pod *> createFormatsParams(spa_pod_builder podBuilder); 0154 0155 void coreFailed(const QString &errorMessage); 0156 QScopedPointer<PipeWireSourceStreamPrivate> d; 0157 }; 0158 0159 Q_DECLARE_METATYPE(QList<DmaBufPlane>);