diff options
author | Jochen Seemann <seemann.jochen@gmail.com> | 2017-12-04 19:58:20 +0100 |
---|---|---|
committer | Jochen Seemann <seemann.jochen@gmail.com> | 2018-01-08 18:32:55 +0000 |
commit | b9440a3047cfca9ae253e850db31b8e9b08538e7 (patch) | |
tree | 2e31f159349f56d8f0a291518e67329b3fca6340 /src | |
parent | 07166f2da9f9d308f5b0671181954fc37fe21737 (diff) | |
download | qtmultimedia-b9440a3047cfca9ae253e850db31b8e9b08538e7.tar.gz |
AVFoundation: use observer for tracking duration
For getting the duration of a video, Apple advises to use
AVPlayerItem.duration and tracking its duration changes
with an observer.
Task-number: QTBUG-49558
Change-Id: Ia2adc0d23deacd185f8c338f7f44948db2444beb
Reviewed-by: Christian Stromme <christian.stromme@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/avfoundation/mediaplayer/avfmediaplayersession.h | 3 | ||||
-rw-r--r-- | src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm | 41 |
2 files changed, 31 insertions, 13 deletions
diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.h b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.h index ef854e23f..9a55b7b74 100644 --- a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.h +++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.h @@ -105,6 +105,9 @@ public Q_SLOTS: void processLoadStateChange(); void processLoadStateFailure(); + + void processDurationChange(qint64 duration); + Q_SIGNALS: void positionChanged(qint64 position); void durationChanged(qint64 duration); diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm index f4eb8a4ea..b6fe01053 100644 --- a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm +++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm @@ -55,12 +55,14 @@ static NSString* const AVF_PLAYABLE_KEY = @"playable"; static NSString* const AVF_STATUS_KEY = @"status"; //AVPlayer keys -static NSString* const AVF_RATE_KEY = @"rate"; -static NSString* const AVF_CURRENT_ITEM_KEY = @"currentItem"; +static NSString* const AVF_RATE_KEY = @"rate"; +static NSString* const AVF_CURRENT_ITEM_KEY = @"currentItem"; +static NSString* const AVF_CURRENT_ITEM_DURATION_KEY = @"currentItem.duration"; static void *AVFMediaPlayerSessionObserverRateObservationContext = &AVFMediaPlayerSessionObserverRateObservationContext; static void *AVFMediaPlayerSessionObserverStatusObservationContext = &AVFMediaPlayerSessionObserverStatusObservationContext; static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMediaPlayerSessionObserverCurrentItemObservationContext; +static void *AVFMediaPlayerSessionObserverCurrentItemDurationObservationContext = &AVFMediaPlayerSessionObserverCurrentItemDurationObservationContext; @interface AVFMediaPlayerSessionObserver : NSObject { @@ -150,6 +152,7 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe } if (m_player) { [m_player setRate:0.0]; + [m_player removeObserver:self forKeyPath:AVF_CURRENT_ITEM_DURATION_KEY]; [m_player removeObserver:self forKeyPath:AVF_CURRENT_ITEM_KEY]; [m_player removeObserver:self forKeyPath:AVF_RATE_KEY]; [m_player release]; @@ -261,6 +264,12 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:AVFMediaPlayerSessionObserverRateObservationContext]; + //Observe the duration for getting the buffer state + [m_player addObserver:self + forKeyPath:AVF_CURRENT_ITEM_DURATION_KEY + options:0 + context:AVFMediaPlayerSessionObserverCurrentItemDurationObservationContext]; + } -(void) assetFailedToPrepareForPlayback:(NSError *)error @@ -343,6 +352,13 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe if (m_playerItem != newPlayerItem) m_playerItem = newPlayerItem; } + else if (context == AVFMediaPlayerSessionObserverCurrentItemDurationObservationContext) + { + const CMTime time = [m_playerItem duration]; + const qint64 duration = static_cast<qint64>(float(time.value) / float(time.timescale) * 1000.0f); + if (self.session) + QMetaObject::invokeMethod(m_session, "processDurationChange", Qt::AutoConnection, Q_ARG(qint64, duration)); + } else { [super observeValueForKeyPath:path ofObject:object change:change context:context]; @@ -515,13 +531,7 @@ qint64 AVFMediaPlayerSession::duration() const #ifdef QT_DEBUG_AVF qDebug() << Q_FUNC_INFO; #endif - AVPlayerItem *playerItem = [(AVFMediaPlayerSessionObserver*)m_observer playerItem]; - - if (!playerItem) - return 0; - - CMTime time = [playerItem duration]; - return static_cast<quint64>(float(time.value) / float(time.timescale) * 1000.0f); + return m_duration; } int AVFMediaPlayerSession::bufferStatus() const @@ -856,10 +866,6 @@ void AVFMediaPlayerSession::processLoadStateChange(QMediaPlayer::State newState) } } - qint64 currentDuration = duration(); - if (m_duration != currentDuration) - Q_EMIT durationChanged(m_duration = currentDuration); - if (m_requestedPosition != -1) { setPosition(m_requestedPosition); m_requestedPosition = -1; @@ -892,6 +898,15 @@ void AVFMediaPlayerSession::processLoadStateFailure() Q_EMIT stateChanged((m_state = QMediaPlayer::StoppedState)); } +void AVFMediaPlayerSession::processDurationChange(qint64 duration) +{ + if (duration == m_duration) + return; + + m_duration = duration; + Q_EMIT durationChanged(duration); +} + void AVFMediaPlayerSession::processPositionChange() { if (m_state == QMediaPlayer::StoppedState) |