15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/renderer/media/webrtc_audio_renderer.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/strings/stringprintf.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/renderer/media/audio_device_factory.h" 12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/renderer/media/media_stream_dispatcher.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/renderer/media/webrtc_audio_device_impl.h" 14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/renderer/media/webrtc_logging.h" 15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/renderer/render_frame_impl.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/audio/audio_output_device.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/audio_parameters.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/sample_rates.h" 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h" 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/libjingle/source/talk/media/base/audiorenderer.h" 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN) 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/win/windows_version.h" 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/win/core_audio_util_win.h" 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// We add a UMA histogram measuring the execution time of the Render() method 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// every |kNumCallbacksBetweenRenderTimeHistograms| callback. Assuming 10ms 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// between each callback leads to one UMA update each 100ms. 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int kNumCallbacksBetweenRenderTimeHistograms = 10; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// This is a simple wrapper class that's handed out to users of a shared 3858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// WebRtcAudioRenderer instance. This class maintains the per-user 'playing' 3958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// and 'started' states to avoid problems related to incorrect usage which 4058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// might violate the implementation assumptions inside WebRtcAudioRenderer 4158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// (see the play reference count). 4258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)class SharedAudioRenderer : public MediaStreamAudioRenderer { 4358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) public: 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Callback definition for a callback that is called when when Play(), Pause() 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // or SetVolume are called (whenever the internal |playing_state_| changes). 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) typedef base::Callback< 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void(const scoped_refptr<webrtc::MediaStreamInterface>&, 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebRtcAudioRenderer::PlayingState*)> OnPlayStateChanged; 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SharedAudioRenderer( 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const scoped_refptr<MediaStreamAudioRenderer>& delegate, 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const scoped_refptr<webrtc::MediaStreamInterface>& media_stream, 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const OnPlayStateChanged& on_play_state_changed) 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : delegate_(delegate), media_stream_(media_stream), started_(false), 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) on_play_state_changed_(on_play_state_changed) { 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!on_play_state_changed_.is_null()); 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(media_stream_.get()); 5858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 5958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) protected: 6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) virtual ~SharedAudioRenderer() { 6258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 6358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DVLOG(1) << __FUNCTION__; 6458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Stop(); 6558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 6658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 6758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) virtual void Start() OVERRIDE { 6858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 6958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (started_) 7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 7158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) started_ = true; 7258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) delegate_->Start(); 7358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 7458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 7558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) virtual void Play() OVERRIDE { 7658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 7758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(started_); 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (playing_state_.playing()) 7958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) playing_state_.set_playing(true); 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) on_play_state_changed_.Run(media_stream_, &playing_state_); 8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) virtual void Pause() OVERRIDE { 8558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 8658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(started_); 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!playing_state_.playing()) 8858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) playing_state_.set_playing(false); 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) on_play_state_changed_.Run(media_stream_, &playing_state_); 9158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 9258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 9358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) virtual void Stop() OVERRIDE { 9458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!started_) 9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Pause(); 9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) started_ = false; 9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) delegate_->Stop(); 10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) virtual void SetVolume(float volume) OVERRIDE { 10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(volume >= 0.0f && volume <= 1.0f); 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) playing_state_.set_volume(volume); 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) on_play_state_changed_.Run(media_stream_, &playing_state_); 10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) virtual base::TimeDelta GetCurrentRenderTime() const OVERRIDE { 11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return delegate_->GetCurrentRenderTime(); 11258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) virtual bool IsLocalRenderer() const OVERRIDE { 11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 11658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return delegate_->IsLocalRenderer(); 11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) private: 12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::ThreadChecker thread_checker_; 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const scoped_refptr<MediaStreamAudioRenderer> delegate_; 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const scoped_refptr<webrtc::MediaStreamInterface> media_stream_; 12358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bool started_; 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebRtcAudioRenderer::PlayingState playing_state_; 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnPlayStateChanged on_play_state_changed_; 12658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}; 12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Returns either AudioParameters::NO_EFFECTS or AudioParameters::DUCKING 129116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// depending on whether or not an input element is currently open with 130116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// ducking enabled. 131116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint GetCurrentDuckingFlag(int render_frame_id) { 132116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch RenderFrameImpl* const frame = 133116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch RenderFrameImpl::FromRoutingID(render_frame_id); 134116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch MediaStreamDispatcher* const dispatcher = frame ? 135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch frame->GetMediaStreamDispatcher() : NULL; 136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (dispatcher && dispatcher->IsAudioDuckingActive()) { 137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return media::AudioParameters::DUCKING; 138116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return media::AudioParameters::NO_EFFECTS; 141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Helper method to get platform specific optimal buffer size. 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint GetOptimalBufferSize(int sample_rate, int hardware_buffer_size) { 1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Use native hardware buffer size as default. On Windows, we strive to open 1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // up using this native hardware buffer size to achieve best 1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // possible performance and to ensure that no FIFO is needed on the browser 1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // side to match the client request. That is why there is no #if case for 1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Windows below. 1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int frames_per_buffer = hardware_buffer_size; 1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_LINUX) || defined(OS_MACOSX) 1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // On Linux and MacOS, the low level IO implementations on the browser side 1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // supports all buffer size the clients want. We use the native peer 1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // connection buffer size (10ms) to achieve best possible performance. 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci frames_per_buffer = sample_rate / 100; 1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#elif defined(OS_ANDROID) 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(henrika): Keep tuning this scheme and espcicially for low-latency 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // cases. Might not be possible to come up with the perfect solution using 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // the render side only. 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int frames_per_10ms = sample_rate / 100; 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (frames_per_buffer < 2 * frames_per_10ms) { 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Examples of low-latency frame sizes and the resulting |buffer_size|: 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Nexus 7 : 240 audio frames => 2*480 = 960 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Nexus 10 : 256 => 2*441 = 882 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Galaxy Nexus: 144 => 2*441 = 882 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci frames_per_buffer = 2 * frames_per_10ms; 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DVLOG(1) << "Low-latency output detected on Android"; 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif 1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DVLOG(1) << "Using sink output buffer size: " << frames_per_buffer; 1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return frames_per_buffer; 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)WebRtcAudioRenderer::WebRtcAudioRenderer( 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const scoped_refptr<webrtc::MediaStreamInterface>& media_stream, 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int source_render_view_id, 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int source_render_frame_id, 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int session_id, 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int sample_rate, 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int frames_per_buffer) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : state_(UNINITIALIZED), 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source_render_view_id_(source_render_view_id), 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) source_render_frame_id_(source_render_frame_id), 18858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) session_id_(session_id), 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) media_stream_(media_stream), 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source_(NULL), 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) play_ref_count_(0), 19258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) start_ref_count_(0), 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_delay_milliseconds_(0), 19458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) fifo_delay_milliseconds_(0), 195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) sink_params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, 1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci media::CHANNEL_LAYOUT_STEREO, sample_rate, 16, 197116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch frames_per_buffer, 1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GetCurrentDuckingFlag(source_render_frame_id)), 1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci render_callback_count_(0) { 200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) WebRtcLogMessage(base::StringPrintf( 201a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "WAR::WAR. source_render_view_id=%d" 202116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ", session_id=%d, sample_rate=%d, frames_per_buffer=%d, effects=%i", 203a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) source_render_view_id, 204a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) session_id, 205a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sample_rate, 206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch frames_per_buffer, 207116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sink_params_.effects())); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebRtcAudioRenderer::~WebRtcAudioRenderer() { 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(state_, UNINITIALIZED); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebRtcAudioRenderer::Initialize(WebRtcAudioRendererSource* source) { 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioRenderer::Initialize()"; 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(state_, UNINITIALIZED); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(source); 221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(!sink_.get()); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!source_); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // WebRTC does not yet support higher rates than 96000 on the client side 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // and 48000 is the preferred sample rate. Therefore, if 192000 is detected, 226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // we change the rate to 48000 instead. The consequence is that the native 227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // layer will be opened up at 192kHz but WebRTC will provide data at 48kHz 228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // which will then be resampled by the audio converted on the browser side 229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // to match the native audio layer. 230a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int sample_rate = sink_params_.sample_rate(); 231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DVLOG(1) << "Audio output hardware sample rate: " << sample_rate; 232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (sample_rate == 192000) { 233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DVLOG(1) << "Resampling from 48000 to 192000 is required"; 234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sample_rate = 48000; 235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 236a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) media::AudioSampleRate asr; 237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (media::ToAudioSampleRate(sample_rate, &asr)) { 238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch UMA_HISTOGRAM_ENUMERATION( 239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "WebRTC.AudioOutputSampleRate", asr, media::kAudioSampleRateMax + 1); 240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("WebRTC.AudioOutputSampleRateUnexpected", 242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) sample_rate); 243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Set up audio parameters for the source, i.e., the WebRTC client. 24690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The WebRTC client only supports multiples of 10ms as buffer size where 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 10ms is preferred for lowest possible delay. 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) media::AudioParameters source_params; 250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const int frames_per_10ms = (sample_rate / 100); 251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DVLOG(1) << "Using WebRTC output buffer size: " << frames_per_10ms; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source_params.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, 2541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci sink_params_.channel_layout(), sink_params_.channels(), 255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) sample_rate, 16, frames_per_10ms); 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const int frames_per_buffer = 2581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GetOptimalBufferSize(sample_rate, sink_params_.frames_per_buffer()); 2597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) sink_params_.Reset(sink_params_.format(), sink_params_.channel_layout(), 2611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci sink_params_.channels(), sample_rate, 16, 262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) frames_per_buffer); 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create a FIFO if re-buffering is required to match the source input with 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the sink request. The source acts as provider here and the sink as 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // consumer. 267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) fifo_delay_milliseconds_ = 0; 268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (source_params.frames_per_buffer() != sink_params_.frames_per_buffer()) { 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "Rebuffering from " << source_params.frames_per_buffer() 270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << " to " << sink_params_.frames_per_buffer(); 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_fifo_.reset(new media::AudioPullFifo( 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source_params.channels(), 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source_params.frames_per_buffer(), 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind( 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &WebRtcAudioRenderer::SourceCallback, 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Unretained(this)))); 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (sink_params_.frames_per_buffer() > source_params.frames_per_buffer()) { 279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int frame_duration_milliseconds = base::Time::kMillisecondsPerSecond / 280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) static_cast<double>(source_params.sample_rate()); 281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) fifo_delay_milliseconds_ = (sink_params_.frames_per_buffer() - 282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) source_params.frames_per_buffer()) * frame_duration_milliseconds; 283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_ = source; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Configure the audio rendering client and start rendering. 2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sink_ = AudioDeviceFactory::NewOutputDevice( 2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) source_render_view_id_, source_render_frame_id_); 29158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 29258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK_GE(session_id_, 0); 293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) sink_->InitializeWithSessionId(sink_params_, this, session_id_); 29458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sink_->Start(); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // User must call Play() before any audio can be heard. 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = PAUSED; 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)scoped_refptr<MediaStreamAudioRenderer> 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)WebRtcAudioRenderer::CreateSharedAudioRendererProxy( 3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const scoped_refptr<webrtc::MediaStreamInterface>& media_stream) { 3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::SharedAudioRenderer::OnPlayStateChanged on_play_state_changed = 3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&WebRtcAudioRenderer::OnPlayStateChanged, this); 3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return new SharedAudioRenderer(this, media_stream, on_play_state_changed); 30958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 31058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 31158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool WebRtcAudioRenderer::IsStarted() const { 31258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 31358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return start_ref_count_ != 0; 31458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 31558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebRtcAudioRenderer::Start() { 31758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DVLOG(1) << "WebRtcAudioRenderer::Start()"; 31858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 31958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ++start_ref_count_; 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebRtcAudioRenderer::Play() { 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioRenderer::Play()"; 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (playing_state_.playing()) 3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) playing_state_.set_playing(true); 3301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci render_callback_count_ = 0; 3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnPlayStateChanged(media_stream_, &playing_state_); 3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebRtcAudioRenderer::EnterPlayState() { 3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "WebRtcAudioRenderer::EnterPlayState()"; 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 33858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK_GT(start_ref_count_, 0) << "Did you forget to call Start()?"; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state_ == UNINITIALIZED) 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(play_ref_count_ == 0 || state_ == PLAYING); 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++play_ref_count_; 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 34658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (state_ != PLAYING) { 34758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) state_ = PLAYING; 34858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 34958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (audio_fifo_) { 35058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) audio_delay_milliseconds_ = 0; 35158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) audio_fifo_->Clear(); 35258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebRtcAudioRenderer::Pause() { 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioRenderer::Pause()"; 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!playing_state_.playing()) 3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) playing_state_.set_playing(false); 3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnPlayStateChanged(media_stream_, &playing_state_); 3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebRtcAudioRenderer::EnterPauseState() { 3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "WebRtcAudioRenderer::EnterPauseState()"; 3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 37058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK_GT(start_ref_count_, 0) << "Did you forget to call Start()?"; 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state_ == UNINITIALIZED) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(state_, PLAYING); 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_GT(play_ref_count_, 0); 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!--play_ref_count_) 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_ = PAUSED; 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebRtcAudioRenderer::Stop() { 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioRenderer::Stop()"; 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 38458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) { 38558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::AutoLock auto_lock(lock_); 38658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (state_ == UNINITIALIZED) 38758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 38858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 38958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (--start_ref_count_) 39058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 39158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 39258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DVLOG(1) << "Calling RemoveAudioRenderer and Stop()."; 39358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 39458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) source_->RemoveAudioRenderer(this); 39558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) source_ = NULL; 39658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) state_ = UNINITIALIZED; 39758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 39958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Make sure to stop the sink while _not_ holding the lock since the Render() 40058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // callback may currently be executing and try to grab the lock while we're 40158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // stopping the thread on which it runs. 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sink_->Stop(); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebRtcAudioRenderer::SetVolume(float volume) { 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(volume >= 0.0f && volume <= 1.0f); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) playing_state_.set_volume(volume); 4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnPlayStateChanged(media_stream_, &playing_state_); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::TimeDelta WebRtcAudioRenderer::GetCurrentRenderTime() const { 414f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 415f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::AutoLock auto_lock(lock_); 416f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return current_time_; 4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool WebRtcAudioRenderer::IsLocalRenderer() const { 4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int WebRtcAudioRenderer::Render(media::AudioBus* audio_bus, 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int audio_delay_milliseconds) { 4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock auto_lock(lock_); 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!source_) 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(2) << "WebRtcAudioRenderer::Render()"; 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(2) << "audio_delay_milliseconds: " << audio_delay_milliseconds; 4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 432868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) audio_delay_milliseconds_ = audio_delay_milliseconds; 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (audio_fifo_) 4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_fifo_->Consume(audio_bus, audio_bus->frames()); 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SourceCallback(0, audio_bus); 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return (state_ == PLAYING) ? audio_bus->frames() : 0; 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebRtcAudioRenderer::OnRenderError() { 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTIMPLEMENTED(); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "OnRenderError()"; 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Called by AudioPullFifo when more data is necessary. 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebRtcAudioRenderer::SourceCallback( 4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int fifo_frame_delay, media::AudioBus* audio_bus) { 4501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::TimeTicks start_time = base::TimeTicks::Now() ; 4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(2) << "WebRtcAudioRenderer::SourceCallback(" 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << fifo_frame_delay << ", " 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << audio_bus->frames() << ")"; 4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int output_delay_milliseconds = audio_delay_milliseconds_; 456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) output_delay_milliseconds += fifo_delay_milliseconds_; 4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(2) << "output_delay_milliseconds: " << output_delay_milliseconds; 4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We need to keep render data for the |source_| regardless of |state_|, 4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // otherwise the data will be buffered up inside |source_|. 461a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) source_->RenderData(audio_bus, sink_params_.sample_rate(), 462f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) output_delay_milliseconds, 463f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ¤t_time_); 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Avoid filling up the audio bus if we are not playing; instead 4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // return here and ensure that the returned value in Render() is 0. 467a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (state_ != PLAYING) 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_bus->Zero(); 4691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (++render_callback_count_ == kNumCallbacksBetweenRenderTimeHistograms) { 4711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::TimeDelta elapsed = base::TimeTicks::Now() - start_time; 4721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci render_callback_count_ = 0; 4731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UMA_HISTOGRAM_TIMES("WebRTC.AudioRenderTimes", elapsed); 4741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebRtcAudioRenderer::UpdateSourceVolume( 4785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) webrtc::AudioSourceInterface* source) { 4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Note: If there are no playing audio renderers, then the volume will be 4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // set to 0.0. 4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) float volume = 0.0f; 4845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SourcePlayingStates::iterator entry = source_playing_states_.find(source); 4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (entry != source_playing_states_.end()) { 4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PlayingStates& states = entry->second; 4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (PlayingStates::const_iterator it = states.begin(); 4895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != states.end(); ++it) { 4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if ((*it)->playing()) 4915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) volume += (*it)->volume(); 4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The valid range for volume scaling of a remote webrtc source is 4965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // 0.0-10.0 where 1.0 is no attenuation/boost. 4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(volume >= 0.0f); 4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (volume > 10.0f) 4995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) volume = 10.0f; 5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Setting remote source volume: " << volume; 5025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) source->SetVolume(volume); 5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool WebRtcAudioRenderer::AddPlayingState( 5065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) webrtc::AudioSourceInterface* source, 5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PlayingState* state) { 5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(state->playing()); 5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Look up or add the |source| to the map. 5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PlayingStates& array = source_playing_states_[source]; 5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (std::find(array.begin(), array.end(), state) != array.end()) 5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) array.push_back(state); 5165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool WebRtcAudioRenderer::RemovePlayingState( 5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) webrtc::AudioSourceInterface* source, 5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PlayingState* state) { 5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!state->playing()); 5255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SourcePlayingStates::iterator found = source_playing_states_.find(source); 5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (found == source_playing_states_.end()) 5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PlayingStates& array = found->second; 5305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PlayingStates::iterator state_it = 5315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::find(array.begin(), array.end(), state); 5325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (state_it == array.end()) 5335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 5345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) array.erase(state_it); 5365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (array.empty()) 5385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) source_playing_states_.erase(found); 5395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebRtcAudioRenderer::OnPlayStateChanged( 5445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const scoped_refptr<webrtc::MediaStreamInterface>& media_stream, 5455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PlayingState* state) { 5465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) webrtc::AudioTrackVector tracks(media_stream->GetAudioTracks()); 5475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (webrtc::AudioTrackVector::iterator it = tracks.begin(); 5485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != tracks.end(); ++it) { 5495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) webrtc::AudioSourceInterface* source = (*it)->GetSource(); 5505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(source); 5515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!state->playing()) { 5525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (RemovePlayingState(source, state)) 5535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EnterPauseState(); 5545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else if (AddPlayingState(source, state)) { 5555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EnterPlayState(); 5565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UpdateSourceVolume(source); 5585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 562