6#include <QtMultimedia/private/qmultimediautils_p.h>
7#include <QtCore/qoperatingsystemversion.h>
10#include <libavutil/pixdesc.h>
21 const AVPixelFormatSet &prohibitedFormats)
27 if (prohibitedFormats.count(fmt))
28 return NotSuitableAVScore;
30 const auto *desc = av_pix_fmt_desc_get(fmt);
32 return NotSuitableAVScore;
34 if (desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
36 return NotSuitableAVScore;
38 AVScore score = DefaultAVScore;
40 if (desc == sourceSwFormatDesc)
44 const int sourceBpp = av_get_bits_per_pixel(sourceSwFormatDesc);
45 const int bpp = av_get_bits_per_pixel(desc);
50 else if (bpp < sourceBpp)
51 score -= 100 + (sourceBpp - bpp);
56 if (desc->log2_chroma_h == 1)
58 if (desc->log2_chroma_w == 1)
61 if constexpr (QOperatingSystemVersion::currentType() == QOperatingSystemVersion::Android) {
64 if (fmt == AV_PIX_FMT_NV12)
68 if (desc->flags & AV_PIX_FMT_FLAG_BE)
70 if (desc->flags & AV_PIX_FMT_FLAG_PAL)
73 if (desc->flags & AV_PIX_FMT_FLAG_RGB)
85 std::reference_wrapper<
const AVPixelFormatSet> prohibitedFormats)
87 const auto sourceSwFormatDesc = av_pix_fmt_desc_get(sourceFormat);
88 return [=](AVPixelFormat fmt) {
89 return calculateTargetSwFormatScore(sourceSwFormatDesc, fmt, prohibitedFormats);
96 case AV_PIX_FMT_MEDIACODEC:
105 const HWAccel &accel,
106 const AVPixelFormatSet &prohibitedFormats)
108 auto scoreCalculator = targetSwFormatScoreCalculator(sourceSWFormat, prohibitedFormats);
110 const auto constraints = accel.constraints();
111 if (constraints && constraints->valid_sw_formats) {
112 QSpan<
const AVPixelFormat> formats = makeSpan(constraints->valid_sw_formats);
113 return findBestAVValue(formats, scoreCalculator);
118 const auto pixelFormats = codec.pixelFormats();
119 return findBestAVValue(pixelFormats, scoreCalculator);
123 const HWAccel *accel,
124 const AVPixelFormatSet &prohibitedFormats)
127 const auto hwFormat = accel->hwFormat();
130 if (!isHwFormatAcceptedByCodec(hwFormat) || prohibitedFormats.count(hwFormat))
131 return findTargetSWFormat(sourceSWFormat, codec, *accel, prohibitedFormats);
133 const auto constraints = accel->constraints();
134 if (constraints && ranges::contains(makeSpan(constraints->valid_hw_formats), hwFormat))
140 if (isAVFormatSupported(codec, hwFormat))
144 const auto pixelFormats = codec.pixelFormats();
145 if (pixelFormats.empty()) {
146 qWarning() <<
"Codec pix formats are undefined, it's likely to behave incorrectly";
148 return sourceSWFormat;
151 auto swScoreCalculator = targetSwFormatScoreCalculator(sourceSWFormat, prohibitedFormats);
152 return findBestAVValue(pixelFormats, swScoreCalculator);
157 const auto pixelFormats = codec.pixelFormats();
158 if (pixelFormats.empty())
162 AVPixelFormatSet emptySet;
163 auto formatScoreCalculator = targetSwFormatScoreCalculator(sourceSWFormat, emptySet);
164 std::optional bestFormatWithScore =
165 findBestAVValueWithScore(pixelFormats, formatScoreCalculator);
166 if (bestFormatWithScore)
167 return bestFormatWithScore->score;
174 auto calcScore = [requestedRate](
const AVRational &rate) {
176 return qMin(requestedRate * rate.den, qreal(rate.num))
177 / qMax(requestedRate * rate.den, qreal(rate.num));
180 const auto result = findBestAVValue(supportedRates, calcScore);
181 if (result && result->num && result->den)
184 const auto [num, den] = qRealToFraction(requestedRate);
191 if (!supportedRates.empty()) {
192 auto hasFrameRate = [&]() {
193 for (AVRational rate : supportedRates)
194 if (rate.den == frameRate.den && rate.num == frameRate.num)
200 Q_ASSERT(hasFrameRate());
202 return { frameRate.den, frameRate.num };
205 constexpr int TimeScaleFactor = 1000;
206 return { frameRate.den, frameRate.num * TimeScaleFactor };
211 if constexpr (QOperatingSystemVersion::currentType() == QOperatingSystemVersion::Windows) {
213 if (codec.name() ==
"h264_mf"_L1) {
214 auto makeEven = [](
int size) {
return size & ~1; };
215 return QSize(makeEven(requestedResolution.width()), makeEven(requestedResolution.height()));
218 return requestedResolution;
223 SwsFlags conversionType = SWS_FAST_BILINEAR;
225 if constexpr (QOperatingSystemVersion::currentType() == QOperatingSystemVersion::Android) {
228 if (targetSize.width() > sourceSize.width() || targetSize.height() > sourceSize.height())
229 conversionType = SWS_BICUBIC;
232 return conversionType;
static auto targetSwFormatScoreCalculator(AVPixelFormat sourceFormat, std::reference_wrapper< const AVPixelFormatSet > prohibitedFormats)
static AVScore calculateTargetSwFormatScore(const AVPixFmtDescriptor *sourceSwFormatDesc, AVPixelFormat fmt, const AVPixelFormatSet &prohibitedFormats)
std::optional< AVPixelFormat > findTargetFormat(AVPixelFormat sourceSWFormat, const Codec &codec, const HWAccel *accel, const AVPixelFormatSet &prohibitedFormats)
AVRational adjustFrameTimeBase(QSpan< const AVRational > supportedRates, AVRational frameRate)
adjustFrameTimeBase gets adjusted timebase by a list of supported frame rates and an already adjusted...
static bool isHwFormatAcceptedByCodec(AVPixelFormat pixFormat)
AVScore findSWFormatScores(const Codec &codec, AVPixelFormat sourceSWFormat)
SwsFlags getScaleConversionType(const QSize &sourceSize, const QSize &targetSize)
QSize adjustVideoResolution(const Codec &codec, QSize requestedResolution)
QT_MANGLE_NAMESPACE(QMacScreenCaptureStreamDelegate) QMacScreenCaptureStreamDelegate
AVRational adjustFrameRate(QSpan< const AVRational > supportedRates, qreal requestedRate)
adjustFrameRate get a rational frame rate be requested qreal rate. If the codec supports fixed frame ...
std::optional< AVPixelFormat > findTargetSWFormat(AVPixelFormat sourceSWFormat, const Codec &codec, const HWAccel &accel, const AVPixelFormatSet &prohibitedFormats)