summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/modules/webrtc/webrtc_audio_renderer.h
blob: d9ab184294d3dcd938931982c981bd455603eca8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBRTC_WEBRTC_AUDIO_RENDERER_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBRTC_WEBRTC_AUDIO_RENDERER_H_

#include <stdint.h>

#include <map>
#include <memory>
#include <string>
#include <vector>

#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/sequence_checker.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
#include "base/unguessable_token.h"
#include "media/base/audio_decoder.h"
#include "media/base/audio_pull_fifo.h"
#include "media/base/audio_renderer_sink.h"
#include "media/base/channel_layout.h"
#include "third_party/blink/public/platform/modules/mediastream/web_media_stream_audio_renderer.h"
#include "third_party/blink/public/platform/web_media_stream.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/webrtc/webrtc_source.h"

namespace webrtc {
class AudioSourceInterface;
}  // namespace webrtc

namespace blink {

class WebLocalFrame;
class WebRtcAudioRendererSource;

// This renderer handles calls from the pipeline and WebRtc ADM. It is used
// for connecting WebRtc MediaStream with the audio pipeline.
class MODULES_EXPORT WebRtcAudioRenderer
    : public media::AudioRendererSink::RenderCallback,
      public blink::WebMediaStreamAudioRenderer {
 public:
  // This is a little utility class that holds the configured state of an audio
  // stream.
  // It is used by both WebRtcAudioRenderer and SharedAudioRenderer (see cc
  // file) so a part of why it exists is to avoid code duplication and track
  // the state in the same way in WebRtcAudioRenderer and SharedAudioRenderer.
  class PlayingState {
   public:
    PlayingState() : playing_(false), volume_(1.0f) {}

    ~PlayingState() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); }

    bool playing() const {
      DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
      return playing_;
    }

    void set_playing(bool playing) {
      DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
      playing_ = playing;
    }

    float volume() const {
      DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
      return volume_;
    }

    void set_volume(float volume) {
      DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
      volume_ = volume;
    }

   private:
    bool playing_;
    float volume_;

    SEQUENCE_CHECKER(sequence_checker_);
  };

  WebRtcAudioRenderer(
      const scoped_refptr<base::SingleThreadTaskRunner>& signaling_thread,
      const blink::WebMediaStream& media_stream,
      WebLocalFrame* web_frame,
      const base::UnguessableToken& session_id,
      const std::string& device_id);

  // Initialize function called by clients like WebRtcAudioDeviceImpl.
  // Stop() has to be called before |source| is deleted.
  bool Initialize(WebRtcAudioRendererSource* source);

  // When sharing a single instance of WebRtcAudioRenderer between multiple
  // users (e.g. WebMediaPlayerMS), call this method to create a proxy object
  // that maintains the Play and Stop states per caller.
  // The wrapper ensures that Play() won't be called when the caller's state
  // is "playing", Pause() won't be called when the state already is "paused"
  // etc and similarly maintains the same state for Stop().
  // When Stop() is called or when the proxy goes out of scope, the proxy
  // will ensure that Pause() is called followed by a call to Stop(), which
  // is the usage pattern that WebRtcAudioRenderer requires.
  scoped_refptr<blink::WebMediaStreamAudioRenderer>
  CreateSharedAudioRendererProxy(const blink::WebMediaStream& media_stream);

  // Used to DCHECK on the expected state.
  bool IsStarted() const;

  // Accessors to the sink audio parameters.
  int channels() const { return sink_params_.channels(); }
  int sample_rate() const { return sink_params_.sample_rate(); }
  int frames_per_buffer() const { return sink_params_.frames_per_buffer(); }

  // Returns true if called on rendering thread, otherwise false.
  bool CurrentThreadIsRenderingThread();

 private:
  // blink::WebMediaStreamAudioRenderer implementation.  This is private since
  // we want callers to use proxy objects.
  // TODO(tommi): Make the blink::WebMediaStreamAudioRenderer implementation a
  // pimpl?
  void Start() override;
  void Play() override;
  void Pause() override;
  void Stop() override;
  void SetVolume(float volume) override;
  base::TimeDelta GetCurrentRenderTime() override;
  bool IsLocalRenderer() override;
  void SwitchOutputDevice(const std::string& device_id,
                          media::OutputDeviceStatusCB callback) override;

  // Called when an audio renderer, either the main or a proxy, starts playing.
  // Here we maintain a reference count of how many renderers are currently
  // playing so that the shared play state of all the streams can be reflected
  // correctly.
  void EnterPlayState();

  // Called when an audio renderer, either the main or a proxy, is paused.
  // See EnterPlayState for more details.
  void EnterPauseState();

 protected:
  ~WebRtcAudioRenderer() override;

 private:
  enum State {
    UNINITIALIZED,
    PLAYING,
    PAUSED,
  };

  // Holds raw pointers to PlaingState objects.  Ownership is managed outside
  // of this type.
  typedef std::vector<PlayingState*> PlayingStates;
  // Maps an audio source to a list of playing states that collectively hold
  // volume information for that source.
  typedef std::map<webrtc::AudioSourceInterface*, PlayingStates>
      SourcePlayingStates;

  // Used to DCHECK that we are called on the correct thread.
  THREAD_CHECKER(thread_checker_);

  // Flag to keep track the state of the renderer.
  State state_;

  // media::AudioRendererSink::RenderCallback implementation.
  // These two methods are called on the AudioOutputDevice worker thread.
  int Render(base::TimeDelta delay,
             base::TimeTicks delay_timestamp,
             int prior_frames_skipped,
             media::AudioBus* audio_bus) override;
  void OnRenderError() override;

  // Called by AudioPullFifo when more data is necessary.
  // This method is called on the AudioOutputDevice worker thread.
  void SourceCallback(int fifo_frame_delay, media::AudioBus* audio_bus);

  // Goes through all renderers for the |source| and applies the proper
  // volume scaling for the source based on the volume(s) of the renderer(s).
  void UpdateSourceVolume(webrtc::AudioSourceInterface* source);

  // Tracks a playing state.  The state must be playing when this method
  // is called.
  // Returns true if the state was added, false if it was already being tracked.
  bool AddPlayingState(webrtc::AudioSourceInterface* source,
                       PlayingState* state);
  // Removes a playing state for an audio source.
  // Returns true if the state was removed from the internal map, false if
  // it had already been removed or if the source isn't being rendered.
  bool RemovePlayingState(webrtc::AudioSourceInterface* source,
                          PlayingState* state);

  // Called whenever the Play/Pause state changes of any of the renderers
  // or if the volume of any of them is changed.
  // Here we update the shared Play state and apply volume scaling to all audio
  // sources associated with the |media_stream| based on the collective volume
  // of playing renderers.
  void OnPlayStateChanged(const blink::WebMediaStream& media_stream,
                          PlayingState* state);

  // Called when |state| is about to be destructed.
  void OnPlayStateRemoved(PlayingState* state);

  // Updates |sink_params_| and |audio_fifo_| based on |sink_|, and initializes
  // |sink_|.
  void PrepareSink();

  // The WebLocalFrame in which the audio is rendered into |sink_|.
  //
  // TODO(crbug.com/704136): Replace |source_internal_frame_| with regular
  // fields once this header file moves to blink/renderer.
  class InternalFrame;
  std::unique_ptr<InternalFrame> source_internal_frame_;

  const base::UnguessableToken session_id_;

  const scoped_refptr<base::SingleThreadTaskRunner> signaling_thread_;

  // The sink (destination) for rendered audio.
  scoped_refptr<media::AudioRendererSink> sink_;

  // The media stream that holds the audio tracks that this renderer renders.
  const blink::WebMediaStream media_stream_;

  // Audio data source from the browser process.
  //
  // TODO(crbug.com/704136): Make it a Member.
  WebRtcAudioRendererSource* source_;

  // Protects access to |state_|, |source_|, |audio_fifo_|,
  // |audio_delay_milliseconds_|, |fifo_delay_milliseconds_|, |current_time_|,
  // |sink_params_|, |render_callback_count_| and |max_render_time_|.
  mutable base::Lock lock_;

  // Ref count for the MediaPlayers which are playing audio.
  int play_ref_count_;

  // Ref count for the MediaPlayers which have called Start() but not Stop().
  int start_ref_count_;

  // Used to buffer data between the client and the output device in cases where
  // the client buffer size is not the same as the output device buffer size.
  std::unique_ptr<media::AudioPullFifo> audio_fifo_;

  // Contains the accumulated delay estimate which is provided to the WebRTC
  // AEC.
  base::TimeDelta audio_delay_;

  base::TimeDelta current_time_;

  // Saved volume and playing state of the root renderer.
  PlayingState playing_state_;

  // Audio params used by the sink of the renderer.
  media::AudioParameters sink_params_;

  // The preferred device id of the output device or empty for the default
  // output device. Can change as a result of a SetSinkId() call.
  std::string output_device_id_;

  // Maps audio sources to a list of active audio renderers.
  // Pointers to PlayingState objects are only kept in this map while the
  // associated renderer is actually playing the stream.  Ownership of the
  // state objects lies with the renderers and they must leave the playing state
  // before being destructed (PlayingState object goes out of scope).
  SourcePlayingStates source_playing_states_;

  // Stores the maximum time spent waiting for render data from the source. Used
  // for logging UMA data. Logged and reset when Stop() is called.
  base::TimeDelta max_render_time_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioRenderer);
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBRTC_WEBRTC_AUDIO_RENDERER_H_