| // 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. | 
 | // | 
 | // 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/synchronization/lock.h" | 
 | #include "base/unguessable_token.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); | 
 |  | 
 |   // TODO(crbug/824019): The following are temporary, as a middle-ground step | 
 |   // necessary to resolve a chicken-and-egg problem as we migrate audio | 
 |   // mirroring into the new AudioService. See media::AudioManager::AddDiverter() | 
 |   // comments for further details. | 
 |   using AddDiverterCallback = | 
 |       base::RepeatingCallback<void(const base::UnguessableToken&, | 
 |                                    media::AudioSourceDiverter*)>; | 
 |   AddDiverterCallback GetAddDiverterCallback(); | 
 |   using RemoveDiverterCallback = | 
 |       base::RepeatingCallback<void(media::AudioSourceDiverter*)>; | 
 |   RemoveDiverterCallback GetRemoveDiverterCallback(); | 
 |   static base::UnguessableToken ToGroupId(int render_process_id, | 
 |                                           int render_frame_id); | 
 |  | 
 |  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_; | 
 |  | 
 |   // Allows calls to Add/RemoveDiverter() and Start/StopMirroring() to be made | 
 |   // from different threads. | 
 |   base::Lock lock_; | 
 |  | 
 |   DISALLOW_COPY_AND_ASSIGN(AudioMirroringManager); | 
 | }; | 
 |  | 
 | }  // namespace content | 
 |  | 
 | #endif  // CONTENT_BROWSER_MEDIA_CAPTURE_AUDIO_MIRRORING_MANAGER_H_ |