Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qmediaplayer.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 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
4#include "qmediaplayer_p.h"
5
6#include <private/qmultimediautils_p.h>
7#include <private/qplatformmediaintegration_p.h>
8#include <qvideosink.h>
9#include <qaudiooutput.h>
10
11#include <QtCore/qcoreevent.h>
12#include <QtCore/qmetaobject.h>
13#include <QtCore/qtimer.h>
14#include <QtCore/qdebug.h>
15#include <QtCore/qdir.h>
16#include <QtCore/qpointer.h>
17#include <QtCore/qfileinfo.h>
18#include <QtCore/qtemporaryfile.h>
19#include <QtCore/qcoreapplication.h>
20
21#if defined(Q_OS_ANDROID)
22# include <QtCore/qjniobject.h>
23#endif
24
26
102{
103 Q_Q(QMediaPlayer);
104
105 if (toState != state) {
106 const auto fromState = std::exchange(state, toState);
107 if (toState == QMediaPlayer::PlayingState || fromState == QMediaPlayer::PlayingState)
108 emit q->playingChanged(toState == QMediaPlayer::PlayingState);
109 emit q->playbackStateChanged(toState);
110 }
111}
112
114{
115 Q_Q(QMediaPlayer);
116
117 emit q->mediaStatusChanged(s);
118}
119
121{
122 Q_Q(QMediaPlayer);
123
124 this->error.setAndNotify(error, errorString, *q);
125}
126
128{
129 if (!control)
130 return;
131
132 std::unique_ptr<QFile> file;
133
134 // Back ends can't play qrc files directly.
135 // If the back end supports StreamPlayback, we pass a QFile for that resource.
136 // If it doesn't, we copy the data to a temporary file and pass its path.
137 if (!media.isEmpty() && !stream && media.scheme() == QLatin1String("qrc")) {
138 qrcMedia = media;
139
140 file.reset(new QFile(QLatin1Char(':') + media.path()));
141 if (!file->open(QFile::ReadOnly)) {
142 file.reset();
143 control->setMedia(QUrl(), nullptr);
145 control->error(QMediaPlayer::ResourceError, QMediaPlayer::tr("Attempting to play invalid Qt resource"));
146
147 } else if (control->streamPlaybackSupported()) {
148 control->setMedia(media, file.get());
149 } else {
150#if QT_CONFIG(temporaryfile)
151#if defined(Q_OS_ANDROID)
152 QString tempFileName = QDir::tempPath() + media.path();
153 QDir().mkpath(QFileInfo(tempFileName).path());
154 QTemporaryFile *tempFile = QTemporaryFile::createNativeFile(*file);
155 if (!tempFile->rename(tempFileName))
156 qWarning() << "Could not rename temporary file to:" << tempFileName;
157#else
158 QTemporaryFile *tempFile = new QTemporaryFile;
159
160 // Preserve original file extension, some back ends might not load the file if it doesn't
161 // have an extension.
162 const QString suffix = QFileInfo(*file).suffix();
163 if (!suffix.isEmpty())
164 tempFile->setFileTemplate(tempFile->fileTemplate() + QLatin1Char('.') + suffix);
165
166 // Copy the qrc data into the temporary file
167 if (!tempFile->open()) {
168 control->setMedia(QUrl(), nullptr);
171 delete tempFile;
172 qrcFile.reset();
173 return;
174 }
175 char buffer[4096];
176 while (true) {
177 qint64 len = file->read(buffer, sizeof(buffer));
178 if (len < 1)
179 break;
180 tempFile->write(buffer, len);
181 }
182 tempFile->close();
183#endif
186#else
187 qWarning("Qt was built with -no-feature-temporaryfile: playback from resource file is not supported!");
188#endif
189 }
190 } else {
191 qrcMedia = QUrl();
193 if (url.scheme() == QLatin1String("content") && !stream) {
194 file.reset(new QFile(media.url()));
195 stream = file.get();
196 }
197
199 }
200
201 qrcFile.swap(file); // Cleans up any previous file
202}
203
205{
206 QList<QMediaMetaData> tracks;
207 if (control) {
208 int count = control->trackCount(s);
209 for (int i = 0; i < count; ++i) {
210 tracks.append(control->trackMetaData(s, i));
211 }
212 }
213 return tracks;
214}
215
221 : QObject(*new QMediaPlayerPrivate, parent)
222{
223 Q_D(QMediaPlayer);
224
225 auto maybeControl = QPlatformMediaIntegration::instance()->createPlayer(this);
226 if (maybeControl) {
227 d->control = maybeControl.value();
228 d->state = d->control->state();
229 } else {
230 qWarning() << "Failed to initialize QMediaPlayer" << maybeControl.error();
231 d->setError(QMediaPlayer::ResourceError, maybeControl.error());
232 }
233}
234
235
241{
242 Q_D(QMediaPlayer);
243
244 // prevents emitting audioOutputChanged and videoOutputChanged.
245 QSignalBlocker blocker(this);
246
247 // Reset audio output and video sink to ensure proper unregistering of the source
248 // To be investigated: registering of the source might be removed after switching on the ffmpeg
249 // backend;
250
251 setAudioOutput(nullptr);
252
253 d->setVideoSink(nullptr);
254 delete d->control;
255}
256
258{
259 Q_D(const QMediaPlayer);
260
261 return d->source;
262}
263
273{
274 Q_D(const QMediaPlayer);
275
276 return d->stream;
277}
278
287{
288 Q_D(const QMediaPlayer);
289
290 // In case if EndOfMedia status is already received
291 // but state is not.
292 if (d->control
293 && d->control->mediaStatus() == QMediaPlayer::EndOfMedia
294 && d->state != d->control->state()) {
295 return d->control->state();
296 }
297
298 return d->state;
299}
300
302{
303 Q_D(const QMediaPlayer);
304 return d->control ? d->control->mediaStatus() : NoMedia;
305}
306
315{
316 Q_D(const QMediaPlayer);
317 return d->control ? d->control->duration() : 0;
318}
319
328{
329 Q_D(const QMediaPlayer);
330 return d->control ? d->control->position() : 0;
331}
332
343{
344 Q_D(const QMediaPlayer);
345 return d->control ? d->control->bufferProgress() : 0;
346}
347
358{
359 Q_D(const QMediaPlayer);
360 return d->control ? d->control->availablePlaybackRanges() : QMediaTimeRange{};
361}
362
374{
375 Q_D(const QMediaPlayer);
376 return d->control && d->control->isAudioAvailable();
377}
378
390{
391 Q_D(const QMediaPlayer);
392 return d->control && d->control->isVideoAvailable();
393}
394
402{
403 Q_D(const QMediaPlayer);
404 return d->control && d->control->isSeekable();
405}
406
408{
409 Q_D(const QMediaPlayer);
410 return d->state == QMediaPlayer::PlayingState;
411}
412
417{
418 Q_D(const QMediaPlayer);
419 return d->control ? d->control->playbackRate() : 0.;
420}
421
449{
450 Q_D(const QMediaPlayer);
451 return d->control ? d->control->loops() : 1;
452}
453
455{
456 Q_D(QMediaPlayer);
457 if (loops == 0)
458 return;
459 if (d->control)
460 d->control->setLoops(loops);
461}
462
467{
468 return d_func()->error.code();
469}
470
484{
485 return d_func()->error.description();
486}
487
503{
504 Q_D(QMediaPlayer);
505
506 if (!d->control)
507 return;
508
509 // Reset error conditions
510 d->setError(NoError, QString());
511
512 d->control->play();
513}
514
530{
531 Q_D(QMediaPlayer);
532
533 if (d->control)
534 d->control->pause();
535}
536
552{
553 Q_D(QMediaPlayer);
554
555 if (d->control)
556 d->control->stop();
557}
558
560{
561 Q_D(QMediaPlayer);
562
563 if (!d->control)
564 return;
565 if (!d->control->isSeekable())
566 return;
567 d->control->setPosition(qMax(position, 0ll));
568}
569
571{
572 Q_D(QMediaPlayer);
573
574 if (d->control)
575 d->control->setPlaybackRate(rate);
576}
577
602{
603 Q_D(QMediaPlayer);
604 stop();
605
606 if (d->source == source && d->stream == nullptr)
607 return;
608
609 d->source = source;
610 d->stream = nullptr;
611
612 d->setMedia(source, nullptr);
613 emit sourceChanged(d->source);
614}
615
631{
632 Q_D(QMediaPlayer);
633 stop();
634
635 if (d->source == sourceUrl && d->stream == device)
636 return;
637
638 d->source = sourceUrl;
639 d->stream = device;
640
641 d->setMedia(d->source, device);
642 emit sourceChanged(d->source);
643}
644
665{
666 Q_D(QMediaPlayer);
667 auto oldOutput = d->audioOutput;
668 if (oldOutput == output)
669 return;
670 d->audioOutput = output;
671 if (d->control)
672 d->control->setAudioOutput(nullptr);
673 if (oldOutput)
674 oldOutput->setDisconnectFunction({});
675 if (output) {
676 output->setDisconnectFunction([this](){ setAudioOutput(nullptr); });
677 if (d->control)
678 d->control->setAudioOutput(output->handle());
679 }
681}
682
684{
685 Q_D(const QMediaPlayer);
686 return d->audioOutput;
687}
688
712QList<QMediaMetaData> QMediaPlayer::audioTracks() const
713{
714 Q_D(const QMediaPlayer);
715 return d->trackMetaData(QPlatformMediaPlayer::AudioStream);
716}
717
737QList<QMediaMetaData> QMediaPlayer::videoTracks() const
738{
739 Q_D(const QMediaPlayer);
740 return d->trackMetaData(QPlatformMediaPlayer::VideoStream);
741}
742
764QList<QMediaMetaData> QMediaPlayer::subtitleTracks() const
765{
766 Q_D(const QMediaPlayer);
767 return d->trackMetaData(QPlatformMediaPlayer::SubtitleStream);
768}
769
788{
789 Q_D(const QMediaPlayer);
790 return d->control ? d->control->activeTrack(QPlatformMediaPlayer::AudioStream) : 0;
791}
792
812{
813 Q_D(const QMediaPlayer);
814 return d->control ? d->control->activeTrack(QPlatformMediaPlayer::VideoStream) : -1;
815}
816
836{
837 Q_D(const QMediaPlayer);
838 return d->control ? d->control->activeTrack(QPlatformMediaPlayer::SubtitleStream) : -1;
839}
840
842{
843 Q_D(QMediaPlayer);
844 if (!d->control)
845 return;
846
847 if (activeAudioTrack() == index)
848 return;
849 d->control->setActiveTrack(QPlatformMediaPlayer::AudioStream, index);
850}
851
853{
854 Q_D(QMediaPlayer);
855 if (!d->control)
856 return;
857
858 if (activeVideoTrack() == index)
859 return;
860 d->control->setActiveTrack(QPlatformMediaPlayer::VideoStream, index);
861}
862
864{
865 Q_D(QMediaPlayer);
866 if (!d->control)
867 return;
868
869 if (activeSubtitleTrack() == index)
870 return;
871 d->control->setActiveTrack(QPlatformMediaPlayer::SubtitleStream, index);
872}
873
894{
895 Q_D(const QMediaPlayer);
896 return d->videoOutput;
897}
898
900{
901 Q_D(QMediaPlayer);
902 if (d->videoOutput == output)
903 return;
904
905 auto *sink = qobject_cast<QVideoSink *>(output);
906 if (!sink && output) {
907 auto *mo = output->metaObject();
908 mo->invokeMethod(output, "videoSink", Q_RETURN_ARG(QVideoSink *, sink));
909 }
910 d->videoOutput = output;
911 d->setVideoSink(sink);
912}
913
919{
920 Q_D(QMediaPlayer);
921 d->videoOutput = nullptr;
922 d->setVideoSink(sink);
923}
924
929{
930 Q_D(const QMediaPlayer);
931 return d->videoSink;
932}
933
934
935#if 0
936/*
937 \since 5.15
938 Sets multiple video sinks as the video output of a media player.
939 This allows the media player to render video frames on several outputs.
940
941 If a video output has already been set on the media player the new surfaces
942 will replace it.
943*/
944void QMediaPlayer::setVideoOutput(const QList<QVideoSink *> &sinks)
945{
946 // ### IMPLEMENT ME
947 Q_UNUSED(sinks);
948// setVideoOutput(!surfaces.empty() ? new QVideoSurfaces(surfaces, this) : nullptr);
949}
950#endif
951
956{
957 Q_D(const QMediaPlayer);
958 return bool(d->control);
959}
960
983{
984 Q_D(const QMediaPlayer);
985 return d->control ? d->control->metaData() : QMediaMetaData{};
986}
987
988// Enums
1154// Properties
1350
1351#include "moc_qmediaplayer.cpp"
IOBluetoothDevice * device
\qmltype AudioOutput \instantiates QAudioOutput
\inmodule QtCore
Definition qdir.h:20
bool mkpath(const QString &dirPath) const
Creates the directory path dirPath.
Definition qdir.cpp:1578
static QString tempPath()
Returns the absolute canonical path of the system's temporary directory.
Definition qdir.cpp:2133
QString suffix() const
Returns the suffix (extension) of the file.
\inmodule QtCore
Definition qfile.h:93
QFILE_MAYBE_NODISCARD bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:904
QString fileName() const override
Returns the name set by setFileName() or to the QFile constructors.
Definition qfile.cpp:277
\inmodule QtCore \reentrant
Definition qiodevice.h:34
virtual bool reset()
Seeks to the start of input for random-access devices.
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read.
\inmodule QtMultimedia
QPlatformMediaPlayer * control
void setState(QMediaPlayer::PlaybackState state)
\qmltype MediaPlayer \instantiates QMediaPlayer
QMediaPlayer::PlaybackState state
QList< QMediaMetaData > trackMetaData(QPlatformMediaPlayer::TrackType s) const
void setMedia(const QUrl &media, QIODevice *stream=nullptr)
QErrorInfo< QMediaPlayer::Error > error
std::unique_ptr< QFile > qrcFile
void setStatus(QMediaPlayer::MediaStatus status)
void setError(QMediaPlayer::Error error, const QString &errorString)
The QMediaPlayer class allows the playing of a media files.
void setActiveAudioTrack(int index)
void setVideoSink(QVideoSink *sink)
Sets sink to be the QVideoSink instance to retrieve video data.
void setSource(const QUrl &source)
\qmlproperty url QtMultimedia::MediaPlayer::source
void setAudioOutput(QAudioOutput *output)
void setActiveVideoTrack(int index)
bool isAvailable() const
Returns true if the media player is supported on this platform.
QVideoSink * videoSink() const
Returns the QVideoSink instance.
int activeVideoTrack
Returns the currently active video track.
qint64 position
\qmlproperty int QtMultimedia::MediaPlayer::position
void sourceChanged(const QUrl &media)
Signals that the media source has been changed to media.
const QIODevice * sourceDevice() const
Returns the stream source of media data.
qint64 duration
\qmlproperty int QtMultimedia::MediaPlayer::duration
void setActiveSubtitleTrack(int index)
MediaStatus mediaStatus
the status of the current media stream.
MediaStatus
\qmlproperty enumeration QtMultimedia::MediaPlayer::playbackState
void setVideoOutput(QObject *)
qreal playbackRate
\qmlproperty real QtMultimedia::MediaPlayer::playbackRate
PlaybackState playbackState
Returns the \l{QMediaPlayer::}{PlaybackState}.
void audioOutputChanged()
QMediaTimeRange bufferedTimeRange() const
Returns a QMediaTimeRange describing the currently buffered data.
QMediaPlayer(QObject *parent=nullptr)
Constructs a QMediaPlayer instance as a child of {parent}.
void stop()
\qmlmethod QtMultimedia::MediaPlayer::stop()
float bufferProgress
\qmlproperty real QtMultimedia::MediaPlayer::bufferProgress
QUrl source
the active media source being used by the player object.
PlaybackState
Defines the current state of a media player.
QObject * videoOutput
\qmlproperty VideoOutput QtMultimedia::MediaPlayer::videoOutput
bool hasVideo
\qmlproperty bool QtMultimedia::MediaPlayer::hasVideo
void setPlaybackRate(qreal rate)
void setLoops(int loops)
~QMediaPlayer()
Destroys the player object.
void setPosition(qint64 position)
void play()
\qmlmethod QtMultimedia::MediaPlayer::play()
int activeAudioTrack
\qmlproperty int QtMultimedia::MediaPlayer::activeAudioTrack
void setSourceDevice(QIODevice *device, const QUrl &sourceUrl=QUrl())
Sets the current source device.
void pause()
\qmlmethod QtMultimedia::MediaPlayer::pause()
Error error
a string describing the last error condition.
bool hasAudio
\qmlproperty bool QtMultimedia::MediaPlayer::hasAudio
int activeSubtitleTrack
Returns the currently active subtitle track.
bool isPlaying() const
int loops
Determines how often the media is played before the player stops.
bool isSeekable() const
Returns true if the media is seekable.
QAudioOutput * audioOutput
\qmlproperty AudioOutput QtMultimedia::MediaPlayer::audioOutput
Error
\qmlproperty enumeration QtMultimedia::MediaPlayer::mediaStatus
QMediaMetaData metaData
\qmlproperty mediaMetaData QtMultimedia::MediaPlayer::metaData
QList< QMediaMetaData > subtitleTracks
\qmlproperty list<mediaMetaData> QtMultimedia::MediaPlayer::subtitleTracks
QList< QMediaMetaData > audioTracks
\qmlproperty list<mediaMetaData> QtMultimedia::MediaPlayer::audioTracks
QString errorString
\qmlproperty string QtMultimedia::MediaPlayer::errorString
QList< QMediaMetaData > videoTracks
\qmlproperty list<mediaMetaData> QtMultimedia::MediaPlayer::videoTracks
The QMediaTimeRange class represents a set of zero or more disjoint time intervals.
\inmodule QtCore
Definition qobject.h:103
static QPlatformMediaIntegration * instance()
virtual int trackCount(TrackType)
void error(int error, const QString &errorString)
virtual void setMedia(const QUrl &media, QIODevice *stream)=0
virtual QMediaMetaData trackMetaData(TrackType, int)
void mediaStatusChanged(QMediaPlayer::MediaStatus status)
virtual bool streamPlaybackSupported() const
Exception-safe wrapper around QObject::blockSignals().
Definition qobject.h:483
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
\inmodule QtCore
Definition qurl.h:94
static QUrl fromLocalFile(const QString &localfile)
Returns a QUrl representation of localFile, interpreted as a local file.
Definition qurl.cpp:3368
QString url(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
Definition qurl.cpp:2817
bool isEmpty() const
Returns true if the URL has no data; otherwise returns false.
Definition qurl.cpp:1896
QString scheme() const
Returns the scheme of the URL.
Definition qurl.cpp:1991
QString path(ComponentFormattingOptions options=FullyDecoded) const
Returns the path of the URL.
Definition qurl.cpp:2468
The QVideoSink class represents a generic sink for video data.
Definition qvideosink.h:22
auto mo
[7]
Combined button and popup list for selecting options.
static QT_BEGIN_NAMESPACE const char tempFile[]
DBusConnection const char DBusError * error
EGLStreamKHR stream
#define qWarning
Definition qlogging.h:166
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
QUrl qMediaFromUserInput(QUrl url)
#define Q_RETURN_ARG(Type, data)
Definition qobjectdefs.h:64
GLuint index
[2]
GLenum GLenum GLsizei count
GLenum GLuint buffer
GLsizei GLsizei GLchar * source
GLdouble s
[6]
Definition qopenglext.h:235
GLuint GLenum * rate
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLsizei const GLchar *const * path
GLsizei GLenum GLboolean sink
GLenum GLsizei len
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define emit
#define Q_UNUSED(x)
long long qint64
Definition qtypes.h:60
double qreal
Definition qtypes.h:187
QT_BEGIN_NAMESPACE typedef uchar * output
QFile file
[0]
QUrl url("example.com")
[constructor-url-reference]
\inmodule QtCore \reentrant
Definition qchar.h:18