• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 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 #include "libcef/browser/audio_loopback_stream_creator.h"
6 
7 #include <memory>
8 #include <utility>
9 
10 #include "base/bind.h"
11 #include "base/check_op.h"
12 #include "base/location.h"
13 #include "content/browser/browser_main_loop.h"
14 #include "content/browser/web_contents/web_contents_impl.h"
15 #include "content/public/browser/browser_task_traits.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/render_frame_host.h"
18 #include "media/audio/audio_device_description.h"
19 #include "media/base/user_input_monitor.h"
20 #include "mojo/public/cpp/bindings/pending_remote.h"
21 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
22 #include "third_party/blink/public/mojom/media/renderer_audio_input_stream_factory.mojom.h"
23 
24 namespace {
25 
26 // A blink::mojom::RendererAudioInputStreamFactoryClient that holds a
27 // CefAudioLoopbackStreamCreator::StreamCreatedCallback. The callback runs when
28 // the requested audio stream is created.
29 class StreamCreatedCallbackAdapter final
30     : public blink::mojom::RendererAudioInputStreamFactoryClient {
31  public:
StreamCreatedCallbackAdapter(const CefAudioLoopbackStreamCreator::StreamCreatedCallback & callback)32   explicit StreamCreatedCallbackAdapter(
33       const CefAudioLoopbackStreamCreator::StreamCreatedCallback& callback)
34       : callback_(callback) {
35     DCHECK(callback_);
36   }
37 
~StreamCreatedCallbackAdapter()38   ~StreamCreatedCallbackAdapter() override {}
39 
40   // blink::mojom::RendererAudioInputStreamFactoryClient implementation.
StreamCreated(mojo::PendingRemote<media::mojom::AudioInputStream> stream,mojo::PendingReceiver<media::mojom::AudioInputStreamClient> client_receiver,media::mojom::ReadOnlyAudioDataPipePtr data_pipe,bool initially_muted,const base::Optional<base::UnguessableToken> & stream_id)41   void StreamCreated(
42       mojo::PendingRemote<media::mojom::AudioInputStream> stream,
43       mojo::PendingReceiver<media::mojom::AudioInputStreamClient>
44           client_receiver,
45       media::mojom::ReadOnlyAudioDataPipePtr data_pipe,
46       bool initially_muted,
47       const base::Optional<base::UnguessableToken>& stream_id) override {
48     DCHECK(!initially_muted);  // Loopback streams shouldn't be started muted.
49     callback_.Run(std::move(stream), std::move(client_receiver),
50                   std::move(data_pipe));
51   }
52 
53  private:
54   const CefAudioLoopbackStreamCreator::StreamCreatedCallback callback_;
55 
56   DISALLOW_COPY_AND_ASSIGN(StreamCreatedCallbackAdapter);
57 };
58 
CreateLoopbackStreamHelper(content::ForwardingAudioStreamFactory::Core * factory,content::AudioStreamBroker::LoopbackSource * loopback_source,const media::AudioParameters & params,uint32_t total_segments,mojo::PendingRemote<blink::mojom::RendererAudioInputStreamFactoryClient> client_remote)59 void CreateLoopbackStreamHelper(
60     content::ForwardingAudioStreamFactory::Core* factory,
61     content::AudioStreamBroker::LoopbackSource* loopback_source,
62     const media::AudioParameters& params,
63     uint32_t total_segments,
64     mojo::PendingRemote<blink::mojom::RendererAudioInputStreamFactoryClient>
65         client_remote) {
66   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
67 
68   const bool mute_source = true;
69   factory->CreateLoopbackStream(-1, -1, loopback_source, params, total_segments,
70                                 mute_source, std::move(client_remote));
71 }
72 
CreateSystemWideLoopbackStreamHelper(content::ForwardingAudioStreamFactory::Core * factory,const media::AudioParameters & params,uint32_t total_segments,mojo::PendingRemote<blink::mojom::RendererAudioInputStreamFactoryClient> client_remote)73 void CreateSystemWideLoopbackStreamHelper(
74     content::ForwardingAudioStreamFactory::Core* factory,
75     const media::AudioParameters& params,
76     uint32_t total_segments,
77     mojo::PendingRemote<blink::mojom::RendererAudioInputStreamFactoryClient>
78         client_remote) {
79   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
80 
81   const bool enable_agc = false;
82   factory->CreateInputStream(
83       -1, -1, media::AudioDeviceDescription::kLoopbackWithMuteDeviceId, params,
84       total_segments, enable_agc, std::move(client_remote));
85 }
86 
87 }  // namespace
88 
CefAudioLoopbackStreamCreator()89 CefAudioLoopbackStreamCreator::CefAudioLoopbackStreamCreator()
90     : factory_(nullptr,
91                content::BrowserMainLoop::GetInstance()
92                    ? static_cast<media::UserInputMonitorBase*>(
93                          content::BrowserMainLoop::GetInstance()
94                              ->user_input_monitor())
95                    : nullptr,
96                content::AudioStreamBrokerFactory::CreateImpl()) {
97   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
98 }
99 
~CefAudioLoopbackStreamCreator()100 CefAudioLoopbackStreamCreator::~CefAudioLoopbackStreamCreator() {
101   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
102 }
103 
CreateLoopbackStream(content::WebContents * loopback_source,const media::AudioParameters & params,uint32_t total_segments,const StreamCreatedCallback & callback)104 void CefAudioLoopbackStreamCreator::CreateLoopbackStream(
105     content::WebContents* loopback_source,
106     const media::AudioParameters& params,
107     uint32_t total_segments,
108     const StreamCreatedCallback& callback) {
109   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
110   mojo::PendingRemote<blink::mojom::RendererAudioInputStreamFactoryClient>
111       client;
112   mojo::MakeSelfOwnedReceiver(
113       std::make_unique<StreamCreatedCallbackAdapter>(callback),
114       client.InitWithNewPipeAndPassReceiver());
115   // Deletion of factory_.core() is posted to the IO thread when |factory_| is
116   // destroyed, so Unretained is safe below.
117   if (loopback_source) {
118     content::GetIOThreadTaskRunner({})->PostTask(
119         FROM_HERE,
120         base::BindOnce(&CreateLoopbackStreamHelper, factory_.core(),
121                        static_cast<content::WebContentsImpl*>(loopback_source)
122                            ->GetAudioStreamFactory()
123                            ->core(),
124                        params, total_segments, std::move(client)));
125     return;
126   }
127   // A null |frame_of_source_web_contents| requests system-wide loopback.
128   content::GetIOThreadTaskRunner({})->PostTask(
129       FROM_HERE,
130       base::BindOnce(&CreateSystemWideLoopbackStreamHelper, factory_.core(),
131                      params, total_segments, std::move(client)));
132 }
133