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
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 <private/qplatformvideosink_p.h>
12#include <qloggingcategory.h>
13
15
16static Q_LOGGING_CATEGORY(lcMediaPlayer, "qt.multimedia.mediaplayer.android")
17
18class StateChangeNotifier
19{
20public:
21 StateChangeNotifier(QAndroidMediaPlayer *mp)
22 : mControl(mp)
23 , mPreviousState(mp->state())
24 , mPreviousMediaStatus(mp->mediaStatus())
25 {
26 ++mControl->mActiveStateChangeNotifiers;
27 }
28
29 ~StateChangeNotifier()
30 {
31 if (--mControl->mActiveStateChangeNotifiers)
32 return;
33
34 if (mPreviousMediaStatus != mControl->mediaStatus())
35 Q_EMIT mControl->mediaStatusChanged(mControl->mediaStatus());
36
37 if (mPreviousState != mControl->state())
38 Q_EMIT mControl->stateChanged(mControl->state());
39 }
40
41private:
42 QAndroidMediaPlayer *mControl;
43 QMediaPlayer::PlaybackState mPreviousState;
44 QMediaPlayer::MediaStatus mPreviousMediaStatus;
45};
46
48 : QPlatformMediaPlayer(parent),
49 mMediaPlayer(new AndroidMediaPlayer),
51{
52 // Set seekable to True by default. It changes if MEDIA_INFO_NOT_SEEKABLE is received
53 seekableChanged(true);
55 &QAndroidMediaPlayer::onBufferingChanged);
56 connect(mMediaPlayer, &AndroidMediaPlayer::info, this, &QAndroidMediaPlayer::onInfo);
57 connect(mMediaPlayer, &AndroidMediaPlayer::error, this, &QAndroidMediaPlayer::onError);
58 connect(mMediaPlayer, &AndroidMediaPlayer::stateChanged, this,
59 &QAndroidMediaPlayer::onStateChanged);
61 &QAndroidMediaPlayer::onVideoSizeChanged);
63 &QAndroidMediaPlayer::positionChanged);
65 &QAndroidMediaPlayer::durationChanged);
67 &QAndroidMediaPlayer::updateTrackInfo);
68}
69
71{
72 if (m_videoSink)
73 disconnect(m_videoSink->platformVideoSink(), nullptr, this, nullptr);
74
75 mMediaPlayer->disconnect();
76 mMediaPlayer->release();
77 delete mMediaPlayer;
78}
79
81{
83 return 0;
84
85 if ((mState & (AndroidMediaPlayer::Prepared
90 return 0;
91 }
92
93 return mMediaPlayer->getDuration();
94}
95
97{
99 return duration();
100
101 if ((mState & (AndroidMediaPlayer::Prepared
105 return mMediaPlayer->getCurrentPosition();
106 }
107
108 return (mPendingPosition == -1) ? 0 : mPendingPosition;
109}
110
112{
113 if (!isSeekable())
114 return;
115
116 const int seekPosition = (position > INT_MAX) ? INT_MAX : position;
117
118 qint64 currentPosition = mMediaPlayer->getCurrentPosition();
119 if (seekPosition == currentPosition) {
120 // update position - will send a new frame of this position
121 // for consistency with other platforms
122 mMediaPlayer->seekTo(seekPosition);
123 return;
124 }
126
128 setMediaStatus(QMediaPlayer::LoadedMedia);
129
130 if ((mState & (AndroidMediaPlayer::Prepared
134 mPendingPosition = seekPosition;
135 } else {
136 mMediaPlayer->seekTo(seekPosition);
137
138 if (mPendingPosition != -1) {
139 mPendingPosition = -1;
140 }
141 }
142
143 Q_EMIT positionChanged(seekPosition);
144}
145
146void QAndroidMediaPlayer::setVolume(float volume)
147{
148 if ((mState & (AndroidMediaPlayer::Idle
155 mPendingVolume = volume;
156 return;
157 }
158
159 mMediaPlayer->setVolume(qRound(volume*100.));
160 mPendingVolume = -1;
161}
162
163void QAndroidMediaPlayer::setMuted(bool muted)
164{
165 if ((mState & (AndroidMediaPlayer::Idle
172 mPendingMute = muted;
173 return;
174 }
175
176 mMediaPlayer->setMuted(muted);
177 mPendingMute = -1;
178}
179
184
186{
187 return mBufferFilled ? 1. : mBufferPercent;
188}
189
191{
192 return mAudioAvailable;
193}
194
196{
197 return mVideoAvailable;
198}
199
201{
202 return mAvailablePlaybackRange;
203}
204
205void QAndroidMediaPlayer::updateAvailablePlaybackRanges()
206{
207 if (mBuffering) {
208 const qint64 pos = position();
209 const qint64 end = (duration() / 100) * mBufferPercent;
210 mAvailablePlaybackRange.addInterval(pos, end);
211 } else if (isSeekable()) {
212 mAvailablePlaybackRange = QMediaTimeRange(0, duration());
213 } else {
214 mAvailablePlaybackRange = QMediaTimeRange();
215 }
216
217// #### Q_EMIT availablePlaybackRangesChanged(mAvailablePlaybackRange);
218}
219
221{
222 return mCurrentPlaybackRate;
223}
224
226{
227 if (mState != AndroidMediaPlayer::Started) {
228 // If video isn't playing, changing speed rate may start it automatically
229 // It need to be postponed
230 if (mCurrentPlaybackRate != rate) {
231 mCurrentPlaybackRate = rate;
232 mHasPendingPlaybackRate = true;
234 }
235 return;
236 }
237
238 if (mMediaPlayer->setPlaybackRate(rate)) {
239 mCurrentPlaybackRate = rate;
241 }
242}
243
245{
246 return mMediaContent;
247}
248
250{
251 return mMediaStream;
252}
253
254void QAndroidMediaPlayer::setMedia(const QUrl &mediaContent,
256{
258
259 mReloadingMedia = (mMediaContent == mediaContent) && !mPendingSetMedia;
260
261 if (!mReloadingMedia) {
262 mMediaContent = mediaContent;
263 mMediaStream = stream;
264 }
265
266 if (mediaContent.isEmpty()) {
267 setMediaStatus(QMediaPlayer::NoMedia);
268 } else {
269 if (mVideoOutput && !mVideoOutput->isReady()) {
270 // if a video output is set but the video texture is not ready, delay loading the media
271 // since it can cause problems on some hardware
272 mPendingSetMedia = true;
273 return;
274 }
275
276 if (mVideoSize.isValid() && mVideoOutput)
277 mVideoOutput->setVideoSize(mVideoSize);
278
279 if (mVideoOutput &&
280 (mMediaPlayer->display() == 0 || mVideoOutput->shouldTextureBeUpdated()))
281 mMediaPlayer->setDisplay(mVideoOutput->surfaceTexture());
282 mMediaPlayer->setDataSource(QNetworkRequest(mediaContent));
283 mMediaPlayer->prepareAsync();
284
285 if (!mReloadingMedia)
286 setMediaStatus(QMediaPlayer::LoadingMedia);
287 }
288
289 resetBufferingProgress();
290
291 mReloadingMedia = false;
292}
293
295{
296 if (m_videoSink == sink)
297 return;
298
299 if (m_videoSink)
300 disconnect(m_videoSink->platformVideoSink(), nullptr, this, nullptr);
301
302 m_videoSink = sink;
303
304 if (!m_videoSink) {
305 return;
306 }
307
308 if (mVideoOutput) {
309 delete mVideoOutput;
310 mVideoOutput = nullptr;
311 mMediaPlayer->setDisplay(nullptr);
312 }
313
314 mVideoOutput = new QAndroidTextureVideoOutput(sink, this);
316 &QAndroidMediaPlayer::onVideoOutputReady);
317 connect(mMediaPlayer, &AndroidMediaPlayer::timedTextChanged, mVideoOutput,
319
320 if (mVideoOutput->isReady())
321 mMediaPlayer->setDisplay(mVideoOutput->surfaceTexture());
322
323 connect(m_videoSink->platformVideoSink(), &QPlatformVideoSink::rhiChanged, this, [&]()
324 { mMediaPlayer->setDisplay(mVideoOutput->surfaceTexture()); });
325}
326
328{
329 if (m_audioOutput == output)
330 return;
331 if (m_audioOutput)
332 m_audioOutput->q->disconnect(this);
333 m_audioOutput = static_cast<QAndroidAudioOutput *>(output);
334 if (m_audioOutput) {
336 connect(m_audioOutput->q, &QAudioOutput::volumeChanged, this, &QAndroidMediaPlayer::setVolume);
337 connect(m_audioOutput->q, &QAudioOutput::mutedChanged, this, &QAndroidMediaPlayer::setMuted);
339 }
340}
341
343{
344 if (m_audioOutput)
345 mMediaPlayer->setAudioOutput(m_audioOutput->device.id());
346}
347
349{
351
353
354 // We need to prepare the mediaplayer again.
355 if ((mState & AndroidMediaPlayer::Stopped) && !mMediaContent.isEmpty()) {
356 setMedia(mMediaContent, mMediaStream);
357 }
358
359 if (!mMediaContent.isEmpty())
361
362 if ((mState & (AndroidMediaPlayer::Prepared
366 mPendingState = QMediaPlayer::PlayingState;
367 return;
368 }
369
370 if (mVideoOutput)
371 mVideoOutput->start();
372
374
375 if (mHasPendingPlaybackRate) {
376 mHasPendingPlaybackRate = false;
377 if (mMediaPlayer->setPlaybackRate(mCurrentPlaybackRate))
378 return;
379 mCurrentPlaybackRate = mMediaPlayer->playbackRate();
380 Q_EMIT playbackRateChanged(mCurrentPlaybackRate);
381 }
382
383 mMediaPlayer->play();
384}
385
387{
388 // cannot pause without media
390 return;
391
393
395
396 if ((mState & (AndroidMediaPlayer::Started
401 mPendingState = QMediaPlayer::PausedState;
402 return;
403 }
404
405 const qint64 currentPosition = mMediaPlayer->getCurrentPosition();
406 setPosition(currentPosition);
407
408 mMediaPlayer->pause();
409}
410
412{
414
416
417 if ((mState & (AndroidMediaPlayer::Prepared
423 mPendingState = QMediaPlayer::StoppedState;
424 return;
425 }
426
427 if (mCurrentPlaybackRate != 1.)
428 // Playback rate need to by reapplied
429 mHasPendingPlaybackRate = true;
430
431 if (mVideoOutput)
432 mVideoOutput->stop();
433
434 mMediaPlayer->stop();
435}
436
437void QAndroidMediaPlayer::onInfo(qint32 what, qint32 extra)
438{
440
441 Q_UNUSED(extra);
442 switch (what) {
444 break;
446 // IGNORE
447 break;
449 break;
451 mPendingState = state();
453 setMediaStatus(QMediaPlayer::StalledMedia);
454 break;
457 flushPendingStates();
458 break;
460 break;
462 seekableChanged(false);
463 break;
466 break;
467 }
468}
469
470void QAndroidMediaPlayer::onError(qint32 what, qint32 extra)
471{
473
476
477 switch (what) {
479 errorString = QLatin1String("Error:");
480 break;
482 errorString = QLatin1String("Error: Server died");
484 break;
486 errorString = QLatin1String("Error: Invalid state");
488 break;
489 }
490
491 switch (extra) {
492 case AndroidMediaPlayer::MEDIA_ERROR_IO: // Network OR file error
493 errorString += QLatin1String(" (I/O operation failed)");
495 setMediaStatus(QMediaPlayer::InvalidMedia);
496 break;
498 errorString += QLatin1String(" (Malformed bitstream)");
500 setMediaStatus(QMediaPlayer::InvalidMedia);
501 break;
503 errorString += QLatin1String(" (Unsupported media)");
505 setMediaStatus(QMediaPlayer::InvalidMedia);
506 break;
508 errorString += QLatin1String(" (Timed out)");
509 break;
511 errorString += QLatin1String(" (Unable to start progressive playback')");
513 setMediaStatus(QMediaPlayer::InvalidMedia);
514 break;
516 errorString += mMediaContent.scheme() == QLatin1String("rtsp")
517 ? QLatin1String(" (Unknown error/Insufficient resources or RTSP may not be supported)")
518 : QLatin1String(" (Unknown error/Insufficient resources)");
520 break;
521 }
522
524}
525
526void QAndroidMediaPlayer::onBufferingChanged(qint32 percent)
527{
529
530 mBuffering = percent != 100;
531 mBufferPercent = percent;
532
533 updateAvailablePlaybackRanges();
534
536 setMediaStatus(mBuffering ? QMediaPlayer::BufferingMedia : QMediaPlayer::BufferedMedia);
537
538 updateBufferStatus();
539}
540
541void QAndroidMediaPlayer::onVideoSizeChanged(qint32 width, qint32 height)
542{
543 QSize newSize(width, height);
544
545 if (width == 0 || height == 0 || newSize == mVideoSize)
546 return;
547
548 setVideoAvailable(true);
549 mVideoSize = newSize;
550
551 if (mVideoOutput)
552 mVideoOutput->setVideoSize(mVideoSize);
553}
554
555void QAndroidMediaPlayer::onStateChanged(qint32 state)
556{
557 // If reloading, don't report state changes unless the new state is Prepared or Error.
558 if ((mState & AndroidMediaPlayer::Stopped)
560 return;
561 }
562
564
565 mState = state;
566 switch (mState) {
568 break;
570 break;
572 if (!mReloadingMedia)
573 setMediaStatus(QMediaPlayer::LoadingMedia);
574 break;
576 setMediaStatus(QMediaPlayer::LoadedMedia);
577 if (mBuffering) {
578 setMediaStatus(mBufferPercent == 100 ? QMediaPlayer::BufferedMedia
579 : QMediaPlayer::BufferingMedia);
580 } else {
581 onBufferingChanged(100);
582 }
583 setPosition(0);
585 setAudioAvailable(true);
586 flushPendingStates();
587 break;
590 if (mBuffering) {
591 setMediaStatus(mBufferPercent == 100 ? QMediaPlayer::BufferedMedia
592 : QMediaPlayer::BufferingMedia);
593 } else {
594 setMediaStatus(QMediaPlayer::BufferedMedia);
595 }
596 Q_EMIT positionChanged(position());
597 break;
601 setPosition(0);
602 setMediaStatus(QMediaPlayer::BufferedMedia);
603 } else {
604 Q_EMIT positionChanged(position());
605 }
606 break;
609 setMediaStatus(QMediaPlayer::InvalidMedia);
610 mMediaPlayer->release();
611 Q_EMIT positionChanged(0);
612 break;
615 setMediaStatus(QMediaPlayer::LoadedMedia);
616 Q_EMIT positionChanged(0);
617 break;
619 if (doLoop()) {
620 setPosition(0);
621 mMediaPlayer->play();
622 break;
623 }
625 setMediaStatus(QMediaPlayer::EndOfMedia);
626 break;
628 // reset some properties (unless we reload the same media)
629 if (!mReloadingMedia) {
630 resetBufferingProgress();
631 mPendingPosition = -1;
632 mPendingSetMedia = false;
633 mPendingState = -1;
634
635 Q_EMIT durationChanged(0);
636 Q_EMIT positionChanged(0);
637
638 setAudioAvailable(false);
639 setVideoAvailable(false);
640 seekableChanged(true);
641 }
642 break;
643 default:
644 break;
645 }
646
648 mMediaPlayer->setDisplay(0);
649 if (mVideoOutput) {
650 mVideoOutput->stop();
651 }
652 }
653}
654
656{
657 if (!mTracksMetadata.contains(trackType))
658 return -1;
659
660 auto tracks = mTracksMetadata.value(trackType);
661 return tracks.count();
662}
663
665{
666 if (!mTracksMetadata.contains(trackType))
667 return QMediaMetaData();
668
669 auto tracks = mTracksMetadata.value(trackType);
670 if (tracks.count() < streamNumber)
671 return QMediaMetaData();
672
673 QAndroidMetaData trackInfo = tracks.at(streamNumber);
674 return static_cast<QMediaMetaData>(trackInfo);
675}
676
695
696int QAndroidMediaPlayer::convertTrackNumber(int androidTrackNumber)
697{
698 int trackNumber = androidTrackNumber;
699
701 if (trackNumber <= videoTrackCount)
702 return trackNumber;
703
704 trackNumber = trackNumber - videoTrackCount;
705
707 if (trackNumber <= audioTrackCount)
708 return trackNumber;
709
710 trackNumber = trackNumber - audioTrackCount;
711
712 auto subtitleTracks = mTracksMetadata.value(QPlatformMediaPlayer::TrackType::SubtitleStream);
713 int timedTextCount = 0;
714 int subtitleTextCount = 0;
715 for (const auto &track : subtitleTracks) {
716 if (track.androidTrackType() == 3) // 3 == TimedText
717 timedTextCount++;
718
719 if (track.androidTrackType() == 4) // 4 == Subtitle
720 subtitleTextCount++;
721 }
722
723 if (trackNumber <= timedTextCount)
724 return trackNumber;
725
726 trackNumber = trackNumber - timedTextCount;
727
728 if (trackNumber <= subtitleTextCount)
729 return trackNumber;
730
731 return -1;
732}
733
735{
736 int androidTrackNumber = -1;
737
738 switch (trackType) {
740 if (!mIsVideoTrackEnabled)
741 return -1;
742 androidTrackNumber = mMediaPlayer->activeTrack(AndroidMediaPlayer::TrackType::Video);
743 }
745 if (!mIsAudioTrackEnabled)
746 return -1;
747
748 androidTrackNumber = mMediaPlayer->activeTrack(AndroidMediaPlayer::TrackType::Audio);
749 }
751 int timedTextSelectedTrack =
753
754 if (timedTextSelectedTrack > -1) {
755 androidTrackNumber = timedTextSelectedTrack;
756 break;
757 }
758
759 int subtitleSelectedTrack =
761 if (subtitleSelectedTrack > -1) {
762 androidTrackNumber = subtitleSelectedTrack;
763 break;
764 }
765
766 return -1;
767 }
769 return -1;
770 }
771
772 return convertTrackNumber(androidTrackNumber);
773}
774
775void QAndroidMediaPlayer::disableTrack(TrackType trackType)
776{
777 const auto track = activeTrack(trackType);
778
779 switch (trackType) {
780 case VideoStream: {
781 if (track > -1) {
782 mMediaPlayer->setDisplay(nullptr);
783 mIsVideoTrackEnabled = false;
784 }
785 break;
786 }
787 case AudioStream: {
788 if (track > -1) {
789 mMediaPlayer->setMuted(true);
790 mMediaPlayer->blockAudio();
791 mIsAudioTrackEnabled = false;
792 }
793 break;
794 }
795 case SubtitleStream: {
796 // subtitles and timedtext tracks can be selected at the same time so deselect both
797 int subtitleSelectedTrack =
799 if (subtitleSelectedTrack > -1)
800 mMediaPlayer->deselectTrack(subtitleSelectedTrack);
801
802 int timedTextSelectedTrack =
804 if (timedTextSelectedTrack > -1)
805 mMediaPlayer->deselectTrack(timedTextSelectedTrack);
806
807 break;
808 }
809 case NTrackTypes:
810 break;
811 }
812}
813
814void QAndroidMediaPlayer::setActiveTrack(TrackType trackType, int streamNumber)
815{
816
817 if (!mTracksMetadata.contains(trackType)) {
818 qCWarning(lcMediaPlayer)
819 << "Trying to set a active track which type has no available tracks.";
820 return;
821 }
822
823 const auto &tracks = mTracksMetadata.value(trackType);
824 if (streamNumber > tracks.count()) {
825 qCWarning(lcMediaPlayer) << "Trying to set a active track that does not exist.";
826 return;
827 }
828
829 // in case of < 0 deselect tracktype
830 if (streamNumber < 0) {
831 disableTrack(trackType);
832 return;
833 }
834
835 const auto currentTrack = activeTrack(trackType);
836 if (streamNumber == currentTrack) {
837 return;
838 }
839
840 if (trackType == TrackType::VideoStream && !mIsVideoTrackEnabled) {
841 // enable video stream
842 mMediaPlayer->setDisplay(mVideoOutput->surfaceTexture());
843 mIsVideoTrackEnabled = true;
844 }
845
846 if (trackType == TrackType::AudioStream && !mIsAudioTrackEnabled) {
847 // enable audio stream
848 mMediaPlayer->unblockAudio();
849 mMediaPlayer->setMuted(false);
850 mIsAudioTrackEnabled = true;
851 }
852
853 if (trackType == TrackType::SubtitleStream) {
854 // subtitles and timedtext tracks can be selected at the same time so deselect both before
855 // selecting a new one
856 disableTrack(TrackType::SubtitleStream);
857 }
858
859 const auto &trackInfo = tracks.at(streamNumber);
860 const auto &trackNumber = trackInfo.androidTrackNumber();
861 mMediaPlayer->selectTrack(trackNumber);
862
864}
865
866void QAndroidMediaPlayer::positionChanged(qint64 position)
867{
869}
870
871void QAndroidMediaPlayer::durationChanged(qint64 duration)
872{
874}
875
876void QAndroidMediaPlayer::onVideoOutputReady(bool ready)
877{
878 if ((mMediaPlayer->display() == 0) && mVideoOutput && ready)
879 mMediaPlayer->setDisplay(mVideoOutput->surfaceTexture());
880
881 flushPendingStates();
882}
883
884void QAndroidMediaPlayer::setMediaStatus(QMediaPlayer::MediaStatus status)
885{
886 mediaStatusChanged(status);
887
888 if (status == QMediaPlayer::NoMedia || status == QMediaPlayer::InvalidMedia) {
889 Q_EMIT durationChanged(0);
891 setAudioAvailable(false);
892 setVideoAvailable(false);
893 }
894
895 if (status == QMediaPlayer::EndOfMedia)
896 Q_EMIT positionChanged(position());
897
898 updateBufferStatus();
899}
900
901void QAndroidMediaPlayer::setAudioAvailable(bool available)
902{
903 if (mAudioAvailable == available)
904 return;
905
906 mAudioAvailable = available;
907 Q_EMIT audioAvailableChanged(mAudioAvailable);
908}
909
910void QAndroidMediaPlayer::setVideoAvailable(bool available)
911{
912 if (mVideoAvailable == available)
913 return;
914
915 if (!available)
916 mVideoSize = QSize();
917
918 mVideoAvailable = available;
919 Q_EMIT videoAvailableChanged(mVideoAvailable);
920}
921
922void QAndroidMediaPlayer::resetBufferingProgress()
923{
924 mBuffering = false;
925 mBufferPercent = 0;
926 mAvailablePlaybackRange = QMediaTimeRange();
927}
928
929void QAndroidMediaPlayer::flushPendingStates()
930{
931 if (mPendingSetMedia) {
932 setMedia(mMediaContent, 0);
933 mPendingSetMedia = false;
934 return;
935 }
936
937 const int newState = mPendingState;
938 mPendingState = -1;
939
940 if (mPendingPosition != -1)
941 setPosition(mPendingPosition);
942 if (mPendingVolume >= 0)
943 setVolume(mPendingVolume);
944 if (mPendingMute != -1)
945 setMuted((mPendingMute == 1));
946
947 switch (newState) {
949 play();
950 break;
952 pause();
953 break;
955 stop();
956 break;
957 default:
958 break;
959 }
960}
961
962void QAndroidMediaPlayer::updateBufferStatus()
963{
964 const auto &status = mediaStatus();
965 bool bufferFilled = (status == QMediaPlayer::BufferedMedia || status == QMediaPlayer::BufferingMedia);
966
967 if (mBufferFilled != bufferFilled)
968 mBufferFilled = bufferFilled;
969
971}
972
973void QAndroidMediaPlayer::updateTrackInfo()
974{
975 const auto &androidTracksInfo = mMediaPlayer->tracksInfo();
976
977 // prepare mTracksMetadata
978 mTracksMetadata[TrackType::VideoStream] = QList<QAndroidMetaData>();
979 mTracksMetadata[TrackType::AudioStream] = QList<QAndroidMetaData>();
980 mTracksMetadata[TrackType::SubtitleStream] = QList<QAndroidMetaData>();
981 mTracksMetadata[TrackType::NTrackTypes] = QList<QAndroidMetaData>();
982
983 for (const auto &androidTrackInfo : androidTracksInfo) {
984
985 const auto &mediaPlayerType = convertTrackType(androidTrackInfo.trackType);
986 auto &tracks = mTracksMetadata[mediaPlayerType];
987
988 const QAndroidMetaData metadata(mediaPlayerType, androidTrackInfo.trackType,
989 androidTrackInfo.trackNumber, androidTrackInfo.mimeType,
990 androidTrackInfo.language);
991 tracks.append(metadata);
992 }
993
995}
996
998
999#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
T value(const Key &key, const T &defaultValue=T()) const
Definition qmap.h:357
bool contains(const Key &key) const
Definition qmap.h:341
\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:2960
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3236
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)
void rhiChanged(QRhi *rhi)
\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:127
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
\inmodule QtCore
Definition qurl.h:94
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
The QVideoSink class represents a generic sink for video data.
Definition qvideosink.h:22
QPlatformVideoSink * platformVideoSink() const
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
constexpr int Uninitialized
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:327
#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:49
long long qint64
Definition qtypes.h:60
double qreal
Definition qtypes.h:187
QT_BEGIN_NAMESPACE typedef uchar * output
myObject disconnect()
[26]