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 onFirstPacketFound(const PlaybackEngineObjectID &id, TrackPosition absSeekPos);
181
182 void onRendererSynchronized(const PlaybackEngineObjectID &id, SteadyClock::time_point timePoint,
183 TrackPosition trackPosition);
184
185 void onRendererFinished(const PlaybackEngineObjectID &id);
186
187 void onRendererLoopChanged(const PlaybackEngineObjectID &id, TrackPosition offset,
188 int loopIndex);
189
190 void triggerStepIfNeeded();
191
192 static QString objectThreadName(const PlaybackEngineObject &object);
193
194 std::optional<CodecContext> codecContextForTrack(QPlatformMediaPlayer::TrackType trackType);
195
196 bool hasMediaStream() const;
197
198 void finilizeTime(TrackPosition pos);
199
200 void finalizeOutputs();
201
202 bool hasRenderer(const PlaybackEngineObjectID &id) const;
203
204 template <typename T>
205 bool checkObjectID(T &object, const PlaybackEngineObjectID &id) const
206 {
207 return object && object->objectID() == id.objectID && id.sessionID == m_currentID.sessionID;
208 }
209
210 void updateVideoSinkSize(QVideoSink *prevSink = nullptr);
211
212 TrackPosition boundPosition(TrackPosition position) const;
213
214 AudioRenderer *getAudioRenderer();
215
216private:
217 MediaDataHolder m_media;
218
219 TimeController m_timeController;
220
222 bool m_threadsDirty = false;
223
224 QPointer<QVideoSink> m_videoSink;
225 QPointer<QAudioOutput> m_audioOutput;
226 QPointer<QAudioBufferOutput> m_audioBufferOutput;
227
228 QMediaPlayer::PlaybackState m_state = QMediaPlayer::StoppedState;
229
230 ObjectPtr<Demuxer> m_demuxer;
231 std::array<StreamPtr, QPlatformMediaPlayer::NTrackTypes> m_streams;
232 std::array<RendererPtr, QPlatformMediaPlayer::NTrackTypes> m_renderers;
233
234 bool m_seekPending = false;
235
237 int m_loops = QMediaPlayer::Once;
238 LoopOffset m_currentLoopOffset;
239
240 bool m_pitchCompensation = true;
241 QPlaybackOptions m_options;
242 PlaybackEngineObjectID m_currentID{ 1, 1 };
243};
244
245template<typename T, typename... Args>
247{
248 ++m_currentID.objectID;
249 auto result = ObjectPtr<T>(new T(m_currentID, std::forward<Args>(args)...), { this });
250 registerObject(*result);
251 return result;
252}
253} // namespace QFFmpeg
254
255QT_END_NAMESPACE
256
257#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
Combined button and popup list for selecting options.
#define qCDebug(category,...)
#define Q_STATIC_LOGGING_CATEGORY(name,...)
void operator()(PlaybackEngineObject *) const