Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qwasmmediaplayer.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 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
7#include "qaudiooutput.h"
8
9#include <QtCore/qloggingcategory.h>
10#include <QUuid>
11#include <QtGlobal>
12
14
15static Q_LOGGING_CATEGORY(lcMediaPlayer, "qt.multimedia.mediaplayer.wasm");
16
19 m_videoOutput(new QWasmVideoOutput),
20 m_State(QWasmMediaPlayer::Idle)
21{
22 qCDebug(lcMediaPlayer) << Q_FUNC_INFO << this;
23
24}
25
27{
28 delete m_videoOutput;
29}
30
31void QWasmMediaPlayer::initVideo()
32{
34 QUuid videoElementId = QUuid::createUuid();
35 qCDebug(lcMediaPlayer) << Q_FUNC_INFO << "videoElementId"<< videoElementId << this;
36
37 m_videoOutput->createVideoElement(videoElementId.toString(QUuid::WithoutBraces).toStdString());
38 m_videoOutput->doElementCallbacks();
39 m_videoOutput->createOffscreenElement(QSize(1280, 720));
40 m_videoOutput->updateVideoElementGeometry(QRect(0, 0, 1280, 720)); // initial size 720p standard
41
42 connect(m_videoOutput, &QWasmVideoOutput::bufferingChanged, this,
43 &QWasmMediaPlayer::bufferingChanged);
44 connect(m_videoOutput, &QWasmVideoOutput::errorOccured, this,
45 &QWasmMediaPlayer::errorOccured);
46 connect(m_videoOutput, &QWasmVideoOutput::stateChanged, this,
47 &QWasmMediaPlayer::mediaStateChanged);
48 connect(m_videoOutput, &QWasmVideoOutput::progressChanged, this,
49 &QWasmMediaPlayer::setPositionChanged);
50 connect(m_videoOutput, &QWasmVideoOutput::durationChanged, this,
51 &QWasmMediaPlayer::setDurationChanged);
52 connect(m_videoOutput, &QWasmVideoOutput::sizeChange, this,
53 &QWasmMediaPlayer::videoSizeChanged);
54 connect(m_videoOutput, &QWasmVideoOutput::readyChanged, this,
55 &QWasmMediaPlayer::videoOutputReady);
56 connect(m_videoOutput, &QWasmVideoOutput::statusChanged, this,
57 &QWasmMediaPlayer::onMediaStatusChanged);
58 connect(m_videoOutput, &QWasmVideoOutput::metaDataLoaded, this,
59 &QWasmMediaPlayer::videoMetaDataChanged);
60
61 setVideoAvailable(true);
62}
63
64void QWasmMediaPlayer::initAudio()
65{
66 connect(m_audioOutput->q, &QAudioOutput::deviceChanged,
68 connect(m_audioOutput->q, &QAudioOutput::volumeChanged,
69 this, &QWasmMediaPlayer::volumeChanged);
70 connect(m_audioOutput->q, &QAudioOutput::mutedChanged,
71 this, &QWasmMediaPlayer::mutedChanged);
72
73 connect(m_audioOutput, &QWasmAudioOutput::bufferingChanged, this,
74 &QWasmMediaPlayer::bufferingChanged);
75 connect(m_audioOutput, &QWasmAudioOutput::errorOccured, this,
76 &QWasmMediaPlayer::errorOccured);
77 connect(m_audioOutput, &QWasmAudioOutput::progressChanged, this,
78 &QWasmMediaPlayer::setPositionChanged);
79 connect(m_audioOutput, &QWasmAudioOutput::durationChanged, this,
80 &QWasmMediaPlayer::setDurationChanged);
81 connect(m_audioOutput, &QWasmAudioOutput::statusChanged, this,
82 &QWasmMediaPlayer::onMediaStatusChanged);
83 connect(m_audioOutput, &QWasmAudioOutput::stateChanged, this,
84 &QWasmMediaPlayer::mediaStateChanged);
85 setAudioAvailable(true);
86}
87
89{
90 return m_videoOutput->getDuration();
91}
92
94{
96 return duration();
97
98 if (m_videoAvailable)
99 return m_videoOutput->getCurrentPosition();
100
101 return 0;
102}
103
105{
106 if (!isSeekable())
107 return;
108
109 const int seekPosition = (position > INT_MAX) ? INT_MAX : position;
110
111 if (seekPosition == this->position())
112 return;
113
115 setMediaStatus(QMediaPlayer::LoadedMedia);
116
117 if (m_videoAvailable)
118 return m_videoOutput->seekTo(position);
119
120 emit positionChanged(seekPosition);
121}
122
123void QWasmMediaPlayer::volumeChanged(float gain)
124{
125 if (m_State != QWasmMediaPlayer::Started)
126 return;
127
128 if (m_videoAvailable)
129 m_videoOutput->setVolume(gain);
130}
131
132void QWasmMediaPlayer::mutedChanged(bool muted)
133{
134 if (m_State != QWasmMediaPlayer::Started)
135 return;
136
137 if (m_videoAvailable)
138 m_videoOutput->setMuted(muted);
139}
140
142{
143 return qBound(0.0, (m_bufferPercent * .01), 1.0);
144}
145
147{
148 return m_audioAvailable;
149}
150
152{
153 return m_videoAvailable;
154}
155
157{
158 return m_availablePlaybackRange;
159}
160
161void QWasmMediaPlayer::updateAvailablePlaybackRanges()
162{
163 if (m_buffering) {
164 const qint64 pos = position();
165 const qint64 end = (duration() / 100) * m_bufferPercent;
166 m_availablePlaybackRange.addInterval(pos, end);
167 } else if (isSeekable()) {
168 m_availablePlaybackRange = QMediaTimeRange(0, duration());
169 } else {
170 m_availablePlaybackRange = QMediaTimeRange();
171 }
172}
173
175{
176 if (m_State != QWasmMediaPlayer::Started)
177 return 0;
178
179 if (isVideoAvailable())
180 return m_videoOutput->playbackRate();
181 return 0;
182}
183
185{
186 if (m_State != QWasmMediaPlayer::Started || !isVideoAvailable())
187 return;
188
189 m_videoOutput->setPlaybackRate(rate);
191}
192
194{
195 return m_mediaContent;
196}
197
199{
200 return m_mediaStream;
201}
202
204{
205 qDebug() << Q_FUNC_INFO << mediaContent << isVideoAvailable()
206 << isAudioAvailable();
207 if (mediaContent.isEmpty()) {
208 if (stream) {
209 m_mediaStream = stream;
210 if (isVideoAvailable()) {
211 m_videoOutput->setSource(m_mediaStream);
212 } else {
213 m_audioOutput->setSource(m_mediaStream);
214 }
215 } else {
216
217 setMediaStatus(QMediaPlayer::NoMedia);
218 }
219 } else {
220 if (isVideoAvailable())
221 m_videoOutput->setSource(mediaContent);
222 else
223 m_audioOutput->setSource(mediaContent);
224 }
225
226 resetBufferingProgress();
227}
228
230{
231 if (m_videoSink == sink)
232 return;
233
234 m_videoSink = sink;
235
236 if (!m_videoSink)
237 return;
238
239 initVideo();
240 m_videoOutput->setSurface(sink);
241}
242
244{
245 if (m_audioOutput == output)
246 return;
247
248 if (m_audioOutput)
249 m_audioOutput->q->disconnect(this);
250 m_audioOutput = static_cast<QWasmAudioOutput *>(output);
251}
252
254{
255 if (m_audioOutput) {
256 m_audioOutput->setAudioDevice(m_audioOutput->q->device());
257 }
258}
259
261{
263
264 if (isVideoAvailable()) {
265 m_videoOutput->start();
266 m_playWhenReady = true;
267 } else {
268 initAudio();
269 if (isAudioAvailable()) {
270 m_audioOutput->start();
271 }
272 }
273
274#ifdef DEBUG_AUDIOENGINE
275 QAudioEnginePrivate::checkNoError("play");
276#endif
277}
278
280{
281 if ((m_State
284 return;
285 }
286 if (isVideoAvailable()) {
287 m_videoOutput->pause();
288 } else {
289 m_audioOutput->pause();
291 }
292}
293
295{
296 m_playWhenReady = false;
297
299 || m_State == QWasmMediaPlayer::Stopped) {
300 qWarning() << Q_FUNC_INFO << __LINE__;
301 return;
302 }
303
304 if (isVideoAvailable()) {
305 m_videoOutput->stop();
306 } else {
307 m_audioOutput->stop();
308 }
309
310}
311
313{
314 return isVideoAvailable() && m_videoOutput->isVideoSeekable();
315}
316
317void QWasmMediaPlayer::errorOccured(qint32 code, const QString &message)
318{
319 QString errorString;
321
322 switch (code) {
324 break;
326 break;
328 break;
331 errorString = message;
332 break;
333 };
334
336}
337
338void QWasmMediaPlayer::bufferingChanged(qint32 percent)
339{
340 m_buffering = percent != 100;
341 m_bufferPercent = percent;
342
343 updateAvailablePlaybackRanges();
345}
346
347void QWasmMediaPlayer::videoSizeChanged(qint32 width, qint32 height)
348{
349 QSize newSize(width, height);
350
351 if (width == 0 || height == 0 || newSize == m_videoSize)
352 return;
353
354 m_videoSize = newSize;
355}
356
357void QWasmMediaPlayer::mediaStateChanged(QWasmMediaPlayer::QWasmMediaPlayerState state)
358{
359 m_State = state;
360 QMediaPlayer::PlaybackState m_mediaPlayerState;
361 switch (m_State) {
363 m_mediaPlayerState = QMediaPlayer::PlayingState;
364 break;
366 m_mediaPlayerState = QMediaPlayer::PausedState;
367 break;
369 m_mediaPlayerState = QMediaPlayer::StoppedState;
370 break;
371 default:
372 m_mediaPlayerState = QMediaPlayer::StoppedState;
373 break;
374 };
375
376 QPlatformMediaPlayer::stateChanged(m_mediaPlayerState);
377}
378
380{
381 Q_UNUSED(trackType)
382 // TODO QTBUG-108517
383 return 0; // tracks.count();
384}
385
386void QWasmMediaPlayer::setPositionChanged(qint64 position)
387{
389}
390
391void QWasmMediaPlayer::setDurationChanged(qint64 duration)
392{
394}
395
396void QWasmMediaPlayer::videoOutputReady(bool ready)
397{
398 setVideoAvailable(ready);
399
400 if (m_playWhenReady && m_videoOutput->isReady())
401 play();
402}
403
404void QWasmMediaPlayer::setMediaStatus(QMediaPlayer::MediaStatus status)
405{
406 mediaStatusChanged(status);
407
408 switch (status) {
412 break;
414 setPositionChanged(position());
415 default:
416 break;
417 };
418}
419
420void QWasmMediaPlayer::setAudioAvailable(bool available)
421{
422 if (m_audioAvailable == available)
423 return;
424
425 m_audioAvailable = available;
426 emit audioAvailableChanged(m_audioAvailable);
427}
428
429void QWasmMediaPlayer::setVideoAvailable(bool available)
430{
431 if (m_videoAvailable == available)
432 return;
433
434 if (!available)
435 m_videoSize = QSize();
436
437 m_videoAvailable = available;
438 emit videoAvailableChanged(m_videoAvailable);
439}
440
441void QWasmMediaPlayer::resetBufferingProgress()
442{
443 m_buffering = false;
444 m_bufferPercent = 0;
445 m_availablePlaybackRange = QMediaTimeRange();
446}
447
448void QWasmMediaPlayer::onMediaStatusChanged(QMediaPlayer::MediaStatus status)
449{
450 setMediaStatus(status);
451}
452
453void QWasmMediaPlayer::videoMetaDataChanged()
454{
456}
457
459
460#include "moc_qwasmmediaplayer_p.cpp"
void deviceChanged()
void mutedChanged(bool muted)
QAudioDevice device
\qmlproperty AudioDevice QtMultimedia::AudioOutput::device
void volumeChanged(float volume)
\inmodule QtCore \reentrant
Definition qiodevice.h:34
The QMediaPlayer class allows the playing of a media files.
MediaStatus
\qmlproperty enumeration QtMultimedia::MediaPlayer::playbackState
PlaybackState
Defines the current state of a media player.
Error
\qmlproperty enumeration QtMultimedia::MediaPlayer::mediaStatus
The QMediaTimeRange class represents a set of zero or more disjoint time intervals.
void addInterval(qint64 start, qint64 end)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3099
virtual QMediaPlayer::PlaybackState state() const
void positionChanged(qint64 position)
virtual QMediaPlayer::MediaStatus mediaStatus() const
void durationChanged(qint64 duration)
void playbackRateChanged(qreal rate)
void error(int error, const QString &errorString)
void audioAvailableChanged(bool audioAvailable)
void stateChanged(QMediaPlayer::PlaybackState newState)
void videoAvailableChanged(bool videoAvailable)
void mediaStatusChanged(QMediaPlayer::MediaStatus status)
void bufferProgressChanged(float progress)
\inmodule QtCore\reentrant
Definition qrect.h:30
\inmodule QtCore
Definition qsize.h:25
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
std::string toStdString() const
Returns a std::string object with the data contained in this QString.
Definition qstring.h:1319
\inmodule QtCore
Definition qurl.h:94
bool isEmpty() const
Returns true if the URL has no data; otherwise returns false.
Definition qurl.cpp:1888
\inmodule QtCore
Definition quuid.h:31
static QUuid createUuid()
On any platform other than Windows, this function returns a new UUID with variant QUuid::DCE and vers...
Definition quuid.cpp:947
@ WithoutBraces
Definition quuid.h:54
QString toString(StringFormat mode=WithBraces) const
Definition quuid.cpp:602
The QVideoSink class represents a generic sink for video data.
Definition qvideosink.h:22
void progressChanged(qint32 position)
void bufferingChanged(qint32 percent)
void errorOccured(qint32 code, const QString &message)
void stateChanged(QWasmMediaPlayer::QWasmMediaPlayerState newState)
void statusChanged(QMediaPlayer::MediaStatus status)
void durationChanged(qint64 duration)
void setAudioDevice(const QAudioDevice &device) final
void setSource(const QUrl &url)
void setVideoSink(QVideoSink *surface) override
qint64 duration() const override
void pause() override
qint64 position() const override
void play() override
const QIODevice * mediaStream() const override
QMediaTimeRange availablePlaybackRanges() const override
qreal playbackRate() const override
float bufferProgress() const override
bool isVideoAvailable() const override
QWasmMediaPlayer(QMediaPlayer *parent=0)
~QWasmMediaPlayer() override
void setMedia(const QUrl &mediaContent, QIODevice *stream) override
void setPosition(qint64 position) override
void setPlaybackRate(qreal rate) override
void setAudioOutput(QPlatformAudioOutput *output) override
bool isSeekable() const override
bool isAudioAvailable() const override
int trackCount(TrackType trackType) override
void stop() override
QUrl media() const override
void readyChanged(bool)
void updateVideoElementGeometry(const QRect &windowGeometry)
void sizeChange(qint32 width, qint32 height)
void durationChanged(qint64 duration)
void setMuted(bool muted)
void setSource(const QUrl &url)
void setVideoMode(QWasmVideoOutput::WasmVideoMode mode)
void bufferingChanged(qint32 percent)
void seekTo(qint64 position)
void setVolume(qreal volume)
void createVideoElement(const std::string &id)
void stateChanged(QWasmMediaPlayer::QWasmMediaPlayerState newState)
void setSurface(QVideoSink *surface)
void statusChanged(QMediaPlayer::MediaStatus status)
void progressChanged(qint32 position)
void errorOccured(qint32 code, const QString &message)
void setPlaybackRate(qreal rate)
void createOffscreenElement(const QSize &offscreenSize)
else opt state
[0]
Combined button and popup list for selecting options.
#define Q_FUNC_INFO
DBusConnection const char DBusError * error
EGLStreamKHR stream
#define qDebug
[1]
Definition qlogging.h:160
#define qWarning
Definition qlogging.h:162
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:44
GLint GLsizei GLsizei height
GLuint GLuint end
GLint GLsizei width
GLuint GLsizei const GLchar * message
GLuint GLenum * rate
GLsizei GLenum GLboolean sink
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define emit
#define Q_UNUSED(x)
int qint32
Definition qtypes.h:44
long long qint64
Definition qtypes.h:55
double qreal
Definition qtypes.h:92
QT_BEGIN_NAMESPACE typedef uchar * output
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent