OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "content/renderer/media/webaudio_media_stream_source.h" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" |
| 9 #include "base/logging.h" |
| 10 |
| 11 namespace content { |
| 12 |
| 13 WebAudioMediaStreamSource::WebAudioMediaStreamSource( |
| 14 const blink::WebMediaStreamSource& blink_source) |
| 15 : MediaStreamAudioSource(false /* is_remote */), |
| 16 blink_source_(blink_source), |
| 17 is_started_(false), |
| 18 rechunker_(base::TimeDelta::FromMilliseconds(10), |
| 19 base::Bind(&WebAudioMediaStreamSource::DeliverRechunkedAudio, |
| 20 base::Unretained(this))) { |
| 21 DVLOG(1) << "WebAudioMediaStreamSource::WebAudioMediaStreamSource()"; |
| 22 } |
| 23 |
| 24 WebAudioMediaStreamSource::~WebAudioMediaStreamSource() { |
| 25 DVLOG(1) << "WebAudioMediaStreamSource::~WebAudioMediaStreamSource()"; |
| 26 // Superclass will call StopSource() just in case. |
| 27 } |
| 28 |
| 29 void WebAudioMediaStreamSource::setFormat( |
| 30 size_t number_of_channels, float sample_rate) { |
| 31 VLOG(1) << "WebAudio media stream source changed format to: channels=" |
| 32 << number_of_channels << ", sample_rate=" << sample_rate; |
| 33 |
| 34 rechunker_.SetSampleRate(sample_rate); |
| 35 if (!wrapper_bus_ || |
| 36 wrapper_bus_->channels() != static_cast<int>(number_of_channels)) { |
| 37 wrapper_bus_ = media::AudioBus::CreateWrapper(number_of_channels); |
| 38 } |
| 39 |
| 40 // If the channel count is greater than 8, use discrete layout. However, |
| 41 // anything beyond 8 is ignored by some audio tracks/sinks. |
| 42 const media::ChannelLayout channel_layout = |
| 43 number_of_channels > 8 ? media::CHANNEL_LAYOUT_DISCRETE |
| 44 : media::GuessChannelLayout(number_of_channels); |
| 45 |
| 46 MediaStreamAudioSource::SetFormat(media::AudioParameters( |
| 47 media::AudioParameters::AUDIO_PCM_LOW_LATENCY, |
| 48 channel_layout, |
| 49 sample_rate, |
| 50 16, // Legacy parameter (data is always in 32-bit float format). |
| 51 rechunker_.output_frames())); |
| 52 } |
| 53 |
| 54 void WebAudioMediaStreamSource::consumeAudio( |
| 55 const blink::WebVector<const float*>& audio_data, |
| 56 size_t number_of_frames) { |
| 57 // TODO(miu): Plumbing is needed to determine the actual capture timestamp |
| 58 // of the audio, instead of just snapshotting TimeTicks::Now(), for proper |
| 59 // audio/video sync. http://crbug.com/335335 |
| 60 base::TimeTicks reference_time = base::TimeTicks::Now(); |
| 61 |
| 62 wrapper_bus_->set_frames(number_of_frames); |
| 63 DCHECK_EQ(wrapper_bus_->channels(), static_cast<int>(audio_data.size())); |
| 64 for (size_t i = 0; i < audio_data.size(); ++i) |
| 65 wrapper_bus_->SetChannelData(i, const_cast<float*>(audio_data[i])); |
| 66 |
| 67 rechunker_.Push(*wrapper_bus_, reference_time - base::TimeTicks()); |
| 68 } |
| 69 |
| 70 void WebAudioMediaStreamSource::DeliverRechunkedAudio( |
| 71 const media::AudioBus& audio_bus, |
| 72 base::TimeDelta reference_timestamp) { |
| 73 MediaStreamAudioSource::DeliverDataToTracks( |
| 74 audio_bus, reference_timestamp + base::TimeTicks()); |
| 75 } |
| 76 |
| 77 void WebAudioMediaStreamSource::DoStopSource() { |
| 78 DCHECK(thread_checker_.CalledOnValidThread()); |
| 79 if (is_stopped_) |
| 80 return; |
| 81 if (is_started_) { |
| 82 if (!blink_source_.isNull()) { |
| 83 blink_source_.removeAudioConsumer(this); |
| 84 blink_source_.reset(); |
| 85 VLOG(1) << "Stopped WebAudio media stream source. Final audio " |
| 86 "parameters={" |
| 87 << GetAudioParameters().AsHumanReadableString() << "}."; |
| 88 } |
| 89 } |
| 90 is_stopped_ = true; |
| 91 } |
| 92 |
| 93 bool WebAudioMediaStreamSource::EnsureSourceIsStarted() { |
| 94 DCHECK(thread_checker_.CalledOnValidThread()); |
| 95 if (is_stopped_) |
| 96 return false; |
| 97 if (is_started_) |
| 98 return true; |
| 99 if (blink_source_.isNull() || !blink_source_.requiresAudioConsumer()) { |
| 100 StopSource(); |
| 101 return false; |
| 102 } |
| 103 VLOG(1) << "Starting WebAudio media stream source."; |
| 104 blink_source_.addAudioConsumer(this); |
| 105 is_started_ = true; |
| 106 return true; |
| 107 } |
| 108 |
| 109 } // namespace content |
OLD | NEW |