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:
parent
ae4c49ea68
commit
75441bc5fa
17 changed files with 85 additions and 22 deletions
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
|
||||
- (void)resetBuffer;
|
||||
|
||||
- (BOOL)paused;
|
||||
|
||||
- (void)process;
|
||||
- (AudioChunk * _Nullable)convert;
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
- (void)resetBuffer;
|
||||
|
||||
- (BOOL)paused;
|
||||
|
||||
- (void)process;
|
||||
- (AudioChunk * _Nullable)convert;
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
- (void)resetBuffer;
|
||||
|
||||
- (BOOL)paused;
|
||||
|
||||
- (void)process;
|
||||
- (AudioChunk * _Nullable)convert;
|
||||
|
||||
|
|
|
@ -132,6 +132,10 @@ static void * kDSPFSurroundNodeContext = &kDSPFSurroundNodeContext;
|
|||
paused = NO;
|
||||
}
|
||||
|
||||
- (BOOL)paused {
|
||||
return paused;
|
||||
}
|
||||
|
||||
- (void)process {
|
||||
while([self shouldContinue] == YES) {
|
||||
if(paused) {
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
|
||||
- (void)resetBuffer;
|
||||
|
||||
- (BOOL)paused;
|
||||
|
||||
- (void)process;
|
||||
- (AudioChunk * _Nullable)convert;
|
||||
|
||||
|
|
|
@ -257,6 +257,10 @@ static void unregisterMotionListener(void) {
|
|||
paused = NO;
|
||||
}
|
||||
|
||||
- (BOOL)paused {
|
||||
return paused;
|
||||
}
|
||||
|
||||
- (void)process {
|
||||
while([self shouldContinue] == YES) {
|
||||
if(paused) {
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
- (void)resetBuffer;
|
||||
|
||||
- (BOOL)paused;
|
||||
|
||||
- (void)process;
|
||||
- (AudioChunk * _Nullable)convert;
|
||||
|
||||
|
|
|
@ -338,6 +338,10 @@ static void * kDSPRubberbandNodeContext = &kDSPRubberbandNodeContext;
|
|||
paused = NO;
|
||||
}
|
||||
|
||||
- (BOOL)paused {
|
||||
return paused;
|
||||
}
|
||||
|
||||
- (void)process {
|
||||
while([self shouldContinue] == YES) {
|
||||
if(paused) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
- (BOOL)setup;
|
||||
- (void)cleanUp;
|
||||
|
||||
- (BOOL)paused;
|
||||
|
||||
- (void)resetBuffer;
|
||||
|
||||
- (void)pop;
|
||||
|
|
|
@ -222,6 +222,10 @@ static VisualizationCollection *theCollection = nil;
|
|||
downmixer = nil;
|
||||
}
|
||||
|
||||
- (BOOL)paused {
|
||||
return paused;
|
||||
}
|
||||
|
||||
- (void)process {
|
||||
while([self shouldContinue] == YES) {
|
||||
if(paused) {
|
||||
|
|
Loading…
Reference in a new issue