Skip to content

Commit 5909925

Browse files
authored
Ensure the processing graph is reconfigured before decoding starts (#713)
1 parent 0da2951 commit 5909925

File tree

1 file changed

+33
-28
lines changed

1 file changed

+33
-28
lines changed

Sources/CSFBAudioEngine/Player/AudioPlayer.mm

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,6 +1108,13 @@ bool PerformSeek() noexcept
11081108
continue;
11091109
}
11101110

1111+
os_log_debug(log_, "Dequeued %{public}@", decoderState->decoder_);
1112+
}
1113+
}
1114+
1115+
if(decoderState) {
1116+
// Before decoding starts determine the decoder and ring buffer format compatibility
1117+
if(!(decoderState->flags_.load(std::memory_order_acquire) & static_cast<unsigned int>(DecoderState::Flags::decodingStarted))) {
11111118
// Start decoding immediately if the join will be gapless (same sample rate, channel count, and channel layout)
11121119
if(auto renderFormat = decoderState->converter_.outputFormat; [renderFormat isEqual:[sourceNode_ outputFormatForBus:0]]) {
11131120
// Allocate the buffer that is the intermediary between the decoder state and the ring buffer
@@ -1125,44 +1132,42 @@ bool PerformSeek() noexcept
11251132
// decoding can't start until the processing graph is reconfigured which occurs after
11261133
// all active decoders complete
11271134
flags_.fetch_or(static_cast<unsigned int>(Flags::formatMismatch), std::memory_order_acq_rel);
1128-
1129-
os_log_debug(log_, "Dequeued %{public}@", decoderState->decoder_);
11301135
}
1131-
}
11321136

1133-
// If there a format mismatch the processing graph requires reconfiguration before decoding can begin
1134-
if(decoderState && (flags_.load(std::memory_order_acquire) & static_cast<unsigned int>(Flags::formatMismatch))) {
1135-
// Wait until all other decoders complete processing before reconfiguring the graph
1136-
const auto okToReconfigure = [&] {
1137-
std::lock_guard lock{activeDecodersLock_};
1138-
return activeDecoders_.size() == 1;
1139-
}();
1137+
// If there is a format mismatch the processing graph requires reconfiguration before decoding can begin
1138+
if((flags_.load(std::memory_order_acquire) & static_cast<unsigned int>(Flags::formatMismatch))) {
1139+
// Wait until all other decoders complete processing before reconfiguring the graph
1140+
const auto okToReconfigure = [&] {
1141+
std::lock_guard lock{activeDecodersLock_};
1142+
return activeDecoders_.size() == 1;
1143+
}();
11401144

1141-
if(okToReconfigure) {
1142-
flags_.fetch_and(~static_cast<unsigned int>(Flags::formatMismatch) & ~static_cast<unsigned int>(Flags::drainRequired), std::memory_order_release);
1145+
if(okToReconfigure) {
1146+
flags_.fetch_and(~static_cast<unsigned int>(Flags::formatMismatch) & ~static_cast<unsigned int>(Flags::drainRequired), std::memory_order_release);
11431147

1144-
os_log_debug(log_, "Non-gapless join for %{public}@", decoderState->decoder_);
1148+
os_log_debug(log_, "Non-gapless join for %{public}@", decoderState->decoder_);
11451149

1146-
auto renderFormat = decoderState->converter_.outputFormat;
1147-
if(NSError *error = nil; !ConfigureProcessingGraphAndRingBufferForFormat(renderFormat, &error)) {
1148-
decoderState->flags_.fetch_or(static_cast<unsigned int>(DecoderState::Flags::isCanceled), std::memory_order_acq_rel);
1149-
SubmitDecodingErrorEvent(error);
1150-
continue;
1151-
}
1152-
1153-
// Allocate the buffer that is the intermediary between the decoder state and the ring buffer
1154-
if(auto format = buffer.format; format.channelCount != renderFormat.channelCount || format.sampleRate != renderFormat.sampleRate) {
1155-
buffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:renderFormat frameCapacity:ringBufferChunkSize];
1156-
if(!buffer) {
1157-
os_log_error(log_, "Error creating AVAudioPCMBuffer with format %{public}@ and frame capacity %d", StringDescribingAVAudioFormat(renderFormat), ringBufferChunkSize);
1150+
auto renderFormat = decoderState->converter_.outputFormat;
1151+
if(NSError *error = nil; !ConfigureProcessingGraphAndRingBufferForFormat(renderFormat, &error)) {
11581152
decoderState->flags_.fetch_or(static_cast<unsigned int>(DecoderState::Flags::isCanceled), std::memory_order_acq_rel);
1159-
SubmitDecodingErrorEvent([NSError errorWithDomain:SFBAudioPlayerErrorDomain code:SFBAudioPlayerErrorCodeInternalError userInfo:nil]);
1153+
SubmitDecodingErrorEvent(error);
11601154
continue;
11611155
}
1156+
1157+
// Allocate the buffer that is the intermediary between the decoder state and the ring buffer
1158+
if(auto format = buffer.format; format.channelCount != renderFormat.channelCount || format.sampleRate != renderFormat.sampleRate) {
1159+
buffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:renderFormat frameCapacity:ringBufferChunkSize];
1160+
if(!buffer) {
1161+
os_log_error(log_, "Error creating AVAudioPCMBuffer with format %{public}@ and frame capacity %d", StringDescribingAVAudioFormat(renderFormat), ringBufferChunkSize);
1162+
decoderState->flags_.fetch_or(static_cast<unsigned int>(DecoderState::Flags::isCanceled), std::memory_order_acq_rel);
1163+
SubmitDecodingErrorEvent([NSError errorWithDomain:SFBAudioPlayerErrorDomain code:SFBAudioPlayerErrorCodeInternalError userInfo:nil]);
1164+
continue;
1165+
}
1166+
}
11621167
}
1168+
else
1169+
decoderState = nullptr;
11631170
}
1164-
else
1165-
decoderState = nullptr;
11661171
}
11671172

11681173
if(decoderState && !(flags_.load(std::memory_order_acquire) & static_cast<unsigned int>(Flags::drainRequired))) {

0 commit comments

Comments
 (0)