blob: 76f0caebe61093e89e68bb52da7a96a1f7c0643a [file] [log] [blame]
// Copyright 2017 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 "content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.h"
#include <limits>
#include <utility>
#include "base/bind.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/optional.h"
#include "base/run_loop.h"
#include "base/sync_socket.h"
#include "content/browser/renderer_host/media/audio_input_device_manager.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/common/media/renderer_audio_input_stream_factory.mojom.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "media/audio/audio_system_impl.h"
#include "media/audio/mock_audio_manager.h"
#include "media/audio/test_audio_thread.h"
#include "media/base/audio_parameters.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
namespace {
using testing::Test;
const size_t kShmemSize = 1234;
const int kSessionId = 234;
const bool kAGC = false;
const uint32_t kSharedMemoryCount = 345;
const int kSampleFrequency = 44100;
const int kSamplesPerBuffer = kSampleFrequency / 100;
const bool kInitiallyMuted = false;
const int kRenderProcessID = -1;
const int kRenderFrameID = MSG_ROUTING_NONE;
media::AudioParameters GetTestAudioParameters() {
return media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::CHANNEL_LAYOUT_MONO, kSampleFrequency,
kSamplesPerBuffer);
}
class FakeAudioInputDelegate : public media::AudioInputDelegate {
public:
FakeAudioInputDelegate() {}
~FakeAudioInputDelegate() override {}
int GetStreamId() override { return 0; };
void OnRecordStream() override{};
void OnSetVolume(double volume) override{};
void OnSetOutputDeviceForAec(const std::string& output_device_id) override {}
private:
DISALLOW_COPY_AND_ASSIGN(FakeAudioInputDelegate);
};
class FakeAudioInputStreamClient : public media::mojom::AudioInputStreamClient {
public:
void OnMutedStateChanged(bool is_muted) override {}
void OnError() override {}
};
class MockRendererAudioInputStreamFactoryClient
: public mojom::RendererAudioInputStreamFactoryClient {
public:
MOCK_METHOD0(Created, void());
void StreamCreated(
media::mojom::AudioInputStreamPtr input_stream,
media::mojom::AudioInputStreamClientRequest client_request,
media::mojom::ReadOnlyAudioDataPipePtr data_pipe,
bool initially_muted,
const base::Optional<base::UnguessableToken>& stream_id) override {
EXPECT_TRUE(stream_id.has_value());
Created();
}
};
// Creates a fake delegate and saves the provided event handler in
// |event_handler_out|.
std::unique_ptr<media::AudioInputDelegate> CreateFakeDelegate(
media::AudioInputDelegate::EventHandler** event_handler_out,
AudioInputDeviceManager* audio_input_device_manager,
media::mojom::AudioLogPtr audio_log,
AudioInputDeviceManager::KeyboardMicRegistration keyboard_mic_registration,
uint32_t shared_memory_count,
int stream_id,
int session_id,
bool automatic_gain_control,
const media::AudioParameters& parameters,
media::AudioInputDelegate::EventHandler* event_handler) {
*event_handler_out = event_handler;
return std::make_unique<FakeAudioInputDelegate>();
}
} // namespace
class OldOldRenderFrameAudioInputStreamFactoryTest : public testing::Test {
public:
OldOldRenderFrameAudioInputStreamFactoryTest()
: thread_bundle_(base::in_place),
audio_manager_(std::make_unique<media::TestAudioThread>()),
audio_system_(&audio_manager_),
media_stream_manager_(&audio_system_, audio_manager_.GetTaskRunner()),
client_binding_(&client_, mojo::MakeRequest(&client_ptr_)),
factory_handle_(RenderFrameAudioInputStreamFactoryHandle::CreateFactory(
base::BindRepeating(&CreateFakeDelegate, &event_handler_),
&media_stream_manager_,
kRenderProcessID,
kRenderFrameID,
mojo::MakeRequest(&factory_ptr_))) {}
~OldOldRenderFrameAudioInputStreamFactoryTest() override {
audio_manager_.Shutdown();
// UniqueAudioInputStreamFactoryPtr uses DeleteOnIOThread and must run
// before |thread_bundle_| tear down.
factory_handle_.reset();
// Shutdown BrowserThread::IO before tearing down members.
thread_bundle_.reset();
}
// |thread_bundle_| needs to be up before the members below (as they use
// BrowserThreads for their initialization) but then needs to be torn down
// before them as some verify they're town down in a single-threaded
// environment (while
// !BrowserThread::IsThreadInitiaslized(BrowserThread::IO)).
base::Optional<TestBrowserThreadBundle> thread_bundle_;
// These members need to be torn down after |thread_bundle_|.
media::MockAudioManager audio_manager_;
media::AudioSystemImpl audio_system_;
MediaStreamManager media_stream_manager_;
mojom::RendererAudioInputStreamFactoryPtr factory_ptr_;
media::mojom::AudioInputStreamPtr stream_ptr_;
MockRendererAudioInputStreamFactoryClient client_;
mojom::RendererAudioInputStreamFactoryClientPtr client_ptr_;
media::AudioInputDelegate::EventHandler* event_handler_ = nullptr;
mojo::Binding<mojom::RendererAudioInputStreamFactoryClient> client_binding_;
UniqueAudioInputStreamFactoryPtr factory_handle_;
};
TEST_F(OldOldRenderFrameAudioInputStreamFactoryTest, CreateStream) {
factory_ptr_->CreateStream(std::move(client_ptr_), kSessionId,
GetTestAudioParameters(), kAGC, kSharedMemoryCount,
nullptr);
// Wait for delegate to be created and |event_handler| set.
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(event_handler_);
auto shared_memory = base::ReadOnlySharedMemoryRegion::Create(kShmemSize);
auto local = std::make_unique<base::CancelableSyncSocket>();
auto remote = std::make_unique<base::CancelableSyncSocket>();
ASSERT_TRUE(
base::CancelableSyncSocket::CreatePair(local.get(), remote.get()));
event_handler_->OnStreamCreated(/*stream_id, irrelevant*/ 0,
std::move(shared_memory.region),
std::move(remote), kInitiallyMuted);
EXPECT_CALL(client_, Created());
base::RunLoop().RunUntilIdle();
}
} // namespace content