From 6d14d257a043f4bf790c18a73effc1f8711bedf3 Mon Sep 17 00:00:00 2001 From: Ryan Heise Date: Sat, 1 Aug 2020 14:59:22 +1000 Subject: [PATCH] Implement bufferedPosition on iOS --- darwin/Classes/AudioPlayer.m | 23 +++++++++++++++++++++++ darwin/Classes/ClippingAudioSource.m | 6 ++++++ darwin/Classes/IndexedAudioSource.m | 4 ++++ darwin/Classes/UriAudioSource.m | 11 +++++++++++ ios/Classes/IndexedAudioSource.h | 1 + macos/Classes/IndexedAudioSource.h | 1 + 6 files changed, 46 insertions(+) diff --git a/darwin/Classes/AudioPlayer.m b/darwin/Classes/AudioPlayer.m index fe62e6f..5e0d692 100644 --- a/darwin/Classes/AudioPlayer.m +++ b/darwin/Classes/AudioPlayer.m @@ -28,6 +28,7 @@ long long _updateTime; int _updatePosition; int _lastPosition; + int _bufferedPosition; // Set when the current item hasn't been played yet so we aren't sure whether sufficient audio has been buffered. BOOL _bufferUnconfirmed; CMTime _seekPos; @@ -67,6 +68,7 @@ _updatePosition = 0; _updateTime = 0; _lastPosition = 0; + _bufferedPosition = 0; _bufferUnconfirmed = NO; _playing = NO; _automaticallyWaitsToMinimizeStalling = YES; @@ -330,6 +332,18 @@ } } +- (int)getBufferedPosition { + if (_state == none || _state == connecting) { + return 0; + } else if (_indexedAudioSources) { + int ms = (int)(1000 * CMTimeGetSeconds(_indexedAudioSources[_index].bufferedPosition)); + if (ms < 0) ms = 0; + return ms; + } else { + return 0; + } +} + - (int)getDuration { if (_state == none) { return -1; @@ -368,6 +382,7 @@ // Get notified of the buffer state [playerItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil]; [playerItem addObserver:self forKeyPath:@"playbackBufferFull" options:NSKeyValueObservingOptionNew context:nil]; + [playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil]; //[playerItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil]; // Get notified when playback has reached the end [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onComplete:) name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem]; @@ -781,6 +796,14 @@ // Already at zero, no need to seek. } } + } else if ([keyPath isEqualToString:@"loadedTimeRanges"]) { + IndexedPlayerItem *playerItem = (IndexedPlayerItem *)object; + if (playerItem != _player.currentItem) return; + int pos = [self getBufferedPosition]; + if (pos != _bufferedPosition) { + _bufferedPosition = pos; + [self broadcastPlaybackEvent]; + } } } diff --git a/darwin/Classes/ClippingAudioSource.m b/darwin/Classes/ClippingAudioSource.m index 8f7eb33..b91d723 100644 --- a/darwin/Classes/ClippingAudioSource.m +++ b/darwin/Classes/ClippingAudioSource.m @@ -68,4 +68,10 @@ return CMTimeSubtract(self.playerItem.currentTime, _start); } +- (CMTime)bufferedPosition { + CMTime pos = CMTimeSubtract(_audioSource.bufferedPosition, _start); + CMTime dur = [self duration]; + return CMTimeCompare(pos, dur) >= 0 ? dur : pos; +} + @end diff --git a/darwin/Classes/IndexedAudioSource.m b/darwin/Classes/IndexedAudioSource.m index c3eecdc..316f900 100644 --- a/darwin/Classes/IndexedAudioSource.m +++ b/darwin/Classes/IndexedAudioSource.m @@ -61,4 +61,8 @@ return kCMTimeInvalid; } +- (CMTime)bufferedPosition { + return kCMTimeInvalid; +} + @end diff --git a/darwin/Classes/UriAudioSource.m b/darwin/Classes/UriAudioSource.m index 0bb07a3..8585d18 100644 --- a/darwin/Classes/UriAudioSource.m +++ b/darwin/Classes/UriAudioSource.m @@ -63,4 +63,15 @@ return _playerItem.currentTime; } +- (CMTime)bufferedPosition { + NSValue *last = _playerItem.loadedTimeRanges.lastObject; + if (last) { + CMTimeRange timeRange = [last CMTimeRangeValue]; + return CMTimeAdd(timeRange.start, timeRange.duration); + } else { + return _playerItem.currentTime; + } + return kCMTimeInvalid; +} + @end diff --git a/ios/Classes/IndexedAudioSource.h b/ios/Classes/IndexedAudioSource.h index 21cb3f1..a308a4f 100644 --- a/ios/Classes/IndexedAudioSource.h +++ b/ios/Classes/IndexedAudioSource.h @@ -8,6 +8,7 @@ @property (readonly, nonatomic) IndexedPlayerItem *playerItem; @property (readwrite, nonatomic) CMTime duration; @property (readonly, nonatomic) CMTime position; +@property (readonly, nonatomic) CMTime bufferedPosition; @property (readonly, nonatomic) BOOL isAttached; - (void)attach:(AVQueuePlayer *)player; diff --git a/macos/Classes/IndexedAudioSource.h b/macos/Classes/IndexedAudioSource.h index 94a6e31..7d343d8 100644 --- a/macos/Classes/IndexedAudioSource.h +++ b/macos/Classes/IndexedAudioSource.h @@ -8,6 +8,7 @@ @property (readonly, nonatomic) IndexedPlayerItem *playerItem; @property (readwrite, nonatomic) CMTime duration; @property (readonly, nonatomic) CMTime position; +@property (readonly, nonatomic) CMTime bufferedPosition; @property (readonly, nonatomic) BOOL isAttached; - (void)attach:(AVQueuePlayer *)player;