Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qandroidmediaplayer.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
9#include "qaudiooutput.h"
10
11#include <qloggingcategory.h>
12
14
15static Q_LOGGING_CATEGORY(lcMediaPlayer, "qt.multimedia.mediaplayer.android")
16
17class StateChangeNotifier
18{
19public:
20 StateChangeNotifier(QAndroidMediaPlayer *mp)
21 : mControl(mp)
22 , mPreviousState(mp->state())
23 , mPreviousMediaStatus(mp->mediaStatus())
24 {
25 ++mControl->mActiveStateChangeNotifiers;
26 }
27
28 ~StateChangeNotifier()
29 {
30 if (--mControl->mActiveStateChangeNotifiers)
31 return;
32
33 if (mPreviousMediaStatus != mControl->mediaStatus())
34 Q_EMIT mControl->mediaStatusChanged(mControl->mediaStatus());
35
36 if (mPreviousState != mControl->state())
37 Q_EMIT mControl->stateChanged(mControl->state());
38 }
39
40private:
41 QAndroidMediaPlayer *mControl;
42 QMediaPlayer::PlaybackState mPreviousState;
43 QMediaPlayer::MediaStatus mPreviousMediaStatus;
44};
45
48 mMediaPlayer(new AndroidMediaPlayer),
50{
51 // Set seekable to True by default. It changes if MEDIA_INFO_NOT_SEEKABLE is received
52 seekableChanged(true);
54 &QAndroidMediaPlayer::onBufferingChanged);
55 connect(mMediaPlayer, &AndroidMediaPlayer::info, this, &QAndroidMediaPlayer::onInfo);
56 connect(mMediaPlayer, &AndroidMediaPlayer::error, this, &QAndroidMediaPlayer::onError);
57 connect(mMediaPlayer, &AndroidMediaPlayer::stateChanged, this,
58 &QAndroidMediaPlayer::onStateChanged);
60 &QAndroidMediaPlayer::onVideoSizeChanged);
62 &QAndroidMediaPlayer::positionChanged);
64 &QAndroidMediaPlayer::durationChanged);
66 &QAndroidMediaPlayer::updateTrackInfo);
67}
68
70{
71 mMediaPlayer->disconnect();
72 mMediaPlayer->release();
73 delete mMediaPlayer;
74}
75
77{
79 return 0;
80
81 if ((mState & (AndroidMediaPlayer::Prepared
86 return 0;
87 }
88
89 return mMediaPlayer->getDuration();
90}
91
93{
95 return duration();
96
97 if ((mState & (AndroidMediaPlayer::Prepared
101 return mMediaPlayer->getCurrentPosition();
102 }
103
104 return (mPendingPosition == -1) ? 0 : mPendingPosition;
105}
106
108{
109 if (!isSeekable())
110 return;
111
112 const int seekPosition = (position > INT_MAX) ? INT_MAX : position;
113
114 qint64 currentPosition = mMediaPlayer->getCurrentPosition();
115 if (seekPosition == currentPosition) {
116 // update position - will send a new frame of this position
117 // for consistency with other platforms
118 mMediaPlayer->seekTo(seekPosition);
119 return;
120 }
122
124 setMediaStatus(QMediaPlayer::LoadedMedia);
125
126 if ((mState & (AndroidMediaPlayer::Prepared
130 mPendingPosition = seekPosition;
131 } else {
132 mMediaPlayer->seekTo(seekPosition);
133
134 if (mPendingPosition != -1) {
135 mPendingPosition = -1;
136 }
137 }
138
139 Q_EMIT positionChanged(seekPosition);
140}
141
142void QAndroidMediaPlayer::setVolume(float volume)
143{
144 if ((mState & (AndroidMediaPlayer::Idle
151 mPendingVolume = volume;
152 return;
153 }
154
155 mMediaPlayer->setVolume(qRound(volume*100.));
156 mPendingVolume = -1;
157}
158
159void QAndroidMediaPlayer::setMuted(bool muted)
160{
161 if ((mState & (AndroidMediaPlayer::Idle
168 mPendingMute = muted;
169 return;
170 }
171
172 mMediaPlayer->setMuted(muted);
173 mPendingMute = -1;
174}
175
177{
178 return QAndroidMetaData::extractMetadata(mMediaContent);
179}
180
182{
183 return mBufferFilled ? 1. : mBufferPercent;
184}
185
187{
188 return mAudioAvailable;
189}
190
192{
193 return mVideoAvailable;
194}
195
197{
198 return mAvailablePlaybackRange;
199}
200
201void QAndroidMediaPlayer::updateAvailablePlaybackRanges()
202{
203 if (mBuffering) {
204 const qint64 pos = position();
205 const qint64 end = (duration() / 100) * mBufferPercent;
206 mAvailablePlaybackRange.addInterval(pos, end);
207 } else if (isSeekable()) {
208 mAvailablePlaybackRange = QMediaTimeRange(0, duration());
209 } else {
210 mAvailablePlaybackRange = QMediaTimeRange();
211 }
212
213// #### Q_EMIT availablePlaybackRangesChanged(mAvailablePlaybackRange);
214}
215
217{
218 return mCurrentPlaybackRate;
219}
220
222{
223 if (mState != AndroidMediaPlayer::Started) {
224 // If video isn't playing, changing speed rate may start it automatically
225 // It need to be postponed
226 if (mCurrentPlaybackRate != rate) {
227 mCurrentPlaybackRate = rate;
228 mHasPendingPlaybackRate = true;
230 }
231 return;
232 }
233
234 if (mMediaPlayer->setPlaybackRate(rate)) {
235 mCurrentPlaybackRate = rate;
237 }
238}
239
241{
242 return mMediaContent;
243}
244
246{
247 return mMediaStream;
248}
249
250void QAndroidMediaPlayer::setMedia(const QUrl &mediaContent,
252{
254
255 mReloadingMedia = (mMediaContent == mediaContent) && !mPendingSetMedia;
256
257 if (!mReloadingMedia) {
258 mMediaContent = mediaContent;
259 mMediaStream = stream;
260 }
261
262 if (mediaContent.isEmpty()) {
263 setMediaStatus(QMediaPlayer::NoMedia);
264 } else {
265 if (mVideoOutput && !mVideoOutput->isReady()) {
266 // if a video output is set but the video texture is not ready, delay loading the media
267 // since it can cause problems on some hardware
268 mPendingSetMedia = true;
269 return;
270 }
271
272 if (mVideoSize.isValid() && mVideoOutput)
273 mVideoOutput->setVideoSize(mVideoSize);
274
275 if (mVideoOutput &&
276 (mMediaPlayer->display() == 0 || mVideoOutput->shouldTextureBeUpdated()))
277 mMediaPlayer->setDisplay(mVideoOutput->surfaceTexture());
278 mMediaPlayer->setDataSource(QNetworkRequest(mediaContent));
279 mMediaPlayer->prepareAsync();
280
281 if (!mReloadingMedia)
282 setMediaStatus(QMediaPlayer::LoadingMedia);
283 }
284
285 resetBufferingProgress();
286
287 mReloadingMedia = false;
288}
289
291{
292 if (m_videoSink == sink)
293 return;
294
295 m_videoSink = sink;
296
297 if (!m_videoSink) {
298 return;
299 }
300
301 if (mVideoOutput) {
302 delete mVideoOutput;
303 mVideoOutput = nullptr;
304 mMediaPlayer->setDisplay(nullptr);
305 }
306
307 mVideoOutput = new QAndroidTextureVideoOutput(sink, this);
309 &QAndroidMediaPlayer::onVideoOutputReady);
310 connect(mMediaPlayer, &AndroidMediaPlayer::timedTextChanged, mVideoOutput,
312
313 if (mVideoOutput->isReady())
314 mMediaPlayer->setDisplay(mVideoOutput->surfaceTexture());
315}
316
318{
319 if (m_audioOutput == output)
320 return;
321 if (m_audioOutput)
322 m_audioOutput->q->disconnect(this);
323 m_audioOutput = static_cast<QAndroidAudioOutput *>(output);
324 if (m_audioOutput) {
326 connect(m_audioOutput->q, &QAudioOutput::volumeChanged, this, &QAndroidMediaPlayer::setVolume);
327 connect(m_audioOutput->q, &QAudioOutput::mutedChanged, this, &QAndroidMediaPlayer::setMuted);
329 }
330}
331
333{
334 if (m_audioOutput)
335 mMediaPlayer->setAudioOutput(m_audioOutput->device.id());
336}
337
339{
341
343
344 // We need to prepare the mediaplayer again.
345 if ((mState & AndroidMediaPlayer::Stopped) && !mMediaContent.isEmpty()) {
346 setMedia(mMediaContent, mMediaStream);
347 }
348
349 if (!mMediaContent.isEmpty())
351
352 if ((mState & (AndroidMediaPlayer::Prepared
356 mPendingState = QMediaPlayer::PlayingState;
357 return;
358 }
359
360 if (mVideoOutput)
361 mVideoOutput->start();
362
364
365 if (mHasPendingPlaybackRate) {
366 mHasPendingPlaybackRate = false;
367 if (mMediaPlayer->setPlaybackRate(mCurrentPlaybackRate))
368 return;
369 mCurrentPlaybackRate = mMediaPlayer->playbackRate();
370 Q_EMIT playbackRateChanged(mCurrentPlaybackRate);
371 }
372
373 mMediaPlayer->play();
374}
375
377{
378 // cannot pause without media
380 return;
381
383
385
386 if ((mState & (AndroidMediaPlayer::Started
391 mPendingState = QMediaPlayer::PausedState;
392 return;
393 }
394
395 const qint64 currentPosition = mMediaPlayer->getCurrentPosition();
396 setPosition(currentPosition);
397
398 mMediaPlayer->pause();
399}
400
402{
404
406
407 if ((mState & (AndroidMediaPlayer::Prepared
413 mPendingState = QMediaPlayer::StoppedState;
414 return;
415 }
416
417 if (mCurrentPlaybackRate != 1.)
418 // Playback rate need to by reapplied
419 mHasPendingPlaybackRate = true;
420
421 if (mVideoOutput)
422 mVideoOutput->stop();
423
424 mMediaPlayer->stop();
425}
426
427void QAndroidMediaPlayer::onInfo(qint32 what, qint32 extra)
428{
430
431 Q_UNUSED(extra);
432 switch (what) {
434 break;
436 // IGNORE
437 break;
439 break;
441 mPendingState = state();
443 setMediaStatus(QMediaPlayer::StalledMedia);
444 break;
447 flushPendingStates();
448 break;
450 break;
452 seekableChanged(false);
453 break;
456 break;
457 }
458}
459
460void QAndroidMediaPlayer::onError(qint32 what, qint32 extra)
461{
463
466
467 switch (what) {
469 errorString = QLatin1String("Error:");
470 break;
472 errorString = QLatin1String("Error: Server died");
474 break;
476 errorString = QLatin1String("Error: Invalid state");
478 break;
479 }
480
481 switch (extra) {
482 case AndroidMediaPlayer::MEDIA_ERROR_IO: // Network OR file error
483 errorString += QLatin1String(" (I/O operation failed)");
485 setMediaStatus(QMediaPlayer::InvalidMedia);
486 break;
488 errorString += QLatin1String(" (Malformed bitstream)");
490 setMediaStatus(QMediaPlayer::InvalidMedia);
491 break;
493 errorString += QLatin1String(" (Unsupported media)");
495 setMediaStatus(QMediaPlayer::InvalidMedia);
496 break;
498 errorString += QLatin1String(" (Timed out)");
499 break;
501 errorString += QLatin1String(" (Unable to start progressive playback')");
503 setMediaStatus(QMediaPlayer::InvalidMedia);
504 break;
506 errorString += mMediaContent.scheme() == QLatin1String("rtsp")
507 ? QLatin1String(" (Unknown error/Insufficient resources or RTSP may not be supported)")
508 : QLatin1String(" (Unknown error/Insufficient resources)");
510 break;
511 }
512
514}
515
516void QAndroidMediaPlayer::onBufferingChanged(qint32 percent)
517{
519
520 mBuffering = percent != 100;
521 mBufferPercent = percent;
522
523 updateAvailablePlaybackRanges();
524
526 setMediaStatus(mBuffering ? QMediaPlayer::BufferingMedia : QMediaPlayer::BufferedMedia);
527
528 updateBufferStatus();
529}
530
531void QAndroidMediaPlayer::onVideoSizeChanged(qint32 width, qint32 height)
532{
533 QSize newSize(width, height);
534
535 if (width == 0 || height == 0 || newSize == mVideoSize)
536 return;
537
538 setVideoAvailable(true);
539 mVideoSize = newSize;
540
541 if (mVideoOutput)
542 mVideoOutput->setVideoSize(mVideoSize);
543}
544
545void QAndroidMediaPlayer::onStateChanged(qint32 state)
546{
547 // If reloading, don't report state changes unless the new state is Prepared or Error.
548 if ((mState & AndroidMediaPlayer::Stopped)
550 return;
551 }
552
554
555 mState = state;
556 switch (mState) {
558 break;
560 break;
562 if (!mReloadingMedia)
563 setMediaStatus(QMediaPlayer::LoadingMedia);
564 break;
566 setMediaStatus(QMediaPlayer::LoadedMedia);
567 if (mBuffering) {
568 setMediaStatus(mBufferPercent == 100 ? QMediaPlayer::BufferedMedia
569 : QMediaPlayer::BufferingMedia);
570 } else {
571 onBufferingChanged(100);
572 }
573 setPosition(0);
575 setAudioAvailable(true);
576 flushPendingStates();
577 break;
580 if (mBuffering) {
581 setMediaStatus(mBufferPercent == 100 ? QMediaPlayer::BufferedMedia
582 : QMediaPlayer::BufferingMedia);
583 } else {
584 setMediaStatus(QMediaPlayer::BufferedMedia);
585 }
586 Q_EMIT positionChanged(position());
587 break;
591 setPosition(0);
592 setMediaStatus(QMediaPlayer::BufferedMedia);
593 } else {
594 Q_EMIT positionChanged(position());
595 }
596 break;
599 setMediaStatus(QMediaPlayer::InvalidMedia);
600 mMediaPlayer->release();
601 Q_EMIT positionChanged(0);
602 break;
605 setMediaStatus(QMediaPlayer::LoadedMedia);
606 Q_EMIT positionChanged(0);
607 break;
609 if (doLoop()) {
610 setPosition(0);
611 mMediaPlayer->play();
612 break;
613 }
615 setMediaStatus(QMediaPlayer::EndOfMedia);
616 break;
618 // reset some properties (unless we reload the same media)
619 if (!mReloadingMedia) {
620 resetBufferingProgress();
621 mPendingPosition = -1;
622 mPendingSetMedia = false;
623 mPendingState = -1;
624
625 Q_EMIT durationChanged(0);
626 Q_EMIT positionChanged(0);
627
628 setAudioAvailable(false);
629 setVideoAvailable(false);
630 seekableChanged(true);
631 }
632 break;
633 default:
634 break;
635 }
636
638 mMediaPlayer->setDisplay(0);
639 if (mVideoOutput) {
640 mVideoOutput->stop();
641 mVideoOutput->reset();
642 }
643 }
644}
645
647{
648 if (!mTracksMetadata.contains(trackType))
649 return -1;
650
651 auto tracks = mTracksMetadata.value(trackType);
652 return tracks.count();
653}
654
656{
657 if (!mTracksMetadata.contains(trackType))
658 return QMediaMetaData();
659
660 auto tracks = mTracksMetadata.value(trackType);
661 if (tracks.count() < streamNumber)
662 return QMediaMetaData();
663
664 QAndroidMetaData trackInfo = tracks.at(streamNumber);
665 return static_cast<QMediaMetaData>(trackInfo);
666}
667
669{
670 switch (type) {
682 }
683
685}
686
687int QAndroidMediaPlayer::convertTrackNumber(int androidTrackNumber)
688{
689 int trackNumber = androidTrackNumber;
690
692 if (trackNumber <= videoTrackCount)
693 return trackNumber;
694
695 trackNumber = trackNumber - videoTrackCount;
696
698 if (trackNumber <= audioTrackCount)
699 return trackNumber;
700
701 trackNumber = trackNumber - audioTrackCount;
702
703 auto subtitleTracks = mTracksMetadata.value(QPlatformMediaPlayer::TrackType::SubtitleStream);
704 int timedTextCount = 0;
705 int subtitleTextCount = 0;
706 for (const auto &track : subtitleTracks) {
707 if (track.androidTrackType() == 3) // 3 == TimedText
708 timedTextCount++;
709
710 if (track.androidTrackType() == 4) // 4 == Subtitle
711 subtitleTextCount++;
712 }
713
714 if (trackNumber <= timedTextCount)
715 return trackNumber;
716
717 trackNumber = trackNumber - timedTextCount;
718
719 if (trackNumber <= subtitleTextCount)
720 return trackNumber;
721
722 return -1;
723}
724
726{
727 int androidTrackNumber = -1;
728
729 switch (trackType) {
731 if (!mIsVideoTrackEnabled)
732 return -1;
733 androidTrackNumber = mMediaPlayer->activeTrack(AndroidMediaPlayer::TrackType::Video);
734 }
736 if (!mIsAudioTrackEnabled)
737 return -1;
738
739 androidTrackNumber = mMediaPlayer->activeTrack(AndroidMediaPlayer::TrackType::Audio);
740 }
742 int timedTextSelectedTrack =
744
745 if (timedTextSelectedTrack > -1) {
746 androidTrackNumber = timedTextSelectedTrack;
747 break;
748 }
749
750 int subtitleSelectedTrack =
752 if (subtitleSelectedTrack > -1) {
753 androidTrackNumber = subtitleSelectedTrack;
754 break;
755 }
756
757 return -1;
758 }
760 return -1;
761 }
762
763 return convertTrackNumber(androidTrackNumber);
764}
765
766void QAndroidMediaPlayer::disableTrack(TrackType trackType)
767{
768 const auto track = activeTrack(trackType);
769
770 switch (trackType) {
771 case VideoStream: {
772 if (track > -1) {
773 mMediaPlayer->setDisplay(nullptr);
774 mIsVideoTrackEnabled = false;
775 }
776 break;
777 }
778 case AudioStream: {
779 if (track > -1) {
780 mMediaPlayer->setMuted(true);
781 mMediaPlayer->blockAudio();
782 mIsAudioTrackEnabled = false;
783 }
784 break;
785 }
786 case SubtitleStream: {
787 // subtitles and timedtext tracks can be selected at the same time so deselect both
788 int subtitleSelectedTrack =
790 if (subtitleSelectedTrack > -1)
791 mMediaPlayer->deselectTrack(subtitleSelectedTrack);
792
793 int timedTextSelectedTrack =
795 if (timedTextSelectedTrack > -1)
796 mMediaPlayer->deselectTrack(timedTextSelectedTrack);
797
798 break;
799 }
800 case NTrackTypes:
801 break;
802 }
803}
804
805void QAndroidMediaPlayer::setActiveTrack(TrackType trackType, int streamNumber)
806{
807
808 if (!mTracksMetadata.contains(trackType)) {
809 qCWarning(lcMediaPlayer)
810 << "Trying to set a active track which type has no available tracks.";
811 return;
812 }
813
814 const auto &tracks = mTracksMetadata.value(trackType);
815 if (streamNumber > tracks.count()) {
816 qCWarning(lcMediaPlayer) << "Trying to set a active track that does not exist.";
817 return;
818 }
819
820 // in case of < 0 deselect tracktype
821 if (streamNumber < 0) {
822 disableTrack(trackType);
823 return;
824 }
825
826 const auto currentTrack = activeTrack(trackType);
827 if (streamNumber == currentTrack) {
828 return;
829 }
830
831 if (trackType == TrackType::VideoStream && !mIsVideoTrackEnabled) {
832 // enable video stream
833 mMediaPlayer->setDisplay(mVideoOutput->surfaceTexture());
834 mIsVideoTrackEnabled = true;
835 }
836
837 if (trackType == TrackType::AudioStream && !mIsAudioTrackEnabled) {
838 // enable audio stream
839 mMediaPlayer->unblockAudio();
840 mMediaPlayer->setMuted(false);
841 mIsAudioTrackEnabled = true;
842 }
843
844 if (trackType == TrackType::SubtitleStream) {
845 // subtitles and timedtext tracks can be selected at the same time so deselect both before
846 // selecting a new one
847 disableTrack(TrackType::SubtitleStream);
848 }
849
850 const auto &trackInfo = tracks.at(streamNumber);
851 const auto &trackNumber = trackInfo.androidTrackNumber();
852 mMediaPlayer->selectTrack(trackNumber);
853
855}
856
857void QAndroidMediaPlayer::positionChanged(qint64 position)
858{
860}
861
862void QAndroidMediaPlayer::durationChanged(qint64 duration)
863{
865}
866
867void QAndroidMediaPlayer::onVideoOutputReady(bool ready)
868{
869 if ((mMediaPlayer->display() == 0) && mVideoOutput && ready)
870 mMediaPlayer->setDisplay(mVideoOutput->surfaceTexture());
871
872 flushPendingStates();
873}
874
875void QAndroidMediaPlayer::setMediaStatus(QMediaPlayer::MediaStatus status)
876{
877 mediaStatusChanged(status);
878
879 if (status == QMediaPlayer::NoMedia || status == QMediaPlayer::InvalidMedia) {
880 Q_EMIT durationChanged(0);
882 setAudioAvailable(false);
883 setVideoAvailable(false);
884 }
885
886 if (status == QMediaPlayer::EndOfMedia)
887 Q_EMIT positionChanged(position());
888
889 updateBufferStatus();
890}
891
892void QAndroidMediaPlayer::setAudioAvailable(bool available)
893{
894 if (mAudioAvailable == available)
895 return;
896
897 mAudioAvailable = available;
898 Q_EMIT audioAvailableChanged(mAudioAvailable);
899}
900
901void QAndroidMediaPlayer::setVideoAvailable(bool available)
902{
903 if (mVideoAvailable == available)
904 return;
905
906 if (!available)
907 mVideoSize = QSize();
908
909 mVideoAvailable = available;
910 Q_EMIT videoAvailableChanged(mVideoAvailable);
911}
912
913void QAndroidMediaPlayer::resetBufferingProgress()
914{
915 mBuffering = false;
916 mBufferPercent = 0;
917 mAvailablePlaybackRange = QMediaTimeRange();
918}
919
920void QAndroidMediaPlayer::flushPendingStates()
921{
922 if (mPendingSetMedia) {
923 setMedia(mMediaContent, 0);
924 mPendingSetMedia = false;
925 return;
926 }
927
928 const int newState = mPendingState;
929 mPendingState = -1;
930
931 if (mPendingPosition != -1)
932 setPosition(mPendingPosition);
933 if (mPendingVolume >= 0)
934 setVolume(mPendingVolume);
935 if (mPendingMute != -1)
936 setMuted((mPendingMute == 1));
937
938 switch (newState) {
940 play();
941 break;
943 pause();
944 break;
946 stop();
947 break;
948 default:
949 break;
950 }
951}
952
953void QAndroidMediaPlayer::updateBufferStatus()
954{
955 const auto &status = mediaStatus();
956 bool bufferFilled = (status == QMediaPlayer::BufferedMedia || status == QMediaPlayer::BufferingMedia);
957
958 if (mBufferFilled != bufferFilled)
959 mBufferFilled = bufferFilled;
960
962}
963
964void QAndroidMediaPlayer::updateTrackInfo()
965{
966 const auto &androidTracksInfo = mMediaPlayer->tracksInfo();
967
968 // prepare mTracksMetadata
973
974 for (const auto &androidTrackInfo : androidTracksInfo) {
975
976 const auto &mediaPlayerType = convertTrackType(androidTrackInfo.trackType);
977 auto &tracks = mTracksMetadata[mediaPlayerType];
978
979 const QAndroidMetaData metadata(mediaPlayerType, androidTrackInfo.trackType,
980 androidTrackInfo.trackNumber, androidTrackInfo.mimeType,
981 androidTrackInfo.language);
982 tracks.append(metadata);
983 }
984
986}
987
989
990#include "moc_qandroidmediaplayer_p.cpp"
DarwinBluetooth::LECBManagerNotifier * notifier
void progressChanged(qint64 progress)
void seekTo(qint32 msec)
void deselectTrack(int trackNumber)
void stateChanged(qint32 state)
void selectTrack(int trackNumber)
QList< TrackInfo > tracksInfo()
void setDataSource(const QNetworkRequest &request)
void videoSizeChanged(qint32 width, qint32 height)
void setDisplay(AndroidSurfaceTexture *surfaceTexture)
void bufferingChanged(qint32 percent)
void durationChanged(qint64 duration)
void timedTextChanged(QString text)
void info(qint32 what, qint32 extra)
void error(qint32 what, qint32 extra)
static bool setAudioOutput(const QByteArray &deviceId)
bool setPlaybackRate(qreal rate)
int activeTrack(TrackType trackType)
void setVolume(int volume)
bool isAudioAvailable() const override
void setPlaybackRate(qreal rate) override
const QIODevice * mediaStream() const override
qreal playbackRate() const override
qint64 duration() const override
QMediaMetaData metaData() const override
int activeTrack(TrackType trackType) override
void setVideoSink(QVideoSink *surface) override
bool isVideoAvailable() const override
void setAudioOutput(QPlatformAudioOutput *output) override
int trackCount(TrackType trackType) override
qint64 position() const override
float bufferProgress() const override
void setMedia(const QUrl &mediaContent, QIODevice *stream) override
QUrl media() const override
void setActiveTrack(TrackType trackType, int streamNumber) override
void setPosition(qint64 position) override
QAndroidMediaPlayer(QMediaPlayer *parent=0)
QMediaMetaData trackMetaData(TrackType trackType, int streamNumber) override
QMediaTimeRange availablePlaybackRanges() const override
static QMediaMetaData extractMetadata(const QUrl &url)
void setSubtitle(const QString &subtitle)
void setVideoSize(const QSize &) override
AndroidSurfaceTexture * surfaceTexture() override
void readyChanged(bool)
QByteArray id
\qmlproperty string QtMultimedia::audioDevice::id
void deviceChanged()
void mutedChanged(bool muted)
void volumeChanged(float volume)
\inmodule QtCore \reentrant
Definition qiodevice.h:34
Definition qlist.h:74
T value(const Key &key, const T &defaultValue=T()) const
Definition qmap.h:356
bool contains(const Key &key) const
Definition qmap.h:340
\inmodule QtMultimedia
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...
The QNetworkRequest class holds a request to be sent with QNetworkAccessManager.
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 seekableChanged(bool seekable)
void durationChanged(qint64 duration)
void playbackRateChanged(qreal rate)
void error(int error, const QString &errorString)
virtual bool isSeekable() const
void audioAvailableChanged(bool audioAvailable)
void stateChanged(QMediaPlayer::PlaybackState newState)
void videoAvailableChanged(bool videoAvailable)
void mediaStatusChanged(QMediaPlayer::MediaStatus status)
void bufferProgressChanged(float progress)
\inmodule QtCore
Definition qsize.h:25
constexpr bool isValid() const noexcept
Returns true if both the width and height is equal to or greater than 0; otherwise returns false.
Definition qsize.h:126
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
\inmodule QtCore
Definition qurl.h:94
bool isEmpty() const
Returns true if the URL has no data; otherwise returns false.
Definition qurl.cpp:1888
QString scheme() const
Returns the scheme of the URL.
Definition qurl.cpp:1983
The QVideoSink class represents a generic sink for video data.
Definition qvideosink.h:22
else opt state
[0]
void newState(QList< State > &states, const char *token, const char *lexem, bool pre)
Combined button and popup list for selecting options.
Q_MULTIMEDIA_EXPORT QString errorString(HRESULT hr)
QPlatformMediaPlayer::TrackType convertTrackType(AndroidMediaPlayer::TrackType type)
DBusConnection const char DBusError * error
EGLStreamKHR stream
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:281
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
n void setPosition(void) \n\
GLint GLsizei GLsizei height
GLuint GLuint end
GLint GLsizei width
GLenum type
GLuint GLenum * rate
GLsizei GLenum GLboolean sink
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define Q_EMIT
#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