Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2137)

Unified Diff: content/renderer/media/media_stream_audio_unittest.cc

Issue 1966043006: Revert of MediaStream audio: Refactor 3 separate "glue" implementations into one. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/renderer/media/media_stream_audio_unittest.cc
diff --git a/content/renderer/media/media_stream_audio_unittest.cc b/content/renderer/media/media_stream_audio_unittest.cc
deleted file mode 100644
index 060dca37b0706d0276decba38199d7792efaf851..0000000000000000000000000000000000000000
--- a/content/renderer/media/media_stream_audio_unittest.cc
+++ /dev/null
@@ -1,450 +0,0 @@
-// Copyright 2016 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 <stdint.h>
-
-#include "base/atomicops.h"
-#include "base/synchronization/lock.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/test/test_timeouts.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/thread_checker.h"
-#include "content/public/renderer/media_stream_audio_sink.h"
-#include "content/renderer/media/media_stream_audio_source.h"
-#include "content/renderer/media/media_stream_audio_track.h"
-#include "media/base/audio_bus.h"
-#include "media/base/audio_parameters.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/web/WebHeap.h"
-
-namespace content {
-
-namespace {
-
-constexpr int kSampleRate = 8000;
-constexpr int kBufferSize = kSampleRate / 100;
-
-// The maximum integer that can be exactly represented by the float data type.
-constexpr int kMaxValueSafelyConvertableToFloat = 1 << 24;
-
-// A simple MediaStreamAudioSource that spawns a real-time audio thread and
-// emits audio samples with monotonically-increasing sample values. Includes
-// hooks for the unit tests to confirm lifecycle status and to change audio
-// format.
-class FakeMediaStreamAudioSource
- : public MediaStreamAudioSource,
- public base::PlatformThread::Delegate {
- public:
- FakeMediaStreamAudioSource()
- : MediaStreamAudioSource(true), stop_event_(true, false),
- next_buffer_size_(kBufferSize), sample_count_(0) {}
-
- ~FakeMediaStreamAudioSource() final {
- CHECK(main_thread_checker_.CalledOnValidThread());
- EnsureSourceIsStopped();
- }
-
- bool was_started() const {
- CHECK(main_thread_checker_.CalledOnValidThread());
- return !thread_.is_null();
- }
-
- bool was_stopped() const {
- CHECK(main_thread_checker_.CalledOnValidThread());
- return stop_event_.IsSignaled();
- }
-
- void SetBufferSize(int new_buffer_size) {
- CHECK(main_thread_checker_.CalledOnValidThread());
- base::subtle::NoBarrier_Store(&next_buffer_size_, new_buffer_size);
- }
-
- protected:
- bool EnsureSourceIsStarted() final {
- CHECK(main_thread_checker_.CalledOnValidThread());
- if (was_started())
- return true;
- if (was_stopped())
- return false;
- base::PlatformThread::CreateWithPriority(
- 0, this, &thread_, base::ThreadPriority::REALTIME_AUDIO);
- return true;
- }
-
- void EnsureSourceIsStopped() final {
- CHECK(main_thread_checker_.CalledOnValidThread());
- if (was_stopped())
- return;
- stop_event_.Signal();
- if (was_started())
- base::PlatformThread::Join(thread_);
- }
-
- void ThreadMain() override {
- while (!stop_event_.IsSignaled()) {
- // If needed, notify of the new format and re-create |audio_bus_|.
- const int buffer_size = base::subtle::NoBarrier_Load(&next_buffer_size_);
- if (!audio_bus_ || audio_bus_->frames() != buffer_size) {
- MediaStreamAudioSource::SetFormat(media::AudioParameters(
- media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_MONO, kSampleRate, 16, buffer_size));
- audio_bus_ = media::AudioBus::Create(1, buffer_size);
- }
-
- // Deliver the next chunk of audio data. Each sample value is its offset
- // from the very first sample.
- float* const data = audio_bus_->channel(0);
- for (int i = 0; i < buffer_size; ++i)
- data[i] = ++sample_count_;
- CHECK_LT(sample_count_, kMaxValueSafelyConvertableToFloat);
- MediaStreamAudioSource::DeliverDataToTracks(*audio_bus_,
- base::TimeTicks::Now());
-
- // Sleep before producing the next chunk of audio.
- base::PlatformThread::Sleep(base::TimeDelta::FromMicroseconds(
- base::Time::kMicrosecondsPerSecond * buffer_size / kSampleRate));
- }
- }
-
- private:
- base::ThreadChecker main_thread_checker_;
-
- base::PlatformThreadHandle thread_;
- mutable base::WaitableEvent stop_event_;
-
- base::subtle::Atomic32 next_buffer_size_;
- std::unique_ptr<media::AudioBus> audio_bus_;
- int sample_count_;
-
- DISALLOW_COPY_AND_ASSIGN(FakeMediaStreamAudioSource);
-};
-
-// A simple MediaStreamAudioSink that consumes audio and confirms the sample
-// values. Includes hooks for the unit tests to monitor the format and flow of
-// audio, whether the audio is silent, and the propagation of the "enabled"
-// state.
-class FakeMediaStreamAudioSink : public MediaStreamAudioSink {
- public:
- enum EnableState {
- NO_ENABLE_NOTIFICATION,
- WAS_ENABLED,
- WAS_DISABLED
- };
-
- FakeMediaStreamAudioSink()
- : MediaStreamAudioSink(), expected_sample_count_(-1),
- num_on_data_calls_(0), audio_is_silent_(true), was_ended_(false),
- enable_state_(NO_ENABLE_NOTIFICATION) {}
-
- ~FakeMediaStreamAudioSink() final {
- CHECK(main_thread_checker_.CalledOnValidThread());
- }
-
- media::AudioParameters params() const {
- CHECK(main_thread_checker_.CalledOnValidThread());
- base::AutoLock auto_lock(params_lock_);
- return params_;
- }
-
- int num_on_data_calls() const {
- CHECK(main_thread_checker_.CalledOnValidThread());
- return base::subtle::NoBarrier_Load(&num_on_data_calls_);
- }
-
- bool is_audio_silent() const {
- CHECK(main_thread_checker_.CalledOnValidThread());
- return !!base::subtle::NoBarrier_Load(&audio_is_silent_);
- }
-
- bool was_ended() const {
- CHECK(main_thread_checker_.CalledOnValidThread());
- return was_ended_;
- }
-
- EnableState enable_state() const {
- CHECK(main_thread_checker_.CalledOnValidThread());
- return enable_state_;
- }
-
- void OnSetFormat(const media::AudioParameters& params) final {
- ASSERT_TRUE(params.IsValid());
- base::AutoLock auto_lock(params_lock_);
- params_ = params;
- }
-
- void OnData(const media::AudioBus& audio_bus,
- base::TimeTicks estimated_capture_time) final {
- ASSERT_TRUE(params_.IsValid());
- ASSERT_FALSE(was_ended_);
-
- ASSERT_EQ(params_.channels(), audio_bus.channels());
- ASSERT_EQ(params_.frames_per_buffer(), audio_bus.frames());
- if (audio_bus.AreFramesZero()) {
- base::subtle::NoBarrier_Store(&audio_is_silent_, 1);
- expected_sample_count_ = -1; // Reset for when audio comes back.
- } else {
- base::subtle::NoBarrier_Store(&audio_is_silent_, 0);
- const float* const data = audio_bus.channel(0);
- if (expected_sample_count_ == -1)
- expected_sample_count_ = static_cast<int64_t>(data[0]);
- CHECK_LE(expected_sample_count_ + audio_bus.frames(),
- kMaxValueSafelyConvertableToFloat);
- for (int i = 0; i < audio_bus.frames(); ++i) {
- const float expected_sample_value = expected_sample_count_;
- ASSERT_EQ(expected_sample_value, data[i]);
- ++expected_sample_count_;
- }
- }
-
- ASSERT_TRUE(!estimated_capture_time.is_null());
- ASSERT_LT(last_estimated_capture_time_, estimated_capture_time);
- last_estimated_capture_time_ = estimated_capture_time;
-
- base::subtle::NoBarrier_AtomicIncrement(&num_on_data_calls_, 1);
- }
-
- void OnReadyStateChanged(
- blink::WebMediaStreamSource::ReadyState state) final {
- CHECK(main_thread_checker_.CalledOnValidThread());
- if (state == blink::WebMediaStreamSource::ReadyStateEnded)
- was_ended_ = true;
- }
-
- void OnEnabledChanged(bool enabled) final {
- CHECK(main_thread_checker_.CalledOnValidThread());
- enable_state_ = enabled ? WAS_ENABLED : WAS_DISABLED;
- }
-
- private:
- base::ThreadChecker main_thread_checker_;
-
- mutable base::Lock params_lock_;
- media::AudioParameters params_;
- int expected_sample_count_;
- base::TimeTicks last_estimated_capture_time_;
- base::subtle::Atomic32 num_on_data_calls_;
- base::subtle::Atomic32 audio_is_silent_;
- bool was_ended_;
- EnableState enable_state_;
-
- DISALLOW_COPY_AND_ASSIGN(FakeMediaStreamAudioSink);
-};
-
-} // namespace
-
-class MediaStreamAudioTest : public ::testing::Test {
- protected:
- void SetUp() override {
- blink_audio_source_.initialize(blink::WebString::fromUTF8("audio_id"),
- blink::WebMediaStreamSource::TypeAudio,
- blink::WebString::fromUTF8("audio_track"),
- false /* remote */);
- blink_audio_track_.initialize(blink_audio_source_.id(),
- blink_audio_source_);
- }
-
- void TearDown() override {
- blink_audio_track_.reset();
- blink_audio_source_.reset();
- blink::WebHeap::collectAllGarbageForTesting();
- }
-
- FakeMediaStreamAudioSource* source() const {
- return static_cast<FakeMediaStreamAudioSource*>(
- MediaStreamAudioSource::From(blink_audio_source_));
- }
-
- MediaStreamAudioTrack* track() const {
- return MediaStreamAudioTrack::From(blink_audio_track_);
- }
-
- blink::WebMediaStreamSource blink_audio_source_;
- blink::WebMediaStreamTrack blink_audio_track_;
-};
-
-// Tests that a simple source-->track-->sink connection and audio data flow
-// works.
-TEST_F(MediaStreamAudioTest, BasicUsage) {
- // Create the source, but it should not be started yet.
- ASSERT_FALSE(source());
- blink_audio_source_.setExtraData(new FakeMediaStreamAudioSource());
- ASSERT_TRUE(source());
- EXPECT_FALSE(source()->was_started());
- EXPECT_FALSE(source()->was_stopped());
-
- // Connect a track to the source. This should auto-start the source.
- ASSERT_FALSE(track());
- EXPECT_TRUE(source()->ConnectToTrack(blink_audio_track_));
- ASSERT_TRUE(track());
- EXPECT_TRUE(source()->was_started());
- EXPECT_FALSE(source()->was_stopped());
-
- // Connect a sink to the track. This should begin audio flow to the
- // sink. Wait and confirm that three OnData() calls were made from the audio
- // thread.
- FakeMediaStreamAudioSink sink;
- EXPECT_FALSE(sink.was_ended());
- track()->AddSink(&sink);
- const int start_count = sink.num_on_data_calls();
- while (sink.num_on_data_calls() - start_count < 3)
- base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
-
- // Check that the audio parameters propagated to the track and sink.
- const media::AudioParameters expected_params(
- media::AudioParameters::AUDIO_PCM_LOW_LATENCY, media::CHANNEL_LAYOUT_MONO,
- kSampleRate, 16, kBufferSize);
- EXPECT_TRUE(expected_params.Equals(track()->GetOutputFormat()));
- EXPECT_TRUE(expected_params.Equals(sink.params()));
-
- // Stop the track. Since this was the last track connected to the source, the
- // source should automatically stop. In addition, the sink should receive a
- // ReadyStateEnded notification.
- track()->Stop();
- EXPECT_TRUE(source()->was_started());
- EXPECT_TRUE(source()->was_stopped());
- EXPECT_TRUE(sink.was_ended());
-
- track()->RemoveSink(&sink);
-}
-
-// Tests that "ended" tracks can be connected after the source has stopped.
-TEST_F(MediaStreamAudioTest, ConnectTrackAfterSourceStopped) {
- // Create the source, connect one track, and stop it. This should
- // automatically stop the source.
- blink_audio_source_.setExtraData(new FakeMediaStreamAudioSource());
- ASSERT_TRUE(source());
- EXPECT_TRUE(source()->ConnectToTrack(blink_audio_track_));
- track()->Stop();
- EXPECT_TRUE(source()->was_started());
- EXPECT_TRUE(source()->was_stopped());
-
- // Now, connect another track. ConnectToTrack() will return false, but there
- // should be a MediaStreamAudioTrack instance created and owned by the
- // blink::WebMediaStreamTrack.
- blink::WebMediaStreamTrack another_blink_track;
- another_blink_track.initialize(blink_audio_source_.id(), blink_audio_source_);
- EXPECT_FALSE(MediaStreamAudioTrack::From(another_blink_track));
- EXPECT_FALSE(source()->ConnectToTrack(another_blink_track));
- EXPECT_TRUE(MediaStreamAudioTrack::From(another_blink_track));
-}
-
-// Tests that a sink is immediately "ended" when connected to a stopped track.
-TEST_F(MediaStreamAudioTest, AddSinkToStoppedTrack) {
- // Create a track and stop it. Then, when adding a sink, the sink should get
- // the ReadyStateEnded notification immediately.
- MediaStreamAudioTrack track(true);
- track.Stop();
- FakeMediaStreamAudioSink sink;
- EXPECT_FALSE(sink.was_ended());
- track.AddSink(&sink);
- EXPECT_TRUE(sink.was_ended());
- EXPECT_EQ(0, sink.num_on_data_calls());
- track.RemoveSink(&sink);
-}
-
-// Tests that audio format changes at the source propagate to the track and
-// sink.
-TEST_F(MediaStreamAudioTest, FormatChangesPropagate) {
- // Create a source, connect it to track, and connect the track to a
- // sink.
- blink_audio_source_.setExtraData(new FakeMediaStreamAudioSource());
- ASSERT_TRUE(source());
- EXPECT_TRUE(source()->ConnectToTrack(blink_audio_track_));
- ASSERT_TRUE(track());
- FakeMediaStreamAudioSink sink;
- ASSERT_TRUE(!sink.params().IsValid());
- track()->AddSink(&sink);
-
- // Wait until valid parameters are propagated to the sink, and then confirm
- // the parameters are correct at the track and the sink.
- while (!sink.params().IsValid())
- base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- const media::AudioParameters expected_params(
- media::AudioParameters::AUDIO_PCM_LOW_LATENCY, media::CHANNEL_LAYOUT_MONO,
- kSampleRate, 16, kBufferSize);
- EXPECT_TRUE(expected_params.Equals(track()->GetOutputFormat()));
- EXPECT_TRUE(expected_params.Equals(sink.params()));
-
- // Now, trigger a format change by doubling the buffer size.
- source()->SetBufferSize(kBufferSize * 2);
-
- // Wait until the new buffer size propagates to the sink.
- while (sink.params().frames_per_buffer() == kBufferSize)
- base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- EXPECT_EQ(kBufferSize * 2, track()->GetOutputFormat().frames_per_buffer());
- EXPECT_EQ(kBufferSize * 2, sink.params().frames_per_buffer());
-
- track()->RemoveSink(&sink);
-}
-
-// Tests that tracks deliver audio when enabled and silent audio when
-// disabled. Whenever a track is enabled or disabled, the sink's
-// OnEnabledChanged() method should be called.
-TEST_F(MediaStreamAudioTest, EnableAndDisableTracks) {
- // Create a source and connect it to track.
- blink_audio_source_.setExtraData(new FakeMediaStreamAudioSource());
- ASSERT_TRUE(source());
- EXPECT_TRUE(source()->ConnectToTrack(blink_audio_track_));
- ASSERT_TRUE(track());
-
- // Connect the track to a sink and expect the sink to be notified that the
- // track is enabled.
- FakeMediaStreamAudioSink sink;
- EXPECT_TRUE(sink.is_audio_silent());
- EXPECT_EQ(FakeMediaStreamAudioSink::NO_ENABLE_NOTIFICATION,
- sink.enable_state());
- track()->AddSink(&sink);
- EXPECT_EQ(FakeMediaStreamAudioSink::WAS_ENABLED, sink.enable_state());
-
- // Wait until non-silent audio reaches the sink.
- while (sink.is_audio_silent())
- base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
-
- // Now, disable the track and expect the sink to be notified.
- track()->SetEnabled(false);
- EXPECT_EQ(FakeMediaStreamAudioSink::WAS_DISABLED, sink.enable_state());
-
- // Wait until silent audio reaches the sink.
- while (!sink.is_audio_silent())
- base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
-
- // Create a second track and a second sink, but this time the track starts out
- // disabled. Expect the sink to be notified at the start that the track is
- // disabled.
- blink::WebMediaStreamTrack another_blink_track;
- another_blink_track.initialize(blink_audio_source_.id(), blink_audio_source_);
- EXPECT_TRUE(source()->ConnectToTrack(another_blink_track));
- MediaStreamAudioTrack::From(another_blink_track)->SetEnabled(false);
- FakeMediaStreamAudioSink another_sink;
- MediaStreamAudioTrack::From(another_blink_track)->AddSink(&another_sink);
- EXPECT_EQ(FakeMediaStreamAudioSink::WAS_DISABLED,
- another_sink.enable_state());
-
- // Wait until OnData() is called on the second sink. Expect the audio to be
- // silent.
- const int start_count = another_sink.num_on_data_calls();
- while (another_sink.num_on_data_calls() == start_count)
- base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- EXPECT_TRUE(another_sink.is_audio_silent());
-
- // Now, enable the second track and expect the second sink to be notified.
- MediaStreamAudioTrack::From(another_blink_track)->SetEnabled(true);
- EXPECT_EQ(FakeMediaStreamAudioSink::WAS_ENABLED, another_sink.enable_state());
-
- // Wait until non-silent audio reaches the second sink.
- while (another_sink.is_audio_silent())
- base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
-
- // The first track and sink should not have been affected by changing the
- // enabled state of the second track and sink. They should still be disabled,
- // with silent audio being consumed at the sink.
- EXPECT_EQ(FakeMediaStreamAudioSink::WAS_DISABLED, sink.enable_state());
- EXPECT_TRUE(sink.is_audio_silent());
-
- MediaStreamAudioTrack::From(another_blink_track)->RemoveSink(&another_sink);
- track()->RemoveSink(&sink);
-}
-
-} // namespace content
« no previous file with comments | « content/renderer/media/media_stream_audio_track_sink.h ('k') | content/renderer/media/media_stream_center.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698