9#include "libx264encoder_p.h"
15#include <libavcodec/avcodec.h>
16#include <libavfilter/buffersink.h>
17#include <libavfilter/buffersrc.h>
18#include <libavutil/pixfmt.h>
21#include "logging_record.h"
23using namespace Qt::StringLiterals;
25LibX264Encoder::LibX264Encoder(H264Profile profile, PipeWireProduce *produce)
26 : SoftwareEncoder(produce)
32 m_filterGraphToParse = u
"pad=ceil(iw/2)*2:ceil(ih/2)*2,format=pix_fmts=yuv420p"_s;
35bool LibX264Encoder::initialize(
const QSize &size)
37 createFilterGraph(size);
39 auto codec = avcodec_find_encoder_by_name(
"libx264");
41 qCWarning(PIPEWIRERECORD_LOGGING) <<
"libx264 codec not found";
45 m_avCodecContext = avcodec_alloc_context3(codec);
46 if (!m_avCodecContext) {
47 qCWarning(PIPEWIRERECORD_LOGGING) <<
"Could not allocate video codec context";
56 m_avCodecContext->width = std::ceil(size.
width() / 2) * 2;
57 m_avCodecContext->height = std::ceil(size.
height() / 2) * 2;
58 m_avCodecContext->max_b_frames = 0;
59 m_avCodecContext->gop_size = 100;
60 m_avCodecContext->pix_fmt = AV_PIX_FMT_YUV420P;
61 m_avCodecContext->time_base = AVRational{1, 1000};
64 m_avCodecContext->global_quality = percentageToAbsoluteQuality(m_quality);
66 m_avCodecContext->global_quality = 35;
70 case H264Profile::Baseline:
71 m_avCodecContext->profile = FF_PROFILE_H264_BASELINE;
73 case H264Profile::Main:
74 m_avCodecContext->profile = FF_PROFILE_H264_MAIN;
76 case H264Profile::High:
77 m_avCodecContext->profile = FF_PROFILE_H264_HIGH;
81 AVDictionary *options =
nullptr;
83 applyEncodingPreference(options);
85 if (
int result = avcodec_open2(m_avCodecContext, codec, &options); result < 0) {
86 qCWarning(PIPEWIRERECORD_LOGGING) <<
"Could not open codec" << av_err2str(result);
93int LibX264Encoder::percentageToAbsoluteQuality(
const std::optional<quint8> &quality)
99 constexpr int MinQuality = 51 + 6 * 6;
100 return std::max(1,
int(MinQuality - (m_quality.value() / 100.0) * MinQuality));
103void LibX264Encoder::applyEncodingPreference(AVDictionary *options)
105 SoftwareEncoder::applyEncodingPreference(options);
107 av_dict_set(&options,
"flags",
"+mv4", 0);
109 av_dict_set(&options,
"-flags",
"+loop", 0);
bool isEmpty() const const