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#include <QtMultimedia/private/qmultimedia_ranges_p.h>
22
23#include <qstring.h>
24#include <optional>
25
26[[maybe_unused]] static inline bool operator==(const AVRational &lhs, const AVRational &rhs)
27{
28 return lhs.num == rhs.num && lhs.den == rhs.den;
29}
30
31[[maybe_unused]] static inline bool operator!=(const AVRational &lhs, const AVRational &rhs)
32{
33 return !(lhs == rhs);
34}
35
36QT_BEGIN_NAMESPACE
37
38namespace QFFmpeg
39{
40
42
43inline std::optional<qint64> mul(qint64 a, AVRational b)
44{
45 if (b.den == 0)
46 return {};
47
48 auto multiplyAndRound = [](qint64 a, AVRational b) { //
49 return (a * b.num + b.den / 2) / b.den;
50 };
51
52 if (a < 0)
53 return -multiplyAndRound(-a, b);
54 else
55 return multiplyAndRound(a, b);
56}
57
58inline std::optional<qreal> mul(qreal a, AVRational b)
59{
60 return b.den != 0 ? a * qreal(b.num) / qreal(b.den) : std::optional<qreal>{};
61}
62
63inline std::optional<qint64> timeStampMs(qint64 ts, AVRational base)
64{
65 return mul(1'000 * ts, base);
66}
67
68inline std::optional<qint64> timeStampUs(qint64 ts, AVRational base)
69{
70 return mul(1'000'000 * ts, base);
71}
72
73inline std::optional<float> toFloat(AVRational r)
74{
75 return r.den != 0 ? float(r.num) / float(r.den) : std::optional<float>{};
76}
77
78inline QString err2str(int errnum)
79{
80 char buffer[AV_ERROR_MAX_STRING_SIZE + 1] = {};
81 av_make_error_string(buffer, AV_ERROR_MAX_STRING_SIZE, errnum);
82 return QString::fromLocal8Bit(buffer);
83}
84
85inline void setAVFrameTime(AVFrame &frame, int64_t pts, const AVRational &timeBase)
86{
87 frame.pts = pts;
88#if QT_FFMPEG_HAS_FRAME_TIME_BASE
89 frame.time_base = timeBase;
90#else
91 Q_UNUSED(timeBase);
92#endif
93}
94
95inline void getAVFrameTime(const AVFrame &frame, int64_t &pts, AVRational &timeBase)
96{
97 pts = frame.pts;
98#if QT_FFMPEG_HAS_FRAME_TIME_BASE
99 timeBase = frame.time_base;
100#else
101 timeBase = { 0, 1 };
102#endif
103}
104
105inline int64_t getAVFrameDuration(const AVFrame &frame)
106{
107#if QT_FFMPEG_HAS_FRAME_DURATION
108 return frame.duration;
109#else
110 return frame.pkt_duration;
111#endif
112}
113
115{
116 AVDictionary *opts = nullptr;
117
118 operator AVDictionary **() { return &opts; }
119
121
123
125 : opts(std::exchange(other.opts, nullptr))
126 {
127 }
128
130 {
131 if (opts)
133 }
134};
135
136template <auto F>
138{
139 template <typename T>
140 void operator()(T *object) const
141 {
142 using FunctionType = decltype(F);
143
144 static_assert(std::is_invocable_v<FunctionType, T *>
145 || std::is_invocable_v<FunctionType, T **>,
146 "F must be invocable with either T* or T**");
147
148 if constexpr (std::is_invocable_v<FunctionType, T **>) {
149 if (object)
150 F(&object);
151 } else
152 F(object);
153 }
154};
155
157
159{
160 return AVFrameUPtr(av_frame_alloc());
161}
162
170
171bool isAVFormatSupported(const Codec &codec, PixelOrSampleFormat format);
172
173// Returns true if the range contains the value, false otherwise
174template <typename Value>
175bool hasValue(QSpan<const Value> range, Value value)
176{
177 return ranges::contains(range, value);
178}
179
180// Search for the first element in the range that satisfies the predicate
181// The predicate is evaluated for each value in the range until it returns
182// true, and the corresponding value is returned. If no match is found,
183// std::nullopt is returned.
184template <typename Value, typename Predicate>
185std::optional<Value> findIf(QSpan<const Value> range, const Predicate &predicate)
186{
187 const auto value = ranges::find_if(range, predicate);
188 if (value == range.end())
189 return {};
190 return *value;
191}
192
193// Search the codec's pixel formats for a format that matches the predicate.
194// If no pixel format is found, repeat the search through the pixel formats
195// of all the codec's hardware configs. If no matching pixel format is found,
196// std::nullopt is returned. The predicate is evaluated once for each pixel
197// format until the predicate returns true.
198template <typename Predicate>
199std::optional<AVPixelFormat> findAVPixelFormat(const Codec &codec, const Predicate &predicate)
200{
201 if (codec.type() != AVMEDIA_TYPE_VIDEO)
202 return {};
203
204 const auto pixelFormats = codec.pixelFormats();
205
206 if (const auto format = findIf(pixelFormats, predicate))
207 return format;
208
209 // No matching pixel format was found. Check the pixel format
210 // of the codec's hardware config.
211 for (const AVCodecHWConfig *const config : codec.hwConfigs()) {
212 const AVPixelFormat format = config->pix_fmt;
213
214 if (format == AV_PIX_FMT_NONE)
215 continue;
216
217 if (predicate(format))
218 return format;
219 }
220 return {};
221}
222
223// Evaluate the function for each of the codec's pixel formats and each of
224// the pixel formats supported by the codec's hardware configs.
225template <typename Function>
226void forEachAVPixelFormat(const Codec &codec, const Function &function)
227{
228 findAVPixelFormat(codec, [&function](AVPixelFormat format) {
229 function(format);
230 return false; // Evaluate the function for all pixel formats
231 });
232}
233
234template <typename ValueT, typename ScoreT = AVScore>
236{
237 std::optional<ValueT> value;
239};
240
241template <typename Value, typename CalculateScore,
242 typename ScoreType = std::invoke_result_t<CalculateScore, Value>>
243ValueAndScore<Value, ScoreType> findBestAVValueWithScore(QSpan<const Value> values,
244 const CalculateScore &calculateScore)
245{
246 static_assert(std::is_invocable_v<CalculateScore, Value>);
247
248 ValueAndScore<Value, ScoreType> result;
249 for (const Value &val : values) {
250 const ScoreType score = calculateScore(val);
251 if (score > result.score)
252 result = { val, score }; // Note: Optional is only set if score > Limits::min()
253
254 if (result.score == std::numeric_limits<ScoreType>::max())
255 break;
256 }
257
258 return result;
259}
260
261template <typename Value, typename CalculateScore>
262std::optional<Value> findBestAVValue(QSpan<const Value> values,
263 const CalculateScore &calculateScore)
264{
265 return findBestAVValueWithScore(values, calculateScore).value;
266}
267
268bool isHwPixelFormat(AVPixelFormat format);
269
270inline bool isSwPixelFormat(AVPixelFormat format)
271{
272 return !isHwPixelFormat(format);
273}
274
275void applyExperimentalCodecOptions(const Codec &codec, AVDictionary **opts);
276
277AVPixelFormat pixelFormatForHwDevice(AVHWDeviceType deviceType);
278
279AVPacketSideData *addStreamSideData(AVStream *stream, AVPacketSideData sideData);
280
281const AVPacketSideData *streamSideData(const AVStream *stream, AVPacketSideDataType type);
282
283SwrContextUPtr createResampleContext(const AVAudioFormat &inputFormat,
284 const AVAudioFormat &outputFormat);
285
286QVideoFrameFormat::ColorTransfer fromAvColorTransfer(AVColorTransferCharacteristic colorTrc);
287
288AVColorTransferCharacteristic toAvColorTransfer(QVideoFrameFormat::ColorTransfer colorTrc);
289
290QVideoFrameFormat::ColorSpace fromAvColorSpace(AVColorSpace colorSpace);
291
292AVColorSpace toAvColorSpace(QVideoFrameFormat::ColorSpace colorSpace);
293
294QVideoFrameFormat::ColorRange fromAvColorRange(AVColorRange colorRange);
295
296AVColorRange toAvColorRange(QVideoFrameFormat::ColorRange colorRange);
297
298AVHWDeviceContext *avFrameDeviceContext(const AVFrame *frame);
299
300SwsContextUPtr createSwsContext(const QSize &srcSize, AVPixelFormat srcPixFmt, const QSize &dstSize,
301 AVPixelFormat dstPixFmt, SwsFlags conversionType = SWS_BICUBIC);
302
303#ifdef Q_OS_DARWIN
305
307
308#endif
309
310enum class AVError : int {
312};
313
314} // namespace QFFmpeg
315
316QDebug operator<<(QDebug, const AVRational &);
317QDebug operator<<(QDebug, const AVDictionary &);
320
321#if QT_FFMPEG_HAS_AV_CHANNEL_LAYOUT
322QDebug operator<<(QDebug, const AVChannelLayout &);
323#endif
324
325QT_END_NAMESPACE
326
327#endif
ValueAndScore< Value, ScoreType > findBestAVValueWithScore(QSpan< const Value > values, const CalculateScore &calculateScore)
Definition qffmpeg_p.h:243
AVFrameUPtr makeAVFrame()
Definition qffmpeg_p.h:158
void getAVFrameTime(const AVFrame &frame, int64_t &pts, AVRational &timeBase)
Definition qffmpeg_p.h:95
AVColorSpace toAvColorSpace(QVideoFrameFormat::ColorSpace colorSpace)
Definition qffmpeg.cpp:259
int64_t getAVFrameDuration(const AVFrame &frame)
Definition qffmpeg_p.h:105
SwsContextUPtr createSwsContext(const QSize &srcSize, AVPixelFormat srcPixFmt, const QSize &dstSize, AVPixelFormat dstPixFmt, SwsFlags conversionType)
Definition qffmpeg.cpp:312
void applyExperimentalCodecOptions(const Codec &codec, AVDictionary **opts)
Definition qffmpeg.cpp:48
bool isHwPixelFormat(AVPixelFormat format)
Definition qffmpeg.cpp:42
AVPacketSideData * addStreamSideData(AVStream *stream, AVPacketSideData sideData)
Definition qffmpeg.cpp:93
QString err2str(int errnum)
Definition qffmpeg_p.h:78
AVHWDeviceContext * avFrameDeviceContext(const AVFrame *frame)
Definition qffmpeg.cpp:299
void setAVFrameTime(AVFrame &frame, int64_t pts, const AVRational &timeBase)
Definition qffmpeg_p.h:85
bool isSwPixelFormat(AVPixelFormat format)
Definition qffmpeg_p.h:270
AVColorTransferCharacteristic toAvColorTransfer(QVideoFrameFormat::ColorTransfer colorTrc)
Definition qffmpeg.cpp:210
std::optional< Value > findIf(QSpan< const Value > range, const Predicate &predicate)
Definition qffmpeg_p.h:185
std::conditional_t< QT_FFMPEG_AVIO_WRITE_CONST, const uint8_t *, uint8_t * > AvioWriteBufferType
void forEachAVPixelFormat(const Codec &codec, const Function &function)
Definition qffmpeg_p.h:226
QVideoFrameFormat::ColorSpace fromAvColorSpace(AVColorSpace colorSpace)
Definition qffmpeg.cpp:232
bool isAVFormatSupported(const Codec &codec, PixelOrSampleFormat format)
Definition qffmpeg.cpp:27
std::optional< AVPixelFormat > findAVPixelFormat(const Codec &codec, const Predicate &predicate)
Definition qffmpeg_p.h:199
QVideoFrameFormat::ColorTransfer fromAvColorTransfer(AVColorTransferCharacteristic colorTrc)
Definition qffmpeg.cpp:180
QVideoFrameFormat::ColorRange fromAvColorRange(AVColorRange colorRange)
Definition qffmpeg.cpp:275
std::optional< qint64 > timeStampMs(qint64 ts, AVRational base)
Definition qffmpeg_p.h:63
SwrContextUPtr createResampleContext(const AVAudioFormat &inputFormat, const AVAudioFormat &outputFormat)
Definition qffmpeg.cpp:134
AVPixelFormat pixelFormatForHwDevice(AVHWDeviceType deviceType)
Definition qffmpeg.cpp:57
std::optional< qint64 > timeStampUs(qint64 ts, AVRational base)
Definition qffmpeg_p.h:68
const AVPacketSideData * streamSideData(const AVStream *stream, AVPacketSideDataType type)
Definition qffmpeg.cpp:119
AVColorRange toAvColorRange(QVideoFrameFormat::ColorRange colorRange)
Definition qffmpeg.cpp:287
std::optional< Value > findBestAVValue(QSpan< const Value > values, const CalculateScore &calculateScore)
Definition qffmpeg_p.h:262
std::optional< float > toFloat(AVRational r)
Definition qffmpeg_p.h:73
bool hasValue(QSpan< const Value > range, Value value)
Definition qffmpeg_p.h:175
std::optional< qint64 > mul(qint64 a, AVRational b)
Definition qffmpeg_p.h:43
QDebug operator<<(QDebug dbg, const QFFmpeg::AVDictionaryHolder &dict)
Definition qffmpeg.cpp:368
QDebug operator<<(QDebug dbg, QFFmpeg::AVError error)
Definition qffmpeg.cpp:377
static bool operator==(const AVRational &lhs, const AVRational &rhs)
Definition qffmpeg_p.h:26
static bool operator!=(const AVRational &lhs, const AVRational &rhs)
Definition qffmpeg_p.h:31
QDebug operator<<(QDebug dbg, const QFileInfo &fi)
QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcSynthesizedIterableAccess, "qt.iterable.synthesized", QtWarningMsg)
void operator()(T *object) const
Definition qffmpeg_p.h:140
std::optional< ValueT > value
Definition qffmpeg_p.h:237