/* SPDX-FileCopyrightText: 2018-2020 Red Hat Inc SPDX-FileCopyrightText: 2020-2021 Aleix Pol Gonzalez SPDX-FileContributor: Jan Grulich SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #undef Status class PipeWireFrameCleanupFunction; class PipeWireCore; struct gbm_device; typedef void *EGLDisplay; struct DmaBufPlane { int fd; ///< The dmabuf file descriptor uint32_t offset; ///< The offset from the start of buffer uint32_t stride; ///< The distance from the start of a row to the next row in bytes }; struct DmaBufAttributes { int width = 0; int height = 0; uint32_t format = 0; uint64_t modifier = 0; ///< The layout modifier QList planes; }; struct PipeWireCursor { QPoint position; QPoint hotspot; QImage texture; bool operator!=(const PipeWireCursor &other) const { return !operator==(other); }; bool operator==(const PipeWireCursor &other) const { return position == other.position && hotspot == other.hotspot && texture == other.texture; } }; class KPIPEWIRE_EXPORT PipeWireFrameData { Q_DISABLE_COPY(PipeWireFrameData) public: PipeWireFrameData(spa_video_format format, void *data, QSize size, qint32 stride, PipeWireFrameCleanupFunction *cleanup); ~PipeWireFrameData(); QImage toImage() const; std::shared_ptr copy() const; const spa_video_format format; void *const data = nullptr; const QSize size; const qint32 stride = 0; PipeWireFrameCleanupFunction *const cleanup = nullptr; }; struct KPIPEWIRE_EXPORT PipeWireFrame { spa_video_format format; std::optional sequential; std::optional presentationTimestamp; std::optional dmabuf; std::optional damage; std::optional cursor; std::shared_ptr dataFrame; }; struct Fraction { bool operator==(const Fraction &other) const { return numerator == other.numerator && denominator == other.denominator; } explicit operator bool() const { return isValid(); } bool isValid() const { return denominator > 0; } quint32 numerator = 0; quint32 denominator = 0; }; struct PipeWireSourceStreamPrivate; class KPIPEWIRE_EXPORT PipeWireSourceStream : public QObject { Q_OBJECT public: /** * A hint to indicate how this stream will be used. * * By default this will be set to Render. */ enum class UsageHint { Render, ///< Stream is intended mainly for reading pixel data and rendering directly to screen. EncodeSoftware, ///< Stream is intended mainly for encoding video using software encoding. EncodeHardware, ///< Stream is intended mainly for encoding video using hardware encoding. }; explicit PipeWireSourceStream(QObject *parent = nullptr); ~PipeWireSourceStream(); Fraction framerate() const; void setMaxFramerate(const Fraction &framerate); uint nodeId(); QString error() const; QSize size() const; pw_stream_state state() const; bool createStream(uint nodeid, int fd); void setActive(bool active); void setDamageEnabled(bool withDamage); UsageHint usageHint() const; void setUsageHint(UsageHint hint); void handleFrame(struct pw_buffer *buffer); void process(); void renegotiateModifierFailed(spa_video_format format, quint64 modifier); std::optional currentPresentationTimestamp() const; static uint32_t spaVideoFormatToDrmFormat(spa_video_format spa_format); bool usingDmaBuf() const; bool allowDmaBuf() const; void setAllowDmaBuf(bool allowed); Q_SIGNALS: void streamReady(); void startStreaming(); void stopStreaming(); void streamParametersChanged(); void frameReceived(const PipeWireFrame &frame); void stateChanged(pw_stream_state state, pw_stream_state oldState); private: static void onStreamParamChanged(void *data, uint32_t id, const struct spa_pod *format); static void onStreamStateChanged(void *data, pw_stream_state old, pw_stream_state state, const char *error_message); static void onRenegotiate(void *data, uint64_t); static void onDestroy(void *data); QList createFormatsParams(spa_pod_builder podBuilder); void coreFailed(const QString &errorMessage); QScopedPointer d; };