Skip to content

Commit e00215d

Browse files
committed
fix seamless loop
1 parent 34afa14 commit e00215d

File tree

3 files changed

+78
-40
lines changed

3 files changed

+78
-40
lines changed

src/AVDemuxThread.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ AVDemuxThread::AVDemuxThread(QObject *parent) :
8282
, audio_thread(0)
8383
, video_thread(0)
8484
, clock_type(-1)
85+
, m_repeat_current(0)
86+
, m_repeat_max(0)
8587
{
8688
seek_tasks.setCapacity(1);
8789
seek_tasks.blockFull(false);
@@ -95,6 +97,8 @@ AVDemuxThread::AVDemuxThread(AVDemuxer *dmx, QObject *parent) :
9597
, m_buffer(0)
9698
, audio_thread(0)
9799
, video_thread(0)
100+
, m_repeat_current(0)
101+
, m_repeat_max(0)
98102
{
99103
setDemuxer(dmx);
100104
seek_tasks.setCapacity(1);
@@ -556,6 +560,14 @@ void AVDemuxThread::run()
556560
//vthread maybe changed by AVPlayer.setPriority() from no dec case
557561
vqueue = video_thread ? video_thread->packetQueue() : 0;
558562
if (demuxer->atEnd()) {
563+
if (getRepeatCurrent() < 0 || (getRepeatCurrent() >= m_repeat_max && m_repeat_max >= 0)) {
564+
m_repeat_current = -1;
565+
} else {
566+
m_repeat_current++;
567+
qDebug() << " m_repeat_current = " << m_repeat_current;
568+
qDebug() << " m_repeat_max = " << m_repeat_max;
569+
seek(qint64(0), AccurateSeek);
570+
}
559571
// if avthread may skip 1st eof packet because of a/v sync
560572
const int kMaxEof = 1;//if buffer packet, we can use qMax(aqueue->bufferValue(), vqueue->bufferValue()) and not call blockEmpty(false);
561573
if (aqueue && (!was_end || aqueue->isEmpty())) {
@@ -731,4 +743,27 @@ bool AVDemuxThread::tryPause(unsigned long timeout)
731743
cond.wait(&buffer_mutex, timeout);
732744
return true;
733745
}
746+
747+
int AVDemuxThread::getRepeatCurrent()
748+
{
749+
return m_repeat_current;
750+
}
751+
752+
void AVDemuxThread::setRepeatCurrent(int repeat_current)
753+
{
754+
m_repeat_current = repeat_current;
755+
}
756+
757+
int AVDemuxThread::getRepeatMax()
758+
{
759+
return m_repeat_max;
760+
}
761+
762+
void AVDemuxThread::setRepeatMax(int repeat_max)
763+
{
764+
m_repeat_max = repeat_max;
765+
if (m_repeat_max < 0)
766+
m_repeat_max = std::numeric_limits<int>::max();
767+
}
768+
734769
} //namespace QtAV

src/AVDemuxThread.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ class AVDemuxThread : public QThread
5959
MediaEndAction mediaEndAction() const;
6060
void setMediaEndAction(MediaEndAction value);
6161
bool waitForStarted(int msec = -1);
62+
int getRepeatCurrent();
63+
int getRepeatMax();
64+
void setRepeatCurrent(int repeat_current);
65+
void setRepeatMax(int repeat_max);
6266
Q_SIGNALS:
6367
void requestClockPause(bool value);
6468
void mediaStatusChanged(QtAV::MediaStatus);
@@ -106,6 +110,8 @@ private slots:
106110
int clock_type; // change happens in different threads(direct connection)
107111
friend class SeekTask;
108112
friend class stepBackwardTask;
113+
int m_repeat_current;
114+
int m_repeat_max;
109115
};
110116

111117
} //namespace QtAV

src/AVPlayer.cpp

Lines changed: 37 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -871,21 +871,19 @@ void AVPlayer::setPosition(qint64 position)
871871

872872
int AVPlayer::repeat() const
873873
{
874-
return d->repeat_max;
874+
return d->read_thread->getRepeatMax();
875875
}
876876

877877
int AVPlayer::currentRepeat() const
878878
{
879-
return d->repeat_current;
879+
return d->read_thread->getRepeatCurrent();
880880
}
881881

882882
// TODO: reset current_repeat?
883883
void AVPlayer::setRepeat(int max)
884884
{
885-
d->repeat_max = max;
886-
if (d->repeat_max < 0)
887-
d->repeat_max = std::numeric_limits<int>::max();
888-
Q_EMIT repeatChanged(d->repeat_max);
885+
d->read_thread->setRepeatMax(max);
886+
Q_EMIT repeatChanged(d->read_thread->getRepeatMax());
889887
}
890888

891889
bool AVPlayer::setExternalAudio(const QString &file)
@@ -1250,8 +1248,8 @@ void AVPlayer::playInternal()
12501248
QMetaObject::invokeMethod(this, "startNotifyTimer", Qt::AutoConnection);
12511249
}
12521250
d->state = PlayingState;
1253-
if (d->repeat_current < 0)
1254-
d->repeat_current = 0;
1251+
if(currentRepeat() < 0)
1252+
d->read_thread->setRepeatCurrent(0);
12551253
} //end lock scoped here to avoid dead lock if connect started() to a slot that call unload()/play()
12561254
if (d->start_position_norm > 0) {
12571255
if (relativeTimeMode())
@@ -1267,34 +1265,30 @@ void AVPlayer::stopFromDemuxerThread()
12671265
{
12681266
qDebug("demuxer thread emit finished. repeat: %d/%d", currentRepeat(), repeat());
12691267
d->seeking = false;
1270-
if (currentRepeat() < 0 || (currentRepeat() >= repeat() && repeat() >= 0)) {
1271-
qreal stop_pts = masterClock()->videoTime();
1272-
if (stop_pts <= 0)
1273-
stop_pts = masterClock()->value();
1274-
masterClock()->reset();
1275-
QMetaObject::invokeMethod(this, "stopNotifyTimer");
1276-
// vars not set by user can be reset
1277-
d->repeat_current = -1;
1278-
d->start_position_norm = 0;
1279-
d->stop_position_norm = kInvalidPosition; // already stopped. so not 0 but invalid. 0 can stop the playback in timerEvent
1280-
d->media_end = kInvalidPosition;
1281-
qDebug("avplayer emit stopped()");
1282-
d->state = StoppedState;
1283-
QMetaObject::invokeMethod(this, "stateChanged", Q_ARG(QtAV::AVPlayer::State, d->state));
1284-
QMetaObject::invokeMethod(this, "stopped");
1285-
QMetaObject::invokeMethod(this, "stoppedAt", Q_ARG(qint64, qint64(stop_pts*1000.0)));
1286-
//Q_EMIT stateChanged(d->state);
1287-
//Q_EMIT stopped();
1288-
//Q_EMIT stoppedAt(stop_pts*1000.0);
12891268

1290-
/*
1291-
* currently preload is not supported. so always unload. Then some properties will be reset, e.g. duration()
1292-
*/
1293-
unload(); //TODO: invoke?
1294-
} else {
1295-
d->repeat_current++;
1296-
QMetaObject::invokeMethod(this, "play"); //ensure play() is called from player thread
1297-
}
1269+
qreal stop_pts = masterClock()->videoTime();
1270+
if (stop_pts <= 0)
1271+
stop_pts = masterClock()->value();
1272+
masterClock()->reset();
1273+
QMetaObject::invokeMethod(this, "stopNotifyTimer");
1274+
// vars not set by user can be reset
1275+
1276+
d->start_position_norm = 0;
1277+
d->stop_position_norm = kInvalidPosition; // already stopped. so not 0 but invalid. 0 can stop the playback in timerEvent
1278+
d->media_end = kInvalidPosition;
1279+
qDebug("avplayer emit stopped()");
1280+
d->state = StoppedState;
1281+
QMetaObject::invokeMethod(this, "stateChanged", Q_ARG(QtAV::AVPlayer::State, d->state));
1282+
QMetaObject::invokeMethod(this, "stopped");
1283+
QMetaObject::invokeMethod(this, "stoppedAt", Q_ARG(qint64, qint64(stop_pts*1000.0)));
1284+
//Q_EMIT stateChanged(d->state);
1285+
//Q_EMIT stopped();
1286+
//Q_EMIT stoppedAt(stop_pts*1000.0);
1287+
1288+
/*
1289+
* currently preload is not supported. so always unload. Then some properties will be reset, e.g. duration()
1290+
*/
1291+
unload(); //TODO: invoke?
12981292
}
12991293

13001294
void AVPlayer::aboutToQuitApp()
@@ -1455,7 +1449,7 @@ void AVPlayer::stop()
14551449
}
14561450
d->seeking = false;
14571451
d->reset_state = true;
1458-
d->repeat_current = -1;
1452+
d->read_thread->setRepeatCurrent(-1);
14591453
if (!isPlaying()) {
14601454
qDebug("Not playing~");
14611455
if (mediaStatus() == LoadingMedia || mediaStatus() == LoadedMedia) {
@@ -1515,22 +1509,25 @@ void AVPlayer::timerEvent(QTimerEvent *te)
15151509
qDebug("stopPosition() == 0, stop");
15161510
stop();
15171511
}
1518-
// t < d->start_position is ok. d->repeat_max<0 means repeat forever
1512+
// t < d->start_position is ok. repeat()< 0 means repeat forever
1513+
15191514
if (currentRepeat() >= repeat() && repeat() >= 0) {
15201515
d->reset_state = true; // true is default, can remove here
15211516
qDebug("stopPosition() %lld/%lld reached and no repeat: %d", t, stopPosition(), repeat());
15221517
stop();
15231518
return;
15241519
}
1520+
15251521
// FIXME: now stop instead of seek if reach media's end. otherwise will not get eof again
15261522
if (d->stop_position_norm == mediaStopPosition() || !isSeekable()) {
15271523
// if not seekable, how it can start to play at specified position?
1528-
qDebug("normalized stopPosition() == mediaStopPosition() or !seekable. d->repeat_current=%d", d->repeat_current);
1524+
qDebug("normalized stopPosition() == mediaStopPosition() or !seekable. currentRepeat()=%d", currentRepeat());
15291525
d->reset_state = false;
15301526
stop(); // repeat after all threads stopped
15311527
} else {
1532-
d->repeat_current++;
1533-
qDebug("noramlized stopPosition() != mediaStopPosition() and seekable. d->repeat_current=%d", d->repeat_current);
1528+
int repeat_current = d->read_thread->getRepeatCurrent();
1529+
d->read_thread->setRepeatCurrent(repeat_current++);
1530+
qDebug("noramlized stopPosition() != mediaStopPosition() and seekable. currentRepeat()=%d", currentRepeat());
15341531
setPosition(d->start_position_norm);
15351532
}
15361533
}

0 commit comments

Comments
 (0)