summaryrefslogtreecommitdiff
path: root/chromium/content/browser/media/capture/audio_mirroring_manager.h
blob: b98cf018c5922e4023b4f32398da0d583b41568d (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
// Copyright (c) 2013 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.
//
// AudioMirroringManager is a singleton object that maintains a set of active
// audio mirroring destinations and auto-connects/disconnects audio streams
// to/from those destinations.  It is meant to be used exclusively on the IO
// thread.
//
// How it works:
//
//   1. AudioRendererHost gets a CreateStream message from the render process
//      and, among other things, creates an AudioOutputController to control the
//      audio data flow between the render and browser processes.  More
//      importantly, it registers the AudioOutputController with
//      AudioMirroringManager (as a Diverter).
//   2. A user request to mirror all the audio for a WebContents is made.  A
//      MirroringDestination is created, and StartMirroring() is called to begin
//      the mirroring session.  The MirroringDestination is queried to determine
//      which of all the known Diverters will re-route their audio to it.
//   3a. During a mirroring session, AudioMirroringManager may encounter new
//       Diverters, and will query all the MirroringDestinations to determine
//       which is a match, if any.
//   3b. During a mirroring session, a call to StartMirroring() can be made to
//       request a "refresh" query on a MirroringDestination, and this will
//       result in AudioMirroringManager starting/stopping only those Diverters
//       that are not correctly routed to the destination.
//   3c. When a mirroring session is stopped, the remaining destinations will be
//       queried to determine whether diverting should continue to a different
//       destination.

#ifndef CONTENT_BROWSER_MEDIA_CAPTURE_AUDIO_MIRRORING_MANAGER_H_
#define CONTENT_BROWSER_MEDIA_CAPTURE_AUDIO_MIRRORING_MANAGER_H_

#include <map>
#include <set>
#include <utility>
#include <vector>

#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
#include "media/audio/audio_source_diverter.h"

namespace media {
class AudioOutputStream;
}

namespace content {

class CONTENT_EXPORT AudioMirroringManager {
 public:
  // Interface for diverting audio data to an alternative AudioOutputStream.
  typedef media::AudioSourceDiverter Diverter;

  // A SourceFrameRef is a RenderFrameHost identified by a <render_process_id,
  // render_frame_id> pair.
  typedef std::pair<int, int> SourceFrameRef;

  // Interface to be implemented by audio mirroring destinations.  See comments
  // for StartMirroring() and StopMirroring() below.
  class MirroringDestination {
   public:
    // Asynchronously query whether this MirroringDestination wants to consume
    // audio sourced from each of the |candidates|.  |results_callback| is run
    // to indicate which of them (or none) should have audio routed to this
    // MirroringDestination.  The second parameter of |results_callback|
    // indicates whether the MirroringDestination wants either: 1) exclusive
    // access to a diverted audio flow versus 2) a duplicate copy of the audio
    // flow. |results_callback| must be run on the same thread as the one that
    // called QueryForMatches().
    typedef base::Callback<void(const std::set<SourceFrameRef>&, bool)>
        MatchesCallback;
    virtual void QueryForMatches(
        const std::set<SourceFrameRef>& candidates,
        const MatchesCallback& results_callback) = 0;

    // Create a consumer of audio data in the format specified by |params|, and
    // connect it as an input to mirroring.  This is used to provide
    // MirroringDestination with exclusive access to pull the audio flow from
    // the source. When Close() is called on the returned AudioOutputStream, the
    // input is disconnected and the object becomes invalid.
    virtual media::AudioOutputStream* AddInput(
        const media::AudioParameters& params) = 0;

    // Create a consumer of audio data in the format specified by |params|, and
    // connect it as an input to mirroring.  This is used to provide
    // MirroringDestination with duplicate audio data, which is pushed from the
    // main audio flow. When Close() is called on the returned AudioPushSink,
    // the input is disconnected and the object becomes invalid.
    virtual media::AudioPushSink* AddPushInput(
        const media::AudioParameters& params) = 0;

   protected:
    virtual ~MirroringDestination() {}
  };

  // Note: Use GetInstance() for non-test code.
  AudioMirroringManager();
  virtual ~AudioMirroringManager();

  // Returns the global instance.
  static AudioMirroringManager* GetInstance();

  // Add/Remove a diverter for an audio stream with a known RenderFrame source
  // (represented by |render_process_id| + |render_frame_id|).  Multiple
  // diverters may be added for the same source frame, but never the same
  // diverter.  |diverter| must live until after RemoveDiverter() is called.
  virtual void AddDiverter(int render_process_id, int render_frame_id,
                           Diverter* diverter);
  virtual void RemoveDiverter(Diverter* diverter);

  // (Re-)Start/Stop mirroring to the given |destination|.  |destination| must
  // live until after StopMirroring() is called.  A client may request a
  // re-start by calling StartMirroring() again; and this will cause
  // AudioMirroringManager to query |destination| and only re-route those
  // diverters that are missing/new to the returned set of matches.
  virtual void StartMirroring(MirroringDestination* destination);
  virtual void StopMirroring(MirroringDestination* destination);

 private:
  friend class AudioMirroringManagerTest;

  struct StreamRoutingState {
    // The source render frame associated with the audio stream.
    SourceFrameRef source_render_frame;

    // The diverter for re-routing the audio stream.
    Diverter* diverter;

    // If not NULL, the audio stream is currently being diverted to this
    // destination.
    MirroringDestination* destination;

    // The destinations to which audio stream is duplicated. AudioPushSink is
    // owned by the Diverter, but AudioMirroringManager must guarantee
    // StopDuplicating() is called to release them.
    std::map<MirroringDestination*, media::AudioPushSink*> duplications;

    StreamRoutingState(const SourceFrameRef& source_frame,
                       Diverter* stream_diverter);
    StreamRoutingState(const StreamRoutingState& other);
    ~StreamRoutingState();
  };

  typedef std::vector<StreamRoutingState> StreamRoutes;
  typedef std::vector<MirroringDestination*> Destinations;

  // Helper to find a destination other than |old_destination| for the given
  // |candidates| to be diverted to.
  void InitiateQueriesToFindNewDestination(
      MirroringDestination* old_destination,
      const std::set<SourceFrameRef>& candidates);

  // MirroringDestination query callback.  |matches| contains all RenderFrame
  // sources that will be diverted or duplicated to |destination|.
  // If |add_only| is false, then any audio flows currently routed to
  // |destination| but not found in |matches| will be stopped.
  // If |is_duplicate| is true, the audio data flow will be duplicated to the
  // destination instead of diverted.
  void UpdateRoutesToDestination(MirroringDestination* destination,
                                 bool add_only,
                                 const std::set<SourceFrameRef>& matches,
                                 bool is_duplicate);

  // |matches| contains all RenderFrame sources that will be diverted to
  // |destination|.  If |add_only| is false, then any Diverters currently routed
  // to |destination| but not found in |matches| will be stopped.
  void UpdateRoutesToDivertDestination(MirroringDestination* destination,
                                       bool add_only,
                                       const std::set<SourceFrameRef>& matches);

  // |matches| contains all RenderFrame sources that will be duplicated to
  // |destination|.  If |add_only| is false, then any Diverters currently
  // duplicating to |destination| but not found in |matches| will be stopped.
  void UpdateRoutesToDuplicateDestination(
      MirroringDestination* destination,
      bool add_only,
      const std::set<SourceFrameRef>& matches);

  // Starts diverting audio to the |new_destination|, if not NULL.  Otherwise,
  // stops diverting audio.
  static void RouteDivertedFlow(StreamRoutingState* route,
                                MirroringDestination* new_destination);

  // Routing table.  Contains one entry for each Diverter.
  StreamRoutes routes_;

  // All active mirroring sessions.
  Destinations sessions_;

  // Used to check that all AudioMirroringManager code runs on the same thread.
  base::ThreadChecker thread_checker_;

  DISALLOW_COPY_AND_ASSIGN(AudioMirroringManager);
};

}  // namespace content

#endif  // CONTENT_BROWSER_MEDIA_CAPTURE_AUDIO_MIRRORING_MANAGER_H_