diff --git a/src/QtAVPlayer/qavaudiooutput.cpp b/src/QtAVPlayer/qavaudiooutput.cpp index d2c3726f..1bff3e8b 100644 --- a/src/QtAVPlayer/qavaudiooutput.cpp +++ b/src/QtAVPlayer/qavaudiooutput.cpp @@ -149,7 +149,7 @@ class QAVAudioOutputPrivate : public QIODevice bool isSequential() const override { return true; } bool atEnd() const override { return false; } - void init(const QAudioFormat &fmt, int bsize) + void tryInit(const QAudioFormat &fmt, int bsize, qreal v) { #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) auto audioDevice = QAudioDeviceInfo::defaultOutputDevice(); @@ -184,6 +184,7 @@ class QAVAudioOutputPrivate : public QIODevice if (bsize > 0) audioOutput->setBufferSize(bsize); + audioOutput->setVolume(v); audioOutput->start(this); } } @@ -201,7 +202,7 @@ class QAVAudioOutputPrivate : public QIODevice auto bsize = bufferSize; locker.unlock(); if (fmt.isValid()) - init(fmt, bsize); + tryInit(fmt, bsize, v); if (audioOutput) audioOutput->setVolume(v); QCoreApplication::processEvents(); diff --git a/src/QtAVPlayer/qavdemuxer.cpp b/src/QtAVPlayer/qavdemuxer.cpp index dd41be85..9afac8c8 100644 --- a/src/QtAVPlayer/qavdemuxer.cpp +++ b/src/QtAVPlayer/qavdemuxer.cpp @@ -831,6 +831,25 @@ void QAVDemuxer::onFrameSent(const QAVStreamFrame &frame) d->progress[index].onFrameSent(frame.pts()); } +bool QAVDemuxer::isStreamMaster(const QAVStream &stream) const +{ + auto s = stream.stream(); + switch (s->codecpar->codec_type) { + case AVMEDIA_TYPE_VIDEO: + return s->disposition != AV_DISPOSITION_ATTACHED_PIC; + case AVMEDIA_TYPE_AUDIO: + // Check if there are any video streams available + for (const auto &vs: currentVideoStreams()) { + if (vs.stream()->disposition != AV_DISPOSITION_ATTACHED_PIC) + return false; + } + return true; + default: + Q_ASSERT(false); + return false; + } +} + QAVStream::Progress QAVDemuxer::progress(const QAVStream &s) const { Q_D(const QAVDemuxer); diff --git a/src/QtAVPlayer/qavdemuxer_p.h b/src/QtAVPlayer/qavdemuxer_p.h index c2a9cf08..671237c8 100644 --- a/src/QtAVPlayer/qavdemuxer_p.h +++ b/src/QtAVPlayer/qavdemuxer_p.h @@ -92,6 +92,8 @@ class QAVDemuxer void onFrameSent(const QAVStreamFrame &frame); QAVStream::Progress progress(const QAVStream &s) const; + bool isStreamMaster(const QAVStream &stream) const; + static QStringList supportedFormats(); static QStringList supportedVideoCodecs(); static QStringList supportedProtocols(); diff --git a/src/QtAVPlayer/qavplayer.cpp b/src/QtAVPlayer/qavplayer.cpp index d25cf391..8c877013 100644 --- a/src/QtAVPlayer/qavplayer.cpp +++ b/src/QtAVPlayer/qavplayer.cpp @@ -88,8 +88,8 @@ class QAVPlayerPrivate const std::vector> &filters, QList &filteredFrames); - void doPlayStep( - bool master, + bool doPlayStep( + bool &master, double refPts, QAVQueueClock &clock, QAVPacketQueue &queue, @@ -279,7 +279,8 @@ void QAVPlayerPrivate::setVideoFrameRate(double v) void QAVPlayerPrivate::setPts(double v) { QMutexLocker locker(&positionMutex); - currPts = v; + if (!isnan(v)) + currPts = v; } double QAVPlayerPrivate::pts() const @@ -688,8 +689,8 @@ bool QAVPlayerPrivate::skipFrame( return result; } -void QAVPlayerPrivate::doPlayStep( - bool master, +bool QAVPlayerPrivate::doPlayStep( + bool &master, double refPts, QAVQueueClock &clock, QAVPacketQueue &queue, @@ -704,6 +705,10 @@ void QAVPlayerPrivate::doPlayStep( bool flushEvents = false; int ret = 0; + // Determine if current thread is handling events and pts + if (decodedFrame) + master = demuxer.isStreamMaster(decodedFrame.stream()); + // 2. Filter decoded frame QList filteredFrames; if (decodedFrame) @@ -715,7 +720,7 @@ void QAVPlayerPrivate::doPlayStep( filteredFrames.clear(); if (ret != AVERROR(ENOTSUP)) { setError(QAVPlayer::FilterError, err_str(ret)); - return; + return master; } applyFilters(true, decodedFrame); } else { @@ -750,12 +755,13 @@ void QAVPlayerPrivate::doPlayStep( if (master) step(flushEvents); + return master; } void QAVPlayerPrivate::doPlayVideo() { videoClock.setFrameRate(demuxer.videoFrameRate()); - const bool master = true; + bool master = true; bool sync = true; while (!quit) { @@ -777,7 +783,7 @@ void QAVPlayerPrivate::doPlayVideo() void QAVPlayerPrivate::doPlayAudio() { - const bool master = demuxer.currentVideoStreams().isEmpty(); + bool master = false; const double ref = -1; bool sync = true; diff --git a/tests/auto/integration/qavplayer/tst_qavplayer.cpp b/tests/auto/integration/qavplayer/tst_qavplayer.cpp index 19fa376b..74c9f415 100644 --- a/tests/auto/integration/qavplayer/tst_qavplayer.cpp +++ b/tests/auto/integration/qavplayer/tst_qavplayer.cpp @@ -40,6 +40,7 @@ private slots: void stopAudio(); void seekAudio(); void speedAudio(); + void audioPositionWithCover(); void playVideo(); void pauseVideo(); void seekVideo(); @@ -434,6 +435,23 @@ void tst_QAVPlayer::speedAudio() QTRY_COMPARE(p.mediaStatus(), QAVPlayer::EndOfMedia); } +void tst_QAVPlayer::audioPositionWithCover() +{ + QAVPlayer p; + qint64 pos = 0; + QAVAudioFrame audioFrame; + QObject::connect(&p, &QAVPlayer::audioFrame, &p, [&](const QAVAudioFrame &f) { pos = p.position(); audioFrame = f; }); + + QFileInfo file(testData("test.mp3")); + p.setSource(file.absoluteFilePath()); + QTRY_COMPARE(p.mediaStatus(), QAVPlayer::LoadedMedia); + p.play(); + p.setSynced(false); + QTRY_COMPARE(p.mediaStatus(), QAVPlayer::EndOfMedia); + QVERIFY(audioFrame); + QVERIFY(pos > 0); +} + void tst_QAVPlayer::playVideo() { QAVPlayer p; @@ -1886,9 +1904,9 @@ void tst_QAVPlayer::multiPlayers() int framesCount2 = 0; qint64 pos1 = 0; qint64 pos2 = 0; - QObject::connect(&p1, &QAVPlayer::videoFrame, &p1, [&](const QAVVideoFrame &f) { ++framesCount1; pos1 = p1.position(); }, Qt::DirectConnection); + QObject::connect(&p1, &QAVPlayer::videoFrame, &p1, [&](const QAVVideoFrame &) { ++framesCount1; pos1 = p1.position(); }, Qt::DirectConnection); QObject::connect(&p1, &QAVPlayer::audioFrame, &p1, [&](const QAVAudioFrame &f) { o1.play(f); }, Qt::DirectConnection); - QObject::connect(&p2, &QAVPlayer::videoFrame, &p2, [&](const QAVVideoFrame &f) { ++framesCount2; pos2 = p2.position(); }, Qt::DirectConnection); + QObject::connect(&p2, &QAVPlayer::videoFrame, &p2, [&](const QAVVideoFrame &) { ++framesCount2; pos2 = p2.position(); }, Qt::DirectConnection); QObject::connect(&p2, &QAVPlayer::audioFrame, &p2, [&](const QAVAudioFrame &f) { o2.play(f); }, Qt::DirectConnection); p1.play(); p2.play(); diff --git a/tests/auto/integration/testdata/test.mp3 b/tests/auto/integration/testdata/test.mp3 new file mode 100644 index 00000000..da9f1d90 Binary files /dev/null and b/tests/auto/integration/testdata/test.mp3 differ