12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- //
- // AVPlayer+KSSeekSmoothly.m
- // KulexiuSchoolStudent
- //
- // Created by 王智 on 2023/11/24.
- //
- #import "AVPlayer+KSSeekSmoothly.h"
- #import <objc/runtime.h>
- @interface AVPlayerSeeker : NSObject
- {
- CMTime targetTime;
- BOOL isSeeking;
- }
- @property (weak, nonatomic) AVPlayer *player;
- @property (nonatomic, strong) dispatch_queue_t queue;
- @end
- @implementation AVPlayerSeeker
- - (instancetype)initWithPlayer:(AVPlayer *)player {
- self = [super init];
- if (self) {
- self.player = player;
- _queue = dispatch_queue_create("ks.seekTimeQueue", DISPATCH_QUEUE_SERIAL);
- }
- return self;
- }
- - (void)seekSmoothlyToTime:(CMTime)time toleranceBefore:(CMTime)toleranceBefore toleranceAfter:(CMTime)toleranceAfter completionHandler:(void (^)(BOOL))completionHandler {
- targetTime = time;
- if (!isSeeking) {
- [self trySeekToTargetTimeWithToleranceBefore:toleranceBefore toleranceAfter:toleranceAfter completionHandler:completionHandler];
- }
- }
- - (void)trySeekToTargetTimeWithToleranceBefore:(CMTime)toleranceBefore toleranceAfter:(CMTime)toleranceAfter completionHandler:(void (^)(BOOL))completionHandler {
- if (self.player.currentItem.status == AVPlayerItemStatusReadyToPlay) {
- [self seekToTargetTimeToleranceBefore:toleranceBefore toleranceAfter:toleranceAfter completionHandler:completionHandler];
- }
- }
- - (void)seekToTargetTimeToleranceBefore:(CMTime)toleranceBefore toleranceAfter:(CMTime)toleranceAfter completionHandler:(void (^)(BOOL))completionHandler {
- isSeeking = YES;
- CMTime seekingTime = targetTime;
-
- dispatch_async(_queue, ^{
- [self.player seekToTime:seekingTime toleranceBefore:toleranceBefore
- toleranceAfter:toleranceAfter completionHandler:
- ^(BOOL isFinished) {
- if (CMTIME_COMPARE_INLINE(seekingTime, ==, self->targetTime)) {
- // seek completed
- self->isSeeking = NO;
- dispatch_main_async_safe(^{
- if (completionHandler) {
- completionHandler(isFinished);
- }
- });
- } else {
- // targetTime has changed, seek again
- [self trySeekToTargetTimeWithToleranceBefore:toleranceBefore toleranceAfter:toleranceAfter completionHandler:completionHandler];
- }
- }];
- });
-
-
- }
- @end
- static NSString *seekerKey = @"ss_seeker";
- @implementation AVPlayer (KSSeekSmoothly)
- - (void)ss_seekToTime:(CMTime)time {
- [self ss_seekToTime:time toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero completionHandler:nil];
- }
- - (void)ss_seekToTime:(CMTime)time toleranceBefore:(CMTime)toleranceBefore toleranceAfter:(CMTime)toleranceAfter completionHandler:(void (^)(BOOL))completionHandler {
- AVPlayerSeeker *seeker = objc_getAssociatedObject(self, &seekerKey);
- if (!seeker) {
- seeker = [[AVPlayerSeeker alloc] initWithPlayer:self];
- objc_setAssociatedObject(self, &seekerKey, seeker, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
- }
- // [self pause];
- [seeker seekSmoothlyToTime:time toleranceBefore:toleranceBefore toleranceAfter:toleranceAfter completionHandler:completionHandler];
- }
- @end
|