2013-02-18 40 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