1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4//
5// AudioMirroringManager is a singleton object that maintains a set of active
6// audio mirroring destinations and auto-connects/disconnects audio streams
7// to/from those destinations.  It is meant to be used exclusively on the IO
8// thread.
9//
10// How it works:
11//
12//   1. AudioRendererHost gets a CreateStream message from the render process
13//      and, among other things, creates an AudioOutputController to control the
14//      audio data flow between the render and browser processes.  More
15//      importantly, it registers the AudioOutputController with
16//      AudioMirroringManager (as a Diverter).
17//   2. A user request to mirror all the audio for a WebContents is made.  A
18//      MirroringDestination is created, and StartMirroring() is called to begin
19//      the mirroring session.  The MirroringDestination is queried to determine
20//      which of all the known Diverters will re-route their audio to it.
21//   3a. During a mirroring session, AudioMirroringManager may encounter new
22//       Diverters, and will query all the MirroringDestinations to determine
23//       which is a match, if any.
24//   3b. During a mirroring session, a call to StartMirroring() can be made to
25//       request a "refresh" query on a MirroringDestination, and this will
26//       result in AudioMirroringManager starting/stopping only those Diverters
27//       that are not correctly routed to the destination.
28//   3c. When a mirroring session is stopped, the remaining destinations will be
29//       queried to determine whether diverting should continue to a different
30//       destination.
31
32#ifndef CONTENT_BROWSER_MEDIA_CAPTURE_AUDIO_MIRRORING_MANAGER_H_
33#define CONTENT_BROWSER_MEDIA_CAPTURE_AUDIO_MIRRORING_MANAGER_H_
34
35#include <set>
36#include <utility>
37#include <vector>
38
39#include "base/basictypes.h"
40#include "base/callback_forward.h"
41#include "base/threading/thread_checker.h"
42#include "content/common/content_export.h"
43#include "media/audio/audio_source_diverter.h"
44
45namespace media {
46class AudioOutputStream;
47}
48
49namespace content {
50
51class CONTENT_EXPORT AudioMirroringManager {
52 public:
53  // Interface for diverting audio data to an alternative AudioOutputStream.
54  typedef media::AudioSourceDiverter Diverter;
55
56  // A SourceFrameRef is a RenderFrameHost identified by a <render_process_id,
57  // render_frame_id> pair.
58  typedef std::pair<int, int> SourceFrameRef;
59
60  // Interface to be implemented by audio mirroring destinations.  See comments
61  // for StartMirroring() and StopMirroring() below.
62  class MirroringDestination {
63   public:
64    // Asynchronously query whether this MirroringDestination wants to consume
65    // audio sourced from each of the |candidates|.  |results_callback| is run
66    // to indicate which of them (or none) should have audio routed to this
67    // MirroringDestination.  |results_callback| must be run on the same thread
68    // as the one that called QueryForMatches().
69    typedef base::Callback<void(const std::set<SourceFrameRef>&)>
70        MatchesCallback;
71    virtual void QueryForMatches(
72        const std::set<SourceFrameRef>& candidates,
73        const MatchesCallback& results_callback) = 0;
74
75    // Create a consumer of audio data in the format specified by |params|, and
76    // connect it as an input to mirroring.  When Close() is called on the
77    // returned AudioOutputStream, the input is disconnected and the object
78    // becomes invalid.
79    virtual media::AudioOutputStream* AddInput(
80        const media::AudioParameters& params) = 0;
81
82   protected:
83    virtual ~MirroringDestination() {}
84  };
85
86  // Note: Use GetInstance() for non-test code.
87  AudioMirroringManager();
88  virtual ~AudioMirroringManager();
89
90  // Returns the global instance.
91  static AudioMirroringManager* GetInstance();
92
93  // Add/Remove a diverter for an audio stream with a known RenderFrame source
94  // (represented by |render_process_id| + |render_frame_id|).  Multiple
95  // diverters may be added for the same source frame, but never the same
96  // diverter.  |diverter| must live until after RemoveDiverter() is called.
97  virtual void AddDiverter(int render_process_id, int render_frame_id,
98                           Diverter* diverter);
99  virtual void RemoveDiverter(Diverter* diverter);
100
101  // (Re-)Start/Stop mirroring to the given |destination|.  |destination| must
102  // live until after StopMirroring() is called.  A client may request a
103  // re-start by calling StartMirroring() again; and this will cause
104  // AudioMirroringManager to query |destination| and only re-route those
105  // diverters that are missing/new to the returned set of matches.
106  virtual void StartMirroring(MirroringDestination* destination);
107  virtual void StopMirroring(MirroringDestination* destination);
108
109 private:
110  friend class AudioMirroringManagerTest;
111
112  struct StreamRoutingState {
113    // The source render frame associated with the audio stream.
114    SourceFrameRef source_render_frame;
115
116    // The diverter for re-routing the audio stream.
117    Diverter* diverter;
118
119    // If not NULL, the audio stream is currently being diverted to this
120    // destination.
121    MirroringDestination* destination;
122
123    StreamRoutingState(const SourceFrameRef& source_frame,
124                       Diverter* stream_diverter);
125    ~StreamRoutingState();
126  };
127
128  typedef std::vector<StreamRoutingState> StreamRoutes;
129  typedef std::vector<MirroringDestination*> Destinations;
130
131  // Helper to find a destination other than |old_destination| for the given
132  // |candidates| to be diverted to.
133  void InitiateQueriesToFindNewDestination(
134      MirroringDestination* old_destination,
135      const std::set<SourceFrameRef>& candidates);
136
137  // MirroringDestination query callback.  |matches| contains all RenderFrame
138  // sources that will be diverted to |destination|.  If |add_only| is false,
139  // then any Diverters currently routed to |destination| but not found in
140  // |matches| will be stopped.
141  void UpdateRoutesToDestination(MirroringDestination* destination,
142                                 bool add_only,
143                                 const std::set<SourceFrameRef>& matches);
144
145  // Starts diverting audio to the |new_destination|, if not NULL.  Otherwise,
146  // stops diverting audio.
147  static void ChangeRoute(StreamRoutingState* route,
148                          MirroringDestination* new_destination);
149
150  // Routing table.  Contains one entry for each Diverter.
151  StreamRoutes routes_;
152
153  // All active mirroring sessions.
154  Destinations sessions_;
155
156  // Used to check that all AudioMirroringManager code runs on the same thread.
157  base::ThreadChecker thread_checker_;
158
159  DISALLOW_COPY_AND_ASSIGN(AudioMirroringManager);
160};
161
162}  // namespace content
163
164#endif  // CONTENT_BROWSER_MEDIA_CAPTURE_AUDIO_MIRRORING_MANAGER_H_
165