mirror of
				https://bitbucket.org/chromiumembedded/cef
				synced 2025-06-05 21:39:12 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			133 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			133 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright 2018 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.
 | |
| 
 | |
| #include "libcef/browser/audio_loopback_stream_creator.h"
 | |
| 
 | |
| #include <memory>
 | |
| #include <utility>
 | |
| 
 | |
| #include "base/bind.h"
 | |
| #include "base/check_op.h"
 | |
| #include "base/location.h"
 | |
| #include "content/browser/browser_main_loop.h"
 | |
| #include "content/browser/web_contents/web_contents_impl.h"
 | |
| #include "content/public/browser/browser_task_traits.h"
 | |
| #include "content/public/browser/browser_thread.h"
 | |
| #include "content/public/browser/render_frame_host.h"
 | |
| #include "media/audio/audio_device_description.h"
 | |
| #include "media/base/user_input_monitor.h"
 | |
| #include "mojo/public/cpp/bindings/pending_remote.h"
 | |
| #include "mojo/public/cpp/bindings/self_owned_receiver.h"
 | |
| #include "third_party/blink/public/mojom/media/renderer_audio_input_stream_factory.mojom.h"
 | |
| 
 | |
| namespace {
 | |
| 
 | |
| // A blink::mojom::RendererAudioInputStreamFactoryClient that holds a
 | |
| // CefAudioLoopbackStreamCreator::StreamCreatedCallback. The callback runs when
 | |
| // the requested audio stream is created.
 | |
| class StreamCreatedCallbackAdapter final
 | |
|     : public blink::mojom::RendererAudioInputStreamFactoryClient {
 | |
|  public:
 | |
|   explicit StreamCreatedCallbackAdapter(
 | |
|       const CefAudioLoopbackStreamCreator::StreamCreatedCallback& callback)
 | |
|       : callback_(callback) {
 | |
|     DCHECK(callback_);
 | |
|   }
 | |
| 
 | |
|   ~StreamCreatedCallbackAdapter() override {}
 | |
| 
 | |
|   // blink::mojom::RendererAudioInputStreamFactoryClient implementation.
 | |
|   void StreamCreated(
 | |
|       mojo::PendingRemote<media::mojom::AudioInputStream> stream,
 | |
|       mojo::PendingReceiver<media::mojom::AudioInputStreamClient>
 | |
|           client_receiver,
 | |
|       media::mojom::ReadOnlyAudioDataPipePtr data_pipe,
 | |
|       bool initially_muted,
 | |
|       const absl::optional<base::UnguessableToken>& stream_id) override {
 | |
|     DCHECK(!initially_muted);  // Loopback streams shouldn't be started muted.
 | |
|     callback_.Run(std::move(stream), std::move(client_receiver),
 | |
|                   std::move(data_pipe));
 | |
|   }
 | |
| 
 | |
|  private:
 | |
|   const CefAudioLoopbackStreamCreator::StreamCreatedCallback callback_;
 | |
| 
 | |
|   DISALLOW_COPY_AND_ASSIGN(StreamCreatedCallbackAdapter);
 | |
| };
 | |
| 
 | |
| void 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) {
 | |
|   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 | |
| 
 | |
|   const bool mute_source = true;
 | |
|   factory->CreateLoopbackStream(-1, -1, loopback_source, params, total_segments,
 | |
|                                 mute_source, std::move(client_remote));
 | |
| }
 | |
| 
 | |
| void CreateSystemWideLoopbackStreamHelper(
 | |
|     content::ForwardingAudioStreamFactory::Core* factory,
 | |
|     const media::AudioParameters& params,
 | |
|     uint32_t total_segments,
 | |
|     mojo::PendingRemote<blink::mojom::RendererAudioInputStreamFactoryClient>
 | |
|         client_remote) {
 | |
|   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 | |
| 
 | |
|   const bool enable_agc = false;
 | |
|   factory->CreateInputStream(
 | |
|       -1, -1, media::AudioDeviceDescription::kLoopbackWithMuteDeviceId, params,
 | |
|       total_segments, enable_agc, std::move(client_remote));
 | |
| }
 | |
| 
 | |
| }  // namespace
 | |
| 
 | |
| CefAudioLoopbackStreamCreator::CefAudioLoopbackStreamCreator()
 | |
|     : factory_(nullptr,
 | |
|                content::BrowserMainLoop::GetInstance()
 | |
|                    ? static_cast<media::UserInputMonitorBase*>(
 | |
|                          content::BrowserMainLoop::GetInstance()
 | |
|                              ->user_input_monitor())
 | |
|                    : nullptr,
 | |
|                content::AudioStreamBrokerFactory::CreateImpl()) {
 | |
|   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 | |
| }
 | |
| 
 | |
| CefAudioLoopbackStreamCreator::~CefAudioLoopbackStreamCreator() {
 | |
|   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 | |
| }
 | |
| 
 | |
| void CefAudioLoopbackStreamCreator::CreateLoopbackStream(
 | |
|     content::WebContents* loopback_source,
 | |
|     const media::AudioParameters& params,
 | |
|     uint32_t total_segments,
 | |
|     const StreamCreatedCallback& callback) {
 | |
|   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 | |
|   mojo::PendingRemote<blink::mojom::RendererAudioInputStreamFactoryClient>
 | |
|       client;
 | |
|   mojo::MakeSelfOwnedReceiver(
 | |
|       std::make_unique<StreamCreatedCallbackAdapter>(callback),
 | |
|       client.InitWithNewPipeAndPassReceiver());
 | |
|   // Deletion of factory_.core() is posted to the IO thread when |factory_| is
 | |
|   // destroyed, so Unretained is safe below.
 | |
|   if (loopback_source) {
 | |
|     content::GetIOThreadTaskRunner({})->PostTask(
 | |
|         FROM_HERE,
 | |
|         base::BindOnce(&CreateLoopbackStreamHelper, factory_.core(),
 | |
|                        static_cast<content::WebContentsImpl*>(loopback_source)
 | |
|                            ->GetAudioStreamFactory()
 | |
|                            ->core(),
 | |
|                        params, total_segments, std::move(client)));
 | |
|     return;
 | |
|   }
 | |
|   // A null |frame_of_source_web_contents| requests system-wide loopback.
 | |
|   content::GetIOThreadTaskRunner({})->PostTask(
 | |
|       FROM_HERE,
 | |
|       base::BindOnce(&CreateSystemWideLoopbackStreamHelper, factory_.core(),
 | |
|                      params, total_segments, std::move(client)));
 | |
| }
 |