Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AVPlayer causes crash while updating progress slider with Assertion failure in -[AVPlayerPeriodicCaller initWithPlayer:interval:queue:block:]

I am getting the error within the app

" Assertion failure in -[AVPlayerPeriodicCaller initWithPlayer:interval:queue:block:], /SourceCache/EmbeddedAVFoundation/EmbeddedAVFoundation-461.12/Fig/AVPlayer.m:3993

 Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: CMTIME_COMPARE_INLINE(interval, >, kCMTimeZero)'

Any ideas why this may be happening?

I am limited to use AvPlayer only because I need to stream large file .AVaudioplayer is not an option. So I have also implemented a scrubber slider. My implementation of AVplayer is as follows:

-(void)playAudioForFile:(NSString *)fileName{

    [self.suraPlayer removeTimeObserver:playbackObserver];
    [self.suraPlayer removeTimeObserver:mTimeObserver];
    self.suraPlayer = nil;

NSURL* url = [self getURLStringForFileName:fileName];

AVPlayer *player = [[AVPlayer alloc]initWithURL:url];

self.suraPlayer = player;

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(playerItemDidReachEnd:)
                                             name:AVPlayerItemDidPlayToEndTimeNotification
                                           object:[suraPlayer currentItem]];


[self.suraPlayer play];



[self.suraPlayer addObserver:self forKeyPath:@"status" options:0 context:nil];

[self initScrubberTimer];

[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(updateProgress) userInfo:nil repeats:YES];

//[self metadataForAsset:self.suraPlayer.currentItem.asset];

}

-(void)updateProgress {



   // NSLog(@"self.mScrubber.value %f", self.mScrubber.value);

//THIS IS THE LINE WHERE THE DEBUGGER SOMETIME STUMPS

float duration = CMTimeGetSeconds(self.suraPlayer.currentItem.duration);

    if (self.suraPlayer.currentItem.status==AVPlayerStatusReadyToPlay )
        [self.mScrubber setMaximumValue:duration];


    self.mScrubber.value = CMTimeGetSeconds(self.suraPlayer.currentTime);

    int seconds = self.mScrubber.value, minutes = seconds/60,hours = minutes/60;

    int secondsRemain = self.mScrubber.maximumValue - seconds,minutesRemain = secondsRemain/60,hoursRemain = minutesRemain/60;

    seconds = seconds-minutes*60;

    minutes = minutes-hours*60;

    secondsRemain = secondsRemain - minutesRemain*60;

    minutesRemain = minutesRemain - hoursRemain*60;

    NSString *hourStr,*minuteStr,*secondStr,*hourStrRemain,*minuteStrRemain,*secondStrRemain;

    hourStr = hours > 9 ? [NSString stringWithFormat:@"%d",hours] : [NSString stringWithFormat:@"0%d",hours];

    minuteStr = minutes > 9 ? [NSString stringWithFormat:@"%d",minutes] : [NSString stringWithFormat:@"0%d",minutes];

    secondStr = seconds > 9 ? [NSString stringWithFormat:@"%d",seconds] : [NSString stringWithFormat:@"0%d",seconds];

    hourStrRemain = hoursRemain > 9 ? [NSString stringWithFormat:@"%d",hoursRemain] : [NSString stringWithFormat:@"0%d",hoursRemain];

    minuteStrRemain = minutesRemain > 9 ? [NSString stringWithFormat:@"%d",minutesRemain] : [NSString stringWithFormat:@"0%d",minutesRemain];

    secondStrRemain = secondsRemain > 9 ? [NSString stringWithFormat:@"%d",secondsRemain] : [NSString stringWithFormat:@"0%d",secondsRemain];

    self.timePlayerLabel.text = [NSString stringWithFormat:@"%@:%@:%@",hourStr,minuteStr,secondStr];

    self.timeRemainingLabel.text = [NSString stringWithFormat:@"-%@:%@:%@",hourStrRemain,minuteStrRemain,secondStrRemain];

}



-(void)initScrubberTimer
{

    double interval = .1f;

    CMTime playerDuration = self.suraPlayer.currentItem.duration;
    if (CMTIME_IS_INVALID(playerDuration))
    {
        return;
    }

    double duration = CMTimeGetSeconds(playerDuration);
    if (isfinite(duration))
    {
        CGFloat width = CGRectGetWidth([self.mScrubber bounds]);
        interval = 0.5f * duration / width;
    }

    /* Update the scrubber during normal playback. */


    mTimeObserver = [self.suraPlayer addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(interval, NSEC_PER_SEC)
                                                                  queue:NULL /* If you pass NULL, the main queue is used. */
                                                             usingBlock:^(CMTime time)
                     {

                     }];
    [self syncScrubber];
}

/* Set the scrubber based on the player current time. */
- (void)syncScrubber
{
    CMTime playerDuration = self.suraPlayer.currentItem.duration;
    if (CMTIME_IS_INVALID(playerDuration))
    {
        self.mScrubber.minimumValue = 0.0;
        return;
    }

    double duration = CMTimeGetSeconds(playerDuration);
    if (isfinite(duration))
    {
        float minValue = [self.mScrubber minimumValue];
        float maxValue = [self.mScrubber maximumValue];
        double time = CMTimeGetSeconds([self.suraPlayer currentTime]);

        [self.mScrubber setValue:(maxValue - minValue) * time / duration + minValue];
    }
}

/* The user is dragging the movie controller thumb to scrub through the movie. */

/* Set the player current time to match the scrubber position. */
- (IBAction)scrub:(id)sender
{
    if ([sender isKindOfClass:[UISlider class]])
    {
        UISlider* slider = sender;

        CMTime playerDuration = self.suraPlayer.currentItem.duration;
        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.suraPlayer seekToTime:CMTimeMakeWithSeconds(time, NSEC_PER_SEC)];
        }
    }
}

- (IBAction)beginScrubbing:(id)sender {



    mRestoreAfterScrubbingRate = [self.suraPlayer rate];
    [self.suraPlayer setRate:0.f];

    /* Remove previous timer. */
    [self removePlayerTimeObserver];
}

/* The user has released the movie thumb control to stop scrubbing through the movie. */

- (IBAction)endScrubbing:(id)sender {

    __weak typeof(self) weakSelf = self;

    if (!mTimeObserver)
    {


        CMTime playerDuration = self.suraPlayer.currentItem.duration;
        if (CMTIME_IS_INVALID(playerDuration))
        {
            return;
        }

        double duration = CMTimeGetSeconds(playerDuration);
        if (isfinite(duration))
        {
            CGFloat width = CGRectGetWidth([self.mScrubber bounds]);
            double tolerance = 0.5f * duration / width;

            mTimeObserver = [self.suraPlayer addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(tolerance, NSEC_PER_SEC) queue:NULL usingBlock:
                             ^(CMTime time)
                             {
                                 [weakSelf syncScrubber];
                             }];
        }
    }

    if (mRestoreAfterScrubbingRate)
    {
        [self.suraPlayer setRate:mRestoreAfterScrubbingRate];
        mRestoreAfterScrubbingRate = 0.f;
    }

}

- (BOOL)isScrubbing
{
    return mRestoreAfterScrubbingRate != 0.f;
}

-(void)enableScrubber
{
    self.mScrubber.enabled = YES;
}

-(void)disableScrubber
{
    self.mScrubber.enabled = NO;
}


-(void)removePlayerTimeObserver
{
    if (mTimeObserver)
    {
        [self.suraPlayer removeTimeObserver:mTimeObserver];
        mTimeObserver = nil;
    }
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {

    if (object == suraPlayer && [keyPath isEqualToString:@"status"]) {
        if (suraPlayer.status == AVPlayerStatusFailed) {
            NSLog(@"AVPlayer Failed");

        } else if (suraPlayer.status == AVPlayerStatusReadyToPlay) {
            NSLog(@"AVPlayerStatusReadyToPlay");

            //   NSLog(@"Common MetaData %@",   self.suraPlayer.currentItem.asset.commonMetadata);


            AVAsset * asset = self.suraPlayer.currentItem.asset;

            [self metadataForAsset:asset];

        } else if (suraPlayer.status == AVPlayerItemStatusUnknown) {
            NSLog(@"AVPlayer Unknown");

        }
    }
}
- (NSString *)titleForAsset:(AVAsset *)asset{

    NSArray *titles = [AVMetadataItem metadataItemsFromArray:asset.commonMetadata withKey:AVMetadataCommonKeyTitle keySpace:AVMetadataKeySpaceCommon];
    AVMetadataItem *title;
    NSString * currentTitle;

    if(titles.count>0)
    {
        title= [titles objectAtIndex:0];
        currentTitle= [title.value copyWithZone:nil];
    }

    if (self.suraPlayer.currentItem.asset != asset)
        asset = nil;

    return currentTitle;
}

- (void)metadataForAsset:(AVAsset *)asset{

    self.artWorkImage.image = [UIImage imageNamed:@"Colorful-Burst-iPad-wallpaper-ilikewallpaper_com.jpg"];

    NSArray *titles = [AVMetadataItem metadataItemsFromArray:asset.commonMetadata withKey:AVMetadataCommonKeyTitle keySpace:AVMetadataKeySpaceCommon];
    NSArray *artists = [AVMetadataItem metadataItemsFromArray:asset.commonMetadata withKey:AVMetadataCommonKeyArtist keySpace:AVMetadataKeySpaceCommon];
    NSArray *albumNames = [AVMetadataItem metadataItemsFromArray:asset.commonMetadata withKey:AVMetadataCommonKeyAlbumName keySpace:AVMetadataKeySpaceCommon];

    AVMetadataItem *artist;
    AVMetadataItem *title;
    AVMetadataItem *albumName;
    NSString * currentTitle;
    NSString * currentArtist;
    NSString * currentAlbumName;

    if(titles.count>0)
    {
        title= [titles objectAtIndex:0];
        currentTitle= [title.value copyWithZone:nil];
        self.audioTitle.text = currentTitle;

    }

    if(artists.count>0)
    {
        artist= [artists objectAtIndex:0];
        currentArtist   = [artist.value copyWithZone:nil];
    }

    if (albumNames.count>0){
        albumName= [albumNames objectAtIndex:0];
        currentAlbumName = [albumName.value copyWithZone:nil];

    }






    NSArray *keys = [NSArray arrayWithObjects:@"commonMetadata", nil];
    [asset loadValuesAsynchronouslyForKeys:keys completionHandler:^{
        NSArray *artworks = [AVMetadataItem metadataItemsFromArray:asset.commonMetadata
                                                           withKey:AVMetadataCommonKeyArtwork
                                                          keySpace:AVMetadataKeySpaceCommon];

        for (AVMetadataItem *item in artworks) {
            if ([item.keySpace isEqualToString:AVMetadataKeySpaceID3]) {
                NSDictionary *d = [item.value copyWithZone:nil];
                self.artWorkImage.image  = [UIImage imageWithData:[d objectForKey:@"data"]];
            } else if ([item.keySpace isEqualToString:AVMetadataKeySpaceiTunes]) {
                self.artWorkImage.image = [UIImage imageWithData:[item.value copyWithZone:nil]];
            }
        }
    }];




}


- (void)playerItemDidReachEnd:(NSNotification *)notification {

    //  code here to play next sound file
    if (indexOfSelectedItem<self.filteredAudiosArray.count){
        indexOfSelectedItem = indexOfSelectedItem+1;
        [self playAudioForFile:[self.filteredAudiosArray objectAtIndex:indexOfSelectedItem]];
        [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:indexOfSelectedItem inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
    }

}

- (IBAction)sliderValueChangedForDuration:(id)sender {
    if ([sender isKindOfClass:[UISlider class]])
    {
        UISlider* slider = sender;

        CMTime playerDuration = self.suraPlayer.currentItem.duration;
        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.suraPlayer seekToTime:CMTimeMakeWithSeconds(time, NSEC_PER_SEC)];
        }
    }

}
like image 512
real 19 Avatar asked Oct 22 '22 03:10

real 19


1 Answers

Late to the game but in case someone else runs into this, I had this issue because of the way I was setting the time interval to the periodic observer.

Changing to:

CMTime interval = CMTimeMake(33, 1000);

Made things work for me.

like image 73
Henry Green Avatar answered Oct 24 '22 05:10

Henry Green