Commit 79723068 authored by Yuri Wiitala's avatar Yuri Wiitala Committed by Commit Bot

Add audio::StreamFactory::CreateLoopbackStream() API.

Adds the mojom declaration and its corresponding audio::StreamFactory
implementation, allowing clients of the Audio Service to create loopback
streams. Loopback streams are virtualized audio input streams. They
collect the audio from one or more audio output streams, and mix it
together into a single input stream. An example use case is tab capture.

Bug: 824019
Change-Id: I10256b516f7e19f6e312aec7fd33dc737df095fa
Reviewed-on: https://chromium-review.googlesource.com/1041662
Commit-Queue: Yuri Wiitala <miu@chromium.org>
Reviewed-by: default avatarYuri Wiitala <miu@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarOlga Sharonova <olka@chromium.org>
Reviewed-by: default avatarMax Morin <maxmorin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#558061}
parent 126956bd
...@@ -46,6 +46,14 @@ class FakeStreamFactory : public mojom::StreamFactory { ...@@ -46,6 +46,14 @@ class FakeStreamFactory : public mojom::StreamFactory {
CreateOutputStreamCallback created_callback) override {} CreateOutputStreamCallback created_callback) override {}
void BindMuter(mojom::LocalMuterAssociatedRequest request, void BindMuter(mojom::LocalMuterAssociatedRequest request,
const base::UnguessableToken& group_id) override {} const base::UnguessableToken& group_id) override {}
void CreateLoopbackStream(
media::mojom::AudioInputStreamRequest stream_request,
media::mojom::AudioInputStreamClientPtr client,
media::mojom::AudioInputStreamObserverPtr observer,
const media::AudioParameters& params,
uint32_t shared_memory_count,
const base::UnguessableToken& group_id,
CreateLoopbackStreamCallback created_callback) override {}
mojo::Binding<mojom::StreamFactory> binding_; mojo::Binding<mojom::StreamFactory> binding_;
}; };
......
...@@ -81,6 +81,15 @@ class FakeStreamFactory : public audio::mojom::StreamFactory { ...@@ -81,6 +81,15 @@ class FakeStreamFactory : public audio::mojom::StreamFactory {
void(mojom::LocalMuterAssociatedRequest request, void(mojom::LocalMuterAssociatedRequest request,
const base::UnguessableToken& group_id)); const base::UnguessableToken& group_id));
MOCK_METHOD7(CreateLoopbackStream,
void(media::mojom::AudioInputStreamRequest stream_request,
media::mojom::AudioInputStreamClientPtr client,
media::mojom::AudioInputStreamObserverPtr observer,
const media::AudioParameters& params,
uint32_t shared_memory_count,
const base::UnguessableToken& group_id,
CreateLoopbackStreamCallback created_callback));
void Bind(mojo::ScopedMessagePipeHandle handle) { void Bind(mojo::ScopedMessagePipeHandle handle) {
binding_.Bind(audio::mojom::StreamFactoryRequest(std::move(handle))); binding_.Bind(audio::mojom::StreamFactoryRequest(std::move(handle)));
} }
......
...@@ -71,4 +71,17 @@ interface StreamFactory { ...@@ -71,4 +71,17 @@ interface StreamFactory {
// is the reason for the associated request argument.) // is the reason for the associated request argument.)
BindMuter(associated LocalMuter& request, BindMuter(associated LocalMuter& request,
mojo_base.mojom.UnguessableToken group_id); mojo_base.mojom.UnguessableToken group_id);
// Creates an AudioInputStream that provides the result of looping-back and
// mixing-together all current and future AudioOutputStreams tagged with the
// given |group_id|. The loopback re-mixes audio, if necessary, so that the
// resulting data stream format matches the specified |params|. All other args
// and the result are as described in CreateInputStream() above.
CreateLoopbackStream(media.mojom.AudioInputStream& stream,
media.mojom.AudioInputStreamClient client,
media.mojom.AudioInputStreamObserver observer,
media.mojom.AudioParameters params,
uint32 shared_memory_count,
mojo_base.mojom.UnguessableToken group_id)
=> (media.mojom.AudioDataPipe? data_pipe);
}; };
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "base/unguessable_token.h" #include "base/unguessable_token.h"
#include "services/audio/input_stream.h" #include "services/audio/input_stream.h"
#include "services/audio/local_muter.h" #include "services/audio/local_muter.h"
#include "services/audio/loopback_stream.h"
#include "services/audio/output_stream.h" #include "services/audio/output_stream.h"
#include "services/audio/user_input_monitor.h" #include "services/audio/user_input_monitor.h"
#include "services/service_manager/public/cpp/service_context_ref.h" #include "services/service_manager/public/cpp/service_context_ref.h"
...@@ -101,6 +102,26 @@ void StreamFactory::BindMuter(mojom::LocalMuterAssociatedRequest request, ...@@ -101,6 +102,26 @@ void StreamFactory::BindMuter(mojom::LocalMuterAssociatedRequest request,
muter->AddBinding(std::move(request)); muter->AddBinding(std::move(request));
} }
void StreamFactory::CreateLoopbackStream(
media::mojom::AudioInputStreamRequest request,
media::mojom::AudioInputStreamClientPtr client,
media::mojom::AudioInputStreamObserverPtr observer,
const media::AudioParameters& params,
uint32_t shared_memory_count,
const base::UnguessableToken& group_id,
CreateLoopbackStreamCallback created_callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
auto stream = std::make_unique<LoopbackStream>(
std::move(created_callback),
base::BindOnce(&StreamFactory::DestroyLoopbackStream,
base::Unretained(this)),
audio_manager_->GetWorkerTaskRunner(), std::move(request),
std::move(client), std::move(observer), params, shared_memory_count,
&coordinator_, group_id);
loopback_streams_.emplace_back(std::move(stream));
}
void StreamFactory::DestroyInputStream(InputStream* stream) { void StreamFactory::DestroyInputStream(InputStream* stream) {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_); DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
size_t erased = input_streams_.erase(stream); size_t erased = input_streams_.erase(stream);
...@@ -123,4 +144,15 @@ void StreamFactory::DestroyMuter(LocalMuter* muter) { ...@@ -123,4 +144,15 @@ void StreamFactory::DestroyMuter(LocalMuter* muter) {
muters_.erase(it); muters_.erase(it);
} }
void StreamFactory::DestroyLoopbackStream(LoopbackStream* stream) {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
DCHECK(stream);
const auto it =
std::find_if(loopback_streams_.begin(), loopback_streams_.end(),
base::MatchesUniquePtr(stream));
DCHECK(it != loopback_streams_.end());
loopback_streams_.erase(it);
}
} // namespace audio } // namespace audio
...@@ -37,6 +37,7 @@ namespace audio { ...@@ -37,6 +37,7 @@ namespace audio {
class InputStream; class InputStream;
class LocalMuter; class LocalMuter;
class LoopbackStream;
class OutputStream; class OutputStream;
// This class is used to provide the StreamFactory interface. It will typically // This class is used to provide the StreamFactory interface. It will typically
...@@ -62,7 +63,6 @@ class StreamFactory final : public mojom::StreamFactory { ...@@ -62,7 +63,6 @@ class StreamFactory final : public mojom::StreamFactory {
bool enable_agc, bool enable_agc,
mojo::ScopedSharedBufferHandle key_press_count_buffer, mojo::ScopedSharedBufferHandle key_press_count_buffer,
CreateInputStreamCallback created_callback) final; CreateInputStreamCallback created_callback) final;
void CreateOutputStream( void CreateOutputStream(
media::mojom::AudioOutputStreamRequest stream_request, media::mojom::AudioOutputStreamRequest stream_request,
media::mojom::AudioOutputStreamObserverAssociatedPtrInfo observer_info, media::mojom::AudioOutputStreamObserverAssociatedPtrInfo observer_info,
...@@ -73,6 +73,14 @@ class StreamFactory final : public mojom::StreamFactory { ...@@ -73,6 +73,14 @@ class StreamFactory final : public mojom::StreamFactory {
CreateOutputStreamCallback created_callback) final; CreateOutputStreamCallback created_callback) final;
void BindMuter(mojom::LocalMuterAssociatedRequest request, void BindMuter(mojom::LocalMuterAssociatedRequest request,
const base::UnguessableToken& group_id) final; const base::UnguessableToken& group_id) final;
void CreateLoopbackStream(
media::mojom::AudioInputStreamRequest stream_request,
media::mojom::AudioInputStreamClientPtr client,
media::mojom::AudioInputStreamObserverPtr observer,
const media::AudioParameters& params,
uint32_t shared_memory_count,
const base::UnguessableToken& group_id,
CreateLoopbackStreamCallback created_callback) final;
private: private:
using InputStreamSet = using InputStreamSet =
...@@ -83,6 +91,7 @@ class StreamFactory final : public mojom::StreamFactory { ...@@ -83,6 +91,7 @@ class StreamFactory final : public mojom::StreamFactory {
void DestroyInputStream(InputStream* stream); void DestroyInputStream(InputStream* stream);
void DestroyOutputStream(OutputStream* stream); void DestroyOutputStream(OutputStream* stream);
void DestroyMuter(LocalMuter* muter); void DestroyMuter(LocalMuter* muter);
void DestroyLoopbackStream(LoopbackStream* stream);
SEQUENCE_CHECKER(owning_sequence_); SEQUENCE_CHECKER(owning_sequence_);
...@@ -95,6 +104,7 @@ class StreamFactory final : public mojom::StreamFactory { ...@@ -95,6 +104,7 @@ class StreamFactory final : public mojom::StreamFactory {
// Order of the following members is important for a clean shutdown. // Order of the following members is important for a clean shutdown.
GroupCoordinator coordinator_; GroupCoordinator coordinator_;
std::vector<std::unique_ptr<LocalMuter>> muters_; std::vector<std::unique_ptr<LocalMuter>> muters_;
std::vector<std::unique_ptr<LoopbackStream>> loopback_streams_;
InputStreamSet input_streams_; InputStreamSet input_streams_;
OutputStreamSet output_streams_; OutputStreamSet output_streams_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment