Changeset 265280 in webkit
- Timestamp:
- Aug 5, 2020, 1:11:50 AM (6 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 4 edited
-
ChangeLog (modified) (1 diff)
-
platform/audio/mac/AudioSampleDataSource.h (modified) (1 diff)
-
platform/audio/mac/AudioSampleDataSource.mm (modified) (6 diffs)
-
platform/mediastream/mac/RealtimeIncomingAudioSourceCocoa.cpp (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r265278 r265280 1 2020-08-05 Youenn Fablet <youenn@apple.com> 2 3 Update AudioSampleDataSource offset computation 4 https://bugs.webkit.org/show_bug.cgi?id=215127 5 <rdar://problem/65938265> 6 7 Reviewed by Eric Carlson. 8 9 As per logs, it sometimes happens that the offset is so big that the timestamp is below the start of the window. 10 In that case, our logic is not able to catch up and reduce the offset. 11 To handle this, we special case if the timestamp is below the start frame and do as if we were starting from scratch. 12 Otherwise, we continue our logic to fine tune the offset by slowly making it bigger to not hit the end of the window but still be close to it. 13 Updated logging to help further debugging this issue if needed. 14 15 * platform/audio/mac/AudioSampleDataSource.h: 16 * platform/audio/mac/AudioSampleDataSource.mm: 17 (WebCore::AudioSampleDataSource::pushSamplesInternal): 18 (WebCore::computeOffsetDelay): 19 (WebCore::AudioSampleDataSource::pullSamplesInternal): 20 (WebCore::AudioSampleDataSource::pullAvalaibleSamplesAsChunks): 21 * platform/mediastream/mac/RealtimeIncomingAudioSourceCocoa.cpp: 22 (WebCore::RealtimeIncomingAudioSourceCocoa::OnData): 23 1 24 2020-08-05 Eric Liang <ericliang@apple.com> 2 25 -
trunk/Source/WebCore/platform/audio/mac/AudioSampleDataSource.h
r265244 r265280 114 114 float m_volume { 1.0 }; 115 115 bool m_muted { false }; 116 bool m_ transitioningFromPaused{ true };116 bool m_shouldComputeOutputSampleOffset { true }; 117 117 118 118 #if !RELEASE_LOG_DISABLED -
trunk/Source/WebCore/platform/audio/mac/AudioSampleDataSource.mm
r265244 r265280 164 164 if (m_inputSampleOffset == MediaTime::invalidTime()) { 165 165 m_inputSampleOffset = MediaTime(1 - sampleTime.timeValue(), sampleTime.timeScale()); 166 dispatch_async(dispatch_get_main_queue(), [ inputSampleOffset = m_inputSampleOffset.timeValue(), maximumSampleCount = m_maximumSampleCount, this, protectedThis = makeRefPtr(*this)] {167 ERROR_LOG("pushSamples: input sample offset is ", inputSampleOffset, ", maximumSampleCount =", maximumSampleCount);166 dispatch_async(dispatch_get_main_queue(), [logIdentifier = LOGIDENTIFIER, inputSampleOffset = m_inputSampleOffset.timeValue(), maximumSampleCount = m_maximumSampleCount, this, protectedThis = makeRefPtr(*this)] { 167 ALWAYS_LOG(logIdentifier, "input sample offset is ", inputSampleOffset, ", maximumSampleCount is ", maximumSampleCount); 168 168 }); 169 169 } … … 178 178 m_ringBuffer->store(sampleBufferList, sampleCount, sampleTime.timeValue()); 179 179 m_lastPushedSampleCount = sampleCount; 180 181 #if !LOG_DISABLED182 uint64_t startFrame2 = 0;183 uint64_t endFrame2 = 0;184 m_ringBuffer->getCurrentFrameBounds(startFrame2, endFrame2);185 dispatch_async(dispatch_get_main_queue(), [sampleCount, sampleTime, presentationTime, absoluteTime = mach_absolute_time(), startFrame1, endFrame1, startFrame2, endFrame2] {186 LOG(MediaCaptureSamples, "@@ pushSamples: added %ld samples for time = %s (was %s), mach time = %lld", sampleCount, toString(sampleTime).utf8().data(), toString(presentationTime).utf8().data(), absoluteTime);187 LOG(MediaCaptureSamples, "@@ pushSamples: buffered range was [%lld .. %lld], is [%lld .. %lld]", startFrame1, endFrame1, startFrame2, endFrame2);188 });189 #endif190 180 } 191 181 … … 205 195 } 206 196 197 static inline int64_t computeOffsetDelay(double sampleRate, uint64_t lastPushedSampleCount) 198 { 199 const double twentyMS = .02; 200 const double tenMS = .01; 201 const double fiveMS = .005; 202 203 if (lastPushedSampleCount > sampleRate * twentyMS) 204 return sampleRate * twentyMS; 205 if (lastPushedSampleCount > sampleRate * tenMS) 206 return sampleRate * tenMS; 207 if (lastPushedSampleCount > sampleRate * fiveMS) 208 return sampleRate * fiveMS; 209 return 0; 210 } 211 207 212 bool AudioSampleDataSource::pullSamplesInternal(AudioBufferList& buffer, size_t& sampleCount, uint64_t timeStamp, double /*hostTime*/, PullMode mode) 208 213 { … … 226 231 m_ringBuffer->getCurrentFrameBounds(startFrame, endFrame); 227 232 228 if (m_ transitioningFromPaused) {233 if (m_shouldComputeOutputSampleOffset) { 229 234 uint64_t buffered = endFrame - startFrame; 230 235 if (buffered < sampleCount * 2) { … … 234 239 } 235 240 236 const double twentyMS = .02; 237 const double tenMS = .01; 238 const double fiveMS = .005; 239 double sampleRate = m_outputDescription->sampleRate(); 241 m_shouldComputeOutputSampleOffset = false; 242 240 243 m_outputSampleOffset = (endFrame - sampleCount) - timeStamp; 241 if (m_lastPushedSampleCount > sampleRate * twentyMS) 242 m_outputSampleOffset -= sampleRate * twentyMS; 243 else if (m_lastPushedSampleCount > sampleRate * tenMS) 244 m_outputSampleOffset -= sampleRate * tenMS; 245 else if (m_lastPushedSampleCount > sampleRate * fiveMS) 246 m_outputSampleOffset -= sampleRate * fiveMS; 247 248 m_transitioningFromPaused = false; 244 m_outputSampleOffset -= computeOffsetDelay(m_outputDescription->sampleRate(), m_lastPushedSampleCount); 245 dispatch_async(dispatch_get_main_queue(), [logIdentifier = LOGIDENTIFIER, outputSampleOffset = m_outputSampleOffset, this, protectedThis = makeRefPtr(*this)] { 246 ALWAYS_LOG(logIdentifier, "setting new offset to ", outputSampleOffset); 247 }); 249 248 } 250 249 251 250 timeStamp += m_outputSampleOffset; 252 251 253 #if !LOG_DISABLED254 dispatch_async(dispatch_get_main_queue(), [sampleCount, timeStamp, sampleOffset = m_outputSampleOffset] {255 LOG(MediaCaptureSamples, "** pullSamplesInternal: asking for %ld samples at time = %lld (was %lld)", sampleCount, timeStamp, timeStamp - sampleOffset);256 });257 #endif258 259 uint64_t framesAvailable = sampleCount;260 252 if (timeStamp < startFrame || timeStamp + sampleCount > endFrame) { 261 if (timeStamp + sampleCount < startFrame || timeStamp >= endFrame) 262 framesAvailable = 0; 263 else if (timeStamp < startFrame) 264 framesAvailable = timeStamp + sampleCount - startFrame; 265 else 266 framesAvailable = timeStamp + sampleCount - endFrame; 267 268 #if !RELEASE_LOG_DISABLED 269 dispatch_async(dispatch_get_main_queue(), [timeStamp, startFrame, endFrame, framesAvailable, sampleCount, this, protectedThis = makeRefPtr(*this)] { 270 ALWAYS_LOG("sample ", timeStamp, " is not completely in range [", startFrame, " .. ", endFrame, "], returning ", framesAvailable, " frames"); 271 if (framesAvailable < sampleCount) 272 ERROR_LOG("not enough data available, returning zeroes"); 253 dispatch_async(dispatch_get_main_queue(), [logIdentifier = LOGIDENTIFIER, timeStamp, startFrame, endFrame, sampleCount, outputSampleOffset = m_outputSampleOffset, this, protectedThis = makeRefPtr(*this)] { 254 ERROR_LOG(logIdentifier, "not enough data, sample ", timeStamp, " with offset ", outputSampleOffset, ", trying to get ", sampleCount, " samples, but not completely in range [", startFrame, " .. ", endFrame, "]"); 273 255 }); 274 #endif 275 276 if (framesAvailable < sampleCount) { 256 257 if (timeStamp < startFrame || timeStamp >= endFrame) { 258 // We are out of the window, let's restart the offset computation. 259 m_shouldComputeOutputSampleOffset = true; 260 } else { 261 // We are too close from endFrame, let's back up a little bit. 262 uint64_t framesAvailable = endFrame - timeStamp; 277 263 m_outputSampleOffset -= sampleCount - framesAvailable; 278 AudioSampleBufferList::zeroABL(buffer, byteCount); 279 return false; 264 dispatch_async(dispatch_get_main_queue(), [logIdentifier = LOGIDENTIFIER, outputSampleOffset = m_outputSampleOffset, this, protectedThis = makeRefPtr(*this)] { 265 ALWAYS_LOG(logIdentifier, "updating offset to ", outputSampleOffset); 266 }); 280 267 } 268 AudioSampleBufferList::zeroABL(buffer, byteCount); 269 return false; 281 270 } 282 271 … … 316 305 uint64_t endFrame = 0; 317 306 m_ringBuffer->getCurrentFrameBounds(startFrame, endFrame); 318 if (m_ transitioningFromPaused) {307 if (m_shouldComputeOutputSampleOffset) { 319 308 m_outputSampleOffset = timeStamp + (endFrame - sampleCountPerChunk); 320 m_ transitioningFromPaused= false;309 m_shouldComputeOutputSampleOffset = false; 321 310 } 322 311 -
trunk/Source/WebCore/platform/mediastream/mac/RealtimeIncomingAudioSourceCocoa.cpp
r259632 r265280 76 76 #endif 77 77 78 CMTime startTime = CMTimeMake(m_numberOfFrames, sampleRate);79 auto mediaTime = PAL::toMediaTime(startTime);80 m_numberOfFrames += numberOfFrames;81 82 78 if (!m_audioBufferList || m_sampleRate != sampleRate || m_numberOfChannels != numberOfChannels) { 83 79 callOnMainThread([identifier = LOGIDENTIFIER, this, protectedThis = makeRef(*this), sampleRate, numberOfChannels] { … … 89 85 m_streamDescription = streamDescription(sampleRate, numberOfChannels); 90 86 m_audioBufferList = makeUnique<WebAudioBufferList>(m_streamDescription); 87 if (m_sampleRate && m_numberOfFrames) 88 m_numberOfFrames = m_numberOfFrames * sampleRate / m_sampleRate; 89 else 90 m_numberOfFrames = 0; 91 91 } 92 93 CMTime startTime = CMTimeMake(m_numberOfFrames, sampleRate); 94 auto mediaTime = PAL::toMediaTime(startTime); 95 m_numberOfFrames += numberOfFrames; 92 96 93 97 auto& bufferList = *m_audioBufferList->buffer(0);
Note:
See TracChangeset
for help on using the changeset viewer.