D
D
deleted-mezhevikin2013-11-18 17:49:53
Objective-C
deleted-mezhevikin, 2013-11-18 17:49:53

Scrubber slows down in AVPlayer?

Following the example from apple, I am making a player based on AVPlayer. ( AVPlayerDemo )
AVPlayer can play remote files, but if you turn on the video from the server and start rewinding the scrubber (UISlider), it starts to fail.
At the same time, everything rewinds smoothly in MPMoviePlayerViewController.
Are there any ideas how to fix this?
My test project code - https://github.com/nullproduction/Player
Rewind is implemented like this:

[scrubberSlider addTarget:self action:@selector(beginScrubbing:) forControlEvents:UIControlEventTouchDown];
    [scrubberSlider addTarget:self action:@selector(endScrubbing:) forControlEvents:UIControlEventTouchUpInside];
    [scrubberSlider addTarget:self action:@selector(endScrubbing:) forControlEvents:UIControlEventTouchUpOutside];
    [scrubberSlider addTarget:self action:@selector(scrub:) forControlEvents:UIControlEventValueChanged];

- (void)initScrubberTimer
{
  double interval = .1f;
  
  CMTime playerDuration = [self playerItemDuration];
  if (CMTIME_IS_INVALID(playerDuration))
  {
    return;
  }
  double duration = CMTimeGetSeconds(playerDuration);
  if (isfinite(duration))
  {
    CGFloat width = CGRectGetWidth([scrubberSlider bounds]);
    interval = 0.5f * duration / width;
  }
    
    __weak id weakSelf = self;
    CMTime intervalSeconds = CMTimeMakeWithSeconds(interval, NSEC_PER_SEC);
    mTimeObserver = [self.player addPeriodicTimeObserverForInterval:intervalSeconds
                                                              queue:dispatch_get_main_queue()
                                                         usingBlock:^(CMTime time) {
                                                             [weakSelf syncScrubber];
                                                         }];
    
}


- (void)syncScrubber
{
  CMTime playerDuration = [self playerItemDuration];
  if (CMTIME_IS_INVALID(playerDuration))
  {
    scrubberSlider.minimumValue = 0.0;
    return;
  }
    
  double duration = CMTimeGetSeconds(playerDuration);
  if (isfinite(duration))
  {
    float minValue = [scrubberSlider minimumValue];
    float maxValue = [scrubberSlider maximumValue];
    double time = CMTimeGetSeconds([self.player currentTime]);
    
    [scrubberSlider setValue:(maxValue - minValue) * time / duration + minValue];
  }
}

- (IBAction)beginScrubbing:(id)sender
{
    mRestoreAfterScrubbingRate = [self.player rate];
  [self.player setRate:0.f];
  
  [self removePlayerTimeObserver];
}


- (IBAction)scrub:(id)sender
{
  if ([sender isKindOfClass:[UISlider class]])
  {
    UISlider* slider = sender;
    
    CMTime playerDuration = [self playerItemDuration];
    if (CMTIME_IS_INVALID(playerDuration))
        {
      return;
    }
    
    double duration = CMTimeGetSeconds(playerDuration);
    if (isfinite(duration))
    {
      float minValue = [slider minimumValue];
      float maxValue = [slider maximumValue];
      float value = [slider value];
      
      double time = duration * (value - minValue) / (maxValue - minValue);
      
      [self.player seekToTime:CMTimeMakeWithSeconds(time, NSEC_PER_SEC)];
    }
  }
}

- (IBAction)endScrubbing:(id)sender
{
    if (!mTimeObserver)
  {
    CMTime playerDuration = [self playerItemDuration];
    if (CMTIME_IS_INVALID(playerDuration))
    {
      return;
    }
    
    double duration = CMTimeGetSeconds(playerDuration);
    if (isfinite(duration))
    {
      CGFloat width = CGRectGetWidth([scrubberSlider bounds]);
      double tolerance = 0.5f * duration / width;
            
            __weak id weakSelf = self;
            CMTime intervalSeconds = CMTimeMakeWithSeconds(tolerance, NSEC_PER_SEC);
            mTimeObserver = [self.player addPeriodicTimeObserverForInterval:intervalSeconds
                                                                      queue:dispatch_get_main_queue()
                                                                 usingBlock: ^(CMTime time) {
                                                                     [weakSelf syncScrubber];
                                                                 }];
    }
  }
    
    if (mRestoreAfterScrubbingRate)
  {
    [self.player setRate:mRestoreAfterScrubbingRate];
    mRestoreAfterScrubbingRate = 0.f;
  }
}

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question