[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
Christopher Snowhill 2022-06-15 21:44:03 -07:00
parent 02d2ab01a7
commit e9230a080c
4 changed files with 10 additions and 15 deletions

View File

@ -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,
// and returns 0 samples when it has nothing more to process at the end of stream.
while([self shouldContinue] == YES) {
[self followWorkgroup];
int amountConverted;
while(paused) {
usleep(500);
}
[self startWorkslice];
@autoreleasepool {
[self startWorkslice];
amountConverted = [self convert:writeBuf amount:CHUNK_SIZE];
[self endWorkslice];
}
[self endWorkslice];
if(!amountConverted) {
if(paused) {
continue;
} else if(streamFormatChanged) {
[self leaveWorkgroup];
[self cleanUp];
[self setupWithInputFormat:newInputFormat withInputConfig:newInputChannelConfig outputFormat:outputFormat outputConfig:outputChannelConfig isLossless:rememberedLossless];
continue;

View File

@ -157,7 +157,6 @@ static void *kInputNodeContext = &kInputNodeContext;
while([self shouldContinue] == YES && [self endOfStream] == NO) {
if(shouldSeek == YES) {
[self leaveWorkgroup];
BufferChain *bufferChain = [[controller controller] bufferChain];
ConverterNode *converter = [bufferChain converter];
DLog(@"SEEKING! Resetting Buffer");
@ -183,15 +182,13 @@ static void *kInputNodeContext = &kInputNodeContext;
}
if(amountInBuffer < CHUNK_SIZE) {
[self followWorkgroup];
int framesToRead = CHUNK_SIZE - amountInBuffer;
int framesRead;
[self startWorkslice];
@autoreleasepool {
[self startWorkslice];
framesRead = [decoder readAudio:((char *)inputBuffer) + bytesInBuffer frames:framesToRead];
[self endWorkslice];
}
[self endWorkslice];
if(framesRead > 0 && !seekError) {
amountInBuffer += framesRead;

View File

@ -29,7 +29,7 @@
BOOL shouldContinue;
BOOL endOfStream; // All data is now in buffer
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;
uint32_t nodeChannelConfig;

View File

@ -222,6 +222,7 @@ BOOL SetPriorityRealtimeAudio(mach_port_t mach_thread_id) {
wg = workgroup;
if(wg && !isRealtimeError) {
int result = os_workgroup_join(wg, &wgToken);
isDeadlineError = NO;
if(result == 0) return;
if(result == EALREADY) {
DLog(@"Thread already in workgroup");
@ -251,13 +252,13 @@ BOOL SetPriorityRealtimeAudio(mach_port_t mach_thread_id) {
- (void)startWorkslice {
if(@available(macOS 11, *)) {
if(wg && !isRealtimeError) {
if(wg && !isRealtimeError && !isDeadlineError) {
const uint64_t currentTime = mach_absolute_time();
const uint64_t deadline = currentTime + intervalMachLength;
int result = os_workgroup_interval_start(wg, currentTime, deadline, nil);
if(result != 0) {
DLog(@"Deadline error = %d", result);
isRealtimeError = YES;
isDeadlineError = YES;
}
}
}
@ -265,11 +266,11 @@ BOOL SetPriorityRealtimeAudio(mach_port_t mach_thread_id) {
- (void)endWorkslice {
if(@available(macOS 11, *)) {
if(wg && !isRealtimeError) {
if(wg && !isRealtimeError && !isDeadlineError) {
int result = os_workgroup_interval_finish(wg, nil);
if(result != 0) {
DLog(@"Deadline end error = %d", result);
isRealtimeError = YES;
isDeadlineError = YES;
}
}
}