7#include "pipewirebaseencodedstream.h"
9#include <logging_libav.h>
10#include <logging_record.h>
15#include <libavcodec/codec.h>
16#include <libavutil/log.h>
20#include "pipewireproduce_p.h"
21#include "vaapiutils_p.h"
23struct PipeWireEncodedStreamPrivate {
25 std::optional<uint> m_fd;
26 Fraction m_maxFramerate;
27 int m_maxPendingFrames = 50;
28 bool m_active =
false;
29 PipeWireBaseEncodedStream::Encoder m_encoder;
30 std::optional<quint8> m_quality;
31 PipeWireBaseEncodedStream::EncodingPreference m_encodingPreference;
33 std::unique_ptr<QThread> m_produceThread;
34 std::unique_ptr<PipeWireProduce> m_produce;
37PipeWireBaseEncodedStream::State PipeWireBaseEncodedStream::state()
const
41 }
else if (d->m_produceThread && d->m_produce->m_deactivated && d->m_produceThread->isRunning()) {
48PipeWireBaseEncodedStream::PipeWireBaseEncodedStream(
QObject *parent)
50 , d(new PipeWireEncodedStreamPrivate)
52 d->m_encoder = suggestedEncoders().value(0, NoEncoder);
54 const auto &
category = PIPEWIRELIBAV_LOGGING();
56 av_log_set_level(AV_LOG_DEBUG);
57 }
else if (
category.isInfoEnabled()) {
58 av_log_set_level(AV_LOG_INFO);
59 }
else if (
category.isWarningEnabled()) {
60 av_log_set_level(AV_LOG_WARNING);
62 av_log_set_level(AV_LOG_ERROR);
66PipeWireBaseEncodedStream::~PipeWireBaseEncodedStream()
75void PipeWireBaseEncodedStream::setNodeId(uint nodeId)
77 if (nodeId == d->m_nodeId)
82 Q_EMIT nodeIdChanged(nodeId);
85void PipeWireBaseEncodedStream::setFd(uint fd)
98Fraction PipeWireBaseEncodedStream::maxFramerate()
const
100 if (d->m_maxFramerate) {
101 return d->m_maxFramerate;
103 return Fraction{60, 1};
106void PipeWireBaseEncodedStream::setMaxFramerate(
const Fraction &framerate)
108 if (d->m_maxFramerate == framerate) {
111 d->m_maxFramerate = framerate;
114 d->m_produce->setMaxFramerate(d->m_maxFramerate);
117 Q_EMIT maxFramerateChanged();
120void PipeWireBaseEncodedStream::setMaxFramerate(quint32 numerator, quint32 denominator)
122 setMaxFramerate({numerator, denominator});
125void PipeWireBaseEncodedStream::setMaxPendingFrames(
int maxPendingFrames)
127 if (d->m_maxPendingFrames == maxPendingFrames) {
131 d->m_produce->setMaxPendingFrames(maxPendingFrames);
133 d->m_maxPendingFrames = maxPendingFrames;
134 Q_EMIT maxPendingFramesChanged();
137int PipeWireBaseEncodedStream::maxBufferSize()
const
139 return d->m_maxPendingFrames;
142void PipeWireBaseEncodedStream::setActive(
bool active)
144 if (d->m_active == active)
147 d->m_active = active;
149 Q_EMIT activeChanged(active);
152std::optional<quint8> PipeWireBaseEncodedStream::quality()
const
157void PipeWireBaseEncodedStream::setQuality(quint8 quality)
159 d->m_quality = quality;
161 d->m_produce->setQuality(d->m_quality);
165void PipeWireBaseEncodedStream::refresh()
167 if (d->m_produceThread) {
169 d->m_produceThread->wait();
171 d->m_produce.reset();
172 d->m_produceThread.reset();
175 if (d->m_active && d->m_nodeId > 0) {
176 d->m_produceThread = std::make_unique<QThread>();
177 d->m_produceThread->setObjectName(
"PipeWireProduce::input");
178 d->m_produce = makeProduce();
179 d->m_produce->setQuality(d->m_quality);
180 d->m_produce->setMaxPendingFrames(d->m_maxPendingFrames);
181 d->m_produce->setEncodingPreference(d->m_encodingPreference);
182 d->m_produce->moveToThread(d->m_produceThread.get());
183 d->m_produceThread->start();
190void PipeWireBaseEncodedStream::setEncoder(Encoder encoder)
192 if (d->m_encoder == encoder || !suggestedEncoders().contains(encoder)) {
195 d->m_encoder = encoder;
199PipeWireBaseEncodedStream::Encoder PipeWireBaseEncodedStream::encoder()
const
206 auto vaapi = VaapiUtils::instance();
209 PipeWireBaseEncodedStream::VP9,
210 PipeWireBaseEncodedStream::H264Main,
211 PipeWireBaseEncodedStream::H264Baseline,
212 PipeWireBaseEncodedStream::WebP,
213 PipeWireBaseEncodedStream::Gif,
215 auto removeUnavailableEncoders = [&vaapi](
const PipeWireBaseEncodedStream::Encoder &encoder) {
217 case PipeWireBaseEncodedStream::VP8:
218 if (vaapi->supportsProfile(VAProfileVP8Version0_3) && avcodec_find_encoder_by_name(
"vp8_vaapi")) {
221 return !avcodec_find_encoder_by_name(
"libvpx");
223 case PipeWireBaseEncodedStream::VP9:
224 return !avcodec_find_encoder_by_name(
"libvpx-vp9");
225 case PipeWireBaseEncodedStream::H264Main:
226 case PipeWireBaseEncodedStream::H264Baseline:
227 if (vaapi->supportsProfile(encoder == PipeWireBaseEncodedStream::H264Main ? VAProfileH264Main : VAProfileH264ConstrainedBaseline)
228 && avcodec_find_encoder_by_name(
"h264_vaapi")) {
231 return !(avcodec_find_encoder_by_name(
"libx264") || avcodec_find_encoder_by_name(
"libopenh264"));
233 case PipeWireBaseEncodedStream::WebP:
234 return !avcodec_find_encoder_by_name(
"libwebp");
235 case PipeWireBaseEncodedStream::Gif:
236 return !avcodec_find_encoder_by_name(
"gif");
241 ret.
removeIf(removeUnavailableEncoders);
245void PipeWireBaseEncodedStream::setEncodingPreference(PipeWireBaseEncodedStream::EncodingPreference preference)
247 d->m_encodingPreference = preference;
249 d->m_produce->setEncodingPreference(d->m_encodingPreference);
253PipeWireBaseEncodedStream::EncodingPreference PipeWireBaseEncodedStream::encodingPreference()
255 return d->m_encodingPreference;
258bool PipeWireBaseEncodedStream::isActive()
const
263uint PipeWireBaseEncodedStream::nodeId()
const
268uint PipeWireBaseEncodedStream::fd()
const
270 return d->m_fd.value_or(0);
273#include "moc_pipewirebaseencodedstream.cpp"
const QList< QKeySequence > & close()
Category category(StandardShortcut id)
qsizetype removeIf(Predicate pred)