Skip to content

Commit aecfc27

Browse files
committed
Audio Processing: Guard converter processing
Guard the converter processor with a mutex instead of a stupid BOOL flag and guard every alloc or cleanup. Also wrap every pair of unified clean plus realloc with its own mutex block, since it's recursive within the same thread. Hopefully this will fix the crashes we've been seeing where it gets freed twice, or freed multiple times overlapping from different threads. Signed-off-by: Christopher Snowhill <[email protected]>
1 parent 08dc7fa commit aecfc27

File tree

2 files changed

+28
-19
lines changed

2 files changed

+28
-19
lines changed

Audio/Chain/ConverterNode.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
double streamTimestamp, streamTimeRatio;
2929

3030
BOOL stopping;
31-
BOOL convertEntered;
3231
BOOL paused;
3332

3433
BOOL skipResampler;

Audio/Chain/ConverterNode.m

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ void PrintStreamDesc(AudioStreamBasicDescription *inDesc) {
4040
DLog(@"- - - - - - - - - - - - - - - - - - - -\n");
4141
}
4242

43-
@implementation ConverterNode
43+
@implementation ConverterNode {
44+
NSRecursiveLock *mutex;
45+
}
4446

4547
static void *kConverterNodeContext = &kConverterNodeContext;
4648

@@ -58,7 +60,6 @@ - (id)initWithController:(id)c previous:(id)p {
5860
floatBufferSize = 0;
5961

6062
stopping = NO;
61-
convertEntered = NO;
6263
paused = NO;
6364

6465
resetProcessed = NO;
@@ -68,6 +69,8 @@ - (id)initWithController:(id)c previous:(id)p {
6869
extrapolateBuffer = NULL;
6970
extrapolateBufferSize = 0;
7071

72+
mutex = [[NSRecursiveLock alloc] init];
73+
7174
#ifdef LOG_CHAINS
7275
[self initLogFiles];
7376
#endif
@@ -137,8 +140,10 @@ - (void)process {
137140
chunk = nil;
138141
}
139142
if(streamFormatChanged) {
143+
[mutex lock];
140144
[self cleanUp];
141145
[self setupWithInputFormat:newInputFormat withInputConfig:newInputChannelConfig outputFormat:self->outputFormat isLossless:rememberedLossless];
146+
[mutex unlock];
142147
}
143148
}
144149
}
@@ -151,18 +156,18 @@ - (AudioChunk *)convert {
151156
if(stopping)
152157
return 0;
153158

154-
convertEntered = YES;
159+
[mutex lock];
155160

156161
if(stopping || [self shouldContinue] == NO) {
157-
convertEntered = NO;
162+
[mutex unlock];
158163
return nil;
159164
}
160165

161166
if(inpOffset == inpSize) {
162167
streamTimestamp = 0.0;
163168
streamTimeRatio = 1.0;
164169
if(![self peekTimestamp:&streamTimestamp timeRatio:&streamTimeRatio]) {
165-
convertEntered = NO;
170+
[mutex unlock];
166171
return nil;
167172
}
168173
}
@@ -219,7 +224,7 @@ - (AudioChunk *)convert {
219224
}
220225

221226
if(!bytesReadFromInput) {
222-
convertEntered = NO;
227+
[mutex unlock];
223228
return nil;
224229
}
225230

@@ -296,7 +301,7 @@ - (AudioChunk *)convert {
296301
}
297302

298303
if(stopping) {
299-
convertEntered = NO;
304+
[mutex unlock];
300305
return nil;
301306
}
302307

@@ -362,11 +367,11 @@ - (AudioChunk *)convert {
362367
resetProcessed = NO;
363368
}
364369
streamTimestamp += [chunk durationRatioed];
365-
convertEntered = NO;
370+
[mutex unlock];
366371
return chunk;
367372
}
368373

369-
convertEntered = NO;
374+
[mutex unlock];
370375
return nil;
371376
}
372377

@@ -432,6 +437,8 @@ - (void)refreshVolumeScaling {
432437

433438
- (BOOL)setupWithInputFormat:(AudioStreamBasicDescription)inf withInputConfig:(uint32_t)inputConfig outputFormat:(AudioStreamBasicDescription)outf isLossless:(BOOL)lossless {
434439
// Make the converter
440+
[mutex lock];
441+
435442
inputFormat = inf;
436443
outputFormat = outf;
437444

@@ -441,8 +448,10 @@ - (BOOL)setupWithInputFormat:(AudioStreamBasicDescription)inf withInputConfig:(u
441448

442449
// These are the only sample formats we support translating
443450
BOOL isFloat = !!(inputFormat.mFormatFlags & kAudioFormatFlagIsFloat);
444-
if((!isFloat && !(inputFormat.mBitsPerChannel >= 1 && inputFormat.mBitsPerChannel <= 32)) || (isFloat && !(inputFormat.mBitsPerChannel == 32 || inputFormat.mBitsPerChannel == 64)))
451+
if((!isFloat && !(inputFormat.mBitsPerChannel >= 1 && inputFormat.mBitsPerChannel <= 32)) || (isFloat && !(inputFormat.mBitsPerChannel == 32 || inputFormat.mBitsPerChannel == 64))) {
452+
[mutex unlock];
445453
return NO;
454+
}
446455

447456
floatFormat = inputFormat;
448457
floatFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked;
@@ -475,8 +484,10 @@ - (BOOL)setupWithInputFormat:(AudioStreamBasicDescription)inf withInputConfig:(u
475484
soxr_error_t error;
476485

477486
soxr = soxr_create(floatFormat.mSampleRate, outputFormat.mSampleRate, floatFormat.mChannelsPerFrame, &error, &io_spec, &q_spec, &runtime_spec);
478-
if(error)
487+
if(error) {
488+
[mutex unlock];
479489
return NO;
490+
}
480491

481492
PRIME_LEN_ = MAX(floatFormat.mSampleRate / 20, 1024u);
482493
PRIME_LEN_ = MIN(PRIME_LEN_, 16384u);
@@ -501,10 +512,11 @@ - (BOOL)setupWithInputFormat:(AudioStreamBasicDescription)inf withInputConfig:(u
501512

502513
// Move this here so process call isn't running the resampler until it's allocated
503514
stopping = NO;
504-
convertEntered = NO;
505515
streamFormatChanged = NO;
506516
paused = NO;
507517

518+
[mutex unlock];
519+
508520
return YES;
509521
}
510522

@@ -526,11 +538,10 @@ - (void)setOutputFormat:(AudioStreamBasicDescription)format {
526538
- (void)inputFormatDidChange:(AudioStreamBasicDescription)format inputConfig:(uint32_t)inputConfig {
527539
DLog(@"FORMAT CHANGED");
528540
paused = YES;
529-
while(convertEntered) {
530-
usleep(500);
531-
}
541+
[mutex lock];
532542
[self cleanUp];
533543
[self setupWithInputFormat:format withInputConfig:inputConfig outputFormat:self->outputFormat isLossless:rememberedLossless];
544+
[mutex unlock];
534545
}
535546

536547
- (void)setRGInfo:(NSDictionary *)rgi {
@@ -541,9 +552,7 @@ - (void)setRGInfo:(NSDictionary *)rgi {
541552

542553
- (void)cleanUp {
543554
stopping = YES;
544-
while(convertEntered) {
545-
usleep(500);
546-
}
555+
[mutex lock];
547556
if(soxr) {
548557
soxr_delete(soxr);
549558
soxr = NULL;
@@ -565,6 +574,7 @@ - (void)cleanUp {
565574
}
566575
inpOffset = 0;
567576
inpSize = 0;
577+
[mutex unlock];
568578
}
569579

570580
- (double)secondsBuffered {

0 commit comments

Comments
 (0)