我有一个音频流,它会播放,然后KVO观察playbackLikelyToKeepUp两次,然后观察playbackBufferEmpty两次就会立即停止播放。首先,我不明白为什么每个消息observeValueForKeyPath都要调用两次。其次,playbackLikelyToKeepUp的存在应该表示不应该发生playbackBufferEmpty。
我应该注意到这是在模拟器和设备中发生的。
- (void)setRetryConnectionTimer:(NSTimer *)newTimer
{
if (_retryConnectionTimer) { // Take care of releasing old Timers here to make things easy.
NSLog(@"[Timer Setter] Timer Exists. Invalidating and releasing.");
[_retryConnectionTimer invalidate];
[_retryConnectionTimer release];
_retryConnectionTimer = nil;
}
_retryConnectionTimer = [newTimer retain];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void *)context {
if (object == self.audioStream && [keyPath isEqualToString:@"status"])
{
if(self.audioStream.status == AVPlayerStatusReadyToPlay)
{
//AVPlayer ready. Kill retry timer.
if(self.retryConnectionTimer){
if([self.retryConnectionTimer isValid]){
NSLog(@"Timer is valid. invalidating and setting to nil.");
[self.retryConnectionTimer invalidate];
self.retryConnectionTimer = nil;
}
}
NSLog(@"Buffering..."); // Allow the buffer to fill some by delaying play message.
[self.audioPlayer performSelector:@selector(play) withObject:nil afterDelay:kBufferSize];
}
}
if ([keyPath isEqualToString:@"playbackBufferEmpty"]){
NSLog(@"BUFFER EMPTY!!!"); // Buffer empty.... why when playbackShouldKeep up was just sent milliseconds ago.
_retries = 0;
[self.audioPlayer pause];
self.retryConnectionTimer = [NSTimer scheduledTimerWithTimeInterval:20.0f
target:self
selector:@selector(tryReconnect:)
userInfo:nil
repeats:YES];
}
if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"]){
NSLog(@"playbackLikelyToKeepUp");
}
}
- (void)tryReconnect:(NSTimer *)sender {
NSLog(@"tryReconnect Called. Retry: %i", _retries);
if (_retries <= kReconnectRetries) {
[self restartStream];
_retries ++;
} else {
NSLog(@"Connection Dropped: invalidating Timer.");
[self.retryConnectionTimer invalidate];
self.retryConnectionTimer = nil;
_retries = 0;
}
}
- (void)restartStream
{
[self.audioStream removeObserver:self forKeyPath:@"status"];
[self.audioStream removeObserver:self forKeyPath:@"playbackBufferEmpty"];
[self.audioStream removeObserver:self forKeyPath:@"playbackLikelyToKeepUp"];
self.audioStream = [AVPlayerItem playerItemWithURL:[NSURL URLWithString:@"http://myaudiostream.com:9094"]];
[self.audioStream addObserver:self forKeyPath:@"status" options:0 context:nil];
[self.audioStream addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil];
[self.audioStream addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil];
NSLog(@"Playing audioPlayer with new AVPlayerItem");
self.audioPlayer = [AVPlayer playerWithPlayerItem:self.audioStream];
}
来自日志。
2014-01-04 13:32:48.121 Audio Test [833:70b] Playing audioPlayer with new AVPlayerItem
2014-01-04 13:32:55.749 Audio Test [833:70b] Buffering...
2014-01-04 13:32:55.752 Audio Test [833:70b] playbackLikelyToKeepUp
2014-01-04 13:36:00.266 Audio Test [833:70b] playbackLikelyToKeepUp
2014-01-04 13:36:00.267 Audio Test [833:70b] BUFFER EMPTY!!!
2014-01-04 13:36:00.267 Audio Test [833:70b] Creating new timer and assigning to self.retryConnectionTimer
2014-01-04 13:36:03.701 Audio Test [833:70b] BUFFER EMPTY!!!
2014-01-04 13:36:03.702 Audio Test [833:70b] Creating new timer and assigning to self.retryConnectionTimer
2014-01-04 13:36:03.702 Audio Test [833:70b] [Timer Setter] Timer Exists. Invalidating and releasing.
2014-01-04 13:36:07.171 Audio Test [833:70b] playbackLikelyToKeepUp
2014-01-04 13:36:23.697 Audio Test [833:70b] tryReconnect Called. Retry: 0
2014-01-04 13:36:23.698 Audio Test [833:70b] Playing audioPlayer with new AVPlayerItem
2014-01-04 13:36:34.002 Audio Test [833:70b] Buffering...
2014-01-04 13:36:34.002 Audio Test [833:70b] Timer is valid. invalidating and setting to nil.
2014-01-04 13:36:34.002 Audio Test [833:70b] [Timer Setter] Timer Exists. Invalidating and releasing.