Audio: Fix more hangs and resume playback on start

Check for paused processing state in various places, so that startup
playback works properly, and resume playback at seek offset works
properly and doesn't hang the player.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
Christopher Snowhill 2025-02-13 22:25:27 -08:00
parent ae4c49ea68
commit 75441bc5fa
17 changed files with 85 additions and 22 deletions

View file

@ -569,7 +569,14 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
double streamTimestamp = 0.0;
double streamTimeRatio = 1.0;
if (![self peekTimestamp:&streamTimestamp timeRatio:&streamTimeRatio]) {
BOOL blocked = NO;
while(![self peekTimestamp:&streamTimestamp timeRatio:&streamTimeRatio]) {
if((blocked = block())) {
break;
}
}
if(blocked) {
inMerger = NO;
return [[AudioChunk alloc] init];
}

View file

@ -73,6 +73,8 @@
- (BOOL)setupWithInputFormat:(AudioStreamBasicDescription)inputFormat withInputConfig:(uint32_t)inputConfig outputFormat:(AudioStreamBasicDescription)outputFormat isLossless:(BOOL)lossless;
- (void)cleanUp;
- (BOOL)paused;
- (void)process;
- (AudioChunk *)convert;

View file

@ -90,6 +90,10 @@ void scale_by_volume(float *buffer, size_t count, float volume) {
}
}
- (BOOL)paused {
return paused;
}
- (void)process {
// Removed endOfStream check from here, since we want to be able to flush the converter
// when the end of stream is reached. Convert function instead processes what it can,

View file

@ -22,6 +22,8 @@
- (void)resetBuffer;
- (BOOL)paused;
- (void)process;
- (AudioChunk * _Nullable)convert;

View file

@ -77,7 +77,6 @@
usleep(500);
}
[super resetBuffer];
[self fullShutdown];
paused = NO;
}
@ -87,6 +86,10 @@
formatSet = YES;
}
- (BOOL)paused {
return paused;
}
- (void)process {
while([self shouldContinue] == YES) {
if(paused) {

View file

@ -21,6 +21,8 @@
- (void)resetBuffer;
- (BOOL)paused;
- (void)process;
- (AudioChunk * _Nullable)convert;

View file

@ -315,6 +315,10 @@ static OSStatus eqRenderCallback(void *inRefCon, AudioUnitRenderActionFlags *ioA
paused = NO;
}
- (BOOL)paused {
return paused;
}
- (void)process {
while([self shouldContinue] == YES) {
if(paused) {

View file

@ -20,6 +20,8 @@
- (void)resetBuffer;
- (BOOL)paused;
- (void)process;
- (AudioChunk * _Nullable)convert;

View file

@ -132,6 +132,10 @@ static void * kDSPFSurroundNodeContext = &kDSPFSurroundNodeContext;
paused = NO;
}
- (BOOL)paused {
return paused;
}
- (void)process {
while([self shouldContinue] == YES) {
if(paused) {

View file

@ -22,6 +22,8 @@
- (void)resetBuffer;
- (BOOL)paused;
- (void)process;
- (AudioChunk * _Nullable)convert;

View file

@ -257,6 +257,10 @@ static void unregisterMotionListener(void) {
paused = NO;
}
- (BOOL)paused {
return paused;
}
- (void)process {
while([self shouldContinue] == YES) {
if(paused) {

View file

@ -20,6 +20,8 @@
- (void)resetBuffer;
- (BOOL)paused;
- (void)process;
- (AudioChunk * _Nullable)convert;

View file

@ -338,6 +338,10 @@ static void * kDSPRubberbandNodeContext = &kDSPRubberbandNodeContext;
paused = NO;
}
- (BOOL)paused {
return paused;
}
- (void)process {
while([self shouldContinue] == YES) {
if(paused) {

View file

@ -46,6 +46,8 @@
- (void)cleanUp;
- (BOOL)paused;
- (void)writeData:(const void *_Nonnull)ptr amount:(size_t)a;
- (void)writeChunk:(AudioChunk *_Nonnull)chunk;
- (AudioChunk *_Nonnull)readChunk:(size_t)maxFrames;

View file

@ -79,7 +79,7 @@
- (void)writeData:(const void *)ptr amount:(size_t)amount {
inWrite = YES;
if(!shouldContinue) {
if(!shouldContinue || [self paused]) {
inWrite = NO;
return;
}
@ -105,7 +105,7 @@
}
}
while(shouldContinue == YES && durationLeft < 0.0) {
while(shouldContinue == YES && ![self paused] && durationLeft < 0.0) {
if(durationLeft < 0.0 || shouldReset) {
[accessLock unlock];
[writeSemaphore timedWait:2000];
@ -132,7 +132,7 @@
- (void)writeChunk:(AudioChunk *)chunk {
inWrite = YES;
if(!shouldContinue) {
if(!shouldContinue || [self paused]) {
inWrite = NO;
return;
}
@ -150,7 +150,7 @@
}
}
while(shouldContinue == YES && durationLeft < 0.0) {
while(shouldContinue == YES && ![self paused] && durationLeft < 0.0) {
if(previousNode && [previousNode shouldContinue] == NO) {
shouldContinue = NO;
break;
@ -192,20 +192,22 @@
- (BOOL)peekFormat:(nonnull AudioStreamBasicDescription *)format channelConfig:(nonnull uint32_t *)config {
inPeek = YES;
if(!shouldContinue) {
if(!shouldContinue || [self paused]) {
inPeek = NO;
return NO;
}
[accessLock lock];
while(shouldContinue && [[previousNode buffer] isEmpty] && [previousNode endOfStream] == NO) {
while(shouldContinue && ![self paused] &&
[[previousNode buffer] isEmpty] && [previousNode endOfStream] == NO) {
[accessLock unlock];
[writeSemaphore signal];
[[previousNode readSemaphore] timedWait:2000];
[accessLock lock];
}
if(!shouldContinue) {
if(!shouldContinue || [self paused]) {
[accessLock unlock];
inPeek = NO;
return NO;
@ -229,20 +231,22 @@
- (BOOL)peekTimestamp:(double *_Nonnull)timestamp timeRatio:(double *_Nonnull)timeRatio {
inPeek = YES;
if(!shouldContinue) {
if(!shouldContinue || [self paused]) {
inPeek = NO;
return NO;
}
[accessLock lock];
while(shouldContinue && [[previousNode buffer] isEmpty] && [previousNode endOfStream] == NO) {
while(shouldContinue && ![self paused] &&
[[previousNode buffer] isEmpty] && [previousNode endOfStream] == NO) {
[accessLock unlock];
[writeSemaphore signal];
[[previousNode readSemaphore] timedWait:2000];
[accessLock lock];
}
if(!shouldContinue) {
if(!shouldContinue || [self paused]) {
[accessLock unlock];
inPeek = NO;
return NO;
@ -266,15 +270,17 @@
- (AudioChunk *)readChunk:(size_t)maxFrames {
inRead = YES;
if(!shouldContinue) {
if(!shouldContinue || [self paused]) {
inRead = NO;
return [[AudioChunk alloc] init];
}
[accessLock lock];
while(shouldContinue && [[previousNode buffer] isEmpty] && [previousNode endOfStream] == NO) {
while(shouldContinue && ![self paused] &&
[[previousNode buffer] isEmpty] && [previousNode endOfStream] == NO) {
[accessLock unlock];
[writeSemaphore signal];
[[previousNode readSemaphore] timedWait:2000];
[accessLock lock];
if([previousNode shouldReset] == YES) {
@ -282,7 +288,7 @@
}
}
if(!shouldContinue) {
if(!shouldContinue || [self paused]) {
[accessLock unlock];
inRead = NO;
return [[AudioChunk alloc] init];
@ -325,15 +331,17 @@
- (AudioChunk *)readChunkAsFloat32:(size_t)maxFrames {
inRead = YES;
if(!shouldContinue) {
if(!shouldContinue || [self paused]) {
inRead = NO;
return [[AudioChunk alloc] init];
}
[accessLock lock];
while(shouldContinue && [[previousNode buffer] isEmpty] && [previousNode endOfStream] == NO) {
while(shouldContinue && ![self paused] &&
[[previousNode buffer] isEmpty] && [previousNode endOfStream] == NO) {
[accessLock unlock];
[writeSemaphore signal];
[[previousNode readSemaphore] timedWait:2000];
[accessLock lock];
if([previousNode shouldReset] == YES) {
@ -341,7 +349,7 @@
}
}
if(!shouldContinue) {
if(!shouldContinue || [self paused]) {
[accessLock unlock];
inRead = NO;
return [[AudioChunk alloc] init];
@ -384,7 +392,7 @@
- (AudioChunk *)readAndMergeChunks:(size_t)maxFrames {
inMerge = YES;
if(!shouldContinue) {
if(!shouldContinue || [self paused]) {
inMerge = NO;
return [[AudioChunk alloc] init];
}
@ -416,7 +424,7 @@
[[previousNode readSemaphore] timedWait:2000];
[accessLock lock];
return !shouldContinue || ([[previousNode buffer] isEmpty] && [previousNode endOfStream] == YES);
return !shouldContinue || [self paused] || ([[previousNode buffer] isEmpty] && [previousNode endOfStream] == YES);
}];
}
@ -433,7 +441,7 @@
- (AudioChunk *)readAndMergeChunksAsFloat32:(size_t)maxFrames {
inMerge = YES;
if(!shouldContinue) {
if(!shouldContinue || [self paused]) {
inMerge = NO;
return [[AudioChunk alloc] init];
}
@ -465,7 +473,7 @@
[[previousNode readSemaphore] timedWait:2000];
[accessLock lock];
return !shouldContinue || ([[previousNode buffer] isEmpty] && [previousNode endOfStream] == YES);
return !shouldContinue || [self paused] || ([[previousNode buffer] isEmpty] && [previousNode endOfStream] == YES);
}];
}
@ -515,6 +523,11 @@
}
}
// Implementations should override
- (BOOL)paused {
return NO;
}
- (Semaphore *)writeSemaphore {
return writeSemaphore;
}

View file

@ -20,6 +20,8 @@
- (BOOL)setup;
- (void)cleanUp;
- (BOOL)paused;
- (void)resetBuffer;
- (void)pop;

View file

@ -222,6 +222,10 @@ static VisualizationCollection *theCollection = nil;
downmixer = nil;
}
- (BOOL)paused {
return paused;
}
- (void)process {
while([self shouldContinue] == YES) {
if(paused) {