KPipewire

libvpxvp9encoder.cpp
1/*
2 SPDX-FileCopyrightText: 2023 Aleix Pol Gonzalez <aleixpol@kde.org>
3 SPDX-FileCopyrightText: 2023 Marco Martin <mart@kde.org>
4 SPDX-FileCopyrightText: 2023 Arjen Hiemstra <ahiemstra@heimr.nl>
5 SPDX-FileCopyrightText: 2023 Noah Davis <noahadvs@gmail.com>
6
7 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
8*/
9
10#include "libvpxvp9encoder_p.h"
11
12#include "pipewireproduce_p.h"
13
14#include <QSize>
15#include <QThread>
16
17extern "C" {
18#include <libavcodec/avcodec.h>
19#include <libavfilter/buffersink.h>
20#include <libavfilter/buffersrc.h>
21#include <libavutil/pixfmt.h>
22}
23
24#include "logging_record.h"
25
26LibVpxVp9Encoder::LibVpxVp9Encoder(PipeWireProduce *produce)
27 : SoftwareEncoder(produce)
28{
29}
30
31bool LibVpxVp9Encoder::initialize(const QSize &size)
32{
33 createFilterGraph(size);
34
35 auto codec = avcodec_find_encoder_by_name("libvpx-vp9");
36 if (!codec) {
37 qCWarning(PIPEWIRERECORD_LOGGING) << "libvpx-vp9 codec not found";
38 return false;
39 }
40
41 m_avCodecContext = avcodec_alloc_context3(codec);
42 if (!m_avCodecContext) {
43 qCWarning(PIPEWIRERECORD_LOGGING) << "Could not allocate video codec context";
44 return false;
45 }
46
47 Q_ASSERT(!size.isEmpty());
48 m_avCodecContext->width = size.width();
49 m_avCodecContext->height = size.height();
50 m_avCodecContext->pix_fmt = AV_PIX_FMT_YUV420P;
51 m_avCodecContext->time_base = AVRational{1, 1000};
52
53 AVDictionary *options = buildEncodingOptions();
54 maybeLogOptions(options);
55
56 const auto area = size.width() * size.height();
57 // m_avCodecContext->framerate is not set, so we use m_produce->maxFramerate() instead.
58 const auto maxFramerate = m_produce->maxFramerate();
59 const auto fps = qreal(maxFramerate.numerator) / std::max(quint32(1), maxFramerate.denominator);
60
61 m_avCodecContext->gop_size = fps * 2;
62
63 if (int result = avcodec_open2(m_avCodecContext, codec, &options); result < 0) {
64 qCWarning(PIPEWIRERECORD_LOGGING) << "Could not open codec" << av_err2str(result);
65 return false;
66 }
67
68 return true;
69}
70
71int LibVpxVp9Encoder::percentageToAbsoluteQuality(const std::optional<quint8> &quality)
72{
73 if (!quality) {
74 return -1;
75 }
76
77 constexpr int MinQuality = 63;
78 return std::max(1, int(MinQuality - (m_quality.value() / 100.0) * MinQuality));
79}
80
81AVDictionary *LibVpxVp9Encoder::buildEncodingOptions()
82{
83 AVDictionary *options = SoftwareEncoder::buildEncodingOptions();
84
85 // We're probably capturing a screen
86 av_dict_set(&options, "tune-content", "screen", 0);
87
88 // Lower crf is higher quality. Max 0, min 63. libvpx-vp9 doesn't use global_quality.
89 int crf = 31;
90 if (m_quality) {
91 crf = percentageToAbsoluteQuality(m_quality);
92 }
93
94 av_dict_set_int(&options, "qmin", std::clamp(crf / 2, 0, crf), 0);
95 av_dict_set_int(&options, "qmax", std::clamp(int(crf * 1.5), crf, 63), 0);
96 av_dict_set_int(&options, "crf", crf, 0);
97
98 // 0-4 are for Video-On-Demand with the good or best deadline.
99 // Don't use best, it's not worth it.
100 // 5-8 are for streaming with the realtime deadline.
101 // Lower is higher quality.
102 int cpuUsed = 5 + std::max(1, int(3 - std::round(m_quality.value_or(50) / 100.0 * 3)));
103 av_dict_set_int(&options, "cpu-used", cpuUsed, 0);
104 av_dict_set(&options, "deadline", "realtime", 0);
105
106 // The value is interpreted as being equivalent to log2(realNumberOfColumns),
107 // so 3 is 8 columns. 6 is the max amount of columns. 2 is the max amount of rows.
108 av_dict_set(&options, "tile-columns", "6", 0);
109 av_dict_set(&options, "tile-rows", "2", 0);
110
111 av_dict_set(&options, "row-mt", "1", 0);
112 av_dict_set(&options, "frame-parallel", "1", 0);
113
114 return options;
115}
int height() const const
bool isEmpty() const const
int width() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Apr 11 2025 11:54:43 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.