Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Player sometime never leaves STKAudioPlayerStateBuffering state #433

Open
zsaraf opened this issue May 6, 2019 · 8 comments
Open

Player sometime never leaves STKAudioPlayerStateBuffering state #433

zsaraf opened this issue May 6, 2019 · 8 comments

Comments

@zsaraf
Copy link

zsaraf commented May 6, 2019

I'm using this library to build a radio iOS app that has a directory of Icecast streams that the user can click on and listen to.

This library works very well 95% of the time, but 5% of the time, the player gets stuck in the STKAudioPlayerStateBuffering state and never changes, not reporting any errors at all. It seems like some kind of a race condition. Any idea why this could be happening?

- (BOOL)startAudioIO
{
    NSError *error = nil;
    
    AVAudioSessionCategory category = AVAudioSessionCategoryPlayAndRecord;
    AVAudioSessionCategoryOptions options = AVAudioSessionCategoryOptionAllowBluetooth | AVAudioSessionCategoryOptionDefaultToSpeaker;
    if ([AVAudioSession sharedInstance].category != category || [AVAudioSession sharedInstance].categoryOptions != options) {
        [[AVAudioSession sharedInstance] setCategory:category withOptions:options error:&error];
        if (error) {
            NSLog(@"STKAudioPlayer: Error setting category on audio session.");
            return NO;
        }
    }
    
    [[AVAudioSession sharedInstance] setActive:YES error:&error];
    if (error) {
        NSLog(@"STKAudioPlayer: Error starting audio session.");
        return NO;
    }
    
    return YES;
}

- (void)setupPlayer
{
    STKAudioPlayerOptions options;
    options.bufferSizeInSeconds = 2;

    _audioPlayer = [[STKAudioPlayer alloc] initWithOptions:options];
    _audioPlayer.delegate = self;
    
    [_audioPlayer appendFrameFilterWithName:@"FFT" block:^(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UInt32 frameCount, void* frames)
     {
         uint16_t bytesPerSample = bytesPerFrame / channelsPerFrame;
         
         if (bytesPerSample == 2) {
             vDSP_vflt16((short *)frames, 1, self->_floatInputBuffer, 1, frameCount * channelsPerFrame);
         } else if (bytesPerSample == 4) {
             vDSP_vflt32((int *)frames, 1, self->_floatInputBuffer, 1, frameCount * channelsPerFrame);
         } else {
             NSLog(@"STKAudioPlayer: Other bytePerSample sizes are not supported. TODO(zsaraf): Test for this now!");
         }
         
         // 2^(n-1) because it is a signed number where n = 16 (short *)
         const float nBits = pow(2, (bytesPerSample * 8) - 1);
         vDSP_vsdiv(self->_floatInputBuffer, 1, &nBits, self->_floatNormalizedInputBuffer, 1, channelsPerFrame * frameCount);
         
         [[DFFTManager shared] processFFTWithInputBuffers:self->_fftArgBuffer inputChannels:channelsPerFrame numberOfSamples:frameCount interleaved:YES];
     }];
}

- (void)startStreamWithUrl:(NSString *)streamUrl
                streamName:(NSString *)streamName
               streamImage:(NSString *)streamImage
     streamCreatorUsername:(NSString *)streamCreatorUsername
{
    // Set values in case we get disconnected and need to reconnect.
    self->_streamUrl = streamUrl;
    self->_streamName = streamName;
    self->_streamImage = streamImage;
    self->_streamCreatorUsername = streamCreatorUsername;
    
    // Begin stream.
    dispatch_async(dispatch_get_main_queue(), ^{
        [self startAudioIO];
        
        if (self->_audioPlayer == nil) {
            [self setupPlayer];
        }
        
        [self->_audioPlayer play:streamUrl];
    });
}

- (void)stopStream
{
    dispatch_async(dispatch_get_main_queue(), ^{
        [self->_audioPlayer stop];
        
        [self cleanupStream];
   });
}

Any ideas at all on where to look?

Thanks
Zach

@zsaraf
Copy link
Author

zsaraf commented May 6, 2019

I've found that this error comes up because of issues with starting the AUGraph. AUGraphStart gets called and returns a successful status of 0. BUT the OutputRenderCallback is not being called.

Any ideas why this could be?

@keba76
Copy link

keba76 commented May 7, 2019

Hi!
Between finish and start stream put a mini delay for example in 0.1 - 0.2 seconds.

@zsaraf
Copy link
Author

zsaraf commented May 7, 2019

This hasn't helped at all unfortunately! The AUGraphStart call is not actually starting the graph/callback functions. Does anyone have any idea how to fix this?

@keba76
Copy link

keba76 commented May 7, 2019

In your method - (void)setupPlayer, try setting bufferSizeInSeconds to 10 seconds instead of 2 seconds.

@keba76
Copy link

keba76 commented May 15, 2019

As one of the options for the occurrence of such a problem, there may be initialization of AudioSession and Remote Control. These actions must be performed before the player is first initialized and preferably as early as possible.

@grzegorzkrukowski
Copy link

grzegorzkrukowski commented Nov 22, 2019

We are experience similar issues - it's for iOS 13 only and we are able to reproduce it when playing audios on 3G - buffering seems to be broken for both foreground and background playing.
Sometimes StreamingKit goes into Buffering (reporting state change by delegate) and never recovers from that - it's also not reporting any errors for that case.
Lot's of users reporting that problem lately - and we didn't change anything within our code around this - it has been just fine for a long long time.

@iDevelopper
Copy link

Is this issue relative to the #398 one?

@grzegorzkrukowski
Copy link

grzegorzkrukowski commented Nov 23, 2019 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants