Commit ec4c42f4 authored by amistry's avatar amistry Committed by Commit bot

Set audio format before adding pepper sink to audio track.

Some audio input devices don't generate caputure data in a continuous basis, and
instead only generate when some event happens. This may be an indefinite amount
of time. However, |AudioSink::OnSetFormat| is only called whenever new samples
come in. For pepper plugins, this means that |MediaStreamAudioTrack::Configure|
can be blocked indefintely on these devices. To work around this, get the
format before attaching to the audio track.

BUG=403138

Review URL: https://codereview.chromium.org/857093002

Cr-Commit-Position: refs/heads/master@{#313458}
parent 3d645c40
...@@ -43,4 +43,17 @@ void MediaStreamAudioSink::RemoveFromAudioTrack( ...@@ -43,4 +43,17 @@ void MediaStreamAudioSink::RemoveFromAudioTrack(
audio_track->RemoveSink(sink); audio_track->RemoveSink(sink);
} }
media::AudioParameters MediaStreamAudioSink::GetFormatFromAudioTrack(
const blink::WebMediaStreamTrack& track) {
MediaStreamTrack* native_track = MediaStreamTrack::GetTrack(track);
if (!native_track->is_local_track()) {
LOG(ERROR) << "Can't get format from a remote audio track";
return media::AudioParameters();
}
WebRtcLocalAudioTrack* audio_track =
static_cast<WebRtcLocalAudioTrack*>(native_track);
return audio_track->GetOutputFormat();
}
} // namespace content } // namespace content
...@@ -37,6 +37,11 @@ class CONTENT_EXPORT MediaStreamAudioSink : public MediaStreamSink { ...@@ -37,6 +37,11 @@ class CONTENT_EXPORT MediaStreamAudioSink : public MediaStreamSink {
static void RemoveFromAudioTrack(MediaStreamAudioSink* sink, static void RemoveFromAudioTrack(MediaStreamAudioSink* sink,
const blink::WebMediaStreamTrack& track); const blink::WebMediaStreamTrack& track);
// Returns the format of the audio track.
// Called on the main render thread.
static media::AudioParameters GetFormatFromAudioTrack(
const blink::WebMediaStreamTrack& track);
// Callback called to deliver audio data. The data in |audio_bus| respects the // Callback called to deliver audio data. The data in |audio_bus| respects the
// AudioParameters passed in the last call to OnSetFormat(). Called on // AudioParameters passed in the last call to OnSetFormat(). Called on
// real-time audio thread. // real-time audio thread.
......
...@@ -434,6 +434,11 @@ int WebRtcAudioCapturer::MaxVolume() const { ...@@ -434,6 +434,11 @@ int WebRtcAudioCapturer::MaxVolume() const {
return WebRtcAudioDeviceImpl::kMaxVolumeLevel; return WebRtcAudioDeviceImpl::kMaxVolumeLevel;
} }
media::AudioParameters WebRtcAudioCapturer::GetOutputFormat() const {
DCHECK(thread_checker_.CalledOnValidThread());
return audio_processor_->OutputFormat();
}
void WebRtcAudioCapturer::Capture(const media::AudioBus* audio_source, void WebRtcAudioCapturer::Capture(const media::AudioBus* audio_source,
int audio_delay_milliseconds, int audio_delay_milliseconds,
double volume, double volume,
......
...@@ -105,6 +105,10 @@ class CONTENT_EXPORT WebRtcAudioCapturer ...@@ -105,6 +105,10 @@ class CONTENT_EXPORT WebRtcAudioCapturer
// call Stop() // call Stop()
void Stop(); void Stop();
// Returns the output format.
// Called on the main render thread.
media::AudioParameters GetOutputFormat() const;
// Used by the unittests to inject their own source to the capturer. // Used by the unittests to inject their own source to the capturer.
void SetCapturerSourceForTesting( void SetCapturerSourceForTesting(
const scoped_refptr<media::AudioCapturerSource>& source, const scoped_refptr<media::AudioCapturerSource>& source,
......
...@@ -40,6 +40,15 @@ WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack() { ...@@ -40,6 +40,15 @@ WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack() {
Stop(); Stop();
} }
media::AudioParameters WebRtcLocalAudioTrack::GetOutputFormat() const {
DCHECK(main_render_thread_checker_.CalledOnValidThread());
if (webaudio_source_.get()) {
return media::AudioParameters();
} else {
return capturer_->GetOutputFormat();
}
}
void WebRtcLocalAudioTrack::Capture(const media::AudioBus& audio_bus, void WebRtcLocalAudioTrack::Capture(const media::AudioBus& audio_bus,
base::TimeTicks estimated_capture_time, base::TimeTicks estimated_capture_time,
bool force_report_nonzero_energy) { bool force_report_nonzero_energy) {
......
...@@ -67,6 +67,11 @@ class CONTENT_EXPORT WebRtcLocalAudioTrack ...@@ -67,6 +67,11 @@ class CONTENT_EXPORT WebRtcLocalAudioTrack
webrtc::AudioTrackInterface* GetAudioAdapter() override; webrtc::AudioTrackInterface* GetAudioAdapter() override;
// Returns the output format of the capture source. May return an invalid
// AudioParameters if the format is not yet available.
// Called on the main render thread.
media::AudioParameters GetOutputFormat() const;
// Method called by the capturer to deliver the capture data. // Method called by the capturer to deliver the capture data.
// Called on the capture audio thread. // Called on the capture audio thread.
void Capture(const media::AudioBus& audio_bus, void Capture(const media::AudioBus& audio_bus,
......
...@@ -364,6 +364,13 @@ void PepperMediaStreamAudioTrackHost::OnNewBufferEnqueued() { ...@@ -364,6 +364,13 @@ void PepperMediaStreamAudioTrackHost::OnNewBufferEnqueued() {
void PepperMediaStreamAudioTrackHost::DidConnectPendingHostToResource() { void PepperMediaStreamAudioTrackHost::DidConnectPendingHostToResource() {
if (!connected_) { if (!connected_) {
media::AudioParameters format =
MediaStreamAudioSink::GetFormatFromAudioTrack(track_);
// Although this should only be called on the audio capture thread, that
// can't happen until the sink is added to the audio track below.
if (format.IsValid())
audio_sink_.OnSetFormat(format);
MediaStreamAudioSink::AddToAudioTrack(&audio_sink_, track_); MediaStreamAudioSink::AddToAudioTrack(&audio_sink_, track_);
connected_ = true; connected_ = true;
} }
......
...@@ -52,6 +52,16 @@ class PepperMediaStreamAudioTrackHost : public PepperMediaStreamTrackHostBase { ...@@ -52,6 +52,16 @@ class PepperMediaStreamAudioTrackHost : public PepperMediaStreamTrackHostBase {
// Send a reply to the currently pending |Configure()| request. // Send a reply to the currently pending |Configure()| request.
void SendConfigureReply(int32_t result); void SendConfigureReply(int32_t result);
// MediaStreamAudioSink overrides:
// These two functions should be called on the audio thread.
// NOTE: For this specific instance, |OnSetFormat()| is also called on the
// main thread. However, the call to |OnSetFormat()| happens before this
// sink is added to an audio track, also on the main thread, which should
// avoid any potential races.
void OnData(const media::AudioBus& audio_bus,
base::TimeTicks estimated_capture_time) override;
void OnSetFormat(const media::AudioParameters& params) override;
private: private:
// Initializes buffers on the main thread. // Initializes buffers on the main thread.
void SetFormatOnMainThread(int bytes_per_second, int bytes_per_frame); void SetFormatOnMainThread(int bytes_per_second, int bytes_per_frame);
...@@ -62,12 +72,6 @@ class PepperMediaStreamAudioTrackHost : public PepperMediaStreamTrackHostBase { ...@@ -62,12 +72,6 @@ class PepperMediaStreamAudioTrackHost : public PepperMediaStreamTrackHostBase {
void SendEnqueueBufferMessageOnMainThread(int32_t index, void SendEnqueueBufferMessageOnMainThread(int32_t index,
int32_t buffers_generation); int32_t buffers_generation);
// MediaStreamAudioSink overrides:
// These two functions should be called on the audio thread.
void OnData(const media::AudioBus& audio_bus,
base::TimeTicks estimated_capture_time) override;
void OnSetFormat(const media::AudioParameters& params) override;
// Unowned host which is available during the AudioSink's lifespan. // Unowned host which is available during the AudioSink's lifespan.
// It is mainly used in the main thread. But the audio thread will use // It is mainly used in the main thread. But the audio thread will use
// host_->buffer_manager() to read some buffer properties. It is safe // host_->buffer_manager() to read some buffer properties. It is safe
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment