1 // Copyright 2018 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
9 #include "base/callback_helpers.h"
10 #include "base/memory/raw_ptr.h"
11 #include "base/run_loop.h"
12 #include "base/test/gmock_callback_support.h"
13 #include "base/test/task_environment.h"
14 #include "base/threading/sequenced_task_runner_handle.h"
15 #include "base/time/time.h"
16 #include "media/base/media_util.h"
17 #include "media/base/mock_filters.h"
18 #include "media/filters/decoder_stream.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
22 using ::base::test::RunCallback;
23 using ::base::test::RunOnceCallback;
25 using testing::AnyNumber;
27 using testing::Invoke;
28 using testing::Return;
29 using testing::SaveArg;
33 MATCHER(IsRegularDecoderBuffer, "") {
34 return !arg->end_of_stream();
37 MATCHER(IsEOSDecoderBuffer, "") {
38 return arg->end_of_stream();
41 static void OnAudioDecoderStreamInitialized(base::OnceClosure closure,
44 std::move(closure).Run();
47 class AudioDecoderStreamTest : public testing::Test {
49 AudioDecoderStreamTest()
50 : audio_decoder_stream_(
51 std::make_unique<AudioDecoderStream::StreamTraits>(
53 CHANNEL_LAYOUT_STEREO,
54 kSampleFormatPlanarF32),
55 task_environment_.GetMainThreadTaskRunner(),
56 base::BindRepeating(&AudioDecoderStreamTest::CreateMockAudioDecoder,
57 base::Unretained(this)),
59 // Any valid config will do.
60 demuxer_stream_.set_audio_decoder_config({AudioCodec::kAAC,
62 CHANNEL_LAYOUT_STEREO,
66 EXPECT_CALL(demuxer_stream_, SupportsConfigChanges())
67 .WillRepeatedly(Return(true));
69 base::RunLoop run_loop;
70 audio_decoder_stream_.Initialize(
72 base::BindOnce(&OnAudioDecoderStreamInitialized,
73 run_loop.QuitClosure()),
74 nullptr, base::DoNothing(), base::DoNothing());
78 AudioDecoderStreamTest(const AudioDecoderStreamTest&) = delete;
79 AudioDecoderStreamTest& operator=(const AudioDecoderStreamTest&) = delete;
81 MockDemuxerStream* demuxer_stream() { return &demuxer_stream_; }
82 MockAudioDecoder* decoder() { return decoder_; }
84 void ReadAudioBuffer(base::OnceClosure closure) {
85 audio_decoder_stream_.Read(
86 base::BindOnce(&AudioDecoderStreamTest::OnAudioBufferReadDone,
87 base::Unretained(this), std::move(closure)));
90 void ProduceDecoderOutput(scoped_refptr<DecoderBuffer> buffer,
91 AudioDecoder::DecodeCB decode_cb) {
92 // Make sure successive AudioBuffers have increasing timestamps.
93 last_timestamp_ += base::Milliseconds(27);
94 const auto& config = demuxer_stream_.audio_decoder_config();
95 base::SequencedTaskRunnerHandle::Get()->PostTask(
99 AudioBuffer::CreateEmptyBuffer(
100 config.channel_layout(), config.channels(),
101 config.samples_per_second(), 1221, last_timestamp_)));
102 base::SequencedTaskRunnerHandle::Get()->PostTask(
104 base::BindOnce(std::move(decode_cb), DecoderStatus::Codes::kOk));
107 void RunUntilIdle() { task_environment_.RunUntilIdle(); }
110 std::vector<std::unique_ptr<AudioDecoder>> CreateMockAudioDecoder() {
111 auto decoder = std::make_unique<MockAudioDecoder>();
112 EXPECT_CALL(*decoder, Initialize_(_, _, _, _, _))
114 .WillRepeatedly(DoAll(SaveArg<3>(&decoder_output_cb_),
115 RunOnceCallback<2>(DecoderStatus::Codes::kOk)));
116 decoder_ = decoder.get();
118 std::vector<std::unique_ptr<AudioDecoder>> result;
119 result.push_back(std::move(decoder));
123 void OnAudioBufferReadDone(base::OnceClosure closure,
124 AudioDecoderStream::ReadResult result) {
125 std::move(closure).Run();
128 base::test::TaskEnvironment task_environment_;
129 NullMediaLog media_log_;
130 testing::NiceMock<MockDemuxerStream> demuxer_stream_{DemuxerStream::AUDIO};
131 AudioDecoderStream audio_decoder_stream_;
133 raw_ptr<MockAudioDecoder> decoder_ = nullptr;
134 AudioDecoder::OutputCB decoder_output_cb_;
135 base::TimeDelta last_timestamp_;
138 TEST_F(AudioDecoderStreamTest, FlushOnConfigChange) {
139 MockAudioDecoder* first_decoder = decoder();
140 ASSERT_NE(first_decoder, nullptr);
142 // Make a regular DemuxerStream::Read().
143 EXPECT_CALL(*demuxer_stream(), OnRead(_))
144 .WillOnce(RunOnceCallback<0>(DemuxerStream::kOk, new DecoderBuffer(12)));
145 EXPECT_CALL(*decoder(), Decode(IsRegularDecoderBuffer(), _))
146 .WillOnce(Invoke(this, &AudioDecoderStreamTest::ProduceDecoderOutput));
147 base::RunLoop run_loop0;
148 ReadAudioBuffer(run_loop0.QuitClosure());
151 // Make a config-change DemuxerStream::Read().
152 // Expect the decoder to be flushed. Upon flushing, the decoder releases
153 // internally buffered output.
154 EXPECT_CALL(*demuxer_stream(), OnRead(_))
155 .WillOnce(RunOnceCallback<0>(DemuxerStream::kConfigChanged, nullptr));
156 EXPECT_CALL(*decoder(), Decode(IsEOSDecoderBuffer(), _))
157 .WillOnce(Invoke(this, &AudioDecoderStreamTest::ProduceDecoderOutput));
158 base::RunLoop run_loop1;
159 ReadAudioBuffer(run_loop1.QuitClosure());
162 // Expect the decoder to be re-initialized when AudioDecoderStream finishes
163 // processing the last decode.
164 EXPECT_CALL(*decoder(), Initialize_(_, _, _, _, _));