MchPcmMixableStream::~MchPcmMixableStream() {
TIZEN_MEDIA_LOG(INFO);
- Stop();
+ DCHECK_EQ(mixable_stream_, nullptr); // Stream has been closed
}
bool MchPcmMixableStream::Open() {
TIZEN_MEDIA_LOG(INFO);
+ DCHECK_NE(mixable_stream_, nullptr);
+ if (mixable_stream_ == nullptr) {
+ LOG(ERROR) << "Called on Closed stream!";
+ return false;
+ }
return mixable_stream_->Open();
}
void MchPcmMixableStream::Start(AudioSourceCallback* callback) {
TIZEN_MEDIA_LOG(INFO);
+ DCHECK_NE(mixable_stream_, nullptr);
+ if (mixable_stream_ == nullptr) {
+ LOG(ERROR) << "Called on Closed stream!";
+ return;
+ }
+
mixer_manager_->StreamStarted(this);
mixable_stream_->Start(callback);
}
void MchPcmMixableStream::Stop() {
TIZEN_MEDIA_LOG(INFO);
+ DCHECK_NE(mixable_stream_, nullptr);
+ if (mixable_stream_ == nullptr) {
+ LOG(ERROR) << "Called on Closed stream!";
+ return;
+ }
+
mixer_manager_->StreamStopped(this);
mixable_stream_->Stop();
}
void MchPcmMixableStream::SetVolume(double volume) {
TIZEN_MEDIA_LOG(INFO) << "volume: " << volume;
+ DCHECK_NE(mixable_stream_, nullptr);
+ if (mixable_stream_ == nullptr) {
+ LOG(ERROR) << "Called on Closed stream!";
+ return;
+ }
+
mixable_stream_->SetVolume(volume);
}
void MchPcmMixableStream::GetVolume(double* volume) {
TIZEN_MEDIA_LOG(INFO);
+ DCHECK_NE(mixable_stream_, nullptr);
+ if (mixable_stream_ == nullptr) {
+ LOG(ERROR) << "Called on Closed stream!";
+ return;
+ }
+
mixable_stream_->GetVolume(volume);
}
void MchPcmMixableStream::Close() {
TIZEN_MEDIA_LOG(INFO);
+ DCHECK_NE(mixable_stream_, nullptr);
+ if (mixable_stream_ == nullptr) {
+ LOG(ERROR) << "Called on Closed stream!";
+ return;
+ }
+
mixer_manager_->StreamStopped(this);
+
+ // `Close` will delete `mixable_stream_`.
mixable_stream_->Close();
+ mixable_stream_ = nullptr;
// `ReleaseOutputStream` deletes "this", must be last in this method.
if (manager_) {
void MchPcmMixableStream::Flush() {
TIZEN_MEDIA_LOG(INFO);
+ DCHECK_NE(mixable_stream_, nullptr);
+ if (mixable_stream_ == nullptr) {
+ LOG(ERROR) << "Called on Closed stream!";
+ return;
+ }
+
mixable_stream_->Flush();
}
--- /dev/null
+// Copyright 2025 Samsung Electronics Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/audio/tizen/mch_pcm_mixable_stream.h"
+
+#include <memory>
+#include <vector>
+
+#include "base/test/task_environment.h"
+#include "media/audio/fake_audio_log_factory.h"
+#include "media/audio/fake_audio_manager.h"
+#include "media/audio/test_audio_thread.h"
+#include "media/audio/tizen/mch_pcm_manager.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media {
+
+namespace {
+
+class MockAudioSourceCallback : public AudioOutputStream::AudioSourceCallback {
+ public:
+ int OnMoreData(base::TimeDelta /* delay */,
+ base::TimeTicks /* delay_timestamp */,
+ const media::AudioGlitchInfo& /* glitch_info */,
+ AudioBus* dest) override {
+ dest->Zero();
+ return dest->frames();
+ }
+ MOCK_METHOD1(OnError, void(ErrorType));
+};
+
+} // namespace
+
+class MchPcmMixableStreamTest : public testing::Test {
+ public:
+ AudioOutputStream* Create51Stream() {
+ return MchPcmManager::GetInstance().CreateOutputStream(
+ Get51Params(), &fake_audio_manager_);
+ }
+
+ AudioOutputStream* CreateStereoStream() {
+ return MchPcmManager::GetInstance().CreateOutputStream(
+ GetStereoParams(), &fake_audio_manager_);
+ }
+
+ AudioParameters GetStereoParams() const {
+ return AudioParameters{AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ ChannelLayoutConfig::Stereo(), 48000, 512};
+ }
+
+ AudioParameters Get51Params() const {
+ return AudioParameters{
+ AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ ChannelLayoutConfig::FromLayout<CHANNEL_LAYOUT_5_1>(), 48000, 512};
+ }
+
+ protected:
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+ FakeAudioLogFactory fake_audio_log_factory_;
+ FakeAudioManager fake_audio_manager_{std::make_unique<TestAudioThread>(),
+ &fake_audio_log_factory_};
+};
+
+TEST_F(MchPcmMixableStreamTest, CreateSingle) {
+ auto* stream = Create51Stream();
+ ASSERT_NE(stream, nullptr);
+ stream->Close();
+ task_environment_.RunUntilIdle();
+}
+
+TEST_F(MchPcmMixableStreamTest, OpenSingle) {
+ auto* stream = Create51Stream();
+ ASSERT_NE(stream, nullptr);
+ EXPECT_TRUE(stream->Open());
+ task_environment_.RunUntilIdle();
+
+ stream->Close();
+ task_environment_.RunUntilIdle();
+}
+
+// TODO(a.bujalski):
+// Refactor `MchPcmMizeManager` to allow mocking audio output, so tests won't
+// hang when run under GBS.
+TEST_F(MchPcmMixableStreamTest, DISABLED_StartAndStopSingle) {
+ auto* stream = Create51Stream();
+ ASSERT_NE(stream, nullptr);
+ EXPECT_TRUE(stream->Open());
+ task_environment_.RunUntilIdle();
+
+ MockAudioSourceCallback audio_callback;
+ stream->Start(&audio_callback);
+ task_environment_.RunUntilIdle();
+
+ stream->Stop();
+ stream->Close();
+ task_environment_.RunUntilIdle();
+}
+
+TEST_F(MchPcmMixableStreamTest, SetVolumeSingle) {
+ auto* stream = Create51Stream();
+ ASSERT_NE(stream, nullptr);
+ EXPECT_TRUE(stream->Open());
+ task_environment_.RunUntilIdle();
+
+ constexpr double kDummyVolume1 = 0.1;
+ stream->SetVolume(kDummyVolume1);
+ double vol1 = 0.0;
+ stream->GetVolume(&vol1);
+ EXPECT_DOUBLE_EQ(vol1, kDummyVolume1);
+
+ task_environment_.RunUntilIdle();
+
+ constexpr double kDummyVolume2 = 0.42;
+ stream->SetVolume(kDummyVolume2);
+ double vol2 = 0.0;
+ stream->GetVolume(&vol2);
+ EXPECT_DOUBLE_EQ(vol2, kDummyVolume2);
+
+ stream->Stop();
+ stream->Close();
+ task_environment_.RunUntilIdle();
+}
+
+TEST_F(MchPcmMixableStreamTest, CreateTwoStreams) {
+ std::vector<AudioOutputStream*> streams;
+ streams.push_back(Create51Stream());
+ streams.push_back(CreateStereoStream());
+
+ for (const auto* stream : streams) {
+ ASSERT_NE(stream, nullptr);
+ }
+
+ for (auto* stream : streams) {
+ stream->Close();
+ }
+
+ task_environment_.RunUntilIdle();
+}
+
+TEST_F(MchPcmMixableStreamTest, OpenTwoStreams) {
+ std::vector<AudioOutputStream*> streams;
+ streams.push_back(Create51Stream());
+ streams.push_back(CreateStereoStream());
+
+ for (const auto* stream : streams) {
+ ASSERT_NE(stream, nullptr);
+ }
+
+ for (auto* stream : streams) {
+ EXPECT_TRUE(stream->Open());
+ }
+ task_environment_.RunUntilIdle();
+
+ for (auto* stream : streams) {
+ stream->Close();
+ }
+
+ task_environment_.RunUntilIdle();
+}
+
+// TODO(a.bujalski):
+// Refactor `MchPcmMizeManager` to allow mocking audio output, so tests won't
+// hang when run under GBS.
+TEST_F(MchPcmMixableStreamTest, DISABLED_StartAndStopStreams) {
+ std::vector<AudioOutputStream*> streams;
+ streams.push_back(Create51Stream());
+ streams.push_back(CreateStereoStream());
+
+ for (const auto* stream : streams) {
+ ASSERT_NE(stream, nullptr);
+ }
+
+ for (auto* stream : streams) {
+ EXPECT_TRUE(stream->Open());
+ }
+ task_environment_.RunUntilIdle();
+
+ MockAudioSourceCallback audio_callback;
+ for (auto* stream : streams) {
+ stream->Start(&audio_callback);
+ }
+
+ task_environment_.RunUntilIdle();
+
+ for (auto* stream : streams) {
+ stream->Stop();
+ }
+
+ for (auto* stream : streams) {
+ stream->Close();
+ }
+
+ task_environment_.RunUntilIdle();
+}
+
+} // namespace media