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
qffmpegplaybackengine_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 QFFMPEGPLAYBACKENGINE_P_H
4#define QFFMPEGPLAYBACKENGINE_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/* Playback engine design description.
18 *
19 *
20 * PLAYBACK ENGINE OBJECTS
21 *
22 * - Playback engine manages 7 objects inside, each one works in a separate thread.
23 * Each object inherits PlaybackEngineObject. The objects are:
24 * Demuxer
25 * Stream Decoders: audio, video, subtitles
26 * Renderers: audio, video, subtitles
27 *
28 *
29 * THREADS:
30 *
31 * - By default, each object works in a separate thread. It's easy to reconfigure
32 * to using several objects in thread.
33 * - New thread is allocated if a new object is created and the engine doesn't
34 * have free threads. If it does, the thread is to be reused.
35 * - If all objects for some thread are deleted, the thread becomes free and the engine
36 * postpones its termination.
37 *
38 * OBJECTS WEAK CONNECTIVITY
39 *
40 * - The objects know nothing about others and about PlaybackEngine.
41 * For any interactions the objects use slots/signals.
42 *
43 * - PlaybackEngine knows the objects object and is able to create/delete them and
44 * call their public methods.
45 *
46 */
47
48#include <QtFFmpegMediaPluginImpl/private/qffmpegplaybackenginedefs_p.h>
49#include <QtFFmpegMediaPluginImpl/private/qffmpegtimecontroller_p.h>
50#include <QtFFmpegMediaPluginImpl/private/qffmpegmediadataholder_p.h>
51#include <QtFFmpegMediaPluginImpl/private/qffmpegcodeccontext_p.h>
52#include <QtFFmpegMediaPluginImpl/private/qffmpegplaybackutils_p.h>
53#include <QtFFmpegMediaPluginImpl/private/qffmpegtime_p.h>
54#include <QtMultimedia/qplaybackoptions.h>
55
56#include <QtCore/qpointer.h>
57
58#include <unordered_map>
59
60QT_BEGIN_NAMESPACE
61
62class QAudioSink;
63class QVideoSink;
64class QAudioOutput;
65class QAudioBufferOutput;
68
69namespace QFFmpeg
70{
71
72class PlaybackEngine : public QObject
73{
75public:
77
79
80 void setMedia(MediaDataHolder media);
81
82 void setVideoSink(QVideoSink *sink);
83
84 void setAudioSink(QAudioOutput *output);
85
86 void setAudioSink(QPlatformAudioOutput *output);
87
88 void setAudioBufferOutput(QAudioBufferOutput *output);
89
90 void setState(QMediaPlayer::PlaybackState state);
91
92 void play() {
93 setState(QMediaPlayer::PlayingState);
94 }
95 void pause() {
96 setState(QMediaPlayer::PausedState);
97 }
98 void stop() {
99 setState(QMediaPlayer::StoppedState);
100 }
101
102 void seek(TrackPosition pos);
103
104 void setLoops(int loopsCount);
105
106 void setPlaybackRate(float rate);
107
108 float playbackRate() const;
109
110 void setActiveTrack(QPlatformMediaPlayer::TrackType type, int streamNumber);
111
112 TrackPosition currentPosition(bool topPos = true) const;
113
114 TrackDuration duration() const;
115
116 bool isSeekable() const;
117
119 streamInfo(QPlatformMediaPlayer::TrackType trackType) const;
120
121 const QMediaMetaData &metaData() const;
122
123 int activeTrack(QPlatformMediaPlayer::TrackType type) const;
124
125 void setPitchCompensation(bool enabled);
126
127signals:
129 void errorOccured(QMediaPlayer::Error, const QString &);
131 void buffered();
132
133protected: // objects managing
135 {
136 void operator()(PlaybackEngineObject *) const;
137
139 };
140
141 template<typename T>
143
146
147 template<typename T, typename... Args>
148 ObjectPtr<T> createPlaybackEngineObject(Args &&...args);
149
150 virtual RendererPtr createRenderer(QPlatformMediaPlayer::TrackType trackType);
151
152 template <typename AudioOutput>
153 void updateActiveAudioOutput(AudioOutput *output);
154
155 void updateActiveVideoOutput(QVideoSink *sink, bool cleanOutput = false);
156
157private:
158 void createStreamAndRenderer(QPlatformMediaPlayer::TrackType trackType);
159
160 void createDemuxer();
161
162 void registerObject(PlaybackEngineObject &object);
163
164 template<typename C, typename Action>
165 void forEachExistingObject(Action &&action);
166
167 template<typename Action>
168 void forEachExistingObject(Action &&action);
169
170 void forceUpdate();
171
172 void recreateObjects();
173
174 void createObjectsIfNeeded();
175
176 void updateObjectsPausedState();
177
178 void deleteFreeThreads();
179
180 void onFirsPacketFound(quint64 id, TrackPosition absSeekPos);
181
182 void onRendererSynchronized(quint64 id, SteadyClock::time_point timePoint,
183 TrackPosition trackPosition);
184
185 void onRendererFinished();
186
187 void onRendererLoopChanged(quint64 id, TrackPosition offset, int loopIndex);
188
189 void triggerStepIfNeeded();
190
191 static QString objectThreadName(const PlaybackEngineObject &object);
192
193 std::optional<CodecContext> codecContextForTrack(QPlatformMediaPlayer::TrackType trackType);
194
195 bool hasMediaStream() const;
196
197 void finilizeTime(TrackPosition pos);
198
199 void finalizeOutputs();
200
201 bool hasRenderer(quint64 id) const;
202
203 void updateVideoSinkSize(QVideoSink *prevSink = nullptr);
204
205 TrackPosition boundPosition(TrackPosition position) const;
206
207 AudioRenderer *getAudioRenderer();
208
209private:
210 MediaDataHolder m_media;
211
212 TimeController m_timeController;
213
215 bool m_threadsDirty = false;
216
217 QPointer<QVideoSink> m_videoSink;
218 QPointer<QAudioOutput> m_audioOutput;
219 QPointer<QAudioBufferOutput> m_audioBufferOutput;
220
221 QMediaPlayer::PlaybackState m_state = QMediaPlayer::StoppedState;
222
223 ObjectPtr<Demuxer> m_demuxer;
224 std::array<StreamPtr, QPlatformMediaPlayer::NTrackTypes> m_streams;
225 std::array<RendererPtr, QPlatformMediaPlayer::NTrackTypes> m_renderers;
226
227 bool m_shouldUpdateTimeOnFirstPacket = false;
228 bool m_seekPending = false;
229
231 int m_loops = QMediaPlayer::Once;
232 LoopOffset m_currentLoopOffset;
233
234 bool m_pitchCompensation = true;
235 QPlaybackOptions m_options;
236};
237
238template<typename T, typename... Args>
240{
241 auto result = ObjectPtr<T>(new T(std::forward<Args>(args)...), { this });
242 registerObject(*result);
243 return result;
244}
245} // namespace QFFmpeg
246
247QT_END_NAMESPACE
248
249#endif // QFFMPEGPLAYBACKENGINE_P_H
void setSource(const QUrl &fileName) override
QIODevice * sourceDevice() const override
~QFFmpegAudioDecoder() override
void errorSignal(int err, const QString &errorString)
QAudioFormat audioFormat() const override
void setAudioFormat(const QAudioFormat &format) override
QAudioBuffer read() override
void setSourceDevice(QIODevice *device) override
QUrl source() const override
void errorOccured(QMediaPlayer::Error, const QString &)
void seek(TrackPosition pos)
int activeTrack(QPlatformMediaPlayer::TrackType type) const
void setVideoSink(QVideoSink *sink)
void setState(QMediaPlayer::PlaybackState state)
void updateActiveAudioOutput(AudioOutput *output)
virtual RendererPtr createRenderer(QPlatformMediaPlayer::TrackType trackType)
void setAudioBufferOutput(QAudioBufferOutput *output)
ObjectPtr< T > createPlaybackEngineObject(Args &&...args)
void setAudioSink(QAudioOutput *output)
void setPitchCompensation(bool enabled)
const QList< MediaDataHolder::StreamInfo > & streamInfo(QPlatformMediaPlayer::TrackType trackType) const
void setActiveTrack(QPlatformMediaPlayer::TrackType type, int streamNumber)
void setMedia(MediaDataHolder media)
TrackPosition currentPosition(bool topPos=true) const
const QMediaMetaData & metaData() const
void updateActiveVideoOutput(QVideoSink *sink, bool cleanOutput=false)
void setAudioSink(QPlatformAudioOutput *output)
The QPlaybackOptions class enables low-level control of media playback options.
std::conditional_t< QT_FFMPEG_AVIO_WRITE_CONST, const uint8_t *, uint8_t * > AvioWriteBufferType
#define qCDebug(category,...)
#define Q_STATIC_LOGGING_CATEGORY(name,...)
void operator()(PlaybackEngineObject *) const