2013-02-18 26 views
2

當蘋果AVPlayerDemo樣本項目的AVPlayerDemoPlaybackViewController設置mPlayer.usesExternalPlaybackWhileExternalScreenIsActiveYES後,你怎麼節流擦洗因此它不會對AppleTV的落後在AVPlayerDemo擦洗?節流UISlider使用AirPlay的

我的意思是,當你移動滑塊確實快速來回移動時,AppleTV會執行每一個操作,但需要更長的時間才能完成,然後用戶需要滑動。

該演示的問題之一是它使用「Touch Drag Inside」和「Value Changed」事件,這會導致它發送兩次相同的值。如果你刪除「價值改變」它會稍微改善一點,但仍然滯後。

我試過整秒鐘,然後只發送seekToTime當第二次更改,但似乎沒有幫助一樣多。我真正需要做的是發送更少的命令,用戶移動滑塊的速度越快,但用戶移動速度越慢,發送越多。

有關如何完成此任何想法?

回答

3

UISlider已經有點扼殺了自己。移動得越快,從A點到B點的數值越少。這還不足以阻止查找操作在AirPlay上疊加。

可以,但是,使用seekToTime:completionHandler:防止堆起來像這樣:

if(seeking) { 
    return; 
} 

seeking = YES; 
[player seekToTime:CMTimeMakeWithSeconds(time, NSEC_PER_SEC) completionHandler:^(BOOL finished) { 
    seeking = NO; 
}]; 

這滴任何新的追求,直到一個正在進行中結束。這似乎運作良好。在用戶停止清理後,您只需確保發送最後一次搜索操作。

雖然NSTimer可以做同樣的事情,但它不夠準確,並且結果會因連接延遲而異。以這種方式使用的completionHandler確保搜索不會疊加,而不管延遲時間如何。

我還發現UISlider的「Value Changed」操作可能發生在任何觸摸開始操作之前。因此,最好使用觸摸拖動內部/外部操作,而不是觸摸開始後纔會發生。

0

改進盧克回答一些額外的代碼:

static NSTimeInterval ToleranceForAsset(AVAsset *asset) { 
    NSTimeInterval tolerance = 0.0; 
    for (AVAssetTrack *track in asset.tracks) { 
     NSTimeInterval trackTolerance = CMTimeGetSeconds(track.minFrameDuration); 
     tolerance = MAX(tolerance, trackTolerance); 
    } 
    return tolerance; 
} 

@interface MyPlayerWrapper() 

@property (strong, nonatomic) AVPlayer *player; 
@property (assign, nonatomic) NSTimeInterval playerTime; 
@property (assign, nonatomic, getter=isSeeking) BOOL seeking; 
@property (assign, nonatomic) CGFloat latestSetTime; 

@end 

@implementation MyPlayerWrapper 

- (NSTimeInterval)playerTime { 
    return CMTimeGetSeconds(self.player.currentItem.currentTime); 
} 

- (void)setPlayerTime:(NSTimeInterval)playerTime { 
    NSTimeInterval tolerance = ToleranceForAsset(self.player.currentItem.asset); 
    if (tolerance) { 
     // round to nearest seek tolerance (for example 1/30 sec) 
     playerTime = floor(playerTime/tolerance) * tolerance; 
    } 

    self.latestSetTime = playerTime; 
    if (self.isSeeking) { 
     return; 
    } 

    self.seeking = YES; 
    [self.player seekToTime:CMTimeMakeWithSeconds(playerTime, self.player.currentItem.duration.timescale) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero completionHandler:^(BOOL finished) { 
     self.seeking = NO; 
     if (ABS(self.player.currentItem.currentTime - latestSetTime) > MAX(tolerance, DBL_EPSILON)) { 
      self.playerTime = latestSetTime; 
     } 
    }]; 
} 

@end