system audio playback fix

This commit is contained in:
True Zhuanjia committed 2026-04-14 14:46:18 +08:00
1 parent 9807a77d9b
commit e87f0f1aa0
3 files changed
+22 -58

No files matched your search

+1
View File
@@ -30,5 +30,6 @@
-(NSString*) getActiveCodecName; -(NSString*) getActiveCodecName;
+ (void)setVolume:(float)newVolume; + (void)setVolume:(float)newVolume;
+ (void)resetSysAudioPlayback;
@end @end
+15 -58
View File
@@ -48,7 +48,6 @@ static SDL_AudioDeviceID audioDevice;
static OPUS_MULTISTREAM_CONFIGURATION audioConfig; static OPUS_MULTISTREAM_CONFIGURATION audioConfig;
static void* audioBuffer; static void* audioBuffer;
static float volume = 1.0; static float volume = 1.0;
static bool sysAudioQueueReset = false;
static int audioFrameSize; static int audioFrameSize;
static bool useSystemAudioEngine; static bool useSystemAudioEngine;
@@ -57,8 +56,6 @@ static AVAudioEngine *audioEngine;
static AVAudioPlayerNode *audioPlayerNode; static AVAudioPlayerNode *audioPlayerNode;
static AVAudioPCMBuffer *pcmBuffer; static AVAudioPCMBuffer *pcmBuffer;
static AVAudioFormat *audioFormat; static AVAudioFormat *audioFormat;
static int64_t systemAudioScheduledFrames;
static CFTimeInterval systemAudioLastFlushTime;
static bool muteInBackground; static bool muteInBackground;
static bool fullColorRange; static bool fullColorRange;
@@ -67,32 +64,6 @@ static VideoDecoderRenderer* renderer;
static BandwidthTracker *bwTracker; static BandwidthTracker *bwTracker;
static int64_t GetSystemAudioQueuedFrames(void)
{
if (audioPlayerNode == nil) {
return 0;
}
AVAudioTime *nodeTime = audioPlayerNode.lastRenderTime;
if (nodeTime == nil) {
return systemAudioScheduledFrames;
}
AVAudioTime *playerTime = [audioPlayerNode playerTimeForNodeTime:nodeTime];
if (playerTime == nil) {
return systemAudioScheduledFrames;
}
int64_t queuedFrames = systemAudioScheduledFrames - playerTime.sampleTime;
return queuedFrames > 0 ? queuedFrames : 0;
}
static void ResetSystemAudioBackpressureState(void)
{
systemAudioScheduledFrames = 0;
systemAudioLastFlushTime = 0;
}
int DrDecoderSetup(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags) int DrDecoderSetup(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags)
{ {
[renderer setupWithVideoFormat:videoFormat width:width height:height frameRate:redrawRate fullRange:fullColorRange]; [renderer setupWithVideoFormat:videoFormat width:width height:height frameRate:redrawRate fullRange:fullColorRange];
@@ -377,7 +348,6 @@ void ArCleanup(void)
} }
void AudioEngineInit(int sampleRate, int channelCount) { void AudioEngineInit(int sampleRate, int channelCount) {
ResetSystemAudioBackpressureState();
audioEngine = [[AVAudioEngine alloc] init]; audioEngine = [[AVAudioEngine alloc] init];
audioPlayerNode = [[AVAudioPlayerNode alloc] init]; audioPlayerNode = [[AVAudioPlayerNode alloc] init];
@@ -430,6 +400,16 @@ void AudioEngineInit(int sampleRate, int channelCount) {
[audioPlayerNode play]; [audioPlayerNode play];
} }
+ (void)resetSysAudioPlayback {
audioSessionInterrupted = true;
[audioPlayerNode stop];
[audioEngine stop];
AudioEngineInit(audioConfig.sampleRate, audioConfig.channelCount);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5*NSEC_PER_SEC), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
audioSessionInterrupted = false;
});
}
void ArDecodeAndPlaySample(char* sampleData, int sampleLength) void ArDecodeAndPlaySample(char* sampleData, int sampleLength)
{ {
if(appDidEnterBackgroundWithoutPip && muteInBackground) return; if(appDidEnterBackgroundWithoutPip && muteInBackground) return;
@@ -456,41 +436,20 @@ void ArDecodeAndPlaySample(char* sampleData, int sampleLength)
float* fbuf = (float*)audioBuffer; float* fbuf = (float*)audioBuffer;
if(useSystemAudioEngine){ if(useSystemAudioEngine){
int64_t maxQueuedFrames = (int64_t)audioConfig.samplesPerFrame * 10; // 创建 AVAudioPCMBuffer
CFTimeInterval now = CACurrentMediaTime();
if (GetSystemAudioQueuedFrames() > maxQueuedFrames &&
now - systemAudioLastFlushTime >= 5) {
// Drop stale local backlog without slowing down upstream packet
// consumption, which keeps background playback stable.
NSLog(@"sdfasfdsfasdfasfasfasdfasfasfdfasf");
sysAudioQueueReset = true;
dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC));
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delayTime), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sysAudioQueueReset = false;
});
[audioPlayerNode reset];
ResetSystemAudioBackpressureState();
systemAudioLastFlushTime = now;
}
AVAudioFrameCount frameCount = decodeLen; AVAudioFrameCount frameCount = decodeLen;
AVAudioPCMBuffer *buffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:audioFormat frameCapacity:frameCount]; AVAudioPCMBuffer *buffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:audioFormat frameCapacity:frameCount];
buffer.frameLength = frameCount; buffer.frameLength = frameCount;
// 拷贝数据到 buffer
for (int ch = 0; ch < audioConfig.channelCount; ch++) { for (int ch = 0; ch < audioConfig.channelCount; ch++) {
float *dst = buffer.floatChannelData[ch]; float *dst = buffer.floatChannelData[ch];
for (int i = 0; i < decodeLen; i++) { for (int i = 0; i < decodeLen; i++) {
dst[i] = fbuf[i * audioConfig.channelCount + ch] * (sysAudioQueueReset ? 0 : volume); // 非交错数据 dst[i] = fbuf[i * audioConfig.channelCount + ch] * volume; // 非交错数据
} }
} }
// 播放
if(!audioSessionInterrupted) { if(!audioSessionInterrupted) [audioPlayerNode scheduleBuffer:buffer completionHandler:nil];
[audioPlayerNode scheduleBuffer:buffer completionHandler:nil];
systemAudioScheduledFrames += frameCount;
}
} }
else{ else{
@@ -586,7 +545,6 @@ void ClSetControllerLED(uint16_t controllerNumber, uint8_t r, uint8_t g, uint8_t
// won't be able to acquire it if LiStartConnection is in // won't be able to acquire it if LiStartConnection is in
// progress. // progress.
LiInterruptConnection(); LiInterruptConnection();
ResetSystemAudioBackpressureState();
[audioPlayerNode stop]; [audioPlayerNode stop];
[audioEngine stop]; [audioEngine stop];
[[NSNotificationCenter defaultCenter] removeObserver:self]; [[NSNotificationCenter defaultCenter] removeObserver:self];
@@ -609,7 +567,6 @@ void ClSetControllerLED(uint16_t controllerNumber, uint8_t r, uint8_t g, uint8_t
switch (type) { switch (type) {
case AVAudioSessionInterruptionTypeBegan: case AVAudioSessionInterruptionTypeBegan:
audioSessionInterrupted = true; audioSessionInterrupted = true;
ResetSystemAudioBackpressureState();
[audioPlayerNode stop]; [audioPlayerNode stop];
[audioEngine stop]; [audioEngine stop];
break; break;
@@ -1087,6 +1087,7 @@
//[self.pipController startPictureInPicture]; //[self.pipController startPictureInPicture];
//sleep(1); //sleep(1);
appDidEnterBackgroundWithoutPip = true; appDidEnterBackgroundWithoutPip = true;
NSLog(@"applicationWillResignActive %f", CACurrentMediaTime()); NSLog(@"applicationWillResignActive %f", CACurrentMediaTime());
[_streamView saveStreamViewWidgetChanges]; [_streamView saveStreamViewWidgetChanges];
@@ -1105,6 +1106,11 @@
- (void)applicationDidBecomeActive:(NSNotification *)notification { - (void)applicationDidBecomeActive:(NSNotification *)notification {
appDidEnterBackgroundWithoutPip = false; appDidEnterBackgroundWithoutPip = false;
[_streamMan setNeedRequeuing:true]; [_streamMan setNeedRequeuing:true];
// dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(15 * NSEC_PER_SEC));
// dispatch_after(delay, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[Connection resetSysAudioPlayback];
// });
// Stop the background timer, since we're foregrounded again // Stop the background timer, since we're foregrounded again
if (_inactivityTimer != nil) { if (_inactivityTimer != nil) {
Log(LOG_I, @"Stopping inactivity timer after becoming active again"); Log(LOG_I, @"Stopping inactivity timer after becoming active again");