Changeset 278905 in webkit
- Timestamp:
- Jun 15, 2021, 2:49:42 PM (4 years ago)
- Location:
- branches/safari-611-branch/Source/WebCore
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/safari-611-branch/Source/WebCore/ChangeLog
r278903 r278905 1 2021-06-15 Alan Coon <alancoon@apple.com> 2 3 Apply patch. rdar://problem/79355311 4 5 2021-06-15 Youenn Fablet <youenn@apple.com> 6 7 Reduce crackling at start of playing a live audio track 8 https://bugs.webkit.org/show_bug.cgi?id=218898 9 <rdar://problem/71625010> 10 11 Reviewed by Eric Carlson. 12 13 We often hear crackles at the beginning of playing a MediaStreamTrack. 14 This is due to starting at a point where there is not enough data, so we start rendering and quickly run short of data. 15 Our heuristic to start was not good since we were not accounting to LibWebRTC audio module which sends audio samples by batch of 5 samples. 16 So we would have needed to at least have 6 samples to be sure to not run out of data. 17 18 What this patch does: 19 - Add an extra parameter to AudioSampleDataSource so that we do not start until we have at least been pushed a given number of sample count. 20 - Change LibWebRTAudioModule to send audio samples by batch of 3 (hence 30 ms) instead of 5 21 - Set this new parameter to 2 for local tracks and 4 for remote tracks 22 - Add a new boolean to AudioSampleDataSource to know whether we start the track for the first time or not. If we start it, use the new parameter to buffer enough data. 23 Otherwise, use current heuristic. 24 25 We also reduce the AudioSampleDataSource buffer to 0.5 seconds instead of 2 seconds, since 2 seconds is too much for real time audio. 26 27 Manually tested. 28 29 * platform/audio/cocoa/AudioSampleDataSource.h: 30 * platform/audio/cocoa/AudioSampleDataSource.mm: 31 (WebCore::AudioSampleDataSource::create): 32 (WebCore::AudioSampleDataSource::AudioSampleDataSource): 33 (WebCore::AudioSampleDataSource::pullSamplesInternal): 34 * platform/mediastream/libwebrtc/LibWebRTCAudioModule.cpp: 35 (WebCore::LibWebRTCAudioModule::pollFromSource): 36 * platform/mediastream/libwebrtc/LibWebRTCAudioModule.h: 37 * platform/mediastream/mac/AudioMediaStreamTrackRendererCocoa.cpp: 38 (WebCore::pollSamplesCount): 39 (WebCore::AudioMediaStreamTrackRendererCocoa::pushSamples): 40 * platform/mediastream/mac/MediaStreamTrackAudioSourceProviderCocoa.cpp: 41 (WebCore::MediaStreamTrackAudioSourceProviderCocoa::MediaStreamTrackAudioSourceProviderCocoa): 42 * platform/mediastream/mac/WebAudioSourceProviderCocoa.h: 43 * platform/mediastream/mac/WebAudioSourceProviderCocoa.mm: 44 (WebCore::WebAudioSourceProviderCocoa::prepare): 45 1 46 2021-06-15 Alan Coon <alancoon@apple.com> 2 47 -
branches/safari-611-branch/Source/WebCore/platform/audio/cocoa/AudioSampleDataSource.h
r269829 r278905 48 48 { 49 49 public: 50 static Ref<AudioSampleDataSource> create(size_t, WTF::LoggerHelper& );50 static Ref<AudioSampleDataSource> create(size_t, WTF::LoggerHelper&, size_t waitToStartForPushCount = 2); 51 51 52 52 ~AudioSampleDataSource(); … … 81 81 82 82 private: 83 AudioSampleDataSource(size_t, LoggerHelper& );83 AudioSampleDataSource(size_t, LoggerHelper&, size_t waitToStartForPushCount); 84 84 85 85 OSStatus setupConverter(); … … 99 99 100 100 uint64_t m_lastPushedSampleCount { 0 }; 101 size_t m_waitToStartForPushCount { 2 }; 101 102 MediaTime m_expectedNextPushedSampleTime { MediaTime::invalidTime() }; 103 bool m_isFirstPull { true }; 102 104 103 105 MediaTime m_inputSampleOffset; -
branches/safari-611-branch/Source/WebCore/platform/audio/cocoa/AudioSampleDataSource.mm
r278488 r278905 45 45 using namespace JSC; 46 46 47 Ref<AudioSampleDataSource> AudioSampleDataSource::create(size_t maximumSampleCount, LoggerHelper& loggerHelper) 48 { 49 return adoptRef(*new AudioSampleDataSource(maximumSampleCount, loggerHelper)); 50 } 51 52 AudioSampleDataSource::AudioSampleDataSource(size_t maximumSampleCount, LoggerHelper& loggerHelper) 53 : m_inputSampleOffset(MediaTime::invalidTime()) 47 Ref<AudioSampleDataSource> AudioSampleDataSource::create(size_t maximumSampleCount, LoggerHelper& loggerHelper, size_t waitToStartForPushCount) 48 { 49 return adoptRef(*new AudioSampleDataSource(maximumSampleCount, loggerHelper, waitToStartForPushCount)); 50 } 51 52 AudioSampleDataSource::AudioSampleDataSource(size_t maximumSampleCount, LoggerHelper& loggerHelper, size_t waitToStartForPushCount) 53 : m_waitToStartForPushCount(waitToStartForPushCount) 54 , m_inputSampleOffset(MediaTime::invalidTime()) 54 55 , m_maximumSampleCount(maximumSampleCount) 55 56 #if !RELEASE_LOG_DISABLED … … 231 232 if (m_shouldComputeOutputSampleOffset) { 232 233 uint64_t buffered = endFrame - startFrame; 233 if (buffered < sampleCount * 2 || (m_endFrameWhenNotEnoughData && m_endFrameWhenNotEnoughData == endFrame)) { 234 if (mode != AudioSampleDataSource::Mix) 235 AudioSampleBufferList::zeroABL(buffer, byteCount); 236 return false; 234 if (m_isFirstPull) { 235 if (buffered >= m_waitToStartForPushCount * m_lastPushedSampleCount) { 236 m_outputSampleOffset = startFrame - timeStamp; 237 m_shouldComputeOutputSampleOffset = false; 238 m_endFrameWhenNotEnoughData = 0; 239 } else { 240 // We wait for one chunk of value before starting to play. 241 if (mode != AudioSampleDataSource::Mix) 242 AudioSampleBufferList::zeroABL(buffer, byteCount); 243 return false; 244 } 245 } else { 246 if (buffered < sampleCount * 2 || (m_endFrameWhenNotEnoughData && m_endFrameWhenNotEnoughData == endFrame)) { 247 if (mode != AudioSampleDataSource::Mix) 248 AudioSampleBufferList::zeroABL(buffer, byteCount); 249 return false; 250 } 251 252 m_shouldComputeOutputSampleOffset = false; 253 m_endFrameWhenNotEnoughData = 0; 254 255 m_outputSampleOffset = (endFrame - sampleCount) - timeStamp; 256 m_outputSampleOffset -= computeOffsetDelay(m_outputDescription->sampleRate(), m_lastPushedSampleCount); 257 dispatch_async(dispatch_get_main_queue(), [logIdentifier = LOGIDENTIFIER, outputSampleOffset = m_outputSampleOffset, this, protectedThis = makeRefPtr(*this)] { 258 ALWAYS_LOG(logIdentifier, "setting new offset to ", outputSampleOffset); 259 }); 237 260 } 238 239 m_shouldComputeOutputSampleOffset = false;240 m_endFrameWhenNotEnoughData = 0;241 242 m_outputSampleOffset = (endFrame - sampleCount) - timeStamp;243 m_outputSampleOffset -= computeOffsetDelay(m_outputDescription->sampleRate(), m_lastPushedSampleCount);244 dispatch_async(dispatch_get_main_queue(), [logIdentifier = LOGIDENTIFIER, outputSampleOffset = m_outputSampleOffset, this, protectedThis = makeRefPtr(*this)] {245 ALWAYS_LOG(logIdentifier, "setting new offset to ", outputSampleOffset);246 });247 261 } 248 262 … … 272 286 } 273 287 288 m_isFirstPull = false; 289 274 290 if (mode == Copy) { 275 291 m_ringBuffer->fetch(&buffer, sampleCount, timeStamp, CARingBuffer::Copy); -
branches/safari-611-branch/Source/WebCore/platform/mediastream/libwebrtc/LibWebRTCAudioModule.cpp
r265135 r278905 72 72 // libwebrtc uses 10ms frames. 73 73 const unsigned frameLengthMs = 1000 * LibWebRTCAudioFormat::chunkSampleCount / LibWebRTCAudioFormat::sampleRate; 74 const unsigned pollSamples = 5; 75 const unsigned pollInterval = 5 * frameLengthMs; 74 const unsigned pollInterval = LibWebRTCAudioModule::PollSamplesCount * frameLengthMs; 76 75 const unsigned channels = 2; 77 76 … … 102 101 return; 103 102 104 for (unsigned i = 0; i < pollSamples; i++) {103 for (unsigned i = 0; i < PollSamplesCount; i++) { 105 104 int64_t elapsedTime = -1; 106 105 int64_t ntpTime = -1; -
branches/safari-611-branch/Source/WebCore/platform/mediastream/libwebrtc/LibWebRTCAudioModule.h
r266454 r278905 45 45 public: 46 46 LibWebRTCAudioModule(); 47 48 static constexpr unsigned PollSamplesCount = 3; 47 49 48 50 private: -
branches/safari-611-branch/Source/WebCore/platform/mediastream/mac/AudioMediaStreamTrackRendererCocoa.cpp
r267472 r278905 32 32 #include "AudioSampleDataSource.h" 33 33 #include "CAAudioStreamDescription.h" 34 #include "LibWebRTCAudioModule.h" 34 35 35 36 namespace WebCore { … … 75 76 } 76 77 78 static unsigned pollSamplesCount() 79 { 80 #if USE(LIBWEBRTC) 81 return LibWebRTCAudioModule::PollSamplesCount + 1; 82 #else 83 return 2; 84 #endif 85 } 86 77 87 void AudioMediaStreamTrackRendererCocoa::pushSamples(const MediaTime& sampleTime, const PlatformAudioData& audioData, const AudioStreamDescription& description, size_t sampleCount) 78 88 { … … 80 90 ASSERT(description.platformDescription().type == PlatformDescription::CAAudioStreamBasicType); 81 91 if (!m_dataSource || m_shouldReset || !m_dataSource->inputDescription() || *m_dataSource->inputDescription() != description) { 82 auto dataSource = AudioSampleDataSource::create(description.sampleRate() * 2, *this); 92 // FIXME: For non libwebrtc sources, we can probably reduce poll samples count to 2. 93 94 auto dataSource = AudioSampleDataSource::create(description.sampleRate() * 0.5, *this, pollSamplesCount()); 83 95 84 96 if (dataSource->setInputFormat(toCAAudioStreamDescription(description))) { -
branches/safari-611-branch/Source/WebCore/platform/mediastream/mac/MediaStreamTrackAudioSourceProviderCocoa.cpp
r268521 r278905 29 29 #if ENABLE(WEB_AUDIO) && ENABLE(MEDIA_STREAM) 30 30 31 #import "LibWebRTCAudioModule.h" 32 31 33 namespace WebCore { 32 34 … … 40 42 , m_source(source.source()) 41 43 { 44 #if USE(LIBWEBRTC) 45 if (m_source->isIncomingAudioSource()) 46 setPollSamplesCount(LibWebRTCAudioModule::PollSamplesCount + 1); 47 #endif 42 48 } 43 49 -
branches/safari-611-branch/Source/WebCore/platform/mediastream/mac/WebAudioSourceProviderCocoa.h
r268521 r278905 61 61 void receivedNewAudioSamples(const PlatformAudioData&, const AudioStreamDescription&, size_t); 62 62 63 void setPollSamplesCount(size_t); 64 63 65 private: 64 66 virtual void hasNewClient(AudioSourceProviderClient*) = 0; … … 81 83 RefPtr<AudioSampleDataSource> m_dataSource; 82 84 85 size_t m_pollSamplesCount { 3 }; 83 86 uint64_t m_writeCount { 0 }; 84 87 uint64_t m_readCount { 0 }; 85 88 }; 86 89 90 inline void WebAudioSourceProviderCocoa::setPollSamplesCount(size_t count) 91 { 92 m_pollSamplesCount = count; 93 } 94 87 95 } 88 96 -
branches/safari-611-branch/Source/WebCore/platform/mediastream/mac/WebAudioSourceProviderCocoa.mm
r268577 r278905 121 121 122 122 if (!m_dataSource) 123 m_dataSource = AudioSampleDataSource::create(kRingBufferDuration * sampleRate, loggerHelper() );123 m_dataSource = AudioSampleDataSource::create(kRingBufferDuration * sampleRate, loggerHelper(), m_pollSamplesCount); 124 124 m_dataSource->setInputFormat(m_inputDescription.value()); 125 125 m_dataSource->setOutputFormat(m_outputDescription.value());
Note:
See TracChangeset
for help on using the changeset viewer.