[Audio Threads] Change workgroup code for safety
The changes include no longer leaving the workgroup for seeking or for converter format changes, and also still leaving the workgroup on thread termination if there was an error with intervals starting or finishing. Signed-off-by: Christopher Snowhill <kode54@gmail.com>swiftingly
parent
02d2ab01a7
commit
e9230a080c
|
@ -446,22 +446,19 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
|
||||||
// when the end of stream is reached. Convert function instead processes what it can,
|
// when the end of stream is reached. Convert function instead processes what it can,
|
||||||
// and returns 0 samples when it has nothing more to process at the end of stream.
|
// and returns 0 samples when it has nothing more to process at the end of stream.
|
||||||
while([self shouldContinue] == YES) {
|
while([self shouldContinue] == YES) {
|
||||||
[self followWorkgroup];
|
|
||||||
|
|
||||||
int amountConverted;
|
int amountConverted;
|
||||||
while(paused) {
|
while(paused) {
|
||||||
usleep(500);
|
usleep(500);
|
||||||
}
|
}
|
||||||
[self startWorkslice];
|
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
|
[self startWorkslice];
|
||||||
amountConverted = [self convert:writeBuf amount:CHUNK_SIZE];
|
amountConverted = [self convert:writeBuf amount:CHUNK_SIZE];
|
||||||
|
[self endWorkslice];
|
||||||
}
|
}
|
||||||
[self endWorkslice];
|
|
||||||
if(!amountConverted) {
|
if(!amountConverted) {
|
||||||
if(paused) {
|
if(paused) {
|
||||||
continue;
|
continue;
|
||||||
} else if(streamFormatChanged) {
|
} else if(streamFormatChanged) {
|
||||||
[self leaveWorkgroup];
|
|
||||||
[self cleanUp];
|
[self cleanUp];
|
||||||
[self setupWithInputFormat:newInputFormat withInputConfig:newInputChannelConfig outputFormat:outputFormat outputConfig:outputChannelConfig isLossless:rememberedLossless];
|
[self setupWithInputFormat:newInputFormat withInputConfig:newInputChannelConfig outputFormat:outputFormat outputConfig:outputChannelConfig isLossless:rememberedLossless];
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -157,7 +157,6 @@ static void *kInputNodeContext = &kInputNodeContext;
|
||||||
|
|
||||||
while([self shouldContinue] == YES && [self endOfStream] == NO) {
|
while([self shouldContinue] == YES && [self endOfStream] == NO) {
|
||||||
if(shouldSeek == YES) {
|
if(shouldSeek == YES) {
|
||||||
[self leaveWorkgroup];
|
|
||||||
BufferChain *bufferChain = [[controller controller] bufferChain];
|
BufferChain *bufferChain = [[controller controller] bufferChain];
|
||||||
ConverterNode *converter = [bufferChain converter];
|
ConverterNode *converter = [bufferChain converter];
|
||||||
DLog(@"SEEKING! Resetting Buffer");
|
DLog(@"SEEKING! Resetting Buffer");
|
||||||
|
@ -183,15 +182,13 @@ static void *kInputNodeContext = &kInputNodeContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(amountInBuffer < CHUNK_SIZE) {
|
if(amountInBuffer < CHUNK_SIZE) {
|
||||||
[self followWorkgroup];
|
|
||||||
|
|
||||||
int framesToRead = CHUNK_SIZE - amountInBuffer;
|
int framesToRead = CHUNK_SIZE - amountInBuffer;
|
||||||
int framesRead;
|
int framesRead;
|
||||||
[self startWorkslice];
|
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
|
[self startWorkslice];
|
||||||
framesRead = [decoder readAudio:((char *)inputBuffer) + bytesInBuffer frames:framesToRead];
|
framesRead = [decoder readAudio:((char *)inputBuffer) + bytesInBuffer frames:framesToRead];
|
||||||
|
[self endWorkslice];
|
||||||
}
|
}
|
||||||
[self endWorkslice];
|
|
||||||
|
|
||||||
if(framesRead > 0 && !seekError) {
|
if(framesRead > 0 && !seekError) {
|
||||||
amountInBuffer += framesRead;
|
amountInBuffer += framesRead;
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
BOOL shouldContinue;
|
BOOL shouldContinue;
|
||||||
BOOL endOfStream; // All data is now in buffer
|
BOOL endOfStream; // All data is now in buffer
|
||||||
BOOL initialBufferFilled;
|
BOOL initialBufferFilled;
|
||||||
BOOL isRealtime, isRealtimeError; // If was successfully set realtime, or if error
|
BOOL isRealtime, isRealtimeError, isDeadlineError; // If was successfully set realtime, or if error
|
||||||
|
|
||||||
AudioStreamBasicDescription nodeFormat;
|
AudioStreamBasicDescription nodeFormat;
|
||||||
uint32_t nodeChannelConfig;
|
uint32_t nodeChannelConfig;
|
||||||
|
|
|
@ -222,6 +222,7 @@ BOOL SetPriorityRealtimeAudio(mach_port_t mach_thread_id) {
|
||||||
wg = workgroup;
|
wg = workgroup;
|
||||||
if(wg && !isRealtimeError) {
|
if(wg && !isRealtimeError) {
|
||||||
int result = os_workgroup_join(wg, &wgToken);
|
int result = os_workgroup_join(wg, &wgToken);
|
||||||
|
isDeadlineError = NO;
|
||||||
if(result == 0) return;
|
if(result == 0) return;
|
||||||
if(result == EALREADY) {
|
if(result == EALREADY) {
|
||||||
DLog(@"Thread already in workgroup");
|
DLog(@"Thread already in workgroup");
|
||||||
|
@ -251,13 +252,13 @@ BOOL SetPriorityRealtimeAudio(mach_port_t mach_thread_id) {
|
||||||
|
|
||||||
- (void)startWorkslice {
|
- (void)startWorkslice {
|
||||||
if(@available(macOS 11, *)) {
|
if(@available(macOS 11, *)) {
|
||||||
if(wg && !isRealtimeError) {
|
if(wg && !isRealtimeError && !isDeadlineError) {
|
||||||
const uint64_t currentTime = mach_absolute_time();
|
const uint64_t currentTime = mach_absolute_time();
|
||||||
const uint64_t deadline = currentTime + intervalMachLength;
|
const uint64_t deadline = currentTime + intervalMachLength;
|
||||||
int result = os_workgroup_interval_start(wg, currentTime, deadline, nil);
|
int result = os_workgroup_interval_start(wg, currentTime, deadline, nil);
|
||||||
if(result != 0) {
|
if(result != 0) {
|
||||||
DLog(@"Deadline error = %d", result);
|
DLog(@"Deadline error = %d", result);
|
||||||
isRealtimeError = YES;
|
isDeadlineError = YES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -265,11 +266,11 @@ BOOL SetPriorityRealtimeAudio(mach_port_t mach_thread_id) {
|
||||||
|
|
||||||
- (void)endWorkslice {
|
- (void)endWorkslice {
|
||||||
if(@available(macOS 11, *)) {
|
if(@available(macOS 11, *)) {
|
||||||
if(wg && !isRealtimeError) {
|
if(wg && !isRealtimeError && !isDeadlineError) {
|
||||||
int result = os_workgroup_interval_finish(wg, nil);
|
int result = os_workgroup_interval_finish(wg, nil);
|
||||||
if(result != 0) {
|
if(result != 0) {
|
||||||
DLog(@"Deadline end error = %d", result);
|
DLog(@"Deadline end error = %d", result);
|
||||||
isRealtimeError = YES;
|
isDeadlineError = YES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue