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;
};
|