Changeset 261063 in webkit
- Timestamp:
- May 3, 2020 11:16:31 AM (4 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r261061 r261063 1 2020-05-03 Youenn Fablet <youenn@apple.com> 2 3 AudioMediaStreamTrackRendererCocoa should create/start/stop its remote unit on the main thread 4 https://bugs.webkit.org/show_bug.cgi?id=211287 5 6 Reviewed by Eric Carlson. 7 8 Creating/starting/stopping audio units in different threads is error prone. 9 Now that we have an observer model where we have observers for when to play in the main thread and 10 based on that, we decide to receive audio samples in a background thread, we can simplify the logic of AudioMediaStreamTrackRendererCocoa. 11 We do this by creating/starting the unit in AudioMediaStreamTrackRendererCocoa::start. 12 At that point, AudioMediaStreamTrackRendererCocoa is not expected to receive any sample. 13 Just after starting, AudioTrackPrivateMediaStream will receive audio samples and forward them to AudioMediaStreamTrackRendererCocoa. 14 AudioMediaStreamTrackRendererCocoa will then create in a background thread the AudioSampleDataSource that is responsible to adapt the received audio samples to the unit. 15 16 Manually tested. 17 18 * platform/audio/mac/AudioSampleDataSource.h: 19 (WebCore::AudioSampleDataSource::inputDescription const): 20 * platform/audio/mac/CAAudioStreamDescription.h: 21 * platform/mediastream/AudioTrackPrivateMediaStream.cpp: 22 (WebCore::AudioTrackPrivateMediaStream::startRenderer): 23 Ensure to start the unit and then start gettting audio samples. 24 * platform/mediastream/mac/AudioMediaStreamTrackRendererCocoa.cpp: 25 (WebCore::AudioMediaStreamTrackRendererCocoa::start): 26 (WebCore::AudioMediaStreamTrackRendererCocoa::stop): 27 (WebCore::AudioMediaStreamTrackRendererCocoa::clear): 28 (WebCore::AudioMediaStreamTrackRendererCocoa::pushSamples): 29 (WebCore::AudioMediaStreamTrackRendererCocoa::render): 30 * platform/mediastream/mac/AudioMediaStreamTrackRendererCocoa.h: 31 1 32 2020-05-03 Rob Buis <rbuis@igalia.com> 2 33 -
trunk/Source/WebCore/platform/audio/mac/AudioSampleDataSource.h
r254446 r261063 74 74 bool muted() const { return m_muted; } 75 75 76 const CAAudioStreamDescription* inputDescription() const { return m_inputDescription.get(); } 77 76 78 #if !RELEASE_LOG_DISABLED 77 79 const Logger& logger() const final { return m_logger; } -
trunk/Source/WebCore/platform/audio/mac/CAAudioStreamDescription.h
r260078 r261063 65 65 uint32_t formatFlags() const { return m_streamDescription.mFormatFlags; } 66 66 67 bool operator==(const AudioStreamBasicDescription& other) { return m_streamDescription == other; }68 bool operator!=(const AudioStreamBasicDescription& other) { return !operator == (other); }69 bool operator==(const AudioStreamDescription& other) 67 bool operator==(const AudioStreamBasicDescription& other) const { return m_streamDescription == other; } 68 bool operator!=(const AudioStreamBasicDescription& other) const { return !operator == (other); } 69 bool operator==(const AudioStreamDescription& other) const 70 70 { 71 71 if (other.platformDescription().type != PlatformDescription::CAAudioStreamBasicType) … … 74 74 return operator==(*WTF::get<const AudioStreamBasicDescription*>(other.platformDescription().description)); 75 75 } 76 bool operator!=(const AudioStreamDescription& other) { return !operator == (other); }76 bool operator!=(const AudioStreamDescription& other) const { return !operator == (other); } 77 77 78 78 const AudioStreamBasicDescription& streamDescription() const { return m_streamDescription; } -
trunk/Source/WebCore/platform/mediastream/AudioMediaStreamTrackRenderer.h
r254562 r261063 48 48 virtual void stop() = 0; 49 49 virtual void clear() = 0; 50 // May be called on a background thread. 50 // May be called on a background thread. It should only be called after start/before stop is called. 51 51 virtual void pushSamples(const WTF::MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) = 0; 52 52 -
trunk/Source/WebCore/platform/mediastream/AudioTrackPrivateMediaStream.cpp
r260380 r261063 140 140 141 141 m_isPlaying = true; 142 m_renderer->start(); 142 143 m_audioSource->addAudioSampleObserver(*this); 143 m_renderer->start();144 144 } 145 145 -
trunk/Source/WebCore/platform/mediastream/mac/AudioMediaStreamTrackRendererCocoa.cpp
r258839 r261063 48 48 clear(); 49 49 50 m_shouldPlay = true; 50 CAAudioStreamDescription outputDescription; 51 auto remoteIOUnit = createAudioUnit(outputDescription); 52 if (!remoteIOUnit) 53 return; 51 54 52 if (m_dataSource) 53 m_dataSource->setPaused(false); 55 if (auto error = AudioOutputUnitStart(remoteIOUnit)) { 56 ERROR_LOG(LOGIDENTIFIER, "AudioOutputUnitStart failed, error = ", error, " (", (const char*)&error, ")"); 57 AudioComponentInstanceDispose(remoteIOUnit); 58 return; 59 } 60 m_outputDescription = makeUnique<CAAudioStreamDescription>(outputDescription); 61 m_remoteIOUnit = remoteIOUnit; 54 62 } 55 63 56 64 void AudioMediaStreamTrackRendererCocoa::stop() 57 65 { 58 m_shouldPlay = false; 66 if (!m_remoteIOUnit) 67 return; 59 68 60 if (m_dataSource) 61 m_dataSource->setPaused(true); 69 AudioOutputUnitStop(m_remoteIOUnit); 70 AudioComponentInstanceDispose(m_remoteIOUnit); 71 m_remoteIOUnit = nullptr; 62 72 } 63 73 64 74 void AudioMediaStreamTrackRendererCocoa::clear() 65 75 { 66 m_shouldPlay = false; 67 68 if (m_dataSource) 69 m_dataSource->setPaused(true); 70 71 if (m_remoteIOUnit) { 72 AudioOutputUnitStop(m_remoteIOUnit); 73 AudioComponentInstanceDispose(m_remoteIOUnit); 74 m_remoteIOUnit = nullptr; 75 } 76 stop(); 76 77 77 78 m_dataSource = nullptr; 78 m_inputDescription = nullptr;79 79 m_outputDescription = nullptr; 80 m_isAudioUnitStarted = false;81 80 } 82 81 … … 149 148 { 150 149 ASSERT(description.platformDescription().type == PlatformDescription::CAAudioStreamBasicType); 151 if (!m_shouldPlay) { 152 if (m_isAudioUnitStarted) { 153 if (m_remoteIOUnit) 154 AudioOutputUnitStop(m_remoteIOUnit); 155 m_isAudioUnitStarted = false; 156 } 150 if (!m_remoteIOUnit) 157 151 return; 158 }159 152 160 if (!m_ inputDescription || *m_inputDescription!= description) {161 m_isAudioUnitStarted = false;153 if (!m_dataSource || !m_dataSource->inputDescription() || *m_dataSource->inputDescription() != description) { 154 auto dataSource = AudioSampleDataSource::create(description.sampleRate() * 2, *this); 162 155 163 if (m_remoteIOUnit) { 164 AudioOutputUnitStop(m_remoteIOUnit); 165 AudioComponentInstanceDispose(m_remoteIOUnit); 166 m_remoteIOUnit = nullptr; 167 } 168 169 m_inputDescription = nullptr; 170 m_outputDescription = nullptr; 171 172 CAAudioStreamDescription inputDescription = toCAAudioStreamDescription(description); 173 CAAudioStreamDescription outputDescription; 174 175 auto remoteIOUnit = createAudioUnit(outputDescription); 176 if (!remoteIOUnit) 177 return; 178 179 m_inputDescription = makeUnique<CAAudioStreamDescription>(inputDescription); 180 m_outputDescription = makeUnique<CAAudioStreamDescription>(outputDescription); 181 182 m_dataSource = AudioSampleDataSource::create(description.sampleRate() * 2, *this); 183 184 if (m_dataSource->setInputFormat(inputDescription) || m_dataSource->setOutputFormat(outputDescription)) { 185 AudioComponentInstanceDispose(remoteIOUnit); 156 if (dataSource->setInputFormat(toCAAudioStreamDescription(description))) { 157 ERROR_LOG(LOGIDENTIFIER, "Unable to set the input format of data source"); 186 158 return; 187 159 } 188 160 189 if (auto error = AudioOutputUnitStart(remoteIOUnit)) { 190 ERROR_LOG(LOGIDENTIFIER, "AudioOutputUnitStart failed, error = ", error, " (", (const char*)&error, ")"); 191 AudioComponentInstanceDispose(remoteIOUnit); 192 m_inputDescription = nullptr; 161 if (dataSource->setOutputFormat(*m_outputDescription)) { 162 ERROR_LOG(LOGIDENTIFIER, "Unable to set the output format of data source"); 193 163 return; 194 164 } 195 165 196 m_isAudioUnitStarted = true; 166 dataSource->setPaused(false); 167 dataSource->setVolume(volume()); 197 168 198 m_dataSource->setVolume(volume()); 199 m_remoteIOUnit = remoteIOUnit; 169 m_dataSource = WTFMove(dataSource); 200 170 } 201 171 202 172 m_dataSource->pushSamples(sampleTime, audioData, sampleCount); 203 204 if (!m_isAudioUnitStarted) {205 if (auto error = AudioOutputUnitStart(m_remoteIOUnit)) {206 ERROR_LOG(LOGIDENTIFIER, "AudioOutputUnitStart failed, error = ", error, " (", (const char*)&error, ")");207 return;208 }209 m_isAudioUnitStarted = true;210 }211 173 } 212 174 175 // May get called on a background thread. 213 176 OSStatus AudioMediaStreamTrackRendererCocoa::render(UInt32 sampleCount, AudioBufferList& ioData, UInt32 /*inBusNumber*/, const AudioTimeStamp& timeStamp, AudioUnitRenderActionFlags& actionFlags) 214 177 { 215 if (isMuted() || !m_shouldPlay || !m_dataSource) { 178 auto dataSource = m_dataSource; 179 if (!dataSource) { 216 180 AudioSampleBufferList::zeroABL(ioData, static_cast<size_t>(sampleCount * m_outputDescription->bytesPerFrame())); 217 181 actionFlags = kAudioUnitRenderAction_OutputIsSilence; … … 219 183 } 220 184 221 m_dataSource->pullSamples(ioData, static_cast<size_t>(sampleCount), timeStamp.mSampleTime, timeStamp.mHostTime, AudioSampleDataSource::Copy); 222 185 dataSource->pullSamples(ioData, static_cast<size_t>(sampleCount), timeStamp.mSampleTime, timeStamp.mHostTime, AudioSampleDataSource::Copy); 223 186 return 0; 224 187 } -
trunk/Source/WebCore/platform/mediastream/mac/AudioMediaStreamTrackRendererCocoa.h
r254562 r261063 58 58 AudioComponentInstance createAudioUnit(CAAudioStreamDescription&); 59 59 60 // Audio thread members61 60 AudioComponentInstance m_remoteIOUnit { nullptr }; 62 std::unique_ptr<CAAudioStreamDescription> m_inputDescription;63 61 std::unique_ptr<CAAudioStreamDescription> m_outputDescription; 64 62 65 // Cross thread members63 // Audio threads member 66 64 RefPtr<AudioSampleDataSource> m_dataSource; 67 bool m_isAudioUnitStarted { false };68 bool m_shouldPlay { false };69 65 }; 70 66
Note: See TracChangeset
for help on using the changeset viewer.