File indexing completed on 2024-05-05 09:46:38

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 #include <kpipewire_export.h>
0025 
0026 #undef Status
0027 
0028 class PipeWireCore;
0029 struct gbm_device;
0030 
0031 typedef void *EGLDisplay;
0032 
0033 struct DmaBufPlane {
0034     int fd; ///< The dmabuf file descriptor
0035     uint32_t offset; ///< The offset from the start of buffer
0036     uint32_t stride; ///< The distance from the start of a row to the next row in bytes
0037 };
0038 
0039 struct DmaBufAttributes {
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     QPoint position;
0050     QPoint hotspot;
0051     QImage texture;
0052     bool operator!=(const PipeWireCursor &other) const
0053     {
0054         return !operator==(other);
0055     };
0056     bool operator==(const PipeWireCursor &other) const
0057     {
0058         return position == other.position && hotspot == other.hotspot && texture == other.texture;
0059     }
0060 };
0061 Q_DECLARE_METATYPE(PipeWireCursor);
0062 
0063 struct KPIPEWIRE_EXPORT PipeWireFrame {
0064     spa_video_format format;
0065     std::optional<int> sequential;
0066     std::optional<std::chrono::nanoseconds> presentationTimestamp;
0067     std::optional<DmaBufAttributes> dmabuf;
0068     std::optional<QImage> image;
0069     std::optional<QRegion> damage;
0070     std::optional<PipeWireCursor> cursor;
0071 };
0072 
0073 struct Fraction {
0074     bool operator==(const Fraction &other) const
0075     {
0076         return numerator == other.numerator && denominator == other.denominator;
0077     }
0078     explicit operator bool() const
0079     {
0080         return isValid();
0081     }
0082     bool isValid() const
0083     {
0084         return denominator > 0;
0085     }
0086     quint32 numerator = 0;
0087     quint32 denominator = 0;
0088 };
0089 
0090 KPIPEWIRE_EXPORT QImage::Format SpaToQImageFormat(quint32 /*spa_video_format*/ format);
0091 
0092 struct PipeWireSourceStreamPrivate;
0093 
0094 class KPIPEWIRE_EXPORT PipeWireSourceStream : public QObject
0095 {
0096     Q_OBJECT
0097 public:
0098     explicit PipeWireSourceStream(QObject *parent = nullptr);
0099     ~PipeWireSourceStream();
0100 
0101     Fraction framerate() const;
0102     void setMaxFramerate(const Fraction &framerate);
0103     uint nodeId();
0104     QString error() const;
0105 
0106     QSize size() const;
0107     pw_stream_state state() const;
0108     bool createStream(uint nodeid, int fd);
0109     void setActive(bool active);
0110     void setDamageEnabled(bool withDamage);
0111 
0112     void handleFrame(struct pw_buffer *buffer);
0113     void process();
0114     void renegotiateModifierFailed(spa_video_format format, quint64 modifier);
0115 
0116     std::optional<std::chrono::nanoseconds> currentPresentationTimestamp() const;
0117 
0118     static uint32_t spaVideoFormatToDrmFormat(spa_video_format spa_format);
0119 
0120     bool usingDmaBuf() const;
0121     bool allowDmaBuf() const;
0122     void setAllowDmaBuf(bool allowed);
0123 
0124 Q_SIGNALS:
0125     void streamReady();
0126     void startStreaming();
0127     void stopStreaming();
0128     void streamParametersChanged();
0129     void frameReceived(const PipeWireFrame &frame);
0130     void stateChanged(pw_stream_state state, pw_stream_state oldState);
0131 
0132 private:
0133     static void onStreamParamChanged(void *data, uint32_t id, const struct spa_pod *format);
0134     static void onStreamStateChanged(void *data, pw_stream_state old, pw_stream_state state, const char *error_message);
0135     static void onRenegotiate(void *data, uint64_t);
0136     QList<const spa_pod *> createFormatsParams(spa_pod_builder podBuilder);
0137 
0138     void coreFailed(const QString &errorMessage);
0139     QScopedPointer<PipeWireSourceStreamPrivate> d;
0140 };
0141 
0142 Q_DECLARE_METATYPE(QList<DmaBufPlane>);