6#include "private/qmultimediautils_p.h"
9#include <libavutil/pixdesc.h>
18 const AVPixelFormatSet &prohibitedFormats)
24 if (prohibitedFormats.count(fmt))
25 return NotSuitableAVScore;
27 const auto *desc = av_pix_fmt_desc_get(fmt);
29 return NotSuitableAVScore;
31 if (desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
33 return NotSuitableAVScore;
35 AVScore score = DefaultAVScore;
37 if (desc == sourceSwFormatDesc)
41 const int sourceBpp = av_get_bits_per_pixel(sourceSwFormatDesc);
42 const int bpp = av_get_bits_per_pixel(desc);
47 else if (bpp < sourceBpp)
48 score -= 100 + (sourceBpp - bpp);
53 if (desc->log2_chroma_h == 1)
55 if (desc->log2_chroma_w == 1)
61 if (fmt == AV_PIX_FMT_NV12)
65 if (desc->flags & AV_PIX_FMT_FLAG_BE)
67 if (desc->flags & AV_PIX_FMT_FLAG_PAL)
70 if (desc->flags & AV_PIX_FMT_FLAG_RGB)
82 std::reference_wrapper<
const AVPixelFormatSet> prohibitedFormats)
84 const auto sourceSwFormatDesc = av_pix_fmt_desc_get(sourceFormat);
85 return [=](AVPixelFormat fmt) {
86 return calculateTargetSwFormatScore(sourceSwFormatDesc, fmt, prohibitedFormats);
93 case AV_PIX_FMT_MEDIACODEC:
102 const HWAccel &accel,
103 const AVPixelFormatSet &prohibitedFormats)
105 auto scoreCalculator = targetSwFormatScoreCalculator(sourceSWFormat, prohibitedFormats);
107 const auto constraints = accel.constraints();
108 if (constraints && constraints->valid_sw_formats) {
109 QSpan<
const AVPixelFormat> formats = makeSpan(constraints->valid_sw_formats);
110 return findBestAVValue(formats, scoreCalculator);
115 const auto pixelFormats = codec.pixelFormats();
116 return findBestAVValue(pixelFormats, scoreCalculator);
120 AVPixelFormat sourceSWFormat,
const Codec &codec,
121 const HWAccel *accel,
122 const AVPixelFormatSet &prohibitedFormats)
124 Q_UNUSED(sourceFormat);
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 && hasValue(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 return findBestAVValueWithScore(pixelFormats, formatScoreCalculator).score;
169 auto calcScore = [requestedRate](
const AVRational &rate) {
171 return qMin(requestedRate * rate.den, qreal(rate.num))
172 / qMax(requestedRate * rate.den, qreal(rate.num));
175 const auto result = findBestAVValue(supportedRates, calcScore);
176 if (result && result->num && result->den)
179 const auto [num, den] = qRealToFraction(requestedRate);
186 if (!supportedRates.empty()) {
187 auto hasFrameRate = [&]() {
188 for (AVRational rate : supportedRates)
189 if (rate.den == frameRate.den && rate.num == frameRate.num)
195 Q_ASSERT(hasFrameRate());
197 return { frameRate.den, frameRate.num };
200 constexpr int TimeScaleFactor = 1000;
201 return { frameRate.den, frameRate.num * TimeScaleFactor };
208 if (codec.name() == u"h264_mf") {
209 auto makeEven = [](
int size) {
return size & ~1; };
210 return QSize(makeEven(requestedResolution.width()), makeEven(requestedResolution.height()));
215 return requestedResolution;
220 SwsFlags conversionType = SWS_FAST_BILINEAR;
225 if (targetSize.width() > sourceSize.width() || targetSize.height() > sourceSize.height())
226 conversionType = SWS_BICUBIC;
228 Q_UNUSED(sourceSize);
229 Q_UNUSED(targetSize);
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 sourceFormat, 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)
std::conditional_t< QT_FFMPEG_AVIO_WRITE_CONST, const uint8_t *, uint8_t * > AvioWriteBufferType
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)