Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qffmpeg_p.h
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3#ifndef QFFMPEG_P_H
4#define QFFMPEG_P_H
5
6//
7// W A R N I N G
8// -------------
9//
10// This file is not part of the Qt API. It exists purely as an
11// implementation detail. This header file may change from version to
12// version without notice, or even be removed.
13//
14// We mean it.
15//
16
17#include <QtFFmpegMediaPluginImpl/private/qffmpegdefs_p.h>
18#include <QtFFmpegMediaPluginImpl/private/qffmpegcodec_p.h>
19#include <QtFFmpegMediaPluginImpl/private/qffmpegavaudioformat_p.h>
20#include <QtMultimedia/qvideoframeformat.h>
21
22#include <qstring.h>
23#include <optional>
24
25[[maybe_unused]] static inline bool operator==(const AVRational &lhs, const AVRational &rhs)
26{
27 return lhs.num == rhs.num && lhs.den == rhs.den;
28}
29
30[[maybe_unused]] static inline bool operator!=(const AVRational &lhs, const AVRational &rhs)
31{
32 return !(lhs == rhs);
33}
34
35QT_BEGIN_NAMESPACE
36
37namespace QFFmpeg
38{
39
40inline std::optional<qint64> mul(qint64 a, AVRational b)
41{
42 if (b.den == 0)
43 return {};
44
45 auto multiplyAndRound = [](qint64 a, AVRational b) { //
46 return (a * b.num + b.den / 2) / b.den;
47 };
48
49 if (a < 0)
50 return -multiplyAndRound(-a, b);
51 else
52 return multiplyAndRound(a, b);
53}
54
55inline std::optional<qreal> mul(qreal a, AVRational b)
56{
57 return b.den != 0 ? a * qreal(b.num) / qreal(b.den) : std::optional<qreal>{};
58}
59
60inline std::optional<qint64> timeStampMs(qint64 ts, AVRational base)
61{
62 return mul(1'000 * ts, base);
63}
64
65inline std::optional<qint64> timeStampUs(qint64 ts, AVRational base)
66{
67 return mul(1'000'000 * ts, base);
68}
69
70inline std::optional<float> toFloat(AVRational r)
71{
72 return r.den != 0 ? float(r.num) / float(r.den) : std::optional<float>{};
73}
74
75inline QString err2str(int errnum)
76{
77 char buffer[AV_ERROR_MAX_STRING_SIZE + 1] = {};
78 av_make_error_string(buffer, AV_ERROR_MAX_STRING_SIZE, errnum);
79 return QString::fromLocal8Bit(buffer);
80}
81
82inline void setAVFrameTime(AVFrame &frame, int64_t pts, const AVRational &timeBase)
83{
84 frame.pts = pts;
85#if QT_FFMPEG_HAS_FRAME_TIME_BASE
86 frame.time_base = timeBase;
87#else
88 Q_UNUSED(timeBase);
89#endif
90}
91
92inline void getAVFrameTime(const AVFrame &frame, int64_t &pts, AVRational &timeBase)
93{
94 pts = frame.pts;
95#if QT_FFMPEG_HAS_FRAME_TIME_BASE
96 timeBase = frame.time_base;
97#else
98 timeBase = { 0, 1 };
99#endif
100}
101
102inline int64_t getAVFrameDuration(const AVFrame &frame)
103{
104#if QT_FFMPEG_HAS_FRAME_DURATION
105 return frame.duration;
106#else
107 return frame.pkt_duration;
108#endif
109}
110
112{
113 AVDictionary *opts = nullptr;
114
115 operator AVDictionary **() { return &opts; }
116
118
120
122 : opts(std::exchange(other.opts, nullptr))
123 {
124 }
125
127 {
128 if (opts)
130 }
131};
132
133template<typename FunctionType, FunctionType F>
135{
136 template <typename T, std::invoke_result_t<FunctionType, T **> * = nullptr>
137 void operator()(T *object) const
138 {
139 if (object)
140 F(&object);
141 }
142
143 template <typename T, std::invoke_result_t<FunctionType, T *> * = nullptr>
144 void operator()(T *object) const
145 {
146 F(object);
147 }
148};
149
151
153{
154 return AVFrameUPtr(av_frame_alloc());
155}
156
159
163
166
170
172
175
176bool isAVFormatSupported(const Codec &codec, PixelOrSampleFormat format);
177
178// Returns true if the range contains the value, false otherwise
179template <typename Value>
180bool hasValue(QSpan<const Value> range, Value value)
181{
182 return std::find(range.begin(), range.end(), value) != range.end();
183}
184
185// Search for the first element in the range that satisfies the predicate
186// The predicate is evaluated for each value in the range until it returns
187// true, and the corresponding value is returned. If no match is found,
188// std::nullopt is returned.
189template <typename Value, typename Predicate>
190std::optional<Value> findIf(QSpan<const Value> range, const Predicate &predicate)
191{
192 const auto value = std::find_if(range.begin(), range.end(), predicate);
193 if (value == range.end())
194 return {};
195 return *value;
196}
197
198// Search the codec's pixel formats for a format that matches the predicate.
199// If no pixel format is found, repeat the search through the pixel formats
200// of all the codec's hardware configs. If no matching pixel format is found,
201// std::nullopt is returned. The predicate is evaluated once for each pixel
202// format until the predicate returns true.
203template <typename Predicate>
204std::optional<AVPixelFormat> findAVPixelFormat(const Codec &codec, const Predicate &predicate)
205{
206 if (codec.type() != AVMEDIA_TYPE_VIDEO)
207 return {};
208
209 const auto pixelFormats = codec.pixelFormats();
210
211 if (const auto format = findIf(pixelFormats, predicate))
212 return format;
213
214 // No matching pixel format was found. Check the pixel format
215 // of the codec's hardware config.
216 for (const AVCodecHWConfig *const config : codec.hwConfigs()) {
217 const AVPixelFormat format = config->pix_fmt;
218
219 if (format == AV_PIX_FMT_NONE)
220 continue;
221
222 if (predicate(format))
223 return format;
224 }
225 return {};
226}
227
228// Evaluate the function for each of the codec's pixel formats and each of
229// the pixel formats supported by the codec's hardware configs.
230template <typename Function>
231void forEachAVPixelFormat(const Codec &codec, const Function &function)
232{
233 findAVPixelFormat(codec, [&function](AVPixelFormat format) {
234 function(format);
235 return false; // Evaluate the function for all pixel formats
236 });
237}
238
239template <typename ValueT, typename ScoreT = AVScore>
241{
242 std::optional<ValueT> value;
244};
245
246template <typename Value, typename CalculateScore,
247 typename ScoreType = std::invoke_result_t<CalculateScore, Value>>
248ValueAndScore<Value, ScoreType> findBestAVValueWithScore(QSpan<const Value> values,
249 const CalculateScore &calculateScore)
250{
251 static_assert(std::is_invocable_v<CalculateScore, Value>);
252
253 ValueAndScore<Value, ScoreType> result;
254 for (const Value &val : values) {
255 const ScoreType score = calculateScore(val);
256 if (score > result.score)
257 result = { val, score }; // Note: Optional is only set if score > Limits::min()
258
259 if (result.score == std::numeric_limits<ScoreType>::max())
260 break;
261 }
262
263 return result;
264}
265
266template <typename Value, typename CalculateScore>
267std::optional<Value> findBestAVValue(QSpan<const Value> values,
268 const CalculateScore &calculateScore)
269{
270 return findBestAVValueWithScore(values, calculateScore).value;
271}
272
273bool isHwPixelFormat(AVPixelFormat format);
274
275inline bool isSwPixelFormat(AVPixelFormat format)
276{
277 return !isHwPixelFormat(format);
278}
279
280void applyExperimentalCodecOptions(const Codec &codec, AVDictionary **opts);
281
282AVPixelFormat pixelFormatForHwDevice(AVHWDeviceType deviceType);
283
284AVPacketSideData *addStreamSideData(AVStream *stream, AVPacketSideData sideData);
285
286const AVPacketSideData *streamSideData(const AVStream *stream, AVPacketSideDataType type);
287
288SwrContextUPtr createResampleContext(const AVAudioFormat &inputFormat,
289 const AVAudioFormat &outputFormat);
290
291QVideoFrameFormat::ColorTransfer fromAvColorTransfer(AVColorTransferCharacteristic colorTrc);
292
293AVColorTransferCharacteristic toAvColorTransfer(QVideoFrameFormat::ColorTransfer colorTrc);
294
295QVideoFrameFormat::ColorSpace fromAvColorSpace(AVColorSpace colorSpace);
296
297AVColorSpace toAvColorSpace(QVideoFrameFormat::ColorSpace colorSpace);
298
299QVideoFrameFormat::ColorRange fromAvColorRange(AVColorRange colorRange);
300
301AVColorRange toAvColorRange(QVideoFrameFormat::ColorRange colorRange);
302
303AVHWDeviceContext *avFrameDeviceContext(const AVFrame *frame);
304
305SwsContextUPtr createSwsContext(const QSize &srcSize, AVPixelFormat srcPixFmt, const QSize &dstSize,
306 AVPixelFormat dstPixFmt, SwsFlags conversionType = SWS_BICUBIC);
307
308#ifdef Q_OS_DARWIN
310
312
313#endif
314
315enum class AVError : int {
317};
318
319} // namespace QFFmpeg
320
321QDebug operator<<(QDebug, const AVRational &);
322QDebug operator<<(QDebug, const AVDictionary &);
325
326#if QT_FFMPEG_HAS_AV_CHANNEL_LAYOUT
327QDebug operator<<(QDebug, const AVChannelLayout &);
328#endif
329
330QT_END_NAMESPACE
331
332#endif
ValueAndScore< Value, ScoreType > findBestAVValueWithScore(QSpan< const Value > values, const CalculateScore &calculateScore)
Definition qffmpeg_p.h:248
AVFrameUPtr makeAVFrame()
Definition qffmpeg_p.h:152
void getAVFrameTime(const AVFrame &frame, int64_t &pts, AVRational &timeBase)
Definition qffmpeg_p.h:92
AVColorSpace toAvColorSpace(QVideoFrameFormat::ColorSpace colorSpace)
Definition qffmpeg.cpp:258
int64_t getAVFrameDuration(const AVFrame &frame)
Definition qffmpeg_p.h:102
SwsContextUPtr createSwsContext(const QSize &srcSize, AVPixelFormat srcPixFmt, const QSize &dstSize, AVPixelFormat dstPixFmt, SwsFlags conversionType)
Definition qffmpeg.cpp:311
void applyExperimentalCodecOptions(const Codec &codec, AVDictionary **opts)
Definition qffmpeg.cpp:47
bool isHwPixelFormat(AVPixelFormat format)
Definition qffmpeg.cpp:41
AVPacketSideData * addStreamSideData(AVStream *stream, AVPacketSideData sideData)
Definition qffmpeg.cpp:92
QString err2str(int errnum)
Definition qffmpeg_p.h:75
AVHWDeviceContext * avFrameDeviceContext(const AVFrame *frame)
Definition qffmpeg.cpp:298
void setAVFrameTime(AVFrame &frame, int64_t pts, const AVRational &timeBase)
Definition qffmpeg_p.h:82
bool isSwPixelFormat(AVPixelFormat format)
Definition qffmpeg_p.h:275
AVColorTransferCharacteristic toAvColorTransfer(QVideoFrameFormat::ColorTransfer colorTrc)
Definition qffmpeg.cpp:209
std::optional< Value > findIf(QSpan< const Value > range, const Predicate &predicate)
Definition qffmpeg_p.h:190
void forEachAVPixelFormat(const Codec &codec, const Function &function)
Definition qffmpeg_p.h:231
QVideoFrameFormat::ColorSpace fromAvColorSpace(AVColorSpace colorSpace)
Definition qffmpeg.cpp:231
bool isAVFormatSupported(const Codec &codec, PixelOrSampleFormat format)
Definition qffmpeg.cpp:26
std::optional< AVPixelFormat > findAVPixelFormat(const Codec &codec, const Predicate &predicate)
Definition qffmpeg_p.h:204
std::conditional_t< QT_FFMPEG_AVIO_WRITE_CONST, const uint8_t *, uint8_t * > AvioWriteBufferType
QVideoFrameFormat::ColorTransfer fromAvColorTransfer(AVColorTransferCharacteristic colorTrc)
Definition qffmpeg.cpp:179
QVideoFrameFormat::ColorRange fromAvColorRange(AVColorRange colorRange)
Definition qffmpeg.cpp:274
std::optional< qint64 > timeStampMs(qint64 ts, AVRational base)
Definition qffmpeg_p.h:60
SwrContextUPtr createResampleContext(const AVAudioFormat &inputFormat, const AVAudioFormat &outputFormat)
Definition qffmpeg.cpp:133
AVPixelFormat pixelFormatForHwDevice(AVHWDeviceType deviceType)
Definition qffmpeg.cpp:56
std::optional< qint64 > timeStampUs(qint64 ts, AVRational base)
Definition qffmpeg_p.h:65
const AVPacketSideData * streamSideData(const AVStream *stream, AVPacketSideDataType type)
Definition qffmpeg.cpp:118
AVColorRange toAvColorRange(QVideoFrameFormat::ColorRange colorRange)
Definition qffmpeg.cpp:286
std::optional< Value > findBestAVValue(QSpan< const Value > values, const CalculateScore &calculateScore)
Definition qffmpeg_p.h:267
std::optional< float > toFloat(AVRational r)
Definition qffmpeg_p.h:70
bool hasValue(QSpan< const Value > range, Value value)
Definition qffmpeg_p.h:180
std::optional< qint64 > mul(qint64 a, AVRational b)
Definition qffmpeg_p.h:40
Q_STATIC_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core")
QDebug operator<<(QDebug dbg, const QFFmpeg::AVDictionaryHolder &dict)
Definition qffmpeg.cpp:367
QDebug operator<<(QDebug dbg, QFFmpeg::AVError error)
Definition qffmpeg.cpp:376
static bool operator==(const AVRational &lhs, const AVRational &rhs)
Definition qffmpeg_p.h:25
static bool operator!=(const AVRational &lhs, const AVRational &rhs)
Definition qffmpeg_p.h:30
QDebug operator<<(QDebug dbg, const QFileInfo &fi)
void operator()(T *object) const
Definition qffmpeg_p.h:137
std::optional< ValueT > value
Definition qffmpeg_p.h:242