File: audio_renderer_mixer_manager.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 (189 lines) | stat: -rw-r--r-- 7,756 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
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
// 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.

#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_AUDIO_AUDIO_RENDERER_MIXER_MANAGER_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_AUDIO_AUDIO_RENDERER_MIXER_MANAGER_H_

#include <list>
#include <memory>
#include <string>

#include "base/containers/flat_map.h"
#include "base/memory/raw_ptr.h"
#include "base/synchronization/lock.h"
#include "base/unguessable_token.h"
#include "media/audio/audio_device_description.h"
#include "media/audio/audio_sink_parameters.h"
#include "media/base/audio_latency.h"
#include "media/base/audio_parameters.h"
#include "media/base/output_device_info.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/public/platform/web_common.h"
#include "third_party/blink/renderer/modules/media/audio/audio_renderer_mixer_pool.h"

namespace media {
class AudioRendererSink;
}  // namespace media

namespace blink {
class AudioRendererMixer;
class AudioRendererMixerInput;

// Manages sharing of an AudioRendererMixer among AudioRendererMixerInputs based
// on their AudioParameters configuration.  Inputs with the same AudioParameters
// configuration will share a mixer while a new AudioRendererMixer will be
// lazily created if one with the exact AudioParameters does not exist. When an
// AudioRendererMixer is returned by AudioRendererMixerInput, it will be deleted
// if its only other reference is held by AudioRendererMixerManager.
//
// There should only be one instance of AudioRendererMixerManager per render
// thread.
class BLINK_MODULES_EXPORT AudioRendererMixerManager final
    : public AudioRendererMixerPool {
 public:
  // Callback which will be used to create sinks. See AudioDeviceFactory for
  // more details on the parameters.
  using CreateSinkCB =
      base::RepeatingCallback<scoped_refptr<media::AudioRendererSink>(
          const blink::LocalFrameToken& source_frame_token,
          const media::AudioSinkParameters& params)>;

  explicit AudioRendererMixerManager(CreateSinkCB create_sink_cb);
  ~AudioRendererMixerManager() final;

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

  // Creates an AudioRendererMixerInput with the proper callbacks necessary to
  // retrieve an AudioRendererMixer instance from AudioRendererMixerManager.
  //
  // `source_frame_token` refers to the RenderFrame containing the entity
  // rendering the audio.  Caller must ensure AudioRendererMixerManager outlives
  // the returned input.
  //
  // `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` and `session_id` identify the output device to use. If
  // `device_id` is empty and `session_id` is nonzero, output device associated
  // with the opened input device designated by `session_id` is used. Otherwise,
  // `session_id` is ignored.
  scoped_refptr<AudioRendererMixerInput> CreateInput(
      const LocalFrameToken& source_frame_token,
      const FrameToken& main_frame_token,
      const base::UnguessableToken& session_id,
      std::string_view device_id,
      media::AudioLatency::Type latency);

  // media::AudioRendererMixerPool implementation. The rest of the
  // implementation is kept private (see comment below).
  AudioRendererMixer* GetMixer(
      const LocalFrameToken& source_frame_token,
      const FrameToken& main_frame_token,
      const media::AudioParameters& input_params,
      media::AudioLatency::Type latency,
      const media::OutputDeviceInfo& sink_info,
      scoped_refptr<media::AudioRendererSink> sink) final;
  void ReturnMixer(AudioRendererMixer* mixer) final;
  scoped_refptr<media::AudioRendererSink> GetSink(
      const LocalFrameToken& source_frame_token,
      const FrameToken& main_frame_token,
      std::string_view device_id) final;

 private:
  friend class AudioRendererMixerManagerTest;

  // Define a key so that only those AudioRendererMixerInputs from the same
  // RenderView, AudioParameters and output device can be mixed together.
  struct MixerKey {
    MixerKey(const LocalFrameToken& source_frame_token,
             const FrameToken& main_frame_token,
             const media::AudioParameters& params,
             media::AudioLatency::Type latency,
             std::string_view device_id);
    MixerKey(const MixerKey& other);
    ~MixerKey();
    blink::LocalFrameToken source_frame_token;
    blink::FrameToken main_frame_token;
    media::AudioParameters params;
    media::AudioLatency::Type latency;
    std::string device_id;
  };

  // Custom compare operator for the AudioRendererMixerMap.  Allows reuse of
  // mixers where only irrelevant keys mismatch.
  struct MixerKeyCompare {
    bool operator()(const MixerKey& a, const MixerKey& b) const {
      if (a.main_frame_token != b.main_frame_token) {
        return a.main_frame_token < b.main_frame_token;
      }
      if (a.params.channels() != b.params.channels()) {
        return a.params.channels() < b.params.channels();
      }
      if (a.latency != b.latency) {
        return a.latency < b.latency;
      }

      // TODO(olka) add buffer duration comparison for kLatencyExactMS when
      // adding support for it.
      DCHECK_NE(media::AudioLatency::Type::kExactMS, a.latency);

      // Ignore format(), and frames_per_buffer(), these parameters do not
      // affect mixer reuse.  All AudioRendererMixer units disable FIFO, so
      // frames_per_buffer() can be safely ignored.
      if (a.params.channel_layout() != b.params.channel_layout()) {
        return a.params.channel_layout() < b.params.channel_layout();
      }
      if (a.params.effects() != b.params.effects()) {
        return a.params.effects() < b.params.effects();
      }

      if (media::AudioDeviceDescription::IsDefaultDevice(a.device_id) &&
          media::AudioDeviceDescription::IsDefaultDevice(b.device_id)) {
        // Both device IDs represent the same default device => do not compare
        // them. We can skip the `source_frame_token` check in this case since
        // the default device is always authorized.
        return false;
      }

      // The lifetime of sinks for non-default devices are bound to the frame
      // that created them. So even if two sub-frames are authorized for the
      // same device, they can't share an output device.
      if (a.source_frame_token != b.source_frame_token) {
        return a.source_frame_token < b.source_frame_token;
      }

      return a.device_id < b.device_id;
    }
  };

  const CreateSinkCB create_sink_cb_;

  // Map of MixerKey to <AudioRendererMixer, Count>.  Count allows
  // AudioRendererMixerManager to keep track explicitly (v.s. RefCounted which
  // is implicit) of the number of outstanding AudioRendererMixers.
  struct AudioRendererMixerReference {
    std::unique_ptr<AudioRendererMixer> mixer;
    size_t ref_count;
  };

  using AudioRendererMixerMap =
      base::flat_map<MixerKey, AudioRendererMixerReference, MixerKeyCompare>;

  // Active mixers.
  AudioRendererMixerMap mixers_;

  // Mixers which encountered errors, but can't yet be destroyed since they are
  // still owned by an input. This must be a list since the same mixer key may
  // end up associated with multiple mixers with errors.
  std::list<AudioRendererMixerReference> dead_mixers_;

  base::Lock mixers_lock_;
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_AUDIO_AUDIO_RENDERER_MIXER_MANAGER_H_