blob: 8fc542ad3c5f53a2a0722bdd0f2d1d86b1b13108 [file] [log] [blame]
// Copyright 2018 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cobalt/media_stream/media_stream_audio_track.h"
#include "base/bind_helpers.h"
#include "cobalt/dom/testing/stub_environment_settings.h"
#include "cobalt/media/base/shell_audio_bus.h"
#include "cobalt/media_stream/media_stream_audio_deliverer.h"
#include "cobalt/media_stream/testing/mock_media_stream_audio_sink.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::_;
using ::testing::StrictMock;
namespace {
const int kFrameCount = 20;
const int kChannelCount = 1;
const int kSampleRate = 1000;
const int kBitsPerSample = 8;
} // namespace
namespace cobalt {
namespace media_stream {
typedef media::ShellAudioBus ShellAudioBus;
// This fixture is created, so it can be added as a friend to
// |MediaStreamAudioTrack|. This enables calling a private method
// called|Start()| on the track, without instantiating an audio source.
class MediaStreamAudioTrackTest : public testing::Test {
public:
MediaStreamAudioTrackTest() = default;
protected:
dom::testing::StubEnvironmentSettings environment_settings_;
};
TEST_F(MediaStreamAudioTrackTest, OnSetFormatAndData) {
media_stream::AudioParameters expected_params(kChannelCount, kSampleRate,
kBitsPerSample);
base::TimeTicks expected_time = base::TimeTicks::Now();
StrictMock<MockMediaStreamAudioSink> mock_sink;
::testing::InSequence seq;
EXPECT_CALL(mock_sink, OnSetFormat(expected_params));
EXPECT_CALL(mock_sink, OnData(_, expected_time));
EXPECT_CALL(mock_sink, OnReadyStateChanged(
MediaStreamTrack::ReadyState::kReadyStateEnded));
scoped_refptr<MediaStreamAudioTrack> track =
new MediaStreamAudioTrack(&environment_settings_);
track->Start(base::Closure(base::Bind([]() {} /*Do nothing*/)));
track->AddSink(&mock_sink);
MediaStreamAudioDeliverer<MediaStreamAudioTrack> deliverer;
deliverer.AddConsumer(track);
deliverer.OnSetFormat(expected_params);
ShellAudioBus audio_bus(kChannelCount, kFrameCount, ShellAudioBus::kInt16,
ShellAudioBus::kInterleaved);
deliverer.OnData(audio_bus, expected_time);
}
TEST_F(MediaStreamAudioTrackTest, OneTrackMultipleSinks) {
media_stream::AudioParameters expected_params(kChannelCount, kSampleRate,
kBitsPerSample);
base::TimeTicks expected_time = base::TimeTicks::Now();
StrictMock<MockMediaStreamAudioSink> mock_sink1;
EXPECT_CALL(mock_sink1, OnSetFormat(expected_params));
EXPECT_CALL(mock_sink1, OnData(_, expected_time));
EXPECT_CALL(mock_sink1, OnReadyStateChanged(
MediaStreamTrack::ReadyState::kReadyStateEnded));
StrictMock<MockMediaStreamAudioSink> mock_sink2;
EXPECT_CALL(mock_sink2, OnSetFormat(expected_params));
EXPECT_CALL(mock_sink2, OnData(_, expected_time));
EXPECT_CALL(mock_sink2, OnReadyStateChanged(
MediaStreamTrack::ReadyState::kReadyStateEnded));
scoped_refptr<MediaStreamAudioTrack> track =
new MediaStreamAudioTrack(&environment_settings_);
track->Start(base::Closure(base::Bind([]() {} /*Do nothing*/)));
track->AddSink(&mock_sink1);
track->AddSink(&mock_sink2);
MediaStreamAudioDeliverer<MediaStreamAudioTrack> deliverer;
deliverer.AddConsumer(track);
deliverer.OnSetFormat(expected_params);
ShellAudioBus audio_bus(kChannelCount, kFrameCount, ShellAudioBus::kInt16,
ShellAudioBus::kInterleaved);
deliverer.OnData(audio_bus, expected_time);
}
TEST_F(MediaStreamAudioTrackTest, TwoTracksWithOneSinkEach) {
media_stream::AudioParameters expected_params(kChannelCount, kSampleRate,
kBitsPerSample);
base::TimeTicks expected_time = base::TimeTicks::Now();
StrictMock<MockMediaStreamAudioSink> mock_sink1;
EXPECT_CALL(mock_sink1, OnSetFormat(expected_params));
EXPECT_CALL(mock_sink1, OnData(_, expected_time));
EXPECT_CALL(mock_sink1, OnReadyStateChanged(
MediaStreamTrack::ReadyState::kReadyStateEnded));
StrictMock<MockMediaStreamAudioSink> mock_sink2;
EXPECT_CALL(mock_sink2, OnSetFormat(expected_params));
EXPECT_CALL(mock_sink2, OnData(_, expected_time));
EXPECT_CALL(mock_sink2, OnReadyStateChanged(
MediaStreamTrack::ReadyState::kReadyStateEnded));
scoped_refptr<MediaStreamAudioTrack> track1 =
new MediaStreamAudioTrack(&environment_settings_);
scoped_refptr<MediaStreamAudioTrack> track2 =
new MediaStreamAudioTrack(&environment_settings_);
track1->Start(base::Closure(base::Bind([]() {} /*Do nothing*/)));
track2->Start(base::Closure(base::Bind([]() {} /*Do nothing*/)));
track1->AddSink(&mock_sink1);
track2->AddSink(&mock_sink2);
MediaStreamAudioDeliverer<MediaStreamAudioTrack> deliverer;
deliverer.AddConsumer(track1);
deliverer.AddConsumer(track2);
deliverer.OnSetFormat(expected_params);
ShellAudioBus audio_bus(kChannelCount, kFrameCount, ShellAudioBus::kInt16,
ShellAudioBus::kInterleaved);
deliverer.OnData(audio_bus, expected_time);
}
TEST_F(MediaStreamAudioTrackTest, AddRemoveSink) {
media_stream::AudioParameters expected_params(kChannelCount, kSampleRate,
kBitsPerSample);
base::TimeTicks expected_time = base::TimeTicks::Now();
// This never receives any data because the sink is removed before the data
// is delivered.
StrictMock<MockMediaStreamAudioSink> mock_sink;
scoped_refptr<MediaStreamAudioTrack> track =
new MediaStreamAudioTrack(&environment_settings_);
track->Start(base::Closure(base::Bind([]() {} /*Do nothing*/)));
track->AddSink(&mock_sink);
MediaStreamAudioDeliverer<MediaStreamAudioTrack> deliverer;
deliverer.AddConsumer(track);
deliverer.OnSetFormat(expected_params);
ShellAudioBus audio_bus(kChannelCount, kFrameCount, ShellAudioBus::kInt16,
ShellAudioBus::kInterleaved);
track->RemoveSink(&mock_sink);
deliverer.OnData(audio_bus, expected_time);
}
TEST_F(MediaStreamAudioTrackTest, Stop) {
StrictMock<MockMediaStreamAudioSink> mock_sink;
scoped_refptr<MediaStreamAudioTrack> track =
new MediaStreamAudioTrack(&environment_settings_);
track->Start(base::Closure(base::Bind([]() {} /*Do nothing*/)));
track->AddSink(&mock_sink);
MediaStreamAudioDeliverer<MediaStreamAudioTrack> deliverer;
deliverer.AddConsumer(track);
EXPECT_CALL(mock_sink, OnReadyStateChanged(
MediaStreamTrack::ReadyState::kReadyStateEnded));
// This should call |OnReadyStateChanged| with |ReadyState::kReadyStateEnded|,
// and |OnReadyStateChanged| should NOT be called when track gets destroyed,
// since the track is already stopped.
track->Stop();
EXPECT_CALL(mock_sink, OnReadyStateChanged(_)).Times(0);
}
TEST_F(MediaStreamAudioTrackTest, ReadyStateEndedNotifyIfAlreadyStopped) {
scoped_refptr<MediaStreamAudioTrack> track =
new MediaStreamAudioTrack(&environment_settings_);
track->Start(base::Closure(base::Bind([]() {} /*Do nothing*/)));
track->Stop();
StrictMock<MockMediaStreamAudioSink> mock_sink;
EXPECT_CALL(mock_sink, OnReadyStateChanged(
MediaStreamTrack::ReadyState::kReadyStateEnded));
track->AddSink(&mock_sink);
}
TEST_F(MediaStreamAudioTrackTest, ReadyStateEndedNotifyIfNeverStarted) {
scoped_refptr<MediaStreamAudioTrack> track =
new MediaStreamAudioTrack(&environment_settings_);
StrictMock<MockMediaStreamAudioSink> mock_sink;
EXPECT_CALL(mock_sink, OnReadyStateChanged(
MediaStreamTrack::ReadyState::kReadyStateEnded));
track->AddSink(&mock_sink);
}
} // namespace media_stream
} // namespace cobalt