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 {
CreateOutputStreamCallback created_callback) override {}
void BindMuter(mojom::LocalMuterAssociatedRequest request,
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_;
};
......
......@@ -81,6 +81,15 @@ class FakeStreamFactory : public audio::mojom::StreamFactory {
void(mojom::LocalMuterAssociatedRequest request,
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) {
binding_.Bind(audio::mojom::StreamFactoryRequest(std::move(handle)));
}
......
......@@ -71,4 +71,17 @@ interface StreamFactory {
// is the reason for the associated request argument.)
BindMuter(associated LocalMuter& request,
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 @@
#include "base/unguessable_token.h"
#include "services/audio/input_stream.h"
#include "services/audio/local_muter.h"
#include "services/audio/loopback_stream.h"
#include "services/audio/output_stream.h"
#include "services/audio/user_input_monitor.h"
#include "services/service_manager/public/cpp/service_context_ref.h"
......@@ -101,6 +102,26 @@ void StreamFactory::BindMuter(mojom::LocalMuterAssociatedRequest 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) {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
size_t erased = input_streams_.erase(stream);
......@@ -123,4 +144,15 @@ void StreamFactory::DestroyMuter(LocalMuter* muter) {
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
......@@ -37,6 +37,7 @@ namespace audio {
class InputStream;
class LocalMuter;
class LoopbackStream;
class OutputStream;
// This class is used to provide the StreamFactory interface. It will typically
......@@ -62,7 +63,6 @@ class StreamFactory final : public mojom::StreamFactory {
bool enable_agc,
mojo::ScopedSharedBufferHandle key_press_count_buffer,
CreateInputStreamCallback created_callback) final;
void CreateOutputStream(
media::mojom::AudioOutputStreamRequest stream_request,
media::mojom::AudioOutputStreamObserverAssociatedPtrInfo observer_info,
......@@ -73,6 +73,14 @@ class StreamFactory final : public mojom::StreamFactory {
CreateOutputStreamCallback created_callback) final;
void BindMuter(mojom::LocalMuterAssociatedRequest request,
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:
using InputStreamSet =
......@@ -83,6 +91,7 @@ class StreamFactory final : public mojom::StreamFactory {
void DestroyInputStream(InputStream* stream);
void DestroyOutputStream(OutputStream* stream);
void DestroyMuter(LocalMuter* muter);
void DestroyLoopbackStream(LoopbackStream* stream);
SEQUENCE_CHECKER(owning_sequence_);
......@@ -95,6 +104,7 @@ class StreamFactory final : public mojom::StreamFactory {
// Order of the following members is important for a clean shutdown.
GroupCoordinator coordinator_;
std::vector<std::unique_ptr<LocalMuter>> muters_;
std::vector<std::unique_ptr<LoopbackStream>> loopback_streams_;
InputStreamSet input_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