From a59049cbdf10b38d8d73bbd9a809b8394b36774c Mon Sep 17 00:00:00 2001 From: Mike Odom Date: Sat, 13 Jan 2018 18:38:39 -0800 Subject: [PATCH 01/31] Actually pausing AVPlayer on stepBackward --- src/AVPlayer.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/AVPlayer.cpp b/src/AVPlayer.cpp index d1f0ebf78..f1bdfa153 100644 --- a/src/AVPlayer.cpp +++ b/src/AVPlayer.cpp @@ -1545,11 +1545,8 @@ void AVPlayer::stepForward() void AVPlayer::stepBackward() { - d->clock->pause(true); - d->state = PausedState; - Q_EMIT stateChanged(d->state); - Q_EMIT paused(true); - d->read_thread->stepBackward(); + pause(true); + d->read_thread->stepBackward(); } void AVPlayer::seek(qreal r) From b1c4a6ded359fa649fc66f6a901bb352c5b22c6b Mon Sep 17 00:00:00 2001 From: Mike Odom <5105729+ThatOdieGuy@users.noreply.github.com> Date: Tue, 9 Jul 2019 16:05:40 -0700 Subject: [PATCH 02/31] Adding displayPosition to AVPlayer This remembers the last seek pos of the player. Prevents the display position from jumping around wildly as we seek. --- src/AVDemuxThread.cpp | 12 ++++++++++++ src/AVDemuxThread.h | 1 + src/AVPlayer.cpp | 21 +++++++++++++++++++++ src/AVPlayerPrivate.cpp | 1 + src/AVPlayerPrivate.h | 1 + src/QtAV/AVPlayer.h | 3 ++- 6 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/AVDemuxThread.cpp b/src/AVDemuxThread.cpp index 6eee37d94..cbc68b623 100644 --- a/src/AVDemuxThread.cpp +++ b/src/AVDemuxThread.cpp @@ -82,6 +82,7 @@ AVDemuxThread::AVDemuxThread(QObject *parent) : , audio_thread(0) , video_thread(0) , clock_type(-1) + , last_seek_pos(0) { seek_tasks.setCapacity(1); seek_tasks.blockFull(false); @@ -95,6 +96,7 @@ AVDemuxThread::AVDemuxThread(AVDemuxer *dmx, QObject *parent) : , m_buffer(0) , audio_thread(0) , video_thread(0) + , last_seek_pos(0) { setDemuxer(dmx); seek_tasks.setCapacity(1); @@ -278,6 +280,7 @@ void AVDemuxThread::seekInternal(qint64 pos, SeekType type, qint64 external_pos) if (external_pos != std::numeric_limits < qint64 >::min() ) t->clock()->updateExternalClock(qMax(qint64(0), external_pos)); t->clock()->updateValue(double(pos)/1000.0); + last_seek_pos = pos; t->requestSeek(); // TODO: the first frame (key frame) will not be decoded correctly if flush() is called. //PacketBuffer *pb = t->packetQueue(); @@ -323,6 +326,11 @@ void AVDemuxThread::processNextSeekTask() delete task; } +qint64 AVDemuxThread::lastSeekPos() +{ + return last_seek_pos; +} + void AVDemuxThread::pauseInternal(bool value) { paused = value; @@ -486,6 +494,10 @@ void AVDemuxThread::frameDeliveredOnStepForward() clock_type = -1; thread->clock()->updateExternalClock((thread->previousHistoryPts() - thread->clock()->initialValue())*1000.0); } + + // Fudge the bit at the end + 33ms so that step forward and step backwards present different values + last_seek_pos = (thread->previousHistoryPts() - thread->clock()->initialValue())*1000.0 + 33; + Q_EMIT stepFinished(); } diff --git a/src/AVDemuxThread.h b/src/AVDemuxThread.h index f2a9080b9..aca42b610 100644 --- a/src/AVDemuxThread.h +++ b/src/AVDemuxThread.h @@ -100,6 +100,7 @@ private slots: QMutex buffer_mutex; QWaitCondition cond; BlockingQueue seek_tasks; + qint64 last_seek_pos; QSemaphore sem; QMutex next_frame_mutex; diff --git a/src/AVPlayer.cpp b/src/AVPlayer.cpp index f1bdfa153..8a7f8c163 100644 --- a/src/AVPlayer.cpp +++ b/src/AVPlayer.cpp @@ -848,6 +848,27 @@ qint64 AVPlayer::position() const return pts; } +qint64 AVPlayer::displayPosition() const +{ + //return d->read_thread->lastSeekPos(); + + // Return a cached value if there are seek tasks + if (d->seeking || (d->read_thread->buffer() && d->read_thread->buffer()->isBuffering())) { + //return d->last_known_good_pts; + return d->last_known_good_pts = d->read_thread->lastSeekPos(); + } + + // TODO: videoTime()? + qint64 pts = d->clock->videoTime()*1000.0; + + if (pts < 0) { + return d->last_known_good_pts; + } + d->last_known_good_pts = pts; + + return pts; +} + void AVPlayer::setPosition(qint64 position) { // FIXME: strange things happen if seek out of eof diff --git a/src/AVPlayerPrivate.cpp b/src/AVPlayerPrivate.cpp index 84f079ef2..f8d815791 100644 --- a/src/AVPlayerPrivate.cpp +++ b/src/AVPlayerPrivate.cpp @@ -111,6 +111,7 @@ AVPlayer::Private::Private() , status(NoMedia) , state(AVPlayer::StoppedState) , end_action(MediaEndAction_Default) + , last_known_good_pts(0) { demuxer.setInterruptTimeout(interrupt_timeout); /* diff --git a/src/AVPlayerPrivate.h b/src/AVPlayerPrivate.h index e404b9bff..7aa532f5a 100644 --- a/src/AVPlayerPrivate.h +++ b/src/AVPlayerPrivate.h @@ -111,6 +111,7 @@ class AVPlayer::Private bool reset_state; qint64 start_position, stop_position; qint64 start_position_norm, stop_position_norm; // real position + qint64 last_known_good_pts; int repeat_max, repeat_current; int timer_id; //notify position change and check AB repeat range. active when playing diff --git a/src/QtAV/AVPlayer.h b/src/QtAV/AVPlayer.h index e297b0370..11ae4d6a5 100644 --- a/src/QtAV/AVPlayer.h +++ b/src/QtAV/AVPlayer.h @@ -178,7 +178,8 @@ class Q_AV_EXPORT AVPlayer : public QObject */ qint64 stopPosition() const; //unit: ms qint64 position() const; //unit: ms - //0: play once. N: play N+1 times. <0: infinity + qint64 displayPosition() const; + //0: play once. N: play N+1 times. <0: infinity int repeat() const; //or repeatMax()? /*! * \brief currentRepeat From 5501862af3cb3d5f55b59ce00a8d82f074d460c9 Mon Sep 17 00:00:00 2001 From: Mike Odom <5105729+ThatOdieGuy@users.noreply.github.com> Date: Tue, 9 Jul 2019 16:06:43 -0700 Subject: [PATCH 03/31] Adding displayPosition to AVPlayer --- src/AVDemuxThread.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/AVDemuxThread.h b/src/AVDemuxThread.h index aca42b610..93bf915f8 100644 --- a/src/AVDemuxThread.h +++ b/src/AVDemuxThread.h @@ -59,6 +59,7 @@ class AVDemuxThread : public QThread MediaEndAction mediaEndAction() const; void setMediaEndAction(MediaEndAction value); bool waitForStarted(int msec = -1); + qint64 lastSeekPos(); Q_SIGNALS: void requestClockPause(bool value); void mediaStatusChanged(QtAV::MediaStatus); From 12da5dd2aa7dab2b51b39e3c29f8174e1c726667 Mon Sep 17 00:00:00 2001 From: Mike Odom <5105729+ThatOdieGuy@users.noreply.github.com> Date: Tue, 9 Jul 2019 18:55:42 -0700 Subject: [PATCH 04/31] Preventing double stepping --- src/AVDemuxThread.cpp | 79 +++++++++++++++++++++++++++++++++++++---- src/AVDemuxThread.h | 9 ++++- src/AVPlayer.cpp | 21 ++++++++--- src/AVPlayerPrivate.cpp | 1 + src/AVPlayerPrivate.h | 1 + 5 files changed, 100 insertions(+), 11 deletions(-) diff --git a/src/AVDemuxThread.cpp b/src/AVDemuxThread.cpp index cbc68b623..db8abbaaf 100644 --- a/src/AVDemuxThread.cpp +++ b/src/AVDemuxThread.cpp @@ -27,6 +27,7 @@ #include "VideoThread.h" #include #include "utils/Logger.h" +#include #define RESUME_ONCE_ON_SEEK 0 @@ -83,6 +84,8 @@ AVDemuxThread::AVDemuxThread(QObject *parent) : , video_thread(0) , clock_type(-1) , last_seek_pos(0) + , current_seek_task(nullptr) + , stepping(false) { seek_tasks.setCapacity(1); seek_tasks.blockFull(false); @@ -97,6 +100,8 @@ AVDemuxThread::AVDemuxThread(AVDemuxer *dmx, QObject *parent) : , audio_thread(0) , video_thread(0) , last_seek_pos(0) + , current_seek_task(nullptr) + , stepping(false) { setDemuxer(dmx); seek_tasks.setCapacity(1); @@ -155,6 +160,8 @@ void AVDemuxThread::stepBackward() { if (!video_thread) return; + if (hasSeekTasks() || m_buffering) + return; AVThread *t = video_thread; const qreal pre_pts = video_thread->previousHistoryPts(); if (pre_pts == 0.0) { @@ -176,6 +183,10 @@ void AVDemuxThread::stepBackward() void run() { AVThread *avt = demux_thread->videoThread(); avt->packetQueue()->clear(); // clear here + + connect(avt, SIGNAL(frameDelivered()), demux_thread, SLOT(finishedStepBackward()), Qt::DirectConnection); + connect(avt, SIGNAL(eofDecoded()), demux_thread, SLOT(finishedStepBackward()), Qt::DirectConnection); + if (pts <= 0) { demux_thread->demuxer->seek(qint64(-pts*1000.0) - 500LL); QVector ts; @@ -195,6 +206,7 @@ void AVDemuxThread::stepBackward() pts -= dt/2.0; } qDebug("step backward: %lld, %f", qint64(pts*1000.0), pts); + demux_thread->video_thread->setDropFrameOnSeek(false); demux_thread->seekInternal(qint64(pts*1000.0), AccurateSeek); } @@ -204,6 +216,14 @@ void AVDemuxThread::stepBackward() }; pause(true); + stepping = true; + + // In case we never get a frame, set a timeout. + auto timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), this, SLOT(finishedStepBackward())); + timer->start(200); + step_timeout_timer = timer; + t->packetQueue()->clear(); // will put new packets before task run t->packetQueue(); Packet pkt; @@ -213,6 +233,19 @@ void AVDemuxThread::stepBackward() newSeekRequest(new stepBackwardTask(this, pre_pts)); } +void AVDemuxThread::finishedStepBackward() +{ + disconnect(video_thread, SIGNAL(frameDelivered()), this, SLOT(finishedStepBackward())); + disconnect(video_thread, SIGNAL(eofDecoded()), this, SLOT(finishedStepBackward())); + + if (step_timeout_timer) { + step_timeout_timer->stop(); + step_timeout_timer = nullptr; + } + + stepping = false; +} + void AVDemuxThread::seek(qint64 external_pos, qint64 pos, SeekType type) { class SeekTask : public QRunnable { @@ -318,12 +351,20 @@ void AVDemuxThread::processNextSeekTask() { if (seek_tasks.isEmpty()) return; - QRunnable *task = seek_tasks.take(); - if (!task) + + current_seek_task = seek_tasks.take(); + if (!current_seek_task) return; - task->run(); - if (task->autoDelete()) - delete task; + current_seek_task->run(); + + if (current_seek_task->autoDelete()) + delete current_seek_task; + current_seek_task = nullptr; +} + +bool AVDemuxThread::hasSeekTasks() +{ + return !seek_tasks.isEmpty() || current_seek_task || stepping; } qint64 AVDemuxThread::lastSeekPos() @@ -428,6 +469,11 @@ void AVDemuxThread::stepForward() { if (end) return; + if (hasSeekTasks() || m_buffering) + return; + + stepping = true; + // clock type will be wrong if no lock because slot frameDeliveredOnStepForward() is in video thread QMutexLocker locker(&next_frame_mutex); Q_UNUSED(locker); @@ -448,6 +494,13 @@ void AVDemuxThread::stepForward() if (!connected) { connect(t, SIGNAL(frameDelivered()), this, SLOT(frameDeliveredOnStepForward()), Qt::DirectConnection); connect(t, SIGNAL(eofDecoded()), this, SLOT(eofDecodedOnStepForward()), Qt::DirectConnection); + + // In case we never get a frame, set a timeout. + auto timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), this, SLOT(frameDeliveredOnStepForward())); + timer->start(200); + step_timeout_timer = timer; + connected = true; } } @@ -497,7 +550,9 @@ void AVDemuxThread::frameDeliveredOnStepForward() // Fudge the bit at the end + 33ms so that step forward and step backwards present different values last_seek_pos = (thread->previousHistoryPts() - thread->clock()->initialValue())*1000.0 + 33; - + + stepForwardDone(); + Q_EMIT stepFinished(); } @@ -516,9 +571,21 @@ void AVDemuxThread::eofDecodedOnStepForward() thread->clock()->setClockType(AVClock::ClockType(clock_type/2)); clock_type = -1; } + + stepForwardDone(); + Q_EMIT stepFinished(); } +void AVDemuxThread::stepForwardDone() +{ + if (step_timeout_timer) { + step_timeout_timer->stop(); + step_timeout_timer = nullptr; + } + stepping = false; +} + void AVDemuxThread::onAVThreadQuit() { AVThread* av[] = { audio_thread, video_thread}; diff --git a/src/AVDemuxThread.h b/src/AVDemuxThread.h index 93bf915f8..6c05942fe 100644 --- a/src/AVDemuxThread.h +++ b/src/AVDemuxThread.h @@ -27,6 +27,7 @@ #include #include #include "PacketBuffer.h" +#include namespace QtAV { @@ -60,6 +61,7 @@ class AVDemuxThread : public QThread void setMediaEndAction(MediaEndAction value); bool waitForStarted(int msec = -1); qint64 lastSeekPos(); + bool hasSeekTasks(); Q_SIGNALS: void requestClockPause(bool value); void mediaStatusChanged(QtAV::MediaStatus); @@ -68,9 +70,11 @@ class AVDemuxThread : public QThread void stepFinished(); void internalSubtitlePacketRead(int index, const QtAV::Packet& packet); private slots: + void finishedStepBackward(); void seekOnPauseFinished(); void frameDeliveredOnStepForward(); void eofDecodedOnStepForward(); + void stepForwardDone(); void onAVThreadQuit(); protected: @@ -102,7 +106,10 @@ private slots: QWaitCondition cond; BlockingQueue seek_tasks; qint64 last_seek_pos; - + QRunnable *current_seek_task; + bool stepping; + QTimer *step_timeout_timer; + QSemaphore sem; QMutex next_frame_mutex; int clock_type; // change happens in different threads(direct connection) diff --git a/src/AVPlayer.cpp b/src/AVPlayer.cpp index 8a7f8c163..94a16b7cd 100644 --- a/src/AVPlayer.cpp +++ b/src/AVPlayer.cpp @@ -583,6 +583,12 @@ void AVPlayer::pause(bool p) return; if (isPaused() == p) return; + + if (!p) { + // TODO: If was stepping, skip our position a little bit behind us. + d->was_stepping = false; + } + audio()->pause(p); //pause thread. check pause state? d->read_thread->pause(p); @@ -850,17 +856,19 @@ qint64 AVPlayer::position() const qint64 AVPlayer::displayPosition() const { - //return d->read_thread->lastSeekPos(); - // Return a cached value if there are seek tasks - if (d->seeking || (d->read_thread->buffer() && d->read_thread->buffer()->isBuffering())) { - //return d->last_known_good_pts; + if (d->seeking || d->read_thread->hasSeekTasks() || (d->read_thread->buffer() && d->read_thread->buffer()->isBuffering())) { return d->last_known_good_pts = d->read_thread->lastSeekPos(); } // TODO: videoTime()? qint64 pts = d->clock->videoTime()*1000.0; + // If we are stepping around, we want the lastSeekPos. + /// But if we're just paused by the user... we want another value. + if (d->was_stepping) { + pts = d->read_thread->lastSeekPos(); + } if (pts < 0) { return d->last_known_good_pts; } @@ -1279,6 +1287,9 @@ void AVPlayer::playInternal() else setPosition((qint64)(d->start_position_norm)); } + + d->was_stepping = false; + Q_EMIT stateChanged(PlayingState); Q_EMIT started(); //we called stop(), so must emit started() } @@ -1561,12 +1572,14 @@ void AVPlayer::stepForward() { // pause clock pause(true); // must pause AVDemuxThread (set user_paused true) + d->was_stepping = true; d->read_thread->stepForward(); } void AVPlayer::stepBackward() { pause(true); + d->was_stepping = true; d->read_thread->stepBackward(); } diff --git a/src/AVPlayerPrivate.cpp b/src/AVPlayerPrivate.cpp index f8d815791..9b9014f43 100644 --- a/src/AVPlayerPrivate.cpp +++ b/src/AVPlayerPrivate.cpp @@ -112,6 +112,7 @@ AVPlayer::Private::Private() , state(AVPlayer::StoppedState) , end_action(MediaEndAction_Default) , last_known_good_pts(0) + , was_stepping(false) { demuxer.setInterruptTimeout(interrupt_timeout); /* diff --git a/src/AVPlayerPrivate.h b/src/AVPlayerPrivate.h index 7aa532f5a..e7be85807 100644 --- a/src/AVPlayerPrivate.h +++ b/src/AVPlayerPrivate.h @@ -112,6 +112,7 @@ class AVPlayer::Private qint64 start_position, stop_position; qint64 start_position_norm, stop_position_norm; // real position qint64 last_known_good_pts; + bool was_stepping; int repeat_max, repeat_current; int timer_id; //notify position change and check AB repeat range. active when playing From cfb454a088df0ce529ceb338edc1b2d30164f890 Mon Sep 17 00:00:00 2001 From: Mike Odom <5105729+ThatOdieGuy@users.noreply.github.com> Date: Tue, 9 Jul 2019 18:59:38 -0700 Subject: [PATCH 05/31] Seeking backwards a bit if we were stepping --- src/AVPlayer.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/AVPlayer.cpp b/src/AVPlayer.cpp index 94a16b7cd..8bef91aad 100644 --- a/src/AVPlayer.cpp +++ b/src/AVPlayer.cpp @@ -585,8 +585,12 @@ void AVPlayer::pause(bool p) return; if (!p) { - // TODO: If was stepping, skip our position a little bit behind us. - d->was_stepping = false; + if (d->was_stepping) { + d->was_stepping = false; + // If was stepping, skip our position a little bit behind us. + // This fixes an issue with the audio timer + seek(position() - 100); + } } audio()->pause(p); From a1a435bd57d3ab96c0f50c6281e4090d5b50fc75 Mon Sep 17 00:00:00 2001 From: Mike Odom <5105729+ThatOdieGuy@users.noreply.github.com> Date: Tue, 9 Jul 2019 21:34:15 -0700 Subject: [PATCH 06/31] Removing the check for buffering on steps Buffering state seems to get stuck, we don't need to check it for stepping. --- src/AVDemuxThread.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AVDemuxThread.cpp b/src/AVDemuxThread.cpp index db8abbaaf..51af2f240 100644 --- a/src/AVDemuxThread.cpp +++ b/src/AVDemuxThread.cpp @@ -160,7 +160,7 @@ void AVDemuxThread::stepBackward() { if (!video_thread) return; - if (hasSeekTasks() || m_buffering) + if (hasSeekTasks()) return; AVThread *t = video_thread; const qreal pre_pts = video_thread->previousHistoryPts(); @@ -469,7 +469,7 @@ void AVDemuxThread::stepForward() { if (end) return; - if (hasSeekTasks() || m_buffering) + if (hasSeekTasks()) return; stepping = true; From 6f0f7fc09f57b424c0cea4e7901d1ce83c1b9a28 Mon Sep 17 00:00:00 2001 From: Mike Odom <5105729+ThatOdieGuy@users.noreply.github.com> Date: Wed, 10 Jul 2019 00:35:29 -0700 Subject: [PATCH 07/31] Fixing the step backwards seek timeout --- src/AVDemuxThread.cpp | 42 ++++++++++++++++-------------------------- src/AVDemuxThread.h | 2 +- 2 files changed, 17 insertions(+), 27 deletions(-) diff --git a/src/AVDemuxThread.cpp b/src/AVDemuxThread.cpp index 51af2f240..995c035f6 100644 --- a/src/AVDemuxThread.cpp +++ b/src/AVDemuxThread.cpp @@ -86,6 +86,7 @@ AVDemuxThread::AVDemuxThread(QObject *parent) : , last_seek_pos(0) , current_seek_task(nullptr) , stepping(false) + , stepping_timeout_time(0) { seek_tasks.setCapacity(1); seek_tasks.blockFull(false); @@ -102,6 +103,7 @@ AVDemuxThread::AVDemuxThread(AVDemuxer *dmx, QObject *parent) : , last_seek_pos(0) , current_seek_task(nullptr) , stepping(false) + , stepping_timeout_time(0) { setDemuxer(dmx); seek_tasks.setCapacity(1); @@ -174,13 +176,18 @@ void AVDemuxThread::stepBackward() audio_thread->packetQueue()->clear(); // will put new packets before task run } - class stepBackwardTask : public QRunnable { + class stepBackwardTask : public QObject, public QRunnable { public: + QTimer timeout_timer; + stepBackwardTask(AVDemuxThread *dt, qreal t) : demux_thread(dt) , pts(t) {} void run() { + demux_thread->stepping = true; + demux_thread->stepping_timeout_time = QDateTime::currentMSecsSinceEpoch() + 200; + AVThread *avt = demux_thread->videoThread(); avt->packetQueue()->clear(); // clear here @@ -216,13 +223,6 @@ void AVDemuxThread::stepBackward() }; pause(true); - stepping = true; - - // In case we never get a frame, set a timeout. - auto timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), this, SLOT(finishedStepBackward())); - timer->start(200); - step_timeout_timer = timer; t->packetQueue()->clear(); // will put new packets before task run t->packetQueue(); @@ -238,12 +238,8 @@ void AVDemuxThread::finishedStepBackward() disconnect(video_thread, SIGNAL(frameDelivered()), this, SLOT(finishedStepBackward())); disconnect(video_thread, SIGNAL(eofDecoded()), this, SLOT(finishedStepBackward())); - if (step_timeout_timer) { - step_timeout_timer->stop(); - step_timeout_timer = nullptr; - } - stepping = false; + stepping_timeout_time = 0; } void AVDemuxThread::seek(qint64 external_pos, qint64 pos, SeekType type) @@ -364,6 +360,10 @@ void AVDemuxThread::processNextSeekTask() bool AVDemuxThread::hasSeekTasks() { + // This is not great. But I couldn't figure out how to get QTimers and stepBackwardTask working + if (stepping && stepping_timeout_time > 0 && stepping_timeout_time < QDateTime::currentMSecsSinceEpoch()) { + finishedStepBackward(); + } return !seek_tasks.isEmpty() || current_seek_task || stepping; } @@ -495,12 +495,6 @@ void AVDemuxThread::stepForward() connect(t, SIGNAL(frameDelivered()), this, SLOT(frameDeliveredOnStepForward()), Qt::DirectConnection); connect(t, SIGNAL(eofDecoded()), this, SLOT(eofDecodedOnStepForward()), Qt::DirectConnection); - // In case we never get a frame, set a timeout. - auto timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), this, SLOT(frameDeliveredOnStepForward())); - timer->start(200); - step_timeout_timer = timer; - connected = true; } } @@ -551,7 +545,7 @@ void AVDemuxThread::frameDeliveredOnStepForward() // Fudge the bit at the end + 33ms so that step forward and step backwards present different values last_seek_pos = (thread->previousHistoryPts() - thread->clock()->initialValue())*1000.0 + 33; - stepForwardDone(); + stepping = false; Q_EMIT stepFinished(); } @@ -572,18 +566,14 @@ void AVDemuxThread::eofDecodedOnStepForward() clock_type = -1; } - stepForwardDone(); + stepping = false; Q_EMIT stepFinished(); } void AVDemuxThread::stepForwardDone() { - if (step_timeout_timer) { - step_timeout_timer->stop(); - step_timeout_timer = nullptr; - } - stepping = false; + } void AVDemuxThread::onAVThreadQuit() diff --git a/src/AVDemuxThread.h b/src/AVDemuxThread.h index 6c05942fe..624b3c0d4 100644 --- a/src/AVDemuxThread.h +++ b/src/AVDemuxThread.h @@ -108,7 +108,7 @@ private slots: qint64 last_seek_pos; QRunnable *current_seek_task; bool stepping; - QTimer *step_timeout_timer; + qint64 stepping_timeout_time; QSemaphore sem; QMutex next_frame_mutex; From 75a0c1ef6930796880f3d474865d59528be56421 Mon Sep 17 00:00:00 2001 From: Mike Odom <5105729+ThatOdieGuy@users.noreply.github.com> Date: Sat, 5 Oct 2019 13:36:13 -0700 Subject: [PATCH 08/31] Replacing tabs with spaces I don't know what editor I was using that put tabs in! --- src/AVDemuxThread.cpp | 2 +- src/AVPlayer.cpp | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/AVDemuxThread.cpp b/src/AVDemuxThread.cpp index 995c035f6..552da2295 100644 --- a/src/AVDemuxThread.cpp +++ b/src/AVDemuxThread.cpp @@ -364,7 +364,7 @@ bool AVDemuxThread::hasSeekTasks() if (stepping && stepping_timeout_time > 0 && stepping_timeout_time < QDateTime::currentMSecsSinceEpoch()) { finishedStepBackward(); } - return !seek_tasks.isEmpty() || current_seek_task || stepping; + return !seek_tasks.isEmpty() || current_seek_task || stepping; } qint64 AVDemuxThread::lastSeekPos() diff --git a/src/AVPlayer.cpp b/src/AVPlayer.cpp index 8bef91aad..b5e05136b 100644 --- a/src/AVPlayer.cpp +++ b/src/AVPlayer.cpp @@ -860,25 +860,25 @@ qint64 AVPlayer::position() const qint64 AVPlayer::displayPosition() const { - // Return a cached value if there are seek tasks - if (d->seeking || d->read_thread->hasSeekTasks() || (d->read_thread->buffer() && d->read_thread->buffer()->isBuffering())) { - return d->last_known_good_pts = d->read_thread->lastSeekPos(); - } + // Return a cached value if there are seek tasks + if (d->seeking || d->read_thread->hasSeekTasks() || (d->read_thread->buffer() && d->read_thread->buffer()->isBuffering())) { + return d->last_known_good_pts = d->read_thread->lastSeekPos(); + } - // TODO: videoTime()? - qint64 pts = d->clock->videoTime()*1000.0; + // TODO: videoTime()? + qint64 pts = d->clock->videoTime()*1000.0; // If we are stepping around, we want the lastSeekPos. /// But if we're just paused by the user... we want another value. if (d->was_stepping) { pts = d->read_thread->lastSeekPos(); } - if (pts < 0) { - return d->last_known_good_pts; - } - d->last_known_good_pts = pts; + if (pts < 0) { + return d->last_known_good_pts; + } + d->last_known_good_pts = pts; - return pts; + return pts; } void AVPlayer::setPosition(qint64 position) @@ -1582,9 +1582,9 @@ void AVPlayer::stepForward() void AVPlayer::stepBackward() { - pause(true); + pause(true); d->was_stepping = true; - d->read_thread->stepBackward(); + d->read_thread->stepBackward(); } void AVPlayer::seek(qreal r) From cf06dbbed3dfd42c17634ac011e4110191381e08 Mon Sep 17 00:00:00 2001 From: Mike Odom <5105729+ThatOdieGuy@users.noreply.github.com> Date: Sat, 5 Oct 2019 13:40:30 -0700 Subject: [PATCH 09/31] Replacing tabs with spaces --- src/AVDemuxThread.cpp | 2 +- src/AVDemuxThread.h | 4 ++-- src/AVPlayerPrivate.h | 2 +- src/QtAV/AVPlayer.h | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/AVDemuxThread.cpp b/src/AVDemuxThread.cpp index 552da2295..432cee641 100644 --- a/src/AVDemuxThread.cpp +++ b/src/AVDemuxThread.cpp @@ -272,7 +272,7 @@ void AVDemuxThread::seek(qint64 external_pos, qint64 pos, SeekType type) }; end = false; - // queue maybe blocked by put() + // queue maybe blocked by put() // These must be here or seeking while paused will not update the video frame if (audio_thread) { audio_thread->packetQueue()->clear(); diff --git a/src/AVDemuxThread.h b/src/AVDemuxThread.h index 624b3c0d4..6d9953783 100644 --- a/src/AVDemuxThread.h +++ b/src/AVDemuxThread.h @@ -60,8 +60,8 @@ class AVDemuxThread : public QThread MediaEndAction mediaEndAction() const; void setMediaEndAction(MediaEndAction value); bool waitForStarted(int msec = -1); - qint64 lastSeekPos(); - bool hasSeekTasks(); + qint64 lastSeekPos(); + bool hasSeekTasks(); Q_SIGNALS: void requestClockPause(bool value); void mediaStatusChanged(QtAV::MediaStatus); diff --git a/src/AVPlayerPrivate.h b/src/AVPlayerPrivate.h index e7be85807..77e45f06a 100644 --- a/src/AVPlayerPrivate.h +++ b/src/AVPlayerPrivate.h @@ -111,7 +111,7 @@ class AVPlayer::Private bool reset_state; qint64 start_position, stop_position; qint64 start_position_norm, stop_position_norm; // real position - qint64 last_known_good_pts; + qint64 last_known_good_pts; bool was_stepping; int repeat_max, repeat_current; int timer_id; //notify position change and check AB repeat range. active when playing diff --git a/src/QtAV/AVPlayer.h b/src/QtAV/AVPlayer.h index 11ae4d6a5..368cdbfe6 100644 --- a/src/QtAV/AVPlayer.h +++ b/src/QtAV/AVPlayer.h @@ -178,8 +178,8 @@ class Q_AV_EXPORT AVPlayer : public QObject */ qint64 stopPosition() const; //unit: ms qint64 position() const; //unit: ms - qint64 displayPosition() const; - //0: play once. N: play N+1 times. <0: infinity + qint64 displayPosition() const; + //0: play once. N: play N+1 times. <0: infinity int repeat() const; //or repeatMax()? /*! * \brief currentRepeat From 5abba7f0505e75fceabd4dd8992a7e02bb149d64 Mon Sep 17 00:00:00 2001 From: Alexander Ivash Date: Tue, 24 Dec 2019 16:04:25 +0300 Subject: [PATCH 10/31] add include --- qml/SGVideoNode.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/qml/SGVideoNode.cpp b/qml/SGVideoNode.cpp index b12089d8e..3f2a07d72 100644 --- a/qml/SGVideoNode.cpp +++ b/qml/SGVideoNode.cpp @@ -25,6 +25,7 @@ #include "QtAV/VideoFrame.h" #include #include +#include #include // all in QSGRenderThread From 79ad87bef9dd70ef6ccc3e45324e30801dd8a7a8 Mon Sep 17 00:00:00 2001 From: Artem Hlumov Date: Sat, 11 Jan 2020 16:59:06 +0100 Subject: [PATCH 11/31] Fix video flickering --- src/VideoThread.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/VideoThread.cpp b/src/VideoThread.cpp index aa677ac26..2b74d106c 100644 --- a/src/VideoThread.cpp +++ b/src/VideoThread.cpp @@ -506,7 +506,6 @@ void VideoThread::run() break; } pkt = Packet(); - v_a = 0; //? continue; } // reduce here to ensure to decode the rest data in the next loop @@ -519,7 +518,6 @@ void VideoThread::run() pkt = Packet(); else pkt_data = pkt.data.constData(); - v_a = 0; //? continue; } pkt_data = pkt.data.constData(); From 2400e073beff3e466522e98ba1011bd11f6647cc Mon Sep 17 00:00:00 2001 From: Ilja Booij Date: Sun, 2 Feb 2020 08:00:48 +0100 Subject: [PATCH 12/31] Possible fix for crash that occurred when external monitor was switched on MacOS --- src/opengl/OpenGLVideo.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/opengl/OpenGLVideo.cpp b/src/opengl/OpenGLVideo.cpp index 8d8e48acc..3d1ad8fb2 100644 --- a/src/opengl/OpenGLVideo.cpp +++ b/src/opengl/OpenGLVideo.cpp @@ -392,7 +392,10 @@ void OpenGLVideo::updateViewport() #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) QSizeF surfaceSize = d.ctx->surface()->size(); #if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0) - surfaceSize *= d.ctx->screen()->devicePixelRatio(); + // When changing monitors (plugging and unplugging), the screen might sometimes be nullptr! + if (d.ctx->screen()) { + surfaceSize *= d.ctx->screen()->devicePixelRatio(); + } #else surfaceSize *= qApp->devicePixelRatio(); //TODO: window()->devicePixelRatio() is the window screen's #endif From d4ca5dfe5d2482968624be4c807ad3967be60347 Mon Sep 17 00:00:00 2001 From: Casper Meijn Date: Sat, 15 Jun 2019 16:44:53 +0200 Subject: [PATCH 13/31] cmake: Use pkg-config for finding libav libraries --- src/CMakeLists.txt | 91 ++++++++++++++++++++++++++++++---------------- 1 file changed, 59 insertions(+), 32 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index db84dbf89..1d93427ae 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,6 +12,8 @@ INCLUDE(CheckTypeSize) include_directories(${QTDIR}/include) #TODO: remove. use external/include get_filename_component(QTDIR "${QTDIR}" ABSOLUTE) +find_package(PkgConfig) + list(APPEND EXTRA_INCLUDE ${QTAV_SOURCE_DIR}/external/include) list(APPEND EXTRA_LIBS ${CMAKE_LIBRARY_PATH_FLAG}${QTAV_SOURCE_DIR}/external/lib) if(APPLE) @@ -28,39 +30,56 @@ if(EXISTS ${QTAV_SOURCE_DIR}/contrib/capi/capi.h) list(APPEND EXTRA_DEFS -DQTAV_HAVE_CAPI=1) endif() -# check ffmpeg headers. assume libs exist. lib order matters if they are static -set(AVMODULES avformat avcodec swscale avutil) # avdevice avfilter avresample swscale) -# CMAKE_FIND_ROOT_PATH_BOTH: ensure find_file can search from given paths for cross compiling, may be set to ONLY in toolchain file -foreach(av ${AVMODULES}) - string(TOUPPER ${av} AV) - find_file(HAVE_${AV} lib${av}/${av}.h HINTS ${EXTRA_INCLUDE} PATHS ${EXTRA_INCLUDE} CMAKE_FIND_ROOT_PATH_BOTH) - message("HAVE_${AV}: ${HAVE_${AV}}") - if(NOT ${HAVE_${AV}} MATCHES HAVE_${AV}-NOTFOUND) - set(HAVE_${AV} 1) - list(APPEND EXTRA_LIBS ${av}) - list(APPEND EXTRA_DEFS "-DQTAV_HAVE_${AV}=1") - else() - message(FATAL_ERROR "${av} is required") - endif() - #check_include_file(lib${av}/${av}.h HAVE_${AV}) # -D__STDC_CONSTANT_MACROS is required! -endforeach() +pkg_check_modules (AVFORMAT libavformat REQUIRED) +if(${AVFORMAT_FOUND}) + list(APPEND PKG_CONFIG_MODULES AVFORMAT) + message("Found AVFORMAT: ${AVFORMAT_LINK_LIBRARIES}") +endif() -foreach(av avfilter avdevice avresample swresample) - string(TOUPPER ${av} AV) - find_file(HAVE_${AV} lib${av}/${av}.h HINTS ${EXTRA_INCLUDE} PATHS ${EXTRA_INCLUDE} CMAKE_FIND_ROOT_PATH_BOTH) - message("HAVE_${AV}: ${HAVE_${AV}}") - if(NOT ${HAVE_${AV}} MATCHES HAVE_${AV}-NOTFOUND) - set(HAVE_${AV} 1) - list(APPEND EXTRA_LIBS ${av}) - list(APPEND EXTRA_DEFS "-DQTAV_HAVE_${AV}=1") - list(APPEND AVMODULES ${av}) - endif() -endforeach() +pkg_check_modules (AVCODEC libavcodec REQUIRED) +if(${AVCODEC_FOUND}) + list(APPEND PKG_CONFIG_MODULES AVCODEC) + message("Found AVCODEC: ${AVCODEC_LINK_LIBRARIES}") +endif() + +pkg_check_modules (SWSCALE libswscale REQUIRED) +if(${SWSCALE_FOUND}) + list(APPEND PKG_CONFIG_MODULES SWSCALE) + message("Found SWSCALE: ${SWSCALE_LINK_LIBRARIES}") +endif() + +pkg_check_modules (AVUTIL libavutil REQUIRED) +if(${AVUTIL_FOUND}) + list(APPEND PKG_CONFIG_MODULES AVUTIL) + message("Found AVUTIL: ${AVUTIL_LINK_LIBRARIES}") +endif() -if (NOT HAVE_SWRESAMPLE) - if (NOT HAVE_AVRESAMPLE) +pkg_check_modules (AVFILTER libavfilter) +if(${AVFILTER_FOUND}) + list(APPEND PKG_CONFIG_MODULES AVFILTER) + message("Found AVFILTER: ${AVFILTER_LINK_LIBRARIES}") +endif() + +pkg_check_modules (AVDEVICE libavdevice) +if(${AVDEVICE_FOUND}) + list(APPEND PKG_CONFIG_MODULES AVDEVICE) + message("Found AVDEVICE: ${AVDEVICE_LINK_LIBRARIES}") +endif() + +pkg_check_modules (AVRESAMPLE libavresample) +if(${AVRESAMPLE_FOUND}) + list(APPEND PKG_CONFIG_MODULES AVRESAMPLE) + message("Found AVRESAMPLE: ${AVRESAMPLE_LINK_LIBRARIES}") +endif() + +pkg_check_modules (SWRESAMPLE libswresample) +if(${SWRESAMPLE_FOUND}) + list(APPEND PKG_CONFIG_MODULES SWRESAMPLE) + message("Found SWRESAMPLE: ${SWRESAMPLE_LINK_LIBRARIES}") +endif() + +if (NOT AVRESAMPLE_FOUND AND NOT SWRESAMPLE_FOUND) message(FATAL_ERROR "swresample or avresample is required") - endif() endif() list(APPEND EXTRA_DEFS -DBUILD_QTAV_LIB -D__STDC_CONSTANT_MACROS) @@ -178,10 +197,10 @@ foreach (D ${DEP_H}) endif() endforeach() -if (HAVE_AVRESAMPLE) +if (AVRESAMPLE_FOUND) list(APPEND SOURCES AudioResamplerLibav.cpp) endif() -if (HAVE_SWRESAMPLE) +if (SWRESAMPLE_FOUND) list(APPEND SOURCES AudioResamplerFF.cpp) endif() @@ -484,6 +503,14 @@ target_link_libraries(${MODULE} LINK_PRIVATE ${EXTRA_LIBS} LINK_PUBLIC Qt5::Core Qt5::Gui # will add include dirs, macros etc. ) + +foreach(PKG_CONFIG_MODULE ${PKG_CONFIG_MODULES}) + target_link_libraries(${MODULE} PRIVATE ${${PKG_CONFIG_MODULE}_LINK_LIBRARIES}) + target_include_directories(${MODULE} PRIVATE ${${PKG_CONFIG_MODULE}_INCLUDE_DIRS}) + target_compile_options(${MODULE} PRIVATE ${${PKG_CONFIG_MODULE}_CFLAGS_OTHER}) + target_compile_definitions(${MODULE} PRIVATE -DQTAV_HAVE_${PKG_CONFIG_MODULE}=1) +endforeach() + set_target_properties(${MODULE} PROPERTIES MACOSX_RPATH ON FRAMEWORK ON From 00048c3f7c405a986cb6c5781349d1db3be2ea5d Mon Sep 17 00:00:00 2001 From: Casper Meijn Date: Sat, 15 Jun 2019 20:33:13 +0200 Subject: [PATCH 14/31] cmake: fix capi logic for Android EGL --- src/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1d93427ae..7781fd632 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -326,13 +326,13 @@ if(HAVE_OPENGL) endif() endif() -if(HAVE_EGL) +if(HAVE_EGL AND HAVE_CAPI) list(APPEND SOURCES capi/egl_api.cpp) # TODO: X11Extras if(DEFINED Qt5Gui_EGL_INCLUDE_DIRS) # ANGLE list(APPEND EXTRA_INCLUDE ${Qt5Gui_EGL_INCLUDE_DIRS}) #list(APPEND EXTRA_DEFS -DQTAV_HAVE_QT_EGL=1) - if(HAVE_CAPI AND NOT IOS) + if(NOT IOS) list(APPEND EXTRA_DEFS -DQTAV_HAVE_EGL_CAPI=1) if(WindowsPhone OR WindowsStore) list(APPEND EXTRA_DEFS -DCAPI_LINK_EGL) From 60acacad51f0d5dad00ea7969f762becf3834ba5 Mon Sep 17 00:00:00 2001 From: Casper Meijn Date: Sun, 16 Jun 2019 17:07:15 +0200 Subject: [PATCH 15/31] cmake: Change qmldir to lib/qml This is in line with KDE (see https://api.kde.org/ecm/kde-module/KDEInstallDirs.html#QMLDIR) --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 88746affe..7ef92f463 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,7 +74,7 @@ if(NOT CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(QTAV_INSTALL_HEADERS ${CMAKE_INSTALL_PREFIX}/include) set(QTAV_INSTALL_LIBS ${CMAKE_INSTALL_PREFIX}/lib) set(QTAV_INSTALL_BINS ${CMAKE_INSTALL_PREFIX}/bin) - set(QTAV_INSTALL_QML ${CMAKE_INSTALL_PREFIX}/qml) + set(QTAV_INSTALL_QML ${QTAV_INSTALL_LIBS}/qml) else() set(CMAKE_INSTALL_PREFIX ${QT_INSTALL_PREFIX} CACHE PATH "default install path" FORCE) set(QTAV_INSTALL_HEADERS ${QT_INSTALL_HEADERS}) From 8f7363195931b4dc1a1a1e16f413ad814b061b0d Mon Sep 17 00:00:00 2001 From: Alexander Ivash Date: Thu, 27 Feb 2020 03:00:37 +0300 Subject: [PATCH 16/31] expose stepFinished signal to AVPlayer --- src/AVPlayer.cpp | 6 ++++++ src/QtAV/AVPlayer.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/AVPlayer.cpp b/src/AVPlayer.cpp index b5e05136b..d5c5c216b 100644 --- a/src/AVPlayer.cpp +++ b/src/AVPlayer.cpp @@ -94,6 +94,7 @@ AVPlayer::AVPlayer(QObject *parent) : connect(d->read_thread, SIGNAL(mediaStatusChanged(QtAV::MediaStatus)), this, SLOT(updateMediaStatus(QtAV::MediaStatus))); connect(d->read_thread, SIGNAL(bufferProgressChanged(qreal)), this, SIGNAL(bufferProgressChanged(qreal))); connect(d->read_thread, SIGNAL(seekFinished(qint64)), this, SLOT(onSeekFinished(qint64)), Qt::DirectConnection); + connect(d->read_thread, SIGNAL(stepFinished()), this, SLOT(onStepFinished()), Qt::DirectConnection); connect(d->read_thread, SIGNAL(internalSubtitlePacketRead(int, QtAV::Packet)), this, SIGNAL(internalSubtitlePacketRead(int, QtAV::Packet)), Qt::DirectConnection); d->vcapture = new VideoCapture(this); } @@ -1414,6 +1415,11 @@ void AVPlayer::onSeekFinished(qint64 value) Q_EMIT positionChanged(value); } +void AVPlayer::onStepFinished() +{ + Q_EMIT stepFinished(); +} + void AVPlayer::tryClearVideoRenderers() { if (!d->vthread) { diff --git a/src/QtAV/AVPlayer.h b/src/QtAV/AVPlayer.h index 368cdbfe6..329aa3c95 100644 --- a/src/QtAV/AVPlayer.h +++ b/src/QtAV/AVPlayer.h @@ -576,6 +576,7 @@ public Q_SLOTS: * \param position The video or audio timestamp when seek is finished */ void seekFinished(qint64 position); + void stepFinished(); void positionChanged(qint64 position); void interruptTimeoutChanged(); void interruptOnTimeoutChanged(); @@ -616,6 +617,7 @@ private Q_SLOTS: void onStarted(); void updateMediaStatus(QtAV::MediaStatus status); void onSeekFinished(qint64 value); + void onStepFinished(); void tryClearVideoRenderers(); void seekChapter(int incr); protected: From 039be0bcb41be4b2311d3d16c54ecfe519ed02ab Mon Sep 17 00:00:00 2001 From: Mladen Milinkovic Date: Mon, 9 Mar 2020 11:58:11 +0100 Subject: [PATCH 17/31] Fix make install with alernate root path --- deploy.pri | 14 +++++++------- .../qtquick2applicationviewer.pri | 8 ++++---- src/libQtAV.pro | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/deploy.pri b/deploy.pri index 3abbde999..0efa9ea4b 100644 --- a/deploy.pri +++ b/deploy.pri @@ -4,7 +4,7 @@ INSTALL_PREFIX = /usr/local share.files = $$PROJECTROOT/qtc_packaging/common/changelog \ $$PROJECTROOT/qtc_packaging/common/copyright \ $$PROJECTROOT/qtc_packaging/common/README -share.path = /usr/share/doc/$${TARGET} +share.path = $$[QT_INSTALL_PREFIX]/share/doc/$${TARGET} isEqual(TEMPLATE, app) { unix:!symbian { @@ -12,22 +12,22 @@ isEqual(TEMPLATE, app) { DEFINES += CACHE_APPDIR INSTALL_PREFIX = /opt/$${TARGET} desktopfile.files = $$PROJECTROOT/qtc_packaging/debian_harmattan/$${TARGET}.desktop - desktopfile.path = /usr/share/applications + desktopfile.path = $$[QT_INSTALL_PREFIX]/share/applications icon.files = $$PROJECTROOT/qtc_packaging/debian_harmattan/$${TARGET}.png - icon.path = /usr/share/icons/hicolor/80x80/apps + icon.path = $$[QT_INSTALL_PREFIX]/share/icons/hicolor/80x80/apps #debian.files = $$PROJECTROOT/qtc_packaging/harmattan/control } else:maemo5 { INSTALL_PREFIX = /opt/$${TARGET} desktopfile.files = $$PROJECTROOT/qtc_packaging/debian_fremantle/$${TARGET}.desktop - desktopfile.path = /usr/share/applications/hildon + desktopfile.path = $$[QT_INSTALL_PREFIX]/share/applications/hildon icon.files = $$PROJECTROOT/qtc_packaging/debian_fremantle/$${TARGET}.png - icon.path = /usr/share/icons/hicolor/64x64/apps + icon.path = $$[QT_INSTALL_PREFIX]/share/icons/hicolor/64x64/apps #debian.files = $$PROJECTROOT/qtc_packaging/fremantle/control } else { desktopfile.files = $$PROJECTROOT/qtc_packaging/debian_generic/$${TARGET}.desktop - desktopfile.path = /usr/share/applications + desktopfile.path = $$[QT_INSTALL_PREFIX]/share/applications icon.files = $$PROJECTROOT/qtc_packaging/debian_generic/$${TARGET}.png - icon.path = /usr/share/icons/hicolor/64x64/apps + icon.path = $$[QT_INSTALL_PREFIX]/share/icons/hicolor/64x64/apps #debian.files = $$PROJECTROOT/qtc_packaging/generic/control } INSTALLS += desktopfile icon diff --git a/examples/QMLPlayer/qtquick2applicationviewer/qtquick2applicationviewer.pri b/examples/QMLPlayer/qtquick2applicationviewer/qtquick2applicationviewer.pri index e5f7990f6..47a18892c 100644 --- a/examples/QMLPlayer/qtquick2applicationviewer/qtquick2applicationviewer.pri +++ b/examples/QMLPlayer/qtquick2applicationviewer/qtquick2applicationviewer.pri @@ -104,14 +104,14 @@ android-no-sdk { } else:unix { maemo5 { desktopfile.files = $${TARGET}.desktop - desktopfile.path = /usr/share/applications/hildon + desktopfile.path = $$[QT_INSTALL_PREFIX]/share/applications/hildon icon.files = $${TARGET}64.png - icon.path = /usr/share/icons/hicolor/64x64/apps + icon.path = $$[QT_INSTALL_PREFIX]/share/icons/hicolor/64x64/apps } else:!isEmpty(MEEGO_VERSION_MAJOR) { desktopfile.files = $${TARGET}_harmattan.desktop - desktopfile.path = /usr/share/applications + desktopfile.path = $$[QT_INSTALL_PREFIX]/share/applications icon.files = $${TARGET}80.png - icon.path = /usr/share/icons/hicolor/80x80/apps + icon.path = $$[QT_INSTALL_PREFIX]/share/icons/hicolor/80x80/apps } else { # Assumed to be a Desktop Unix copyCommand = for(deploymentfolder, DEPLOYMENTFOLDERS) { diff --git a/src/libQtAV.pro b/src/libQtAV.pro index 8e49668c4..8361f628c 100644 --- a/src/libQtAV.pro +++ b/src/libQtAV.pro @@ -621,7 +621,7 @@ mac { unix:!mac:!cross_compile { icon.files = $$PWD/$${TARGET}.svg -icon.path = /usr/share/icons/hicolor/scalable/apps +icon.path = $$[QT_INSTALL_PREFIX]/share/icons/hicolor/scalable/apps INSTALLS += icon #debian DEB_INSTALL_LIST = .$$[QT_INSTALL_LIBS]/libQt*AV.so.* From 84427df90c72e769c68480e3dded1e446d3cc743 Mon Sep 17 00:00:00 2001 From: Adrian Date: Wed, 11 Mar 2020 12:37:57 +0100 Subject: [PATCH 18/31] Fix android build with Qt5.14 --- common.pri | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common.pri b/common.pri index 70101f0b7..9a9a9f135 100644 --- a/common.pri +++ b/common.pri @@ -134,6 +134,7 @@ defineReplace(qtLibName) { } } RET = $$RET$$platformTargetSuffix() + qtAtLeast(5, 14):android:RET = $${RET}_$$ANDROID_TARGET_ARCH !win32: return($$RET) isEmpty(2): VERSION_EXT = $$VERSION @@ -166,6 +167,7 @@ defineReplace(qtSharedLib) { return($$LIB_FULLNAME) } + defineReplace(qtLongName) { unset(LONG_NAME) LONG_NAME = $$1$${_OS}_$$join(TARGET_ARCH,+)$${_EXTRA} From 05eaf254a1986b5ce32a45753b952db58e437a5e Mon Sep 17 00:00:00 2001 From: Adrian Date: Wed, 11 Mar 2020 12:39:10 +0100 Subject: [PATCH 19/31] Fix android build with Qt5.14 --- common.pri | 1 - 1 file changed, 1 deletion(-) diff --git a/common.pri b/common.pri index 9a9a9f135..07608d60c 100644 --- a/common.pri +++ b/common.pri @@ -167,7 +167,6 @@ defineReplace(qtSharedLib) { return($$LIB_FULLNAME) } - defineReplace(qtLongName) { unset(LONG_NAME) LONG_NAME = $$1$${_OS}_$$join(TARGET_ARCH,+)$${_EXTRA} From 935472a7bbd96dda867f8a92568abd77e2ab90c8 Mon Sep 17 00:00:00 2001 From: Adrian Date: Fri, 13 Mar 2020 03:57:42 +0100 Subject: [PATCH 20/31] Avoid setting invalid framerate --- src/AVPlayerPrivate.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/AVPlayerPrivate.cpp b/src/AVPlayerPrivate.cpp index 9b9014f43..5cd5fd6a5 100644 --- a/src/AVPlayerPrivate.cpp +++ b/src/AVPlayerPrivate.cpp @@ -275,7 +275,9 @@ void AVPlayer::Private::initCommonStatistics(int s, Statistics::Common *st, AVCo #if (defined FF_API_R_FRAME_RATE && FF_API_R_FRAME_RATE) //removed in libav10 //FIXME: which 1 should we choose? avg_frame_rate may be nan, r_frame_rate may be wrong(guessed value) else if (stream->r_frame_rate.den && stream->r_frame_rate.num) { - st->frame_rate = av_q2d(stream->r_frame_rate); + if (stream->r_frame_rate.num < 90000) + st->frame_rate = av_q2d(stream->r_frame_rate); + qDebug("%d/%d", stream->r_frame_rate.num, stream->r_frame_rate.den); } #endif //FF_API_R_FRAME_RATE From 04a2bba7e9be167acea2c2e445942067b4a25a40 Mon Sep 17 00:00:00 2001 From: Gilles Caulier Date: Tue, 19 May 2020 15:55:55 +0200 Subject: [PATCH 21/31] Add new CMake option to be able to disable QML interface --- CMakeLists.txt | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ef92f463..f0c84ae58 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,7 @@ option(BUILD_EXAMPLES "Build examples" ON) option(BUILD_PLAYERS "Build players" ON) option(BUILD_TESTS "Build tests" ON) option(BUILD_QT5OPENGL "Build with Qt5 OpenGL module" ON) +option(BUILD_QML "Build QML interfaces" ON) list(APPEND CMAKE_FIND_ROOT_PATH ${QTDIR}) @@ -116,13 +117,17 @@ if(CMAKE_GENERATOR MATCHES "Visual Studio.*") endif() add_subdirectory(src) + find_package(Qt5Widgets) if(Qt5Widgets_FOUND) add_subdirectory(widgets) endif() -find_package(Qt5 COMPONENTS Qml Quick) -if(Qt5Qml_FOUND AND Qt5Quick_FOUND) - add_subdirectory(qml) + +if(BUILD_QML) + find_package(Qt5 COMPONENTS Qml Quick) + if(Qt5Qml_FOUND AND Qt5Quick_FOUND) + add_subdirectory(qml) + endif() endif() if(BUILD_EXAMPLES OR BUILD_PLAYERS) From 5263d9d9ee29303a919d33d52b15acda554226c5 Mon Sep 17 00:00:00 2001 From: rezso Date: Mon, 1 Jun 2020 13:30:21 +0200 Subject: [PATCH 22/31] Fix build with Qt 5.15 Solves https://github.com/wang-bin/QtAV/issues/1309 --- src/QtAV/FilterContext.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/QtAV/FilterContext.h b/src/QtAV/FilterContext.h index 6d2f9a041..7cc2fc1c5 100644 --- a/src/QtAV/FilterContext.h +++ b/src/QtAV/FilterContext.h @@ -26,6 +26,7 @@ #include #include #include +#include /* * QPainterFilterContext, D2DFilterContext, ... */ From 6b285478b82c7fd73f7b32707c39326681a0f694 Mon Sep 17 00:00:00 2001 From: lvzhaobing Date: Mon, 15 Jun 2020 11:25:31 +0800 Subject: [PATCH 23/31] QML Player supports changing notifyInterval --- qml/QmlAV/QmlAVPlayer.h | 9 +++++++-- qml/QmlAVPlayer.cpp | 18 +++++++++++++++++- qml/Video.qml | 3 ++- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/qml/QmlAV/QmlAVPlayer.h b/qml/QmlAV/QmlAVPlayer.h index 9e7eba93a..c0ed79ce7 100644 --- a/qml/QmlAV/QmlAVPlayer.h +++ b/qml/QmlAV/QmlAVPlayer.h @@ -1,4 +1,4 @@ -/****************************************************************************** +/****************************************************************************** QtAV: Multimedia framework based on Qt and FFmpeg Copyright (C) 2012-2017 Wang Bin @@ -98,6 +98,7 @@ class QmlAVPlayer : public QObject, public QQmlParserStatus // TODO: startPosition/stopPosition Q_PROPERTY(QStringList audioBackends READ audioBackends WRITE setAudioBackends NOTIFY audioBackendsChanged) Q_PROPERTY(QStringList supportedAudioBackends READ supportedAudioBackends) + Q_PROPERTY(int notifyInterval READ notifyInterval WRITE setNotifyInterval NOTIFY notifyIntervalChanged) public: enum Loop { Infinite = -1 }; // use (1<<31)-1 @@ -280,6 +281,7 @@ class QmlAVPlayer : public QObject, public QQmlParserStatus QStringList supportedAudioBackends() const; QStringList audioBackends() const; void setAudioBackends(const QStringList& value); + int notifyInterval() const; public Q_SLOTS: void play(); @@ -290,7 +292,7 @@ public Q_SLOTS: void seek(int offset); void seekForward(); void seekBackward(); - + void setNotifyInterval(int notifyInterval); Q_SIGNALS: void volumeChanged(); void mutedChanged(); @@ -340,6 +342,8 @@ public Q_SLOTS: void statusChanged(); void mediaObjectChanged(); void audioBackendsChanged(); + void notifyIntervalChanged(int notifyInterval); + private Q_SLOTS: // connect to signals from player void _q_error(const QtAV::AVError& e); @@ -397,6 +401,7 @@ private Q_SLOTS: QList m_afilters; QList m_vfilters; QStringList m_ao; + int m_notifyInterval; }; #endif // QTAV_QML_AVPLAYER_H diff --git a/qml/QmlAVPlayer.cpp b/qml/QmlAVPlayer.cpp index c76f52d67..2e778b1e2 100644 --- a/qml/QmlAVPlayer.cpp +++ b/qml/QmlAVPlayer.cpp @@ -1,4 +1,4 @@ -/****************************************************************************** +/****************************************************************************** QtAV: Multimedia framework based on Qt and FFmpeg Copyright (C) 2012-2017 Wang Bin @@ -89,6 +89,7 @@ void QmlAVPlayer::classBegin() connect(mpPlayer, SIGNAL(seekableChanged()), SIGNAL(seekableChanged())); connect(mpPlayer, SIGNAL(seekFinished(qint64)), this, SIGNAL(seekFinished()), Qt::DirectConnection); connect(mpPlayer, SIGNAL(bufferProgressChanged(qreal)), SIGNAL(bufferProgressChanged())); + connect(mpPlayer, SIGNAL(notifyIntervalChanged), SIGNAL(notifyIntervalChanged())); connect(this, SIGNAL(channelLayoutChanged()), SLOT(applyChannelLayout())); // direct connection to ensure volume() in slots is correct connect(mpPlayer->audio(), SIGNAL(volumeChanged(qreal)), SLOT(applyVolume()), Qt::DirectConnection); @@ -604,6 +605,13 @@ void QmlAVPlayer::setAudioBackends(const QStringList &value) Q_EMIT audioBackendsChanged(); } +int QmlAVPlayer::notifyInterval() const +{ + if(!mpPlayer) + return -1; + return mpPlayer->notifyInterval(); +} + QStringList QmlAVPlayer::supportedAudioBackends() const { return AudioOutput::backendsAvailable(); @@ -898,6 +906,14 @@ void QmlAVPlayer::seekBackward() mpPlayer->seekBackward(); } +void QmlAVPlayer::setNotifyInterval(int notifyInterval) +{ + if (!mpPlayer) + return; + mpPlayer->setNotifyInterval(notifyInterval); +} + + void QmlAVPlayer::_q_error(const AVError &e) { mError = NoError; diff --git a/qml/Video.qml b/qml/Video.qml index e24ab06d2..868e53685 100644 --- a/qml/Video.qml +++ b/qml/Video.qml @@ -1,4 +1,4 @@ - + import QtQuick 2.0 import QtAV 1.7 @@ -91,6 +91,7 @@ Item { property alias internalVideoTracks: player.internalVideoTracks property alias internalSubtitleTracks: player.internalSubtitleTracks property alias internalSubtitleTrack: player.internalSubtitleTrack + property alias notifyInterval: player.notifyInterval /*** Properties of VideoOutput ***/ /*! \qmlproperty enumeration Video::fillMode From dc3d8ef04adfd4d3fa217e96214d035c35037123 Mon Sep 17 00:00:00 2001 From: lvzhaobing Date: Mon, 15 Jun 2020 11:46:41 +0800 Subject: [PATCH 24/31] A detail modification of code style --- qml/QmlAVPlayer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qml/QmlAVPlayer.cpp b/qml/QmlAVPlayer.cpp index 2e778b1e2..2800b6a7b 100644 --- a/qml/QmlAVPlayer.cpp +++ b/qml/QmlAVPlayer.cpp @@ -89,7 +89,7 @@ void QmlAVPlayer::classBegin() connect(mpPlayer, SIGNAL(seekableChanged()), SIGNAL(seekableChanged())); connect(mpPlayer, SIGNAL(seekFinished(qint64)), this, SIGNAL(seekFinished()), Qt::DirectConnection); connect(mpPlayer, SIGNAL(bufferProgressChanged(qreal)), SIGNAL(bufferProgressChanged())); - connect(mpPlayer, SIGNAL(notifyIntervalChanged), SIGNAL(notifyIntervalChanged())); + connect(mpPlayer, SIGNAL(notifyIntervalChanged()), SIGNAL(notifyIntervalChanged())); connect(this, SIGNAL(channelLayoutChanged()), SLOT(applyChannelLayout())); // direct connection to ensure volume() in slots is correct connect(mpPlayer->audio(), SIGNAL(volumeChanged(qreal)), SLOT(applyVolume()), Qt::DirectConnection); From e3bb7fe84ca5b1c2bfe541a5ed26561e6373e69d Mon Sep 17 00:00:00 2001 From: lvzhaobing Date: Mon, 15 Jun 2020 12:52:56 +0800 Subject: [PATCH 25/31] fix notifyIntervalproperty intellisense problem (cherry picked from commit 4c7c772f5558e1820eab9cfe506f232a71aba63c) --- qml/QmlAV/QmlAVPlayer.h | 1 - qml/plugins.qmltypes | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/qml/QmlAV/QmlAVPlayer.h b/qml/QmlAV/QmlAVPlayer.h index c0ed79ce7..966f459f1 100644 --- a/qml/QmlAV/QmlAVPlayer.h +++ b/qml/QmlAV/QmlAVPlayer.h @@ -401,7 +401,6 @@ private Q_SLOTS: QList m_afilters; QList m_vfilters; QStringList m_ao; - int m_notifyInterval; }; #endif // QTAV_QML_AVPLAYER_H diff --git a/qml/plugins.qmltypes b/qml/plugins.qmltypes index fe3a793f0..4f553af69 100644 --- a/qml/plugins.qmltypes +++ b/qml/plugins.qmltypes @@ -1,4 +1,4 @@ -import QtQuick.tooling 1.1 +import QtQuick.tooling 1.1 // This file describes the plugin-supplied types contained in the library. // It is used for QML tooling purposes only. @@ -248,6 +248,7 @@ Module { Property { name: "videoFilters"; type: "QuickVideoFilter"; isList: true; isReadonly: true } Property { name: "audioBackends"; type: "QStringList" } Property { name: "supportedAudioBackends"; type: "QStringList"; isReadonly: true } + Property { name: "notifyInterval"; type: "int" } Signal { name: "loopCountChanged" } Signal { name: "videoOutChanged" } Signal { name: "paused" } From f6cc32ee098b50f7f4f7ad84ca92681f0e882f88 Mon Sep 17 00:00:00 2001 From: lvzhaobing Date: Wed, 17 Jun 2020 16:46:04 +0800 Subject: [PATCH 26/31] fix signal connection error --- qml/QmlAV/QmlAVPlayer.h | 2 +- qml/QmlAVPlayer.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/qml/QmlAV/QmlAVPlayer.h b/qml/QmlAV/QmlAVPlayer.h index 966f459f1..71513b298 100644 --- a/qml/QmlAV/QmlAVPlayer.h +++ b/qml/QmlAV/QmlAVPlayer.h @@ -342,7 +342,7 @@ public Q_SLOTS: void statusChanged(); void mediaObjectChanged(); void audioBackendsChanged(); - void notifyIntervalChanged(int notifyInterval); + void notifyIntervalChanged(); private Q_SLOTS: // connect to signals from player diff --git a/qml/QmlAVPlayer.cpp b/qml/QmlAVPlayer.cpp index 2800b6a7b..f1bc5a0e2 100644 --- a/qml/QmlAVPlayer.cpp +++ b/qml/QmlAVPlayer.cpp @@ -89,7 +89,7 @@ void QmlAVPlayer::classBegin() connect(mpPlayer, SIGNAL(seekableChanged()), SIGNAL(seekableChanged())); connect(mpPlayer, SIGNAL(seekFinished(qint64)), this, SIGNAL(seekFinished()), Qt::DirectConnection); connect(mpPlayer, SIGNAL(bufferProgressChanged(qreal)), SIGNAL(bufferProgressChanged())); - connect(mpPlayer, SIGNAL(notifyIntervalChanged()), SIGNAL(notifyIntervalChanged())); + connect(mpPlayer, SIGNAL(notifyIntervalChanged()), this,SIGNAL(notifyIntervalChanged())); connect(this, SIGNAL(channelLayoutChanged()), SLOT(applyChannelLayout())); // direct connection to ensure volume() in slots is correct connect(mpPlayer->audio(), SIGNAL(volumeChanged(qreal)), SLOT(applyVolume()), Qt::DirectConnection); From 45ac4c6d002b2a1eb2a1681c1277a4fe1ef823de Mon Sep 17 00:00:00 2001 From: lvzhaobing Date: Wed, 9 Sep 2020 19:13:17 +0800 Subject: [PATCH 27/31] Fixed a QmlMediaPlayer problem: when the video file does not contain audio and autoPlay = false, the video and location are still moving after loaded, although the playback status is pause --- src/AVPlayer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/AVPlayer.cpp b/src/AVPlayer.cpp index d5c5c216b..15a0a10f1 100644 --- a/src/AVPlayer.cpp +++ b/src/AVPlayer.cpp @@ -1520,6 +1520,7 @@ void AVPlayer::timerEvent(QTimerEvent *te) if (te->timerId() == d->timer_id) { // killTimer() should be in the same thread as object. kill here? if (isPaused()) { + d->clock->pause(true); //return; //ensure positionChanged emitted for stepForward() } // active only when playing From 657671983f2432ae9e171d2b3fb3856a97088dc9 Mon Sep 17 00:00:00 2001 From: Alexander Ivash Date: Sun, 17 Jan 2021 23:31:24 +0300 Subject: [PATCH 28/31] notify player about self-pause in case of MediaEndAction_Pause triggering --- src/AVDemuxThread.cpp | 1 + src/AVDemuxThread.h | 1 + src/AVPlayer.cpp | 11 +++++++++++ src/QtAV/AVPlayer.h | 1 + 4 files changed, 14 insertions(+) diff --git a/src/AVDemuxThread.cpp b/src/AVDemuxThread.cpp index 432cee641..85bbdb7c1 100644 --- a/src/AVDemuxThread.cpp +++ b/src/AVDemuxThread.cpp @@ -674,6 +674,7 @@ void AVDemuxThread::run() break; pause(true); Q_EMIT requestClockPause(true); + Q_EMIT mediaEndActionPauseTriggered(); if (aqueue) aqueue->blockEmpty(true); if (vqueue) diff --git a/src/AVDemuxThread.h b/src/AVDemuxThread.h index 6d9953783..5a84ba359 100644 --- a/src/AVDemuxThread.h +++ b/src/AVDemuxThread.h @@ -64,6 +64,7 @@ class AVDemuxThread : public QThread bool hasSeekTasks(); Q_SIGNALS: void requestClockPause(bool value); + void mediaEndActionPauseTriggered(); void mediaStatusChanged(QtAV::MediaStatus); void bufferProgressChanged(qreal); void seekFinished(qint64 timestamp); diff --git a/src/AVPlayer.cpp b/src/AVPlayer.cpp index 15a0a10f1..1996a65a3 100644 --- a/src/AVPlayer.cpp +++ b/src/AVPlayer.cpp @@ -91,6 +91,7 @@ AVPlayer::AVPlayer(QObject *parent) : //direct connection can not sure slot order? connect(d->read_thread, SIGNAL(finished()), this, SLOT(stopFromDemuxerThread()), Qt::DirectConnection); connect(d->read_thread, SIGNAL(requestClockPause(bool)), masterClock(), SLOT(pause(bool)), Qt::DirectConnection); + connect(d->read_thread, SIGNAL(mediaEndActionPauseTriggered()), this, SLOT(onMediaEndActionPauseTriggered())); connect(d->read_thread, SIGNAL(mediaStatusChanged(QtAV::MediaStatus)), this, SLOT(updateMediaStatus(QtAV::MediaStatus))); connect(d->read_thread, SIGNAL(bufferProgressChanged(qreal)), this, SIGNAL(bufferProgressChanged(qreal))); connect(d->read_thread, SIGNAL(seekFinished(qint64)), this, SLOT(onSeekFinished(qint64)), Qt::DirectConnection); @@ -1404,6 +1405,16 @@ void AVPlayer::updateMediaStatus(QtAV::MediaStatus status) Q_EMIT mediaStatusChanged(d->status); } +void AVPlayer::onMediaEndActionPauseTriggered() +{ + if(d->state == PausedState) + return; + + d->state = PausedState; + Q_EMIT stateChanged(d->state); + Q_EMIT paused(true); +} + void AVPlayer::onSeekFinished(qint64 value) { d->seeking = false; diff --git a/src/QtAV/AVPlayer.h b/src/QtAV/AVPlayer.h index 329aa3c95..ea2627db6 100644 --- a/src/QtAV/AVPlayer.h +++ b/src/QtAV/AVPlayer.h @@ -616,6 +616,7 @@ private Q_SLOTS: void stopNotifyTimer(); void onStarted(); void updateMediaStatus(QtAV::MediaStatus status); + void onMediaEndActionPauseTriggered(); void onSeekFinished(qint64 value); void onStepFinished(); void tryClearVideoRenderers(); From fe42d67f5695a58172f5a99dca059aecf82bb25f Mon Sep 17 00:00:00 2001 From: Alexander Ivash Date: Fri, 22 Jan 2021 18:14:44 +0300 Subject: [PATCH 29/31] Qt doesn't use debug suffix for mingw-built libraries, so QtAV shouldn't use it too --- common.pri | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/common.pri b/common.pri index 07608d60c..37d0455eb 100644 --- a/common.pri +++ b/common.pri @@ -109,7 +109,10 @@ defineReplace(platformTargetSuffix) { CONFIG(debug, debug|release) { !debug_and_release|build_pass { mac: return($${suffix}_debug) - win32: return($${suffix}d) + win32: { + win32-g++: return($${suffix}) + !win32-g++: return($${suffix}d) + } } } return($$suffix) From 07db1da47e1bcfa1423d94ad3913348ce9b9dcd5 Mon Sep 17 00:00:00 2001 From: Aron Bierbaum Date: Thu, 12 Jul 2018 14:42:22 -0500 Subject: [PATCH 30/31] Wait for the PositionWatcher thread to stop --- src/output/audio/AudioOutputDSound.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/output/audio/AudioOutputDSound.cpp b/src/output/audio/AudioOutputDSound.cpp index 227fba991..1b7905699 100644 --- a/src/output/audio/AudioOutputDSound.cpp +++ b/src/output/audio/AudioOutputDSound.cpp @@ -193,6 +193,12 @@ bool AudioOutputDSound::close() available = false; destroy(); CloseHandle(notify_event); // FIXME: is it ok if thread is still waiting? + + // Wait for the PositionWatcher thread to stop. + while (watcher.isRunning()) { + watcher.wait(500); + } + return true; } From 59b8bc863a25ab3333a05a305c84dd75a553efc8 Mon Sep 17 00:00:00 2001 From: Aron Bierbaum Date: Tue, 10 Sep 2019 22:38:56 -0500 Subject: [PATCH 31/31] Workaround compile error with SIP_OVERRIDE --- python/sip/QtAVWidgets/GLWidgetRenderer2.sip | 2 +- python/sip/QtAVWidgets/GraphicsItemRenderer.sip | 2 +- python/sip/QtAVWidgets/OpenGLWidgetRenderer.sip | 2 +- python/sip/QtAVWidgets/WidgetRenderer.sip | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/python/sip/QtAVWidgets/GLWidgetRenderer2.sip b/python/sip/QtAVWidgets/GLWidgetRenderer2.sip index 81bebe5e6..3f983d6d4 100644 --- a/python/sip/QtAVWidgets/GLWidgetRenderer2.sip +++ b/python/sip/QtAVWidgets/GLWidgetRenderer2.sip @@ -34,7 +34,7 @@ public: public: GLWidgetRenderer2(QWidget* parent /TransferThis/ = 0, const QGLWidget* shareWidget = 0, Qt::WindowFlags f = 0); - virtual VideoRendererId id(); + VideoRendererId id(); virtual QWidget* widget(); signals: diff --git a/python/sip/QtAVWidgets/GraphicsItemRenderer.sip b/python/sip/QtAVWidgets/GraphicsItemRenderer.sip index fbc520f52..75348448b 100644 --- a/python/sip/QtAVWidgets/GraphicsItemRenderer.sip +++ b/python/sip/QtAVWidgets/GraphicsItemRenderer.sip @@ -34,7 +34,7 @@ public: public: GraphicsItemRenderer(QGraphicsItem* parent /TransferThis/ = 0); - virtual VideoRendererId id(); + VideoRendererId id(); bool isSupported(VideoFormat::PixelFormat pixfmt); diff --git a/python/sip/QtAVWidgets/OpenGLWidgetRenderer.sip b/python/sip/QtAVWidgets/OpenGLWidgetRenderer.sip index 38844862d..aa9768a76 100644 --- a/python/sip/QtAVWidgets/OpenGLWidgetRenderer.sip +++ b/python/sip/QtAVWidgets/OpenGLWidgetRenderer.sip @@ -34,7 +34,7 @@ public: public: explicit OpenGLWidgetRenderer(QWidget* parent /TransferThis/ = 0, Qt::WindowFlags f = 0); - virtual VideoRendererId id(); + VideoRendererId id() const; virtual QWidget* widget(); signals: diff --git a/python/sip/QtAVWidgets/WidgetRenderer.sip b/python/sip/QtAVWidgets/WidgetRenderer.sip index 5f2561b93..b4d38583a 100644 --- a/python/sip/QtAVWidgets/WidgetRenderer.sip +++ b/python/sip/QtAVWidgets/WidgetRenderer.sip @@ -24,7 +24,7 @@ public: public: WidgetRenderer(QWidget* parent /TransferThis/ = 0, Qt::WindowFlags f = 0); - virtual VideoRendererId id(); + VideoRendererId id(); virtual QWidget* widget(); signals: