File: audio_renderer_mixer_input.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (162 lines) | stat: -rw-r--r-- 6,928 bytes parent folder | download | duplicates (6)
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
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// THREAD SAFETY
//
// This class is generally not thread safe. Callers should ensure thread safety.
// For instance, the `sink_lock_` in WebAudioSourceProvider synchronizes access
// to this object across the main thread (for WebAudio APIs) and the
// media thread (for HTMLMediaElement APIs).
//
// The one exception is protection for `volume_` via `volume_lock_`. This lock
// prevents races between SetVolume() (called on any thread) and ProvideInput
// (called on audio device thread). See http://crbug.com/588992.

#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_AUDIO_AUDIO_RENDERER_MIXER_INPUT_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_AUDIO_AUDIO_RENDERER_MIXER_INPUT_H_

#include <string>

#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/synchronization/lock.h"
#include "base/thread_annotations.h"
#include "base/unguessable_token.h"
#include "media/base/audio_converter.h"
#include "media/base/audio_latency.h"
#include "media/base/audio_renderer_sink.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/public/platform/web_common.h"

namespace blink {

class AudioRendererMixerPool;
class AudioRendererMixer;

class BLINK_MODULES_EXPORT AudioRendererMixerInput
    : public media::SwitchableAudioRendererSink,
      public media::AudioConverter::InputCallback {
 public:
  // `mixer_pool` is used to request sinks and mixer instances.
  // `source_frame_token` refers to the local RenderFrame containing the entity
  // producing the audio. It is used to request output sinks.
  // `main_frame_token` refers to the local or remote main frame at the root of
  // the tree containing the RenderFrame referenced by `source_frame_token` and
  // is used for sharing the underlying audio output device.
  // `device_id` is the name of the output device which should be used.
  // `latency` is used to configure buffer size for the output device.
  AudioRendererMixerInput(AudioRendererMixerPool* mixer_pool,
                          const LocalFrameToken& source_frame_token,
                          const FrameToken& main_frame_token,
                          std::string_view device_id,
                          media::AudioLatency::Type latency);

  AudioRendererMixerInput(const AudioRendererMixerInput&) = delete;
  AudioRendererMixerInput& operator=(const AudioRendererMixerInput&) = delete;

  // SwitchableAudioRendererSink implementation.
  void Start() override;
  void Stop() override;
  void Play() override;
  void Pause() override;
  void Flush() override;
  bool SetVolume(double volume) override;
  media::OutputDeviceInfo GetOutputDeviceInfo() override;
  void GetOutputDeviceInfoAsync(OutputDeviceInfoCB info_cb) override;

  bool IsOptimizedForHardwareParameters() override;
  void Initialize(const media::AudioParameters& params,
                  media::AudioRendererSink::RenderCallback* renderer) override;
  void SwitchOutputDevice(const std::string& device_id,
                          media::OutputDeviceStatusCB callback) override;
  // This is expected to be called on the audio rendering thread. The caller
  // must ensure that this input has been added to a mixer before calling the
  // function, and that it is not removed from the mixer before this function
  // returns.
  bool CurrentThreadIsRenderingThread() override;

  // Called by AudioRendererMixer when an error occurs.
  void OnRenderError();

 private:
  ~AudioRendererMixerInput() override;

  friend class AudioRendererMixerInputTest;

  // Pool to obtain mixers from / return them to.
  const raw_ptr<AudioRendererMixerPool> mixer_pool_;

  // Protect `volume_`, accessed by separate threads in ProvideInput() and
  // SetVolume().
  base::Lock volume_lock_;

  bool started_ = false;
  bool playing_ = false;
  double volume_ GUARDED_BY(volume_lock_) = 1.0;

  scoped_refptr<AudioRendererSink> sink_;
  std::optional<media::OutputDeviceInfo> device_info_;

  // AudioConverter::InputCallback implementation.
  double ProvideInput(media::AudioBus* audio_bus,
                      uint32_t frames_delayed,
                      const media::AudioGlitchInfo& glitch_info) override;

  void OnDeviceInfoReceived(OutputDeviceInfoCB info_cb,
                            media::OutputDeviceInfo device_info);

  // Method to help handle device changes. Must be static to ensure we can still
  // execute the `switch_cb` even if the pipeline is destructed. Restarts (if
  // necessary) Start() and Play() state with a new `sink` and `device_info`.
  //
  // `switch_cb` is the callback given to the SwitchOutputDevice() call.
  // `sink` is a fresh sink which should be used if device info is good.
  // `device_info` is the OutputDeviceInfo for `sink` after
  // GetOutputDeviceInfoAsync() completes.
  void OnDeviceSwitchReady(media::OutputDeviceStatusCB switch_cb,
                           scoped_refptr<media::AudioRendererSink> sink,
                           media::OutputDeviceInfo device_info);

  // AudioParameters received during Initialize().
  media::AudioParameters params_;

  // Linearly fades in the input volume during the first ProvideInput() calls,
  // avoiding audible pops.
  int total_fade_in_frames_;
  int remaining_fade_in_frames_ = 0;

  const LocalFrameToken source_frame_token_;
  const FrameToken main_frame_token_;

  std::string device_id_;  // ID of hardware device to use
  const media::AudioLatency::Type latency_;

  // AudioRendererMixer obtained from mixer pool during Initialize(),
  // guaranteed to live (at least) until it is returned to the pool.
  raw_ptr<AudioRendererMixer> mixer_ = nullptr;

  // Source of audio data which is provided to the mixer.
  raw_ptr<AudioRendererSink::RenderCallback> callback_ = nullptr;

  // SwitchOutputDevice() and GetOutputDeviceInfoAsync() must be mutually
  // exclusive when executing; these flags indicate whether one or the other is
  // in progress. Each method will use the other method's to defer its action.
  bool godia_in_progress_ = false;
  bool switch_output_device_in_progress_ = false;

  // Set by GetOutputDeviceInfoAsync() if a SwitchOutputDevice() call is in
  // progress. GetOutputDeviceInfoAsync() will be invoked again with this value
  // once OnDeviceSwitchReady() from the SwitchOutputDevice() call completes.
  OutputDeviceInfoCB pending_device_info_cb_;

  // Set by SwitchOutputDevice() if a GetOutputDeviceInfoAsync() call is in
  // progress. SwitchOutputDevice() will be invoked again with these values once
  // the OnDeviceInfoReceived() from the GODIA() call completes.
  std::string pending_device_id_;
  media::OutputDeviceStatusCB pending_switch_cb_;
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_AUDIO_AUDIO_RENDERER_MIXER_INPUT_H_