现在播放指示器与 AVPlayer 播放不同步
Now playing indicator out of sync with AVPlayer playback
我有一个正在播放的指示器视图,这是我为视频播放制作的,大部分情况下它都在工作,但是我注意到我的指示器在播放结束时没有完全同步时间.
视频播放完毕,但没有像应有的那样循环播放,因为指示器的 X 原点没有穿过右洗涤器的 X 原点,这意味着同步不正确。
如果能提供任何帮助,我将不胜感激。这是播放结束时指示器错误定位的图片。
- (void)observePlayerTime
{
CMTime intervalTime = CMTimeMake(33, 1000);
__weak typeof(self) weakSelf = self;
self.playbackObserver = [self.playerLayer.player addPeriodicTimeObserverForInterval:
intervalTime queue:dispatch_get_main_queue() usingBlock:^(CMTime time)
{
UICollectionViewFlowLayout *videoFrameLayout =
(UICollectionViewFlowLayout *)
weakSelf.videoFramesCollectionView.collectionViewLayout;
if (weakSelf.playerLayer.player.rate >= 1.0)
{
CGRect newFrame = weakSelf.nowPlayingIndicatorView.frame;
newFrame.origin.x += (videoFrameLayout.itemSize.width / intervalTime.value);
if (newFrame.origin.x >= weakSelf.rightScrubberView.frame.origin.x)
{
// Here we loop the player
CGRect newIndicatorFrame = weakSelf.nowPlayingIndicatorView.frame;
newIndicatorFrame.origin.x = (weakSelf.leftScrubberView.frame.origin.x
+ weakSelf.leftScrubberView.bounds.size.width)
- newIndicatorFrame.size.width;
weakSelf.nowPlayingIndicatorView.frame = newIndicatorFrame;
[weakSelf.playerLayer.player seekToTime:weakSelf.lastPlayerTime
toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
}
else
{
weakSelf.nowPlayingIndicatorView.frame = newFrame;
}
}
}];
}
我似乎已经使用 dispatch_source_t
而不是 addPeriodicTimeObserverForInterval
解决了这个问题
代码:
@property (nonatomic, strong) dispatch_source_t playbackTimer;
- (void)observePlaybackTime
{
self.playbackTimer = CreateTimerDispatchSource(50000000, 0,
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),^
{
dispatch_async(dispatch_get_main_queue(),^
{
if (self.playerLayer.player.rate >= 1.0)
{
UICollectionViewFlowLayout *videoFrameLayout =
(UICollectionViewFlowLayout *)
self.videoFramesCollectionView.collectionViewLayout;
CGRect newFrame = self.nowPlayingIndicatorView.frame;
newFrame.origin.x += videoFrameLayout.itemSize.width / 20.7;
if (newFrame.origin.x >= self.rightScrubberView.frame.origin.x)
{
if (CMTIME_IS_VALID(self.lastPlayerTime))
{
// Loop playback
CGRect newIndicatorFrame = self.nowPlayingIndicatorView.frame;
newIndicatorFrame.origin.x =
self.leftScrubberView.frame.origin.x
+ self.leftScrubberView.bounds.size.width;
self.nowPlayingIndicatorView.frame = newIndicatorFrame;
[self.playerLayer.player
seekToTime:self.lastPlayerTime
toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
}
}
else
{
self.nowPlayingIndicatorView.frame = newFrame;
}
}
});
});
}
dispatch_source_t CreateTimerDispatchSource(uint64_t interval, uint64_t leeway,
dispatch_queue_t queue, dispatch_block_t block)
{
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,
queue);
if (timer)
{
dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), interval, leeway);
dispatch_source_set_event_handler(timer, block);
dispatch_resume(timer);
}
return timer;
}
我有一个正在播放的指示器视图,这是我为视频播放制作的,大部分情况下它都在工作,但是我注意到我的指示器在播放结束时没有完全同步时间.
视频播放完毕,但没有像应有的那样循环播放,因为指示器的 X 原点没有穿过右洗涤器的 X 原点,这意味着同步不正确。
如果能提供任何帮助,我将不胜感激。这是播放结束时指示器错误定位的图片。
- (void)observePlayerTime
{
CMTime intervalTime = CMTimeMake(33, 1000);
__weak typeof(self) weakSelf = self;
self.playbackObserver = [self.playerLayer.player addPeriodicTimeObserverForInterval:
intervalTime queue:dispatch_get_main_queue() usingBlock:^(CMTime time)
{
UICollectionViewFlowLayout *videoFrameLayout =
(UICollectionViewFlowLayout *)
weakSelf.videoFramesCollectionView.collectionViewLayout;
if (weakSelf.playerLayer.player.rate >= 1.0)
{
CGRect newFrame = weakSelf.nowPlayingIndicatorView.frame;
newFrame.origin.x += (videoFrameLayout.itemSize.width / intervalTime.value);
if (newFrame.origin.x >= weakSelf.rightScrubberView.frame.origin.x)
{
// Here we loop the player
CGRect newIndicatorFrame = weakSelf.nowPlayingIndicatorView.frame;
newIndicatorFrame.origin.x = (weakSelf.leftScrubberView.frame.origin.x
+ weakSelf.leftScrubberView.bounds.size.width)
- newIndicatorFrame.size.width;
weakSelf.nowPlayingIndicatorView.frame = newIndicatorFrame;
[weakSelf.playerLayer.player seekToTime:weakSelf.lastPlayerTime
toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
}
else
{
weakSelf.nowPlayingIndicatorView.frame = newFrame;
}
}
}];
}
我似乎已经使用 dispatch_source_t
而不是 addPeriodicTimeObserverForInterval
代码:
@property (nonatomic, strong) dispatch_source_t playbackTimer;
- (void)observePlaybackTime
{
self.playbackTimer = CreateTimerDispatchSource(50000000, 0,
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),^
{
dispatch_async(dispatch_get_main_queue(),^
{
if (self.playerLayer.player.rate >= 1.0)
{
UICollectionViewFlowLayout *videoFrameLayout =
(UICollectionViewFlowLayout *)
self.videoFramesCollectionView.collectionViewLayout;
CGRect newFrame = self.nowPlayingIndicatorView.frame;
newFrame.origin.x += videoFrameLayout.itemSize.width / 20.7;
if (newFrame.origin.x >= self.rightScrubberView.frame.origin.x)
{
if (CMTIME_IS_VALID(self.lastPlayerTime))
{
// Loop playback
CGRect newIndicatorFrame = self.nowPlayingIndicatorView.frame;
newIndicatorFrame.origin.x =
self.leftScrubberView.frame.origin.x
+ self.leftScrubberView.bounds.size.width;
self.nowPlayingIndicatorView.frame = newIndicatorFrame;
[self.playerLayer.player
seekToTime:self.lastPlayerTime
toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
}
}
else
{
self.nowPlayingIndicatorView.frame = newFrame;
}
}
});
});
}
dispatch_source_t CreateTimerDispatchSource(uint64_t interval, uint64_t leeway,
dispatch_queue_t queue, dispatch_block_t block)
{
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,
queue);
if (timer)
{
dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), interval, leeway);
dispatch_source_set_event_handler(timer, block);
dispatch_resume(timer);
}
return timer;
}