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
78 explicit PlaybackEngine(const QPlaybackOptions &options);
79
81
82 void setMedia(MediaDataHolder media);
83
84 void setVideoSink(QVideoSink *sink);
85
86 void setAudioSink(QAudioOutput *output);
87
88 void setAudioSink(QPlatformAudioOutput *output);
89
90 void setAudioBufferOutput(QAudioBufferOutput *output);
91
92 void setState(QMediaPlayer::PlaybackState state);
93
94 void play() {
95 setState(QMediaPlayer::PlayingState);
96 }
97 void pause() {
98 setState(QMediaPlayer::PausedState);
99 }
100 void stop() {
101 setState(QMediaPlayer::StoppedState);
102 }
103
104 void seek(TrackPosition pos);
105
106 void setLoops(int loopsCount);
107
108 void setPlaybackRate(float rate);
109
110 float playbackRate() const;
111
112 void setActiveTrack(TrackType type, int streamNumber);
113
114 TrackPosition currentPosition(bool topPos = true) const;
115
116 TrackDuration duration() const;
117
118 bool isSeekable() const;
119
121 streamInfo(TrackType trackType) const;
122
123 const QMediaMetaData &metaData() const;
124
125 int activeTrack(TrackType type) const;
126
127 void setPitchCompensation(bool enabled);
128
129signals:
131 void errorOccured(QMediaPlayer::Error, const QString &);
133 void buffered();
134
135protected: // objects managing
137 {
138 void operator()(PlaybackEngineObject *) const;
139
141 };
142
143 template<typename T>
145
148
149 template<typename T, typename... Args>
150 ObjectPtr<T> createPlaybackEngineObject(Args &&...args);
151
152 virtual RendererPtr createRenderer(TrackType trackType);
153
154 template <typename AudioOutput>
155 void updateActiveAudioOutput(AudioOutput *output);
156
157 void updateActiveVideoOutput(QVideoSink *sink, bool cleanOutput = false);
158
159private:
160 void createStreamAndRenderer(TrackType trackType);
161
162 void createDemuxer();
163
164 void registerObject(PlaybackEngineObject &object);
165
166 template<typename C, typename Action>
167 void forEachExistingObject(Action &&action);
168
169 template<typename Action>
170 void forEachExistingObject(Action &&action);
171
172 void forceUpdate();
173
174 void recreateObjects();
175
176 void createObjectsIfNeeded();
177
178 void updateObjectsPausedState();
179
180 void deleteFreeThreads();
181
182 void onFirstPacketFound(const PlaybackEngineObjectID &id, TrackPosition absSeekPos);
183
184 void onRendererSynchronized(const PlaybackEngineObjectID &id, SteadyClock::time_point timePoint,
185 TrackPosition trackPosition);
186
187 void onRendererFinished(const PlaybackEngineObjectID &id);
188
189 void onRendererLoopChanged(const PlaybackEngineObjectID &id, TrackPosition offset,
190 int loopIndex);
191
192 void triggerStepIfNeeded();
193
194 static QString objectThreadName(const PlaybackEngineObject &object);
195
196 std::optional<CodecContext> codecContextForTrack(TrackType trackType);
197
198 bool hasMediaStream() const;
199
200 void finilizeTime(TrackPosition pos);
201
202 void finalizeOutputs();
203
204 bool hasRenderer(const PlaybackEngineObjectID &id) const;
205
206 template <typename T>
207 bool checkObjectID(T &object, const PlaybackEngineObjectID &id) const
208 {
209 return object && object->objectID() == id.objectID && id.sessionID == m_currentID.sessionID;
210 }
211
212 void updateVideoSinkSize(QVideoSink *prevSink = nullptr);
213
214 TrackPosition boundPosition(TrackPosition position) const;
215
216 AudioRenderer *getAudioRenderer();
217
218private:
219 MediaDataHolder m_media;
220
221 TimeController m_timeController;
222
224 bool m_threadsDirty = false;
225
226 QPointer<QVideoSink> m_videoSink;
227 QPointer<QAudioOutput> m_audioOutput;
228 QPointer<QAudioBufferOutput> m_audioBufferOutput;
229
230 QMediaPlayer::PlaybackState m_state = QMediaPlayer::StoppedState;
231
232 ObjectPtr<Demuxer> m_demuxer;
233 QPlatformMediaPlayer::TrackTypeMap<StreamPtr> m_streams;
234 QPlatformMediaPlayer::TrackTypeMap<RendererPtr> m_renderers;
235
236 bool m_seekPending = false;
237
239 int m_loops = QMediaPlayer::Once;
240 LoopOffset m_currentLoopOffset;
241
242 bool m_pitchCompensation = true;
243 QPlaybackOptions m_options;
244 PlaybackEngineObjectID m_currentID{ 1, 1 };
245};
246
247template<typename T, typename... Args>
249{
250 ++m_currentID.objectID;
251 auto result = ObjectPtr<T>(new T(m_currentID, std::forward<Args>(args)...), { this });
252 registerObject(*result);
253 return result;
254}
255} // namespace QFFmpeg
256
257QT_END_NAMESPACE
258
259#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)
void setVideoSink(QVideoSink *sink)
void setState(QMediaPlayer::PlaybackState state)
void updateActiveAudioOutput(AudioOutput *output)
void setAudioBufferOutput(QAudioBufferOutput *output)
ObjectPtr< T > createPlaybackEngineObject(Args &&...args)
void setAudioSink(QAudioOutput *output)
const QList< MediaDataHolder::StreamInfo > & streamInfo(TrackType trackType) const
void setPitchCompensation(bool enabled)
void setActiveTrack(TrackType type, int streamNumber)
void setMedia(MediaDataHolder media)
TrackPosition currentPosition(bool topPos=true) const
const QMediaMetaData & metaData() const
int activeTrack(TrackType type) const
void updateActiveVideoOutput(QVideoSink *sink, bool cleanOutput=false)
PlaybackEngine(const QPlaybackOptions &options)
void setAudioSink(QPlatformAudioOutput *output)
virtual RendererPtr createRenderer(TrackType trackType)
The QPlaybackOptions class enables low-level control of media playback options.
QT_MANGLE_NAMESPACE(QMacScreenCaptureStreamDelegate) QMacScreenCaptureStreamDelegate
Combined button and popup list for selecting options.
#define qCDebug(category,...)
#define Q_STATIC_LOGGING_CATEGORY(name,...)
void operator()(PlaybackEngineObject *) const