Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support infinite buff #1373

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/player/config/AVFormatConfigPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@ AVFormatConfigPage::AVFormatConfigPage(QWidget *parent) :
gl->addWidget(m_direct, r++, 0);
gl->addWidget(new QLabel(tr("Probe size")), r, 0, Qt::AlignRight);
m_probeSize = new QSpinBox();
m_probeSize->setMaximum(std::numeric_limits<int>::max());
m_probeSize->setMaximum((std::numeric_limits<int>::max)());
m_probeSize->setMinimum(0);
m_probeSize->setToolTip(tr("0: auto"));
gl->addWidget(m_probeSize, r++, 1, Qt::AlignLeft);
gl->addWidget(new QLabel(tr("Max analyze duration")), r, 0, Qt::AlignRight);
m_analyzeDuration = new QSpinBox();
m_analyzeDuration->setMaximum(std::numeric_limits<int>::max());
m_analyzeDuration->setMaximum((std::numeric_limits<int>::max)());
m_analyzeDuration->setToolTip(tr("0: auto. how many microseconds are analyzed to probe the input"));
gl->addWidget(m_analyzeDuration, r++, 1, Qt::AlignLeft);

Expand Down
91 changes: 77 additions & 14 deletions src/AVDemuxThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ AVDemuxThread::AVDemuxThread(QObject *parent) :
, current_seek_task(nullptr)
, stepping(false)
, stepping_timeout_time(0)
, audioBufferInfinite(false)
, videoBufferInfinite(false)
{
seek_tasks.setCapacity(1);
seek_tasks.blockFull(false);
Expand All @@ -104,6 +106,8 @@ AVDemuxThread::AVDemuxThread(AVDemuxer *dmx, QObject *parent) :
, current_seek_task(nullptr)
, stepping(false)
, stepping_timeout_time(0)
, audioBufferInfinite(false)
, videoBufferInfinite(false)
{
setDemuxer(dmx);
seek_tasks.setCapacity(1);
Expand Down Expand Up @@ -140,11 +144,17 @@ void AVDemuxThread::setAVThread(AVThread*& pOld, AVThread *pNew)

void AVDemuxThread::setAudioThread(AVThread *thread)
{
auto aqueue = thread ? thread->packetQueue() : 0;
if(aqueue)
aqueue->setIsInfinite(audioBufferInfinite);
setAVThread(audio_thread, thread);
}

void AVDemuxThread::setVideoThread(AVThread *thread)
{
auto vqueue = thread ? thread->packetQueue() : 0;
if(vqueue)
vqueue->setIsInfinite(videoBufferInfinite);
setAVThread(video_thread, thread);
}

Expand Down Expand Up @@ -306,7 +316,7 @@ void AVDemuxThread::seekInternal(qint64 pos, SeekType type, qint64 external_pos)
Q_ASSERT(sync_id != 0);
qDebug("demuxer sync id: %d/%d", sync_id, t->clock()->syncId());
t->packetQueue()->clear();
if (external_pos != std::numeric_limits < qint64 >::min() )
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;
Expand Down Expand Up @@ -367,6 +377,32 @@ bool AVDemuxThread::hasSeekTasks()
return !seek_tasks.isEmpty() || current_seek_task || stepping;
}

bool AVDemuxThread::isAudioBufferInfinite() const
{
return audioBufferInfinite;
}

void AVDemuxThread::setIsAudioBufferInfinite(const bool &value)
{
audioBufferInfinite = value;
PacketBuffer *aqueue = audio_thread ? audio_thread->packetQueue() : 0;
if(aqueue)
aqueue->setIsInfinite(audioBufferInfinite);
}

bool AVDemuxThread::isVideoBufferInfinite() const
{
return videoBufferInfinite;
}

void AVDemuxThread::setIsVideoBufferInfinite(const bool &value)
{
videoBufferInfinite = value;
PacketBuffer *vqueue = video_thread ? video_thread->packetQueue() : 0;
if(vqueue)
vqueue->setIsInfinite(videoBufferInfinite);
}

qint64 AVDemuxThread::lastSeekPos()
{
return last_seek_pos;
Expand Down Expand Up @@ -590,7 +626,7 @@ void AVDemuxThread::onAVThreadQuit()

bool AVDemuxThread::waitForStarted(int msec)
{
if (!sem.tryAcquire(1, msec > 0 ? msec : std::numeric_limits<int>::max()))
if (!sem.tryAcquire(1, msec > 0 ? msec : (std::numeric_limits<int>::max)()))
return false;
sem.release(1); //ensure other waitForStarted() calls continue
return true;
Expand All @@ -611,6 +647,10 @@ void AVDemuxThread::run()
qDebug("get av queue a/v thread = %p %p", audio_thread, video_thread);
PacketBuffer *aqueue = audio_thread ? audio_thread->packetQueue() : 0;
PacketBuffer *vqueue = video_thread ? video_thread->packetQueue() : 0;
if(aqueue)
aqueue->setIsInfinite(audioBufferInfinite);
if(vqueue)
vqueue->setIsInfinite(videoBufferInfinite);
// aqueue as a primary buffer: music with/without cover
AVThread* thread = !video_thread || (audio_thread && demuxer->hasAttacedPicture()) ? audio_thread : video_thread;
m_buffer = thread->packetQueue();
Expand All @@ -634,6 +674,14 @@ void AVDemuxThread::run()

AutoSem as(&sem);
Q_UNUSED(as);

if(false){
seek_again:
last_apts = 0;
last_vpts = 0;
end = false;
}

while (!end) {
processNextSeekTask();
//vthread maybe changed by AVPlayer.setPriority() from no dec case
Expand Down Expand Up @@ -693,7 +741,14 @@ void AVDemuxThread::run()
continue; //the queue is empty and will block
}
updateBufferState();
if (!demuxer->readFrame()) {
if(audioBufferInfinite || videoBufferInfinite){
for(int i = 0; i < 500 ; ++i){ // 5 second to avoid 'eof'.... -Gim
if(demuxer->readFrame()){
break;
}
msleep(10);
}
} else if (!demuxer->readFrame()) {
continue;
}
stream = demuxer->stream();
Expand Down Expand Up @@ -752,7 +807,7 @@ void AVDemuxThread::run()
}
// must ensure bufferValue set correctly before continue
if (m_buffer != aqueue)
aqueue->setBufferValue(m_buffer->isBuffering() ? std::numeric_limits<qint64>::max() : buf2);
aqueue->setBufferValue(m_buffer->isBuffering() ? (std::numeric_limits<qint64>::max)() : buf2);
// always block full if no vqueue because empty callback may set false
// attached picture is cover for song, 1 frame
aqueue->blockFull(!video_thread || !video_thread->isRunning() || !vqueue || audio_has_pic);
Expand All @@ -778,26 +833,34 @@ void AVDemuxThread::run()
continue;
}
}
m_buffering = false;
m_buffer = 0;
while (audio_thread && audio_thread->isRunning()) {
qDebug("waiting audio thread.......");
Packet quit_pkt(Packet::createEOF());
quit_pkt.position = 0;
aqueue->put(quit_pkt);
aqueue->blockEmpty(false); //FIXME: why need this
if(!seek_tasks.isEmpty())
goto seek_again;
if(aqueue->isEmpty()){
Packet quit_pkt(Packet::createEOF());
quit_pkt.position = 0;
aqueue->put(quit_pkt);
aqueue->blockEmpty(false); //FIXME: why need this
}
audio_thread->pause(false);
audio_thread->wait(500);
}
while (video_thread && video_thread->isRunning()) {
if(!seek_tasks.isEmpty())
goto seek_again;
qDebug("waiting video thread.......");
Packet quit_pkt(Packet::createEOF());
quit_pkt.position = 0;
vqueue->put(quit_pkt);
vqueue->blockEmpty(false);
if(aqueue->isEmpty()){
Packet quit_pkt(Packet::createEOF());
quit_pkt.position = 0;
vqueue->put(quit_pkt);
vqueue->blockEmpty(false);
}
video_thread->pause(false);
video_thread->wait(500);
}
m_buffering = false;
m_buffer = 0;
thread->disconnect(this, SIGNAL(seekFinished(qint64)));
qDebug("Demux thread stops running....");
if (demuxer->atEnd())
Expand Down
9 changes: 8 additions & 1 deletion src/AVDemuxThread.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ class AVDemuxThread : public QThread
bool waitForStarted(int msec = -1);
qint64 lastSeekPos();
bool hasSeekTasks();

bool isAudioBufferInfinite() const;
void setIsAudioBufferInfinite(const bool &value);
bool isVideoBufferInfinite() const;
void setIsVideoBufferInfinite(const bool &value);
Q_SIGNALS:
void requestClockPause(bool value);
void mediaEndActionPauseTriggered();
Expand Down Expand Up @@ -90,7 +95,7 @@ private slots:
void setAVThread(AVThread *&pOld, AVThread* pNew);
void newSeekRequest(QRunnable *r);
void processNextSeekTask();
void seekInternal(qint64 pos, SeekType type, qint64 external_pos = std::numeric_limits < qint64 >::min()); //must call in AVDemuxThread
void seekInternal(qint64 pos, SeekType type, qint64 external_pos = (std::numeric_limits<qint64>::min)()); //must call in AVDemuxThread
void pauseInternal(bool value);

bool paused;
Expand All @@ -116,6 +121,8 @@ private slots:
int clock_type; // change happens in different threads(direct connection)
friend class SeekTask;
friend class stepBackwardTask;
bool audioBufferInfinite;
bool videoBufferInfinite;
};

} //namespace QtAV
Expand Down
5 changes: 5 additions & 0 deletions src/AVDemuxer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,11 @@ bool AVDemuxer::readFrame()
qWarning("[AVDemuxer] error: %s", av_err2str(ret));
av_packet_unref(&packet); //important!
return false;
} else {
// (under infinite buffer mode...)
// calling the 'av_read_frame' too fast will cause the 'av_read_frame' return 'eof', but it is not over in fact.
// -Gim
d->eof = false;
}
d->stream = packet.stream_index;
//check whether the 1st frame is alreay got. emit only once
Expand Down
22 changes: 21 additions & 1 deletion src/AVPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,26 @@ void AVPlayer::setMediaEndAction(MediaEndAction value)
d->read_thread->setMediaEndAction(value);
}

bool AVPlayer::isAudioBufferInfinite() const
{
return d->read_thread->isAudioBufferInfinite();
}

void AVPlayer::setIsAudioBufferInfinite(const bool &value)
{
d->read_thread->setIsAudioBufferInfinite(value);
}

bool AVPlayer::isVideoBufferInfinite() const
{
return d->read_thread->isVideoBufferInfinite();
}

void AVPlayer::setIsVideoBufferInfinite(const bool &value)
{
d->read_thread->setIsVideoBufferInfinite(value);
}

MediaEndAction AVPlayer::mediaEndAction() const
{
return d->end_action;
Expand Down Expand Up @@ -917,7 +937,7 @@ void AVPlayer::setRepeat(int max)
{
d->repeat_max = max;
if (d->repeat_max < 0)
d->repeat_max = std::numeric_limits<int>::max();
d->repeat_max = (std::numeric_limits<int>::max)();
Q_EMIT repeatChanged(d->repeat_max);
}

Expand Down
2 changes: 1 addition & 1 deletion src/AVPlayerPrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

namespace QtAV {

static const qint64 kInvalidPosition = std::numeric_limits<qint64>::max();
static const qint64 kInvalidPosition = (std::numeric_limits<qint64>::max)();
class AVPlayer::Private
{
public:
Expand Down
2 changes: 1 addition & 1 deletion src/AVThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ void AVThread::setStatistics(Statistics *statistics)

bool AVThread::waitForStarted(int msec)
{
if (!d_func().sem.tryAcquire(1, msec > 0 ? msec : std::numeric_limits<int>::max()))
if (!d_func().sem.tryAcquire(1, msec > 0 ? msec : (std::numeric_limits<int>::max)()))
return false;
d_func().sem.release(1); //ensure another waitForStarted() continues
return true;
Expand Down
2 changes: 1 addition & 1 deletion src/PacketBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ bool PacketBuffer::checkEnough() const

bool PacketBuffer::checkFull() const
{
return buffered() >= qint64(qreal(bufferValue())*bufferMax());
return !checkInfinite() && buffered() >= qint64(qreal(bufferValue())*bufferMax());
}

void PacketBuffer::onPut(const Packet &p)
Expand Down
9 changes: 7 additions & 2 deletions src/QtAV/AVPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,11 @@ class Q_AV_EXPORT AVPlayer : public QObject
MediaEndAction mediaEndAction() const;
void setMediaEndAction(MediaEndAction value);

bool isAudioBufferInfinite() const;
void setIsAudioBufferInfinite(const bool &value);

bool isVideoBufferInfinite() const;
void setIsVideoBufferInfinite(const bool &value);
public Q_SLOTS:
/*!
* \brief load
Expand Down Expand Up @@ -474,12 +479,12 @@ public Q_SLOTS:
* pos < 0: duration() + pos
* With the default value, the playback will not stop until the end of media (including dynamically changed media duration, e.g. recording video)
*/
void setStopPosition(qint64 pos = std::numeric_limits<qint64>::max());
void setStopPosition(qint64 pos = (std::numeric_limits<qint64>::max)());
/*!
* \brief setTimeRange
* Set startPosition and stopPosition. Make sure start <= stop.
*/
void setTimeRange(qint64 start, qint64 stop = std::numeric_limits<qint64>::max());
void setTimeRange(qint64 start, qint64 stop = (std::numeric_limits<qint64>::max)());

bool isSeekable() const;
/*!
Expand Down
6 changes: 3 additions & 3 deletions src/filter/EncodeFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ void AudioEncodeFilter::finish()
return;
qDebug("About finish audio encoding");
AudioFrame f;
f.setTimestamp(std::numeric_limits<qreal>::max());
f.setTimestamp((std::numeric_limits<qreal>::max)());
if (isAsync()) {
Q_EMIT requestToEncode(f);
} else {
Expand Down Expand Up @@ -160,7 +160,7 @@ void AudioEncodeFilter::encode(const AudioFrame& frame)
}
Q_EMIT readyToEncode();
}
if (!frame.isValid() && frame.timestamp() == std::numeric_limits<qreal>::max()) {
if (!frame.isValid() && frame.timestamp() == (std::numeric_limits<qreal>::max)()) {
while (d.enc->encode()) {
qDebug("encode delayed audio frames...");
Q_EMIT frameEncoded(d.enc->encoded());
Expand Down Expand Up @@ -350,7 +350,7 @@ void VideoEncodeFilter::encode(const VideoFrame& frame)
if (f.pixelFormat() != d.enc->pixelFormat() || d.enc->width() != f.width() || d.enc->height() != f.height())
f = f.to(d.enc->pixelFormat(), QSize(d.enc->width(), d.enc->height()));
if (!d.enc->encode(f)) {
if (f.timestamp() == std::numeric_limits<qreal>::max()) {
if (f.timestamp() == (std::numeric_limits<qreal>::max)()) {
Q_EMIT finished();
d.finishing = 0;
}
Expand Down
Loading