Changeset 278905 in webkit


Ignore:
Timestamp:
Jun 15, 2021, 2:49:42 PM (4 years ago)
Author:
Alan Coon
Message:

Apply patch. rdar://problem/79355311

Location:
branches/safari-611-branch/Source/WebCore
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • branches/safari-611-branch/Source/WebCore/ChangeLog

    r278903 r278905  
     12021-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
    1462021-06-15  Alan Coon  <alancoon@apple.com>
    247
  • branches/safari-611-branch/Source/WebCore/platform/audio/cocoa/AudioSampleDataSource.h

    r269829 r278905  
    4848    {
    4949public:
    50     static Ref<AudioSampleDataSource> create(size_t, WTF::LoggerHelper&);
     50    static Ref<AudioSampleDataSource> create(size_t, WTF::LoggerHelper&, size_t waitToStartForPushCount = 2);
    5151
    5252    ~AudioSampleDataSource();
     
    8181
    8282private:
    83     AudioSampleDataSource(size_t, LoggerHelper&);
     83    AudioSampleDataSource(size_t, LoggerHelper&, size_t waitToStartForPushCount);
    8484
    8585    OSStatus setupConverter();
     
    9999
    100100    uint64_t m_lastPushedSampleCount { 0 };
     101    size_t m_waitToStartForPushCount { 2 };
    101102    MediaTime m_expectedNextPushedSampleTime { MediaTime::invalidTime() };
     103    bool m_isFirstPull { true };
    102104
    103105    MediaTime m_inputSampleOffset;
  • branches/safari-611-branch/Source/WebCore/platform/audio/cocoa/AudioSampleDataSource.mm

    r278488 r278905  
    4545using namespace JSC;
    4646
    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())
     47Ref<AudioSampleDataSource> AudioSampleDataSource::create(size_t maximumSampleCount, LoggerHelper& loggerHelper, size_t waitToStartForPushCount)
     48{
     49    return adoptRef(*new AudioSampleDataSource(maximumSampleCount, loggerHelper, waitToStartForPushCount));
     50}
     51
     52AudioSampleDataSource::AudioSampleDataSource(size_t maximumSampleCount, LoggerHelper& loggerHelper, size_t waitToStartForPushCount)
     53    : m_waitToStartForPushCount(waitToStartForPushCount)
     54    , m_inputSampleOffset(MediaTime::invalidTime())
    5455    , m_maximumSampleCount(maximumSampleCount)
    5556#if !RELEASE_LOG_DISABLED
     
    231232    if (m_shouldComputeOutputSampleOffset) {
    232233        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            });
    237260        }
    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         });
    247261    }
    248262
     
    272286    }
    273287
     288    m_isFirstPull = false;
     289
    274290    if (mode == Copy) {
    275291        m_ringBuffer->fetch(&buffer, sampleCount, timeStamp, CARingBuffer::Copy);
  • branches/safari-611-branch/Source/WebCore/platform/mediastream/libwebrtc/LibWebRTCAudioModule.cpp

    r265135 r278905  
    7272// libwebrtc uses 10ms frames.
    7373const unsigned frameLengthMs = 1000 * LibWebRTCAudioFormat::chunkSampleCount / LibWebRTCAudioFormat::sampleRate;
    74 const unsigned pollSamples = 5;
    75 const unsigned pollInterval = 5 * frameLengthMs;
     74const unsigned pollInterval = LibWebRTCAudioModule::PollSamplesCount * frameLengthMs;
    7675const unsigned channels = 2;
    7776
     
    102101        return;
    103102
    104     for (unsigned i = 0; i < pollSamples; i++) {
     103    for (unsigned i = 0; i < PollSamplesCount; i++) {
    105104        int64_t elapsedTime = -1;
    106105        int64_t ntpTime = -1;
  • branches/safari-611-branch/Source/WebCore/platform/mediastream/libwebrtc/LibWebRTCAudioModule.h

    r266454 r278905  
    4545public:
    4646    LibWebRTCAudioModule();
     47
     48    static constexpr unsigned PollSamplesCount = 3;
    4749
    4850private:
  • branches/safari-611-branch/Source/WebCore/platform/mediastream/mac/AudioMediaStreamTrackRendererCocoa.cpp

    r267472 r278905  
    3232#include "AudioSampleDataSource.h"
    3333#include "CAAudioStreamDescription.h"
     34#include "LibWebRTCAudioModule.h"
    3435
    3536namespace WebCore {
     
    7576}
    7677
     78static unsigned pollSamplesCount()
     79{
     80#if USE(LIBWEBRTC)
     81    return LibWebRTCAudioModule::PollSamplesCount + 1;
     82#else
     83    return 2;
     84#endif
     85}
     86
    7787void AudioMediaStreamTrackRendererCocoa::pushSamples(const MediaTime& sampleTime, const PlatformAudioData& audioData, const AudioStreamDescription& description, size_t sampleCount)
    7888{
     
    8090    ASSERT(description.platformDescription().type == PlatformDescription::CAAudioStreamBasicType);
    8191    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());
    8395
    8496        if (dataSource->setInputFormat(toCAAudioStreamDescription(description))) {
  • branches/safari-611-branch/Source/WebCore/platform/mediastream/mac/MediaStreamTrackAudioSourceProviderCocoa.cpp

    r268521 r278905  
    2929#if ENABLE(WEB_AUDIO) && ENABLE(MEDIA_STREAM)
    3030
     31#import "LibWebRTCAudioModule.h"
     32
    3133namespace WebCore {
    3234
     
    4042    , m_source(source.source())
    4143{
     44#if USE(LIBWEBRTC)
     45    if (m_source->isIncomingAudioSource())
     46        setPollSamplesCount(LibWebRTCAudioModule::PollSamplesCount + 1);
     47#endif
    4248}
    4349
  • branches/safari-611-branch/Source/WebCore/platform/mediastream/mac/WebAudioSourceProviderCocoa.h

    r268521 r278905  
    6161    void receivedNewAudioSamples(const PlatformAudioData&, const AudioStreamDescription&, size_t);
    6262
     63    void setPollSamplesCount(size_t);
     64
    6365private:
    6466    virtual void hasNewClient(AudioSourceProviderClient*) = 0;
     
    8183    RefPtr<AudioSampleDataSource> m_dataSource;
    8284
     85    size_t m_pollSamplesCount { 3 };
    8386    uint64_t m_writeCount { 0 };
    8487    uint64_t m_readCount { 0 };
    8588};
    8689
     90inline void WebAudioSourceProviderCocoa::setPollSamplesCount(size_t count)
     91{
     92    m_pollSamplesCount = count;
     93}
     94
    8795}
    8896
  • branches/safari-611-branch/Source/WebCore/platform/mediastream/mac/WebAudioSourceProviderCocoa.mm

    r268577 r278905  
    121121
    122122    if (!m_dataSource)
    123         m_dataSource = AudioSampleDataSource::create(kRingBufferDuration * sampleRate, loggerHelper());
     123        m_dataSource = AudioSampleDataSource::create(kRingBufferDuration * sampleRate, loggerHelper(), m_pollSamplesCount);
    124124    m_dataSource->setInputFormat(m_inputDescription.value());
    125125    m_dataSource->setOutputFormat(m_outputDescription.value());
Note: See TracChangeset for help on using the changeset viewer.