Skip to content

Commit

Permalink
add bufferProgress property to player
Browse files Browse the repository at this point in the history
  • Loading branch information
wang-bin committed Mar 19, 2015
1 parent ce7b02b commit df3208c
Show file tree
Hide file tree
Showing 11 changed files with 83 additions and 9 deletions.
9 changes: 8 additions & 1 deletion examples/QMLPlayer/qml/QMLPlayer/main.qml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 101,13 @@ Rectangle {
control.volume = value
}
}
onStatusChanged: {
if (status == MediaPlayer.LoadingMedia)
msg.info("Loading " source)
}
onBufferProgressChanged: {
msg.info("Buffering " Math.floor(bufferProgress*100) "%...")
}
}
Subtitle {
id: subtitle
Expand Down Expand Up @@ -203,7 210,7 @@ Rectangle {
player.play()
}
}
onVolumeChanged: player.volume = volume
volume: player.volume
onOpenFile: fileDialog.open()
onShowInfo: pageLoader.source = "MediaInfoPage.qml"
onShowHelp: pageLoader.source = "About.qml"
Expand Down
8 changes: 7 additions & 1 deletion examples/player/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 166,7 @@ void MainWindow::initPlayer()
connect(mpVolumeSlider, SIGNAL(valueChanged(int)), SLOT(setVolume()));

connect(mpPlayer, SIGNAL(mediaStatusChanged(QtAV::MediaStatus)), SLOT(onMediaStatusChanged()));
connect(mpPlayer, SIGNAL(bufferProgressChanged(qreal)), SLOT(onBufferProgress(qreal)));
connect(mpPlayer, SIGNAL(error(QtAV::AVError)), this, SLOT(handleError(QtAV::AVError)));
connect(mpPlayer, SIGNAL(started()), this, SLOT(onStartPlay()));
connect(mpPlayer, SIGNAL(stopped()), this, SLOT(onStopPlay()));
Expand Down Expand Up @@ -1293,7 1294,12 @@ void MainWindow::onMediaStatusChanged()
onStopPlay();
break;
}
setWindowTitle(status);
setWindowTitle(status " " mTitle);
}

void MainWindow::onBufferProgress(qreal percent)
{
setWindowTitle(QString("Buffering... %1% ").arg(percent*100.0, 0, 'f', 1) mTitle);
}

void MainWindow::onVideoEQEngineChanged()
Expand Down
3 changes: 2 additions & 1 deletion examples/player/MainWindow.h
Original file line number Diff line number Diff line change
@@ -1,6 1,6 @@
/******************************************************************************
QtAV Player Demo: this file is part of QtAV examples
Copyright (C) 2012-2014 Wang Bin <[email protected]>
Copyright (C) 2012-2015 Wang Bin <[email protected]>
* This file is part of QtAV
Expand Down Expand Up @@ -111,6 111,7 @@ private slots:
void onTimeSliderLeave();
void handleError(const QtAV::AVError& e);
void onMediaStatusChanged();
void onBufferProgress(qreal percent);

void onVideoEQEngineChanged();
void onBrightnessChanged(int b);
Expand Down
9 changes: 4 additions & 5 deletions qml/QmlAV/QmlAVPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 29,6 @@
#include <QtAV/AVError.h>
#include <QtAV/CommonTypes.h>

/*!
* Qt.Multimedia like api
* MISSING:
* bufferProgress
*/
namespace QtAV {
class AVPlayer;
}
Expand All @@ -56,6 51,7 @@ class QmlAVPlayer : public QObject, public QQmlParserStatus
Q_PROPERTY(qreal playbackRate READ playbackRate WRITE setPlaybackRate NOTIFY playbackRateChanged)
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
Q_PROPERTY(int loops READ loopCount WRITE setLoopCount NOTIFY loopCountChanged)
Q_PROPERTY(qreal bufferProgress READ bufferProgress NOTIFY bufferProgressChanged)
Q_PROPERTY(bool seekable READ isSeekable NOTIFY seekableChanged)
Q_PROPERTY(MediaMetaData *metaData READ metaData CONSTANT)
Q_PROPERTY(QObject *mediaObject READ mediaObject)
Expand Down Expand Up @@ -136,6 132,8 @@ class QmlAVPlayer : public QObject, public QQmlParserStatus
bool isFastSeek() const;
void setFastSeek(bool value);

qreal bufferProgress() const;

Status status() const;
Error error() const;
QString errorString() const;
Expand Down Expand Up @@ -198,6 196,7 @@ public Q_SLOTS:
void playing();
void seekableChanged();
void fastSeekChanged();
void bufferProgressChanged();
void videoCodecPriorityChanged();
void videoCodecOptionsChanged();
void channelLayoutChanged();
Expand Down
8 changes: 8 additions & 0 deletions qml/QmlAVPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 85,7 @@ void QmlAVPlayer::classBegin()
connect(mpPlayer, SIGNAL(stopped()), SLOT(_q_stopped()));
connect(mpPlayer, SIGNAL(positionChanged(qint64)), SIGNAL(positionChanged()));
connect(mpPlayer, SIGNAL(seekableChanged()), SIGNAL(seekableChanged()));
connect(mpPlayer, SIGNAL(bufferProgressChanged(qreal)), SIGNAL(bufferProgressChanged()));
connect(this, SIGNAL(channelLayoutChanged()), SLOT(applyChannelLayout()));

mVideoCodecs << "FFmpeg";
Expand Down Expand Up @@ -360,6 361,13 @@ void QmlAVPlayer::setFastSeek(bool value)
emit fastSeekChanged();
}

qreal QmlAVPlayer::bufferProgress() const
{
if (!mpPlayer)
return 0;
return mpPlayer->bufferProgress();
}

QmlAVPlayer::Status QmlAVPlayer::status() const
{
return (Status)m_status;
Expand Down
2 changes: 1 addition & 1 deletion qml/Video.qml
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 140,7 @@ Item {
from 0.0 (empty) to 1.0
(full).
*/
//property alias bufferProgress: player.bufferProgress
property alias bufferProgress: player.bufferProgress

/*!
\qmlproperty int Video::duration
Expand Down
1 change: 1 addition & 0 deletions qml/plugins.qmltypes
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 189,7 @@ Module {
Property { name: "playbackRate"; type: "double" }
Property { name: "source"; type: "QUrl" }
Property { name: "loops"; type: "int" }
Property { name: "bufferProgress"; type: "double"; isReadonly: true }
Property { name: "seekable"; type: "bool"; isReadonly: true }
Property { name: "metaData"; type: "MediaMetaData"; isReadonly: true; isPointer: true }
Property { name: "mediaObject"; type: "QObject"; isReadonly: true; isPointer: true }
Expand Down
27 changes: 27 additions & 0 deletions src/AVDemuxThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 60,9 @@ AVDemuxThread::AVDemuxThread(QObject *parent) :
, paused(false)
, user_paused(false)
, end(true)
, m_buffering(false)
, m_buffered(0)
, m_buffer(0)
, demuxer(0)
, audio_thread(0)
, video_thread(0)
Expand All @@ -74,6 77,9 @@ AVDemuxThread::AVDemuxThread(AVDemuxer *dmx, QObject *parent) :
QThread(parent)
, paused(false)
, end(true)
, m_buffering(false)
, m_buffered(0)
, m_buffer(0)
, audio_thread(0)
, video_thread(0)
{
Expand Down Expand Up @@ -240,6 246,11 @@ bool AVDemuxThread::isEnd() const
return end;
}

PacketBuffer* AVDemuxThread::buffer()
{
return m_buffer;
}

//No more data to put. So stop blocking the queue to take the reset elements
void AVDemuxThread::stop()
{
Expand Down Expand Up @@ -269,6 280,9 @@ void AVDemuxThread::stop()
cond.wakeAll();
qDebug("all avthread finished. try to exit demux thread<<<<<<");
end = true;
m_buffering = false;
m_buffered = false;
m_buffer = 0;
}

void AVDemuxThread::pause(bool p)
Expand Down Expand Up @@ -365,6 379,8 @@ void AVDemuxThread::frameDeliveredNextFrame()

void AVDemuxThread::run()
{
m_buffering = false;
m_buffered = false;
end = false;
if (audio_thread && !audio_thread->isRunning())
audio_thread->start(QThread::HighPriority);
Expand All @@ -383,6 399,7 @@ 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;
m_buffer = vqueue ? vqueue : aqueue;
if (aqueue) {
aqueue->clear();
aqueue->setBlocking(true);
Expand Down Expand Up @@ -414,6 431,10 @@ void AVDemuxThread::run()
qDebug("no running avthreads. exit demuxer thread");
break;
}
if (m_buffering != m_buffer->isBuffering()) {
m_buffering = m_buffer->isBuffering();
Q_EMIT mediaStatusChanged(m_buffering ? QtAV::BufferingMedia : QtAV::BufferedMedia);
}
QMutexLocker locker(&buffer_mutex);
Q_UNUSED(locker);
if (!demuxer->readFrame()) {
Expand Down Expand Up @@ -460,6 481,12 @@ void AVDemuxThread::run()
} else { //subtitle
continue;
}
if (m_buffering) {
if (m_buffered != m_buffer->buffered()) {
m_buffered = m_buffer->buffered();
Q_EMIT bufferProgressChanged(m_buffer->bufferProgress());
}
}
}
//flush. seeking will be omitted when stopped
if (aqueue)
Expand Down
7 changes: 7 additions & 0 deletions src/AVDemuxThread.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 48,17 @@ class AVDemuxThread : public QThread
//AVDemuxer* demuxer
bool isPaused() const;
bool isEnd() const;
PacketBuffer* buffer();

public slots:
void stop(); //TODO: remove it?
void pause(bool p);
void nextFrame(); // show next video frame and pause

Q_SIGNALS:
void requestClockPause(bool value);
void mediaStatusChanged(QtAV::MediaStatus);
void bufferProgressChanged(qreal);

private slots:
void frameDeliveredSeekOnPause();
Expand All @@ -79,6 83,9 @@ private slots:
bool paused;
bool user_paused;
volatile bool end;
bool m_buffering;
int m_buffered;
PacketBuffer *m_buffer;
AVDemuxer *demuxer;
AVThread *audio_thread, *video_thread;
int audio_stream, video_stream;
Expand Down
8 changes: 8 additions & 0 deletions src/AVPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 87,8 @@ AVPlayer::AVPlayer(QObject *parent) :
//direct connection can not sure slot order?
connect(d->read_thread, SIGNAL(finished()), this, SLOT(stopFromDemuxerThread()));
connect(d->read_thread, SIGNAL(requestClockPause(bool)), masterClock(), SLOT(pause(bool)), Qt::DirectConnection);
connect(d->read_thread, SIGNAL(mediaStatusChanged(QtAV::MediaStatus)), this, SIGNAL(mediaStatusChanged(QtAV::MediaStatus)));
connect(d->read_thread, SIGNAL(bufferProgressChanged(qreal)), this, SIGNAL(bufferProgressChanged(qreal)));

d->vcapture = new VideoCapture(this);
}
Expand Down Expand Up @@ -1310,6 1312,12 @@ SeekType AVPlayer::seekType() const
return d->seek_type;
}

qreal AVPlayer::bufferProgress() const
{
const PacketBuffer* buf = d->read_thread->buffer();
return buf ? buf->bufferProgress() : 0;
}

void AVPlayer::updateClock(qint64 msecs)
{
d->clock->updateExternalClock(msecs);
Expand Down
10 changes: 10 additions & 0 deletions src/QtAV/AVPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 48,7 @@ class Q_AV_EXPORT AVPlayer : public QObject
Q_PROPERTY(bool autoLoad READ isAutoLoad WRITE setAutoLoad NOTIFY autoLoadChanged)
Q_PROPERTY(bool asyncLoad READ isAsyncLoad WRITE setAsyncLoad NOTIFY asyncLoadChanged)
Q_PROPERTY(bool mute READ isMute WRITE setMute NOTIFY muteChanged)
Q_PROPERTY(qreal bufferProgress READ bufferProgress NOTIFY bufferProgressChanged)
Q_PROPERTY(bool seekable READ isSeekable NOTIFY seekableChanged)
Q_PROPERTY(qint64 position READ position WRITE setPosition NOTIFY positionChanged)
Q_PROPERTY(qint64 startPosition READ startPosition WRITE setStartPosition NOTIFY startPositionChanged)
Expand Down Expand Up @@ -346,6 347,14 @@ public slots:
void seekBackward();
void setSeekType(SeekType type);
SeekType seekType() const;

/*!
* \brief bufferProgress
* How much the data buffer is currently filled. From 0.0 to 1.0.
* Playback can start or resume only when the buffer is entirely filled.
*/
qreal bufferProgress() const;

/*!
* \brief setNotifyInterval
* The interval at which progress will update
Expand All @@ -362,6 371,7 @@ public slots:
void setSaturation(int val);

signals:
void bufferProgressChanged(qreal);
void relativeTimeModeChanged();
void autoLoadChanged();
void asyncLoadChanged();
Expand Down

0 comments on commit df3208c

Please sign in to comment.