File: pipewirebaseencodedstream.h

package info (click to toggle)
kpipewire 6.3.6-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 1,364 kB
  • sloc: cpp: 6,192; xml: 133; makefile: 5; sh: 1
file content (166 lines) | stat: -rw-r--r-- 5,295 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/*
    SPDX-FileCopyrightText: 2022 Aleix Pol Gonzalez <aleixpol@kde.org>

    SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/

#pragma once

#include <QObject>

#include <kpipewire_export.h>

struct Fraction;
struct PipeWireEncodedStreamPrivate;
class PipeWireProduce;

class KPIPEWIRE_EXPORT PipeWireBaseEncodedStream : public QObject
{
    Q_OBJECT
    /// Specify the pipewire node id that we want to record
    Q_PROPERTY(uint nodeId READ nodeId WRITE setNodeId NOTIFY nodeIdChanged)
    /**
     * Specifies the file descriptor we are connected to, if none 0 will be returned
     *
     * Transfers the ownership of the fd, will close it when it's done with it.
     */
    Q_PROPERTY(uint fd READ fd WRITE setFd NOTIFY fdChanged)
    Q_PROPERTY(bool active READ isActive NOTIFY activeChanged)
    Q_PROPERTY(State state READ state NOTIFY stateChanged)
    Q_PROPERTY(Encoder encoder READ encoder WRITE setEncoder NOTIFY encoderChanged)

public:
    enum Encoder {
        NoEncoder,
        VP8,
        VP9,
        H264Main,
        H264Baseline,
        WebP,
        Gif,
    };
    Q_ENUM(Encoder)

    PipeWireBaseEncodedStream(QObject *parent = nullptr);
    ~PipeWireBaseEncodedStream() override;

    void setNodeId(uint nodeId);
    uint nodeId() const;

    void setFd(uint fd);
    uint fd() const;

    Fraction maxFramerate() const;
    void setMaxFramerate(const Fraction &framerate);
    void setMaxFramerate(quint32 numerator, quint32 denominator = 1);

    /**
     * Defines how many frames are kept in the encoding buffer.
     * New frames after the buffer is full will be dropped.
     *
     * This needs to be high enough for intra-frame analysis.
     * The default value is 50.
     *
     * There is a minimum value of 3.
     */
    void setMaxPendingFrames(int maxBufferSize);
    int maxBufferSize() const;

    bool isActive() const;
    /**
     * Set the active state of recording.
     *
     * @deprecated Since 6.4, use the separate `start()`/`stop()`calls instead.
     * This function now just calls `start()`/`stop()`.
     *
     * @note When calling `setActive(false)`, unlike `stop()`, this function will
     * block until the internal encoding threads are finished.
     */
    KPIPEWIRE_DEPRECATED void setActive(bool active);

    /**
     * Request to start recording.
     *
     * This will create everything required to perform recording, like a PipeWire
     * stream and an encoder, then start receiving frames from the stream and
     * encoding those.
     *
     * This requires a valid node ID to be set and that the current state is Idle.
     *
     * Note that recording all happens on separate threads, this method only
     * starts the process, only when state() returns Recording is recording
     * actually happening.
     */
    Q_INVOKABLE void start();
    /**
     * Request to stop recording.
     *
     * This will terminate receiving frames from PipeWire and do any cleanup
     * necessary to fully terminate recording after that.
     *
     * Note that after this request, there may still be some processing required
     * due to internal queues. As long as state() does not return Idle processing
     * is still happening and teardown has not been completed.
     */
    Q_INVOKABLE void stop();

    /**
     * The quality used for encoding.
     */
    std::optional<quint8> quality() const;
    /**
     * Set the quality to use for encoding.
     *
     * This uses a range of 0-100 as a percentage, with 0 being lowest quality
     * and 100 being highest. This is internally converted to a value relevant to
     * the encoder.
     *
     * @param quality The quality level to use.
     */
    void setQuality(quint8 quality);

    enum State {
        Idle, //< ready to get started
        Recording, //< actively recording
        Rendering, //< recording is over but there are still frames being processed.
    };
    Q_ENUM(State)
    State state() const;

    /**
     * Set the FFmpeg @p encoder that will be used to create the video
     *
     * They can be inspected using:
     * ffmpeg -encoders | grep "^ V"
     */
    void setEncoder(Encoder encoder);
    Encoder encoder() const;

    /// Returns the encoders that are tested to work, sorted by preference
    QList<PipeWireBaseEncodedStream::Encoder> suggestedEncoders() const;

    enum EncodingPreference {
        NoPreference, ///< Default settings, good for most usecases
        Quality, ///< A bit slower than default, but more consistent bitrate, use for high quality
        Speed, ///< Encode as fast as possible and use zerolatency tune, good for streaming
        Size, ///< Slowest encoding but reduces the size of the file
    };
    Q_ENUM(EncodingPreference);
    void setEncodingPreference(EncodingPreference profile);

Q_SIGNALS:
    void activeChanged(bool active);
    void nodeIdChanged(uint nodeId);
    void fdChanged(uint fd);
    void errorFound(const QString &error);
    void maxFramerateChanged();
    void maxPendingFramesChanged();
    void stateChanged();
    void encoderChanged();

protected:
    virtual std::unique_ptr<PipeWireProduce> makeProduce() = 0;
    EncodingPreference encodingPreference();

    QScopedPointer<PipeWireEncodedStreamPrivate> d;
};