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 <private/qaudiobufferoutput_p.h>
9#include <qvideosink.h>
10#include <qaudiooutput.h>
11
12#include <QtCore/qcoreevent.h>
13#include <QtCore/qmetaobject.h>
14#include <QtCore/qtimer.h>
15#include <QtCore/qdebug.h>
16#include <QtCore/qdir.h>
17#include <QtCore/qpointer.h>
18#include <QtCore/qfileinfo.h>
19#include <QtCore/qtemporaryfile.h>
20#include <QtCore/qcoreapplication.h>
21
22#if defined(Q_OS_ANDROID)
23# include <QtCore/qjniobject.h>
24#endif
25
26QT_BEGIN_NAMESPACE
27
28/*!
29 \class QMediaPlayer
30 \brief The QMediaPlayer class allows the playing of a media files.
31 \inmodule QtMultimedia
32 \ingroup multimedia
33 \ingroup multimedia_playback
34 \ingroup multimedia_video
35
36 The QMediaPlayer class is a high level media playback class. It can be used
37 to playback audio of video media files. The content
38 to playback is specified as a QUrl object.
39
40 \snippet multimedia-snippets/media.cpp Player
41
42 QVideoWidget can be used with QMediaPlayer for video rendering.
43
44 \sa QVideoWidget
45*/
46
47/*!
48 \qmltype MediaPlayer
49 \nativetype QMediaPlayer
50 \brief Adds media playback to a scene.
51
52 \inqmlmodule QtMultimedia
53 \ingroup multimedia_qml
54 \ingroup multimedia_audio_qml
55 \ingroup multimedia_video_qml
56
57 \qml
58 Text {
59 text: "Click Me!";
60 font.pointSize: 24;
61 width: 150; height: 50;
62
63 MediaPlayer {
64 id: playMusic
65 source: "music.wav"
66 audioOutput: AudioOutput {}
67 }
68 MouseArea {
69 anchors.fill: parent
70 onPressed: { playMusic.play() }
71 }
72 }
73 \endqml
74
75 You can use MediaPlayer together with a MultiMedia::AudioOutput to play audio content, or you can use it
76 in conjunction with a Multimedia::VideoOutput for rendering video.
77
78 \qml
79 Item {
80 MediaPlayer {
81 id: mediaplayer
82 source: "groovy_video.mp4"
83 audioOutput: AudioOutput {}
84 videoOutput: videoOutput
85 }
86
87 VideoOutput {
88 id: videoOutput
89 anchors.fill: parent
90 }
91
92 MouseArea {
93 anchors.fill: parent
94 onPressed: mediaplayer.play();
95 }
96 }
97 \endqml
98
99 \sa AudioOutput, VideoOutput
100*/
101
102void QMediaPlayerPrivate::setState(QMediaPlayer::PlaybackState toState)
103{
104 Q_Q(QMediaPlayer);
105
106 if (toState != state) {
107 const auto fromState = std::exchange(obj&: state, new_val&: toState);
108 if (toState == QMediaPlayer::PlayingState || fromState == QMediaPlayer::PlayingState)
109 emit q->playingChanged(playing: toState == QMediaPlayer::PlayingState);
110 emit q->playbackStateChanged(newState: toState);
111 }
112}
113
114void QMediaPlayerPrivate::setStatus(QMediaPlayer::MediaStatus s)
115{
116 Q_Q(QMediaPlayer);
117
118 emit q->mediaStatusChanged(status: s);
119}
120
121void QMediaPlayerPrivate::setError(QMediaPlayer::Error error, const QString &errorString)
122{
123 Q_Q(QMediaPlayer);
124
125 this->error.setAndNotify(code: error, description: errorString, notifier&: *q);
126}
127
128void QMediaPlayerPrivate::setMedia(const QUrl &media, QIODevice *stream)
129{
130 setError(error: QMediaPlayer::NoError, errorString: {});
131
132 if (!control)
133 return;
134
135 std::unique_ptr<QFile> file;
136
137 // Back ends can't play qrc files directly.
138 // If the back end supports StreamPlayback, we pass a QFile for that resource.
139 // If it doesn't, we copy the data to a temporary file and pass its path.
140 if (!media.isEmpty() && !stream && media.scheme() == QLatin1String("qrc")
141 && !control->canPlayQrc()) {
142 qrcMedia = media;
143
144 file.reset(p: new QFile(QLatin1Char(':') + media.path()));
145 if (!file->open(flags: QFile::ReadOnly)) {
146 file.reset();
147 control->setMedia(media: QUrl(), stream: nullptr);
148 control->mediaStatusChanged(status: QMediaPlayer::InvalidMedia);
149 control->error(QMediaPlayer::ResourceError, errorString: QMediaPlayer::tr(s: "Attempting to play invalid Qt resource"));
150
151 } else if (control->streamPlaybackSupported()) {
152 control->setMedia(media, stream: file.get());
153 } else {
154#if QT_CONFIG(temporaryfile)
155#if defined(Q_OS_ANDROID)
156 QString tempFileName = QDir::tempPath() + media.path();
157 QDir().mkpath(QFileInfo(tempFileName).path());
158 QTemporaryFile *tempFile = QTemporaryFile::createNativeFile(*file);
159 if (tempFile == nullptr) {
160 control->setMedia(QUrl(), nullptr);
161 control->mediaStatusChanged(QMediaPlayer::InvalidMedia);
162 control->error(QMediaPlayer::ResourceError, QMediaPlayer::tr("Failed to establish temporary file during playback"));
163 return;
164 }
165 if (!tempFile->rename(tempFileName))
166 qWarning() << "Could not rename temporary file to:" << tempFileName;
167#else
168 QTemporaryFile *tempFile = new QTemporaryFile;
169
170 // Preserve original file extension, some back ends might not load the file if it doesn't
171 // have an extension.
172 const QString suffix = QFileInfo(*file).suffix();
173 if (!suffix.isEmpty())
174 tempFile->setFileTemplate(tempFile->fileTemplate() + QLatin1Char('.') + suffix);
175
176 // Copy the qrc data into the temporary file
177 if (!tempFile->open()) {
178 control->setMedia(media: QUrl(), stream: nullptr);
179 control->mediaStatusChanged(status: QMediaPlayer::InvalidMedia);
180 control->error(QMediaPlayer::ResourceError, errorString: tempFile->errorString());
181 delete tempFile;
182 qrcFile.reset();
183 return;
184 }
185 char buffer[4096];
186 while (true) {
187 qint64 len = file->read(data: buffer, maxlen: sizeof(buffer));
188 if (len < 1)
189 break;
190 tempFile->write(data: buffer, len);
191 }
192 tempFile->close();
193#endif
194 file.reset(p: tempFile);
195 control->setMedia(media: QUrl(QUrl::fromLocalFile(localfile: file->fileName())), stream: nullptr);
196#else
197 qWarning("Qt was built with -no-feature-temporaryfile: playback from resource file is not supported!");
198#endif
199 }
200 } else {
201 qrcMedia = QUrl();
202 QUrl url = qMediaFromUserInput(fileName: media);
203 if (url.scheme() == QLatin1String("content") && !stream) {
204 file.reset(p: new QFile(media.url()));
205 stream = file.get();
206 }
207
208 control->setMedia(media: url, stream);
209 }
210
211 qrcFile.swap(u&: file); // Cleans up any previous file
212}
213
214QList<QMediaMetaData> QMediaPlayerPrivate::trackMetaData(QPlatformMediaPlayer::TrackType s) const
215{
216 QList<QMediaMetaData> tracks;
217 if (control) {
218 int count = control->trackCount(s);
219 for (int i = 0; i < count; ++i) {
220 tracks.append(t: control->trackMetaData(s, i));
221 }
222 }
223 return tracks;
224}
225
226/*!
227 Constructs a QMediaPlayer instance as a child of \a{parent}.
228*/
229
230QMediaPlayer::QMediaPlayer(QObject *parent)
231 : QObject(*new QMediaPlayerPrivate, parent)
232{
233 Q_D(QMediaPlayer);
234
235 auto maybeControl = QPlatformMediaIntegration::instance()->createPlayer(this);
236 if (maybeControl) {
237 d->control = maybeControl.value();
238 d->state = d->control->state();
239 } else {
240 qWarning() << "Failed to initialize QMediaPlayer" << maybeControl.error();
241 d->setError(error: QMediaPlayer::ResourceError, errorString: maybeControl.error());
242 }
243}
244
245
246/*!
247 Destroys the player object.
248*/
249
250QMediaPlayer::~QMediaPlayer()
251{
252 Q_D(QMediaPlayer);
253
254 // prevents emitting audioOutputChanged and videoOutputChanged.
255 QSignalBlocker blocker(this);
256
257 // Reset audio output and video sink to ensure proper unregistering of the source
258 // To be investigated: registering of the source might be removed after switching on the ffmpeg
259 // backend;
260
261 // Workaround to prevent freeze in GStreamer when setting audioOutput while stopped
262 if (d->control)
263 d->control->qmediaplayerDestructorCalled = true;
264 setAudioOutput(nullptr);
265
266 d->setVideoSink(nullptr);
267 delete d->control;
268}
269
270QUrl QMediaPlayer::source() const
271{
272 Q_D(const QMediaPlayer);
273
274 return d->source;
275}
276
277/*!
278 Returns the stream source of media data.
279
280 This is only valid if a stream was passed to setSource().
281
282 \sa setSource()
283*/
284
285const QIODevice *QMediaPlayer::sourceDevice() const
286{
287 Q_D(const QMediaPlayer);
288
289 return d->stream;
290}
291
292/*!
293 \property QMediaPlayer::playbackState
294
295 Returns the \l{QMediaPlayer::}{PlaybackState}.
296
297 \sa playing
298*/
299QMediaPlayer::PlaybackState QMediaPlayer::playbackState() const
300{
301 Q_D(const QMediaPlayer);
302
303 // In case if EndOfMedia status is already received
304 // but state is not.
305 if (d->control
306 && d->control->mediaStatus() == QMediaPlayer::EndOfMedia
307 && d->state != d->control->state()) {
308 return d->control->state();
309 }
310
311 return d->state;
312}
313
314QMediaPlayer::MediaStatus QMediaPlayer::mediaStatus() const
315{
316 Q_D(const QMediaPlayer);
317 return d->control ? d->control->mediaStatus() : NoMedia;
318}
319
320/*!
321 Returns the duration of the current media in ms.
322
323 Returns 0 if the media player doesn't have a valid media file or stream.
324 For live streams, the duration usually changes during playback as more
325 data becomes available.
326*/
327qint64 QMediaPlayer::duration() const
328{
329 Q_D(const QMediaPlayer);
330 return d->control ? d->control->duration() : 0;
331}
332
333/*!
334 Returns the current position inside the media being played back in ms.
335
336 Returns 0 if the media player doesn't have a valid media file or stream.
337 For live streams, the duration usually changes during playback as more
338 data becomes available.
339*/
340qint64 QMediaPlayer::position() const
341{
342 Q_D(const QMediaPlayer);
343 return d->control ? d->control->position() : 0;
344}
345
346/*!
347 Returns a number between 0 and 1 when buffering data.
348
349 0 means that there is no buffered data available, playback is usually
350 stalled in this case. Playback will resume once the buffer reaches 1,
351 meaning enough data has been buffered to be able to resume playback.
352
353 bufferProgress() will always return 1 for local files.
354*/
355float QMediaPlayer::bufferProgress() const
356{
357 Q_D(const QMediaPlayer);
358 return d->control ? d->control->bufferProgress() : 0;
359}
360
361/*!
362 Returns a QMediaTimeRange describing the currently buffered data.
363
364 When streaming media from a remote source, different parts of the media
365 file can be available locally. The returned QMediaTimeRange object describes
366 the time ranges that are buffered and available for immediate playback.
367
368 \sa QMediaTimeRange
369*/
370QMediaTimeRange QMediaPlayer::bufferedTimeRange() const
371{
372 Q_D(const QMediaPlayer);
373 return d->control ? d->control->availablePlaybackRanges() : QMediaTimeRange{};
374}
375
376/*!
377 \qmlproperty bool QtMultimedia::MediaPlayer::hasAudio
378
379 This property holds whether the media contains audio.
380*/
381
382/*!
383 \property QMediaPlayer::hasAudio
384 \brief This property holds whether the media contains audio.
385*/
386bool QMediaPlayer::hasAudio() const
387{
388 Q_D(const QMediaPlayer);
389 return d->control && d->control->isAudioAvailable();
390}
391
392/*!
393 \qmlproperty bool QtMultimedia::MediaPlayer::hasVideo
394
395 This property holds whether the media contains video.
396*/
397
398/*!
399 \property QMediaPlayer::hasVideo
400 \brief This property holds whether the media contains video.
401*/
402bool QMediaPlayer::hasVideo() const
403{
404 Q_D(const QMediaPlayer);
405 return d->control && d->control->isVideoAvailable();
406}
407
408/*!
409 Returns true if the media is seekable. Most file based media files are seekable,
410 but live streams usually are not.
411
412 \sa position
413*/
414bool QMediaPlayer::isSeekable() const
415{
416 Q_D(const QMediaPlayer);
417 return d->control && d->control->isSeekable();
418}
419
420bool QMediaPlayer::isPlaying() const
421{
422 Q_D(const QMediaPlayer);
423 return d->state == QMediaPlayer::PlayingState;
424}
425
426/*!
427 Returns the current playback rate.
428*/
429qreal QMediaPlayer::playbackRate() const
430{
431 Q_D(const QMediaPlayer);
432 return d->control ? d->control->playbackRate() : 0.;
433}
434
435/*!
436 \enum QMediaPlayer::Loops
437
438 Some predefined constants for the \l loops property.
439
440 \value Infinite Loop forever.
441 \value Once Play the media once (the default).
442*/
443
444/*!
445 \property QMediaPlayer::loops
446
447 Determines how often the media is played before the player stops.
448 Set to QMediaPlayer::Infinite to loop the current media file forever.
449
450 The default value is \c 1. Setting this property to \c 0 has no effect.
451*/
452
453/*!
454 \qmlproperty int QtMultimedia::MediaPlayer::loops
455
456 Determines how often the media is played before the player stops.
457 Set to MediaPlayer::Infinite to loop the current media file forever.
458
459 The default value is \c 1. Setting this property to \c 0 has no effect.
460*/
461int QMediaPlayer::loops() const
462{
463 Q_D(const QMediaPlayer);
464 return d->control ? d->control->loops() : 1;
465}
466
467void QMediaPlayer::setLoops(int loops)
468{
469 Q_D(QMediaPlayer);
470 if (loops == 0)
471 return;
472 if (d->control)
473 d->control->setLoops(loops);
474}
475
476/*!
477 Returns the current error state.
478*/
479QMediaPlayer::Error QMediaPlayer::error() const
480{
481 return d_func()->error.code();
482}
483
484/*!
485 \qmlproperty string QtMultimedia::MediaPlayer::errorString
486
487 This property holds a string describing the current error condition in more
488 detail.
489*/
490
491/*!
492 \property QMediaPlayer::errorString
493 \brief This property holds a string describing the current error condition in
494 more detail.
495*/
496QString QMediaPlayer::errorString() const
497{
498 return d_func()->error.description();
499}
500
501/*!
502 \qmlmethod QtMultimedia::MediaPlayer::play()
503
504 Starts or resumes playback of the media.
505
506 Sets the \l playbackState property to PlayingState, and changes
507 \l playing to \c true.
508*/
509
510/*!
511 Start or resume playing the current source.
512
513 \sa pause(), stop()
514*/
515void QMediaPlayer::play()
516{
517 Q_D(QMediaPlayer);
518
519 if (!d->control)
520 return;
521
522 d->control->play();
523}
524
525/*!
526 \qmlmethod QtMultimedia::MediaPlayer::pause()
527
528 Pauses playback of the media.
529
530 Sets the \l playbackState property to PausedState,
531 and changes \l playing to \c false.
532*/
533
534/*!
535 Pause playing the current source.
536
537 \sa play(), stop()
538*/
539void QMediaPlayer::pause()
540{
541 Q_D(QMediaPlayer);
542
543 if (d->control)
544 d->control->pause();
545}
546
547/*!
548 \qmlmethod QtMultimedia::MediaPlayer::stop()
549
550 Stops playback of the media.
551
552 Sets the \l playbackState property to StoppedState,
553 and changes \l playing to \c false.
554*/
555
556/*!
557 Stop playing, and reset the play position to the beginning.
558
559 \sa play(), pause()
560*/
561void QMediaPlayer::stop()
562{
563 Q_D(QMediaPlayer);
564
565 if (d->control)
566 d->control->stop();
567}
568
569void QMediaPlayer::setPosition(qint64 position)
570{
571 Q_D(QMediaPlayer);
572
573 if (!d->control)
574 return;
575 if (!d->control->isSeekable())
576 return;
577 d->control->setPosition(qMax(a: position, b: 0ll));
578}
579
580void QMediaPlayer::setPlaybackRate(qreal rate)
581{
582 Q_D(QMediaPlayer);
583
584 if (d->control)
585 d->control->setPlaybackRate(rate);
586}
587
588/*!
589 \qmlproperty url QtMultimedia::MediaPlayer::source
590
591 This property holds the source URL of the media.
592
593 \snippet multimedia-snippets/qtvideosink.qml complete
594
595 \sa QMediaPlayer::setSource()
596*/
597
598/*!
599 Sets the current \a source.
600
601 Setting the media to a null QUrl will cause the player to discard all
602 information relating to the current media source and to cease all I/O operations related
603 to that media. Setting the media will stop the playback.
604
605 \note This function returns immediately after recording the specified source of the media.
606 It does not wait for the media to finish loading and does not check for errors. Listen for
607 the mediaStatusChanged() and error() signals to be notified when the media is loaded and
608 when an error occurs during loading.
609
610 \note FFmpeg, used by the FFmpeg media backend, restricts use of nested protocols for
611 security reasons. In controlled environments where all inputs are trusted, the list of
612 approved protocols can be overridden using the QT_FFMPEG_PROTOCOL_WHITELIST environment
613 variable. This environment variable is Qt's private API and can change between patch
614 releases without notice.
615*/
616
617void QMediaPlayer::setSource(const QUrl &source)
618{
619 Q_D(QMediaPlayer);
620 stop();
621
622 if (d->source == source && d->stream == nullptr)
623 return;
624
625 d->source = source;
626 d->stream = nullptr;
627
628 d->setMedia(media: source, stream: nullptr);
629 emit sourceChanged(media: d->source);
630}
631
632/*!
633 Sets the current source \a device.
634
635 The media data will be read from \a device. The \a sourceUrl can be provided
636 to resolve additional information about the media, mime type etc. The
637 \a device must be open and readable.
638
639 For macOS the \a device should also be seek-able.
640
641 \note This function returns immediately after recording the specified source
642 of the media. It does not wait for the media to finish loading and does not
643 check for errors. Listen for the mediaStatusChanged() and error() signals to
644 be notified when the media is loaded, and if an error occurs during loading.
645*/
646void QMediaPlayer::setSourceDevice(QIODevice *device, const QUrl &sourceUrl)
647{
648 Q_D(QMediaPlayer);
649 stop();
650
651 if (d->source == sourceUrl && d->stream == device)
652 return;
653
654 d->source = sourceUrl;
655 d->stream = device;
656
657 d->setMedia(media: d->source, stream: device);
658 emit sourceChanged(media: d->source);
659}
660
661/*!
662 \qmlproperty QAudioBufferOutput QtMultimedia::MediaPlayer::audioBufferOutput
663 \since 6.8
664
665 This property holds the target audio buffer output.
666
667 Normal usage of MediaPlayer from QML should not require using this property.
668
669 \sa QMediaPlayer::audioBufferOutput()
670*/
671
672/*!
673 \property QMediaPlayer::audioBufferOutput
674 \since 6.8
675 \brief The output audio buffer used by the media player.
676
677 Sets an audio buffer \a output to the media player.
678
679 If \l QAudioBufferOutput is specified and the media source
680 contains an audio stream, the media player, it will emit
681 the signal \l{QAudioBufferOutput::audioBufferReceived} with
682 audio buffers containing decoded audio data. At the end of
683 the audio stream, \c QMediaPlayer emits an empty \l QAudioBuffer.
684
685 \c QMediaPlayer emits outputs audio buffers at the same time as it
686 pushes the matching data to the audio output if it's specified.
687 However, the sound can be played with a small delay due to
688 audio bufferization.
689
690 The format of emitted audio buffers is taken from the
691 specified \a output or from the matching audio stream
692 if the \a output returns an invalid format. Emitted
693 audio data is not scaled depending on the current playback rate.
694
695 Potential use cases of utilizing \c QAudioBufferOutput
696 with \c QMediaPlayer might be:
697 \list
698 \li Audio visualization. If the playback rate of the media player
699 is not \c 1, you may scale the output image dimensions,
700 or image update interval according to the requirements
701 of the visualizer.
702 \li Any AI sound processing, e.g. voice recognition.
703 \li Sending the data to external audio output.
704 Playback rate changing, synchronization with video, and manual
705 flushing on stoping and seeking should be considered.
706 We don't recommend using the audio buffer output
707 for this purpose unless you have a strong reason for this.
708 \endlist
709
710*/
711void QMediaPlayer::setAudioBufferOutput(QAudioBufferOutput *output)
712{
713 Q_D(QMediaPlayer);
714
715 QAudioBufferOutput *oldOutput = d->audioBufferOutput;
716 if (oldOutput == output)
717 return;
718
719 d->audioBufferOutput = output;
720
721 if (oldOutput) {
722 auto oldPlayer = QAudioBufferOutputPrivate::exchangeMediaPlayer(output&: *oldOutput, player: this);
723 if (oldPlayer)
724 oldPlayer->setAudioBufferOutput(nullptr);
725 }
726
727 if (d->control)
728 d->control->setAudioBufferOutput(output);
729
730 emit audioBufferOutputChanged();
731}
732
733QAudioBufferOutput *QMediaPlayer::audioBufferOutput() const
734{
735 Q_D(const QMediaPlayer);
736 return d->audioBufferOutput;
737}
738
739/*!
740 \qmlproperty AudioOutput QtMultimedia::MediaPlayer::audioOutput
741
742 This property holds the target audio output.
743 Accepts one AudioOutput elements.
744
745 \sa QMediaPlayer::setAudioOutput()
746*/
747
748
749/*!
750 \property QMediaPlayer::audioOutput
751 \brief The audio output device used by the media player.
752
753 The current audio output to be used when playing back media. Setting
754 a new audio output will replace the currently used output.
755
756 Setting this property to \c nullptr will disable any audio output.
757*/
758void QMediaPlayer::setAudioOutput(QAudioOutput *output)
759{
760 Q_D(QMediaPlayer);
761 auto oldOutput = d->audioOutput;
762 if (oldOutput == output)
763 return;
764 d->audioOutput = output;
765 if (d->control)
766 d->control->setAudioOutput(nullptr);
767 if (oldOutput)
768 oldOutput->setDisconnectFunction({});
769 if (output) {
770 output->setDisconnectFunction([this](){ setAudioOutput(nullptr); });
771 if (d->control)
772 d->control->setAudioOutput(output->handle());
773 }
774 emit audioOutputChanged();
775}
776
777QAudioOutput *QMediaPlayer::audioOutput() const
778{
779 Q_D(const QMediaPlayer);
780 return d->audioOutput;
781}
782
783/*!
784 \qmlproperty list<mediaMetaData> QtMultimedia::MediaPlayer::audioTracks
785
786 This property holds a list of metadata.
787 Each index refers to an audio track.
788
789 The metadata holds properties describing the individual tracks. For
790 audio tracks the \l{QMediaMetaData}{Language} is usually the most
791 important property.
792
793 \sa mediaMetaData
794*/
795
796/*!
797 \property QMediaPlayer::audioTracks
798
799 Lists the set of available audio tracks inside the media.
800
801 The QMediaMetaData returned describes the properties of individual
802 tracks.
803
804 Different audio tracks can for example contain audio in different languages.
805*/
806QList<QMediaMetaData> QMediaPlayer::audioTracks() const
807{
808 Q_D(const QMediaPlayer);
809 return d->trackMetaData(s: QPlatformMediaPlayer::AudioStream);
810}
811
812/*!
813 \qmlproperty list<mediaMetaData> QtMultimedia::MediaPlayer::videoTracks
814
815 This property holds a list of metadata.
816 Each index refers to a video track.
817
818 The metadata holds properties describing the individual tracks.
819
820 \sa mediaMetaData
821*/
822
823/*!
824 \property QMediaPlayer::videoTracks
825
826 Lists the set of available video tracks inside the media.
827
828 The QMediaMetaData returned describes the properties of individual
829 tracks.
830*/
831QList<QMediaMetaData> QMediaPlayer::videoTracks() const
832{
833 Q_D(const QMediaPlayer);
834 return d->trackMetaData(s: QPlatformMediaPlayer::VideoStream);
835}
836
837/*!
838 \qmlproperty list<mediaMetaData> QtMultimedia::MediaPlayer::subtitleTracks
839
840 This property holds a list of metadata.
841 Each index refers to a subtitle track.
842
843 The metadata holds properties describing the individual tracks. For
844 subtitle tracks the \l{QMediaMetaData}{Language} is usually the most
845 important property.
846
847 \sa mediaMetaData
848*/
849
850/*!
851 \property QMediaPlayer::subtitleTracks
852
853 Lists the set of available subtitle tracks inside the media.
854
855 The QMediaMetaData returned describes the properties of individual
856 tracks.
857*/
858QList<QMediaMetaData> QMediaPlayer::subtitleTracks() const
859{
860 Q_D(const QMediaPlayer);
861 return d->trackMetaData(s: QPlatformMediaPlayer::SubtitleStream);
862}
863
864/*!
865 \qmlproperty int QtMultimedia::MediaPlayer::activeAudioTrack
866
867 This property holds the track number of the currently active audio track.
868 Set to \c{-1} to disable audio track.
869
870 The default property value is \c{0}: the first audio track.
871*/
872
873/*!
874 \property QMediaPlayer::activeAudioTrack
875 \brief Returns the currently active audio track.
876
877 By default, the first available audio track will be chosen.
878
879 Set \a index to \c -1 to disable all audio tracks.
880*/
881int QMediaPlayer::activeAudioTrack() const
882{
883 Q_D(const QMediaPlayer);
884 return d->control ? d->control->activeTrack(QPlatformMediaPlayer::AudioStream) : 0;
885}
886
887/*!
888 \since 6.2
889 \qmlproperty int QtMultimedia::MediaPlayer::activeVideoTrack
890
891 This property holds the track number of the currently active video audio track.
892 Set to \c{-1} to disable video track.
893
894 The default property value is \c{0}: the first video track.
895*/
896
897/*!
898 \property QMediaPlayer::activeVideoTrack
899 \brief Returns the currently active video track.
900
901 By default, the first available audio track will be chosen.
902
903 Set \a index to \c -1 to disable all video tracks.
904*/
905int QMediaPlayer::activeVideoTrack() const
906{
907 Q_D(const QMediaPlayer);
908 return d->control ? d->control->activeTrack(QPlatformMediaPlayer::VideoStream) : -1;
909}
910
911/*!
912 \since 6.2
913 \qmlproperty int QtMultimedia::MediaPlayer::activeSubtitleTrack
914
915 This property holds the track number of the currently active subtitle track.
916 Set to \c{-1} to disable subtitle track.
917
918 The default property value is \c{-1}: no subtitles active.
919*/
920
921/*!
922 \property QMediaPlayer::activeSubtitleTrack
923 \brief Returns the currently active subtitle track.
924
925 Set \a index to \c -1 to disable subtitles.
926
927 Subtitles are disabled by default.
928*/
929int QMediaPlayer::activeSubtitleTrack() const
930{
931 Q_D(const QMediaPlayer);
932 return d->control ? d->control->activeTrack(QPlatformMediaPlayer::SubtitleStream) : -1;
933}
934
935void QMediaPlayer::setActiveAudioTrack(int index)
936{
937 Q_D(QMediaPlayer);
938 if (!d->control)
939 return;
940
941 if (activeAudioTrack() == index)
942 return;
943 d->control->setActiveTrack(QPlatformMediaPlayer::AudioStream, index);
944}
945
946void QMediaPlayer::setActiveVideoTrack(int index)
947{
948 Q_D(QMediaPlayer);
949 if (!d->control)
950 return;
951
952 if (activeVideoTrack() == index)
953 return;
954 d->control->setActiveTrack(QPlatformMediaPlayer::VideoStream, index);
955}
956
957void QMediaPlayer::setActiveSubtitleTrack(int index)
958{
959 Q_D(QMediaPlayer);
960 if (!d->control)
961 return;
962
963 if (activeSubtitleTrack() == index)
964 return;
965 d->control->setActiveTrack(QPlatformMediaPlayer::SubtitleStream, index);
966}
967
968/*!
969 \qmlproperty VideoOutput QtMultimedia::MediaPlayer::videoOutput
970
971 This property holds the target video output.
972 Accepts one VideoOutput elements.
973
974 \sa QMediaPlayer::setVideoOutput()
975*/
976
977/*!
978 \property QMediaPlayer::videoOutput
979 \brief The video output to be used by the media player.
980
981 A media player can only have one video output attached, so
982 setting this property will replace the previously connected
983 video output.
984
985 Setting this property to \c nullptr will disable video output.
986*/
987QObject *QMediaPlayer::videoOutput() const
988{
989 Q_D(const QMediaPlayer);
990 return d->videoOutput;
991}
992
993void QMediaPlayer::setVideoOutput(QObject *output)
994{
995 Q_D(QMediaPlayer);
996 if (d->videoOutput == output)
997 return;
998
999 auto *sink = qobject_cast<QVideoSink *>(object: output);
1000 if (!sink && output) {
1001 auto *mo = output->metaObject();
1002 mo->invokeMethod(obj: output, member: "videoSink", Q_RETURN_ARG(QVideoSink *, sink));
1003 }
1004 d->videoOutput = output;
1005 d->setVideoSink(sink);
1006}
1007
1008/*!
1009 Sets \a sink to be the QVideoSink instance to
1010 retrieve video data.
1011*/
1012void QMediaPlayer::setVideoSink(QVideoSink *sink)
1013{
1014 Q_D(QMediaPlayer);
1015 d->videoOutput = nullptr;
1016 d->setVideoSink(sink);
1017}
1018
1019/*!
1020 Returns the QVideoSink instance.
1021*/
1022QVideoSink *QMediaPlayer::videoSink() const
1023{
1024 Q_D(const QMediaPlayer);
1025 return d->videoSink;
1026}
1027
1028
1029#if 0
1030/*
1031 \since 5.15
1032 Sets multiple video sinks as the video output of a media player.
1033 This allows the media player to render video frames on several outputs.
1034
1035 If a video output has already been set on the media player the new surfaces
1036 will replace it.
1037*/
1038void QMediaPlayer::setVideoOutput(const QList<QVideoSink *> &sinks)
1039{
1040 // ### IMPLEMENT ME
1041 Q_UNUSED(sinks);
1042// setVideoOutput(!surfaces.empty() ? new QVideoSurfaces(surfaces, this) : nullptr);
1043}
1044#endif
1045
1046/*!
1047 Returns true if the media player is supported on this platform.
1048*/
1049bool QMediaPlayer::isAvailable() const
1050{
1051 Q_D(const QMediaPlayer);
1052 return bool(d->control);
1053}
1054
1055/*!
1056 \qmlproperty mediaMetaData QtMultimedia::MediaPlayer::metaData
1057
1058 Returns meta data for the current media used by the media player.
1059
1060 Meta data can contain information such as the title of the video or its creation date.
1061
1062 \note The Windows implementation provides metadata only for media located on the local file
1063 system.
1064*/
1065
1066/*!
1067 \property QMediaPlayer::metaData
1068
1069 Returns meta data for the current media used by the media player.
1070
1071 Meta data can contain information such as the title of the video or its creation date.
1072
1073 \note The Windows implementation provides metadata only for media located on the local file
1074 system.
1075*/
1076QMediaMetaData QMediaPlayer::metaData() const
1077{
1078 Q_D(const QMediaPlayer);
1079 return d->control ? d->control->metaData() : QMediaMetaData{};
1080}
1081
1082/*!
1083 \qmlproperty bool QtMultimedia::MediaPlayer::pitchCompensation
1084 \since 6.10
1085
1086 This property holds whether pitch compensation is enabled.
1087*/
1088
1089/*!
1090 \property QMediaPlayer::pitchCompensation
1091 \brief The pitch compensation status of the media player.
1092 \since 6.10
1093
1094 Indicates whether pitch compensation is enabled. When enabled, changing the playback rate
1095 will not affect the pitch of the audio signal.
1096
1097 \note The pitch compensation will increase the CPU load of the QMediaPlayer.
1098
1099 By default is \c{true} if pitch compensation, is available, else \c{false}.
1100*/
1101
1102/*!
1103 Returns the state of pitch compensation.
1104 \since 6.10
1105*/
1106bool QMediaPlayer::pitchCompensation() const
1107{
1108 Q_D(const QMediaPlayer);
1109 return d->control ? d->control->pitchCompensation() : false;
1110}
1111
1112/*!
1113 Sets the state (\a enabled or disabled) of pitch compensation. This only
1114 has an effect if the audio pitch compensation can be configured on the
1115 backend at runtime.
1116 \since 6.10
1117*/
1118void QMediaPlayer::setPitchCompensation(bool enabled) const
1119{
1120 Q_D(const QMediaPlayer);
1121 if (d->control)
1122 d->control->setPitchCompensation(enabled);
1123}
1124
1125/*!
1126 \enum QMediaPlayer::PitchCompensationAvailability
1127 \since 6.10
1128
1129 Availablility of pitch compensation.
1130
1131 Different backends have different behavior regarding pitch compensation when changing
1132 playback rate.
1133
1134 \value AlwaysOn The media player is always performing pitch compensation.
1135 \value Available The media player can be configured to use pitch compensation.
1136 If pitch compensation is available on the current platform, it will be enabled by default,
1137 but users can disable if needed.
1138 \value Unavailable The media player is not able to perform pitch compensation
1139 on the current platform.
1140*/
1141
1142/*!
1143 \qmlproperty enumeration QtMultimedia::MediaPlayer::pitchCompensationAvailability
1144 \since 6.10
1145
1146 Indicates the availability of pitch compensation of the \c MediaPlayer on the current backend.
1147 The enumeration \c PitchCompensationAvailability is scoped.
1148
1149 \qmlenumeratorsfrom QMediaPlayer::PitchCompensationAvailability
1150*/
1151
1152/*!
1153 \property QMediaPlayer::pitchCompensationAvailability
1154 \brief The pitch compensation availability of the current QtMultimedia backend.
1155 \since 6.10
1156
1157 Indicates the availability of pitch compensation of the QMediaPlayer on the current backend.
1158
1159 \note Different backends may have different behavior.
1160
1161 For more information, see \l{QMediaPlayer::PitchCompensationAvailability}.
1162*/
1163
1164/*!
1165 Returns availability of pitch compensation of the current backend.
1166 \since 6.10
1167*/
1168
1169QMediaPlayer::PitchCompensationAvailability QMediaPlayer::pitchCompensationAvailability() const
1170{
1171 Q_D(const QMediaPlayer);
1172 return d->control->pitchCompensationAvailability();
1173}
1174
1175/*!
1176 \qmlproperty playbackOptions MediaPlayer::playbackOptions
1177 \since 6.10
1178
1179 This property exposes the \l playbackOptions API that gives low-level control of media playback
1180 options. Although we strongly recommend to rely on the default settings of \l MediaPlayer,
1181 this API can be used to optimize media playback for specific use cases where the default
1182 options are not ideal.
1183
1184 Playback options take effect the next time \l MediaPlayer::source is changed.
1185*/
1186
1187/*!
1188 \property QMediaPlayer::playbackOptions
1189 \brief Advanced playback options used to configure media playback and decoding.
1190 \since 6.10
1191
1192 This property exposes the \l QPlaybackOptions API that gives low-level control of media
1193 playback options. Although we strongly recommend to rely on the default settings of
1194 \l QMediaPlayer, this API can be used to optimize media playback for specific use cases where
1195 the default options are not ideal.
1196
1197 Playback options take effect the next time \l QMediaPlayer::setSource() is called.
1198*/
1199
1200QPlaybackOptions QMediaPlayer::playbackOptions() const
1201{
1202 Q_D(const QMediaPlayer);
1203 return d->playbackOptions;
1204}
1205
1206void QMediaPlayer::setPlaybackOptions(const QPlaybackOptions &options)
1207{
1208 Q_D(QMediaPlayer);
1209 if (std::exchange(obj&: d->playbackOptions, new_val: options) != options)
1210 emit playbackOptionsChanged();
1211}
1212
1213void QMediaPlayer::resetPlaybackOptions()
1214{
1215 Q_D(QMediaPlayer);
1216 QPlaybackOptions defaultOptions{ };
1217 if (std::exchange(obj&: d->playbackOptions, new_val&: defaultOptions) != defaultOptions)
1218 emit playbackOptionsChanged();
1219}
1220
1221// Enums
1222/*!
1223 \enum QMediaPlayer::PlaybackState
1224
1225 Defines the current state of a media player.
1226
1227 \value StoppedState The media player is not playing content, playback will begin from the start
1228 of the current track.
1229 \value PlayingState The media player is currently playing content. This indicates the same as the \l playing property.
1230 \value PausedState The media player has paused playback, playback of the current track will
1231 resume from the position the player was paused at.
1232*/
1233
1234/*!
1235 \qmlproperty enumeration QtMultimedia::MediaPlayer::playbackState
1236
1237 This property holds the state of media playback. It can be one of the following:
1238
1239 \table
1240 \header \li Property value
1241 \li Description
1242 \row \li PlayingState
1243 \li The media is currently playing. This indicates the same as the \l playing property.
1244 \row \li PausedState
1245 \li Playback of the media has been suspended.
1246 \row \li StoppedState
1247 \li Playback of the media is yet to begin.
1248 \endtable
1249*/
1250
1251/*!
1252 \qmlsignal QtMultimedia::MediaPlayer::playbackStateChanged()
1253
1254 This signal is emitted when the \l playbackState property is altered.
1255*/
1256
1257/*!
1258 \qmlsignal QtMultimedia::MediaPlayer::playingChanged()
1259
1260 This signal is emitted when the \l playing property changes.
1261*/
1262
1263/*!
1264 \enum QMediaPlayer::MediaStatus
1265
1266 Defines the status of a media player's current media.
1267
1268 \value NoMedia The is no current media. The player is in the StoppedState.
1269 \value LoadingMedia The current media is being loaded. The player may be in any state.
1270 \value LoadedMedia The current media has been loaded. The player is in the StoppedState.
1271 \value StalledMedia Playback of the current media has stalled due to insufficient buffering or
1272 some other temporary interruption. The player is in the PlayingState or PausedState.
1273 \value BufferingMedia The player is buffering data but has enough data buffered for playback to
1274 continue for the immediate future. The player is in the PlayingState or PausedState.
1275 \value BufferedMedia The player has fully buffered the current media. The player is in the
1276 PlayingState or PausedState.
1277 \value EndOfMedia Playback has reached the end of the current media. The player is in the
1278 StoppedState.
1279 \value InvalidMedia The current media cannot be played. The player is in the StoppedState.
1280*/
1281
1282/*!
1283 \qmlproperty enumeration QtMultimedia::MediaPlayer::mediaStatus
1284
1285 This property holds the status of media loading. It can be one of the following:
1286
1287 \table
1288 \header
1289 \li Property value
1290 \li Description
1291 \row \li NoMedia
1292 \li No media has been set.
1293 \row \li LoadingMedia
1294 \li The media is currently being loaded.
1295 \row \li LoadedMedia
1296 \li The media has been loaded.
1297 \row \li BufferingMedia
1298 \li The media is buffering data.
1299 \row \li StalledMedia
1300 \li Playback has been interrupted while the media is buffering data.
1301 \row \li BufferedMedia
1302 \li The media has buffered data.
1303 \row \li EndOfMedia
1304 \li The media has played to the end.
1305 \row \li InvalidMedia
1306 \li The media cannot be played.
1307 \endtable
1308*/
1309
1310/*!
1311 \qmlproperty enumeration QtMultimedia::MediaPlayer::error
1312
1313 This property holds the error state of the audio. It can be one of the following.
1314
1315 \table
1316 \header \li Value \li Description
1317 \row \li NoError
1318 \li There is no current error.
1319 \row \li ResourceError
1320 \li The audio cannot be played due to a problem allocating resources.
1321 \row \li FormatError
1322 \li The audio format is not supported.
1323 \row \li NetworkError
1324 \li The audio cannot be played due to network issues.
1325 \row \li AccessDeniedError
1326 \li The audio cannot be played due to insufficient permissions.
1327 \endtable
1328*/
1329
1330/*!
1331 \enum QMediaPlayer::Error
1332
1333 Defines a media player error condition.
1334
1335 \value NoError No error has occurred.
1336 \value ResourceError A media resource couldn't be resolved.
1337 \value FormatError The format of a media resource isn't (fully) supported. Playback may still
1338 be possible, but without an audio or video component.
1339 \value NetworkError A network error occurred.
1340 \value AccessDeniedError There are not the appropriate permissions to play a media resource.
1341*/
1342
1343/*!
1344 \qmlsignal QtMultimedia::MediaPlayer::errorOccurred(error, errorString)
1345
1346 This signal is emitted when an \a error has occurred. The \a errorString
1347 parameter may contain more detailed information about the error.
1348
1349 \sa QMediaPlayer::Error
1350*/
1351
1352/*!
1353 \fn QMediaPlayer::errorOccurred(QMediaPlayer::Error error, const QString &errorString)
1354
1355 Signals that an \a error condition has occurred, with \a errorString
1356 containing a description of the error.
1357
1358 \sa errorString()
1359*/
1360
1361/*!
1362 \fn QMediaPlayer::mediaStatusChanged(QMediaPlayer::MediaStatus status)
1363
1364 Signals that the \a status of the current media has changed.
1365
1366 \sa mediaStatus()
1367*/
1368
1369/*!
1370 \fn void QMediaPlayer::sourceChanged(const QUrl &media);
1371
1372 Signals that the media source has been changed to \a media.
1373*/
1374
1375/*!
1376 \fn void QMediaPlayer::playbackRateChanged(qreal rate);
1377
1378 Signals the playbackRate has changed to \a rate.
1379*/
1380
1381/*!
1382 \fn void QMediaPlayer::seekableChanged(bool seekable);
1383
1384 Signals the \a seekable status of the player object has changed.
1385*/
1386
1387// Properties
1388/*!
1389 \property QMediaPlayer::error
1390 \brief a string describing the last error condition.
1391
1392 \sa error()
1393*/
1394
1395/*!
1396 \property QMediaPlayer::source
1397 \brief the active media source being used by the player object.
1398
1399 The player object will use the QUrl for selection of the content to
1400 be played.
1401
1402 By default this property has a null QUrl.
1403
1404 Setting this property to a null QUrl will cause the player to discard all
1405 information relating to the current media source and to cease all I/O operations related
1406 to that media.
1407
1408 \sa QUrl
1409*/
1410
1411/*!
1412 \property QMediaPlayer::mediaStatus
1413 \brief the status of the current media stream.
1414
1415 The stream status describes how the playback of the current stream is
1416 progressing.
1417
1418 By default this property is QMediaPlayer::NoMedia
1419
1420*/
1421
1422/*!
1423 \qmlproperty int QtMultimedia::MediaPlayer::duration
1424
1425 This property holds the duration of the media in milliseconds.
1426
1427 If the media doesn't have a fixed duration (a live stream for example) this
1428 will be set to \c{0}.
1429*/
1430
1431/*!
1432 \property QMediaPlayer::duration
1433 \brief the duration of the current media.
1434
1435 The value is the total playback time in milliseconds of the current media.
1436 The value may change across the life time of the QMediaPlayer object and
1437 may not be available when initial playback begins, connect to the
1438 durationChanged() signal to receive status notifications.
1439*/
1440
1441/*!
1442 \qmlproperty int QtMultimedia::MediaPlayer::position
1443
1444 The value is the current playback position, expressed in milliseconds since
1445 the beginning of the media. Periodically changes in the position will be
1446 indicated with the positionChanged() signal.
1447
1448 If the \l seekable property is true, this property can be set to milliseconds.
1449*/
1450
1451/*!
1452 \property QMediaPlayer::position
1453 \brief the playback position of the current media.
1454
1455 The value is the current playback position, expressed in milliseconds since
1456 the beginning of the media. Periodically changes in the position will be
1457 indicated with the positionChanged() signal.
1458
1459 If the \l seekable property is true, this property can be set to milliseconds.
1460*/
1461
1462/*!
1463 \qmlproperty real QtMultimedia::MediaPlayer::bufferProgress
1464
1465 This property holds how much of the data buffer is currently filled,
1466 from \c 0.0 (empty) to \c 1.0 (full).
1467
1468 Playback can start or resume only when the buffer is entirely filled.
1469 When the buffer is filled, \c MediaPlayer.Buffered is true.
1470 When buffer progress is between \c 0.0 and \c 1.0, \c MediaPlayer.Buffering
1471 is set to \c{true}.
1472
1473 A value lower than \c 1.0 implies that the property \c MediaPlayer.StalledMedia
1474 is \c{true}.
1475
1476 \sa mediaStatus
1477 */
1478
1479/*!
1480 \property QMediaPlayer::bufferProgress
1481 \brief the percentage of the temporary buffer filled before playback begins or resumes, from
1482 \c 0. (empty) to \c 1. (full).
1483
1484 When the player object is buffering; this property holds the percentage of
1485 the temporary buffer that is filled. The buffer will need to reach 100%
1486 filled before playback can start or resume, at which time mediaStatus() will return
1487 BufferedMedia or BufferingMedia. If the value is anything lower than \c 100, mediaStatus() will
1488 return StalledMedia.
1489
1490 \sa mediaStatus()
1491*/
1492
1493/*!
1494 \qmlproperty bool QtMultimedia::MediaPlayer::seekable
1495
1496 This property holds whether the \l position of the media can be changed.
1497*/
1498
1499/*!
1500 \property QMediaPlayer::seekable
1501 \brief the seek-able status of the current media
1502
1503 If seeking is supported this property will be true; false otherwise. The
1504 status of this property may change across the life time of the QMediaPlayer
1505 object, use the seekableChanged signal to monitor changes.
1506*/
1507
1508/*!
1509 \qmlproperty bool QtMultimedia::MediaPlayer::playing
1510 \since 6.5
1511
1512 Indicates whether the media is currently playing.
1513
1514 \sa playbackState
1515*/
1516
1517/*!
1518 \property QMediaPlayer::playing
1519 \brief Whether the media is playing.
1520 \since 6.5
1521
1522 \sa playbackState, PlayingState
1523*/
1524
1525/*!
1526 \qmlproperty real QtMultimedia::MediaPlayer::playbackRate
1527
1528 This property holds the rate at which media is played at as a multiple of
1529 the normal rate.
1530
1531 For more information, see \l{QMediaPlayer::playbackRate}.
1532
1533 Defaults to \c{1.0}.
1534*/
1535
1536/*!
1537 \property QMediaPlayer::playbackRate
1538 \brief the playback rate of the current media.
1539
1540 This value is a multiplier applied to the media's standard playback
1541 rate. By default this value is 1.0, indicating that the media is
1542 playing at the standard speed. Values higher than 1.0 will increase
1543 the playback speed, while values between 0.0 and 1.0 results in
1544 slower playback. Negative playback rates are not supported.
1545
1546 Not all playback services support change of the playback rate. It is
1547 framework defined as to the status and quality of audio and video
1548 while fast forwarding or rewinding.
1549*/
1550
1551/*!
1552 \fn void QMediaPlayer::durationChanged(qint64 duration)
1553
1554 Signals the duration of the content has changed to \a duration, expressed in milliseconds.
1555*/
1556
1557/*!
1558 \fn void QMediaPlayer::positionChanged(qint64 position)
1559
1560 Signals the position of the content has changed to \a position, expressed in
1561 milliseconds.
1562*/
1563
1564/*!
1565 \fn void QMediaPlayer::hasVideoChanged(bool videoAvailable)
1566
1567 Signals the availability of visual content has changed to \a videoAvailable.
1568*/
1569
1570/*!
1571 \fn void QMediaPlayer::hasAudioChanged(bool available)
1572
1573 Signals the availability of audio content has changed to \a available.
1574*/
1575
1576/*!
1577 \fn void QMediaPlayer::bufferProgressChanged(float filled)
1578
1579 Signals the amount of the local buffer \a filled as a number between 0 and 1.
1580*/
1581
1582QT_END_NAMESPACE
1583
1584#include "moc_qmediaplayer.cpp"
1585

source code of qtmultimedia/src/multimedia/playback/qmediaplayer.cpp