Index: media/renderers/audio_renderer_impl_unittest.cc |
diff --git a/media/renderers/audio_renderer_impl_unittest.cc b/media/renderers/audio_renderer_impl_unittest.cc |
index b67788937980f81c26a5bbb9f2069170838140ae..6fad71cd0296d268445041856f39f0e4ee3bc5af 100644 |
--- a/media/renderers/audio_renderer_impl_unittest.cc |
+++ b/media/renderers/audio_renderer_impl_unittest.cc |
@@ -66,6 +66,25 @@ ACTION_P(EnterPendingDecoderInitStateAction, test) { |
class AudioRendererImplTest : public ::testing::Test, public RendererClient { |
public: |
+ ScopedVector<AudioDecoder> CreateAudioDecoderForTest() { |
+ MockAudioDecoder* decoder = new MockAudioDecoder(); |
+ if (!enter_pending_decoder_init_) { |
+ EXPECT_CALL(*decoder, Initialize(_, _, _, _)) |
+ .WillOnce(DoAll(SaveArg<3>(&output_cb_), |
+ RunCallback<2>(expected_init_result_))); |
+ } else { |
+ EXPECT_CALL(*decoder, Initialize(_, _, _, _)) |
+ .WillOnce(EnterPendingDecoderInitStateAction(this)); |
+ } |
+ EXPECT_CALL(*decoder, Decode(_, _)) |
+ .WillRepeatedly(Invoke(this, &AudioRendererImplTest::DecodeDecoder)); |
+ EXPECT_CALL(*decoder, Reset(_)) |
+ .WillRepeatedly(Invoke(this, &AudioRendererImplTest::ResetDecoder)); |
+ ScopedVector<AudioDecoder> decoders; |
+ decoders.push_back(decoder); |
+ return decoders; |
+ } |
+ |
// Give the decoder some non-garbage media properties. |
AudioRendererImplTest() |
: hardware_params_(AudioParameters::AUDIO_PCM_LOW_LATENCY, |
@@ -76,14 +95,14 @@ class AudioRendererImplTest : public ::testing::Test, public RendererClient { |
sink_(new FakeAudioRendererSink(hardware_params_)), |
tick_clock_(new base::SimpleTestTickClock()), |
demuxer_stream_(DemuxerStream::AUDIO), |
- decoder_(new MockAudioDecoder()), |
+ expected_init_result_(true), |
+ enter_pending_decoder_init_(false), |
ended_(false) { |
AudioDecoderConfig audio_config(kCodec, kSampleFormat, kChannelLayout, |
kInputSamplesPerSecond, EmptyExtraData(), |
Unencrypted()); |
demuxer_stream_.set_audio_decoder_config(audio_config); |
- ConfigureDecoder(); |
ConfigureDemuxerStream(true); |
AudioParameters out_params(AudioParameters::AUDIO_PCM_LOW_LATENCY, |
@@ -91,11 +110,11 @@ class AudioRendererImplTest : public ::testing::Test, public RendererClient { |
kOutputSamplesPerSecond, |
SampleFormatToBytesPerChannel(kSampleFormat) * 8, |
512); |
- ScopedVector<AudioDecoder> decoders; |
- decoders.push_back(decoder_); |
- renderer_.reset(new AudioRendererImpl(message_loop_.task_runner(), |
- sink_.get(), std::move(decoders), |
- new MediaLog())); |
+ renderer_.reset(new AudioRendererImpl( |
+ message_loop_.task_runner(), sink_.get(), |
+ base::Bind(&AudioRendererImplTest::CreateAudioDecoderForTest, |
+ base::Unretained(this)), |
+ new MediaLog())); |
renderer_->tick_clock_.reset(tick_clock_); |
tick_clock_->Advance(base::TimeDelta::FromSeconds(1)); |
} |
@@ -104,14 +123,6 @@ class AudioRendererImplTest : public ::testing::Test, public RendererClient { |
SCOPED_TRACE("~AudioRendererImplTest()"); |
} |
- // Used to save callbacks and run them at a later time. |
- void ConfigureDecoder() { |
- EXPECT_CALL(*decoder_, Decode(_, _)) |
- .WillRepeatedly(Invoke(this, &AudioRendererImplTest::DecodeDecoder)); |
- EXPECT_CALL(*decoder_, Reset(_)) |
- .WillRepeatedly(Invoke(this, &AudioRendererImplTest::ResetDecoder)); |
- } |
- |
// Mock out demuxer reads. |
void ConfigureDemuxerStream(bool supports_config_changes) { |
EXPECT_CALL(demuxer_stream_, Read(_)) |
@@ -126,13 +137,11 @@ class AudioRendererImplTest : public ::testing::Test, public RendererClient { |
void ConfigureBasicRenderer(const AudioParameters& params) { |
hardware_params_ = params; |
sink_ = new FakeAudioRendererSink(hardware_params_); |
- decoder_ = new MockAudioDecoder(); |
- ConfigureDecoder(); |
- ScopedVector<AudioDecoder> decoders; |
- decoders.push_back(decoder_); |
- renderer_.reset(new AudioRendererImpl(message_loop_.task_runner(), |
- sink_.get(), std::move(decoders), |
- new MediaLog())); |
+ renderer_.reset(new AudioRendererImpl( |
+ message_loop_.task_runner(), sink_.get(), |
+ base::Bind(&AudioRendererImplTest::CreateAudioDecoderForTest, |
+ base::Unretained(this)), |
+ new MediaLog())); |
testing::Mock::VerifyAndClearExpectations(&demuxer_stream_); |
ConfigureDemuxerStream(false); |
} |
@@ -142,22 +151,15 @@ class AudioRendererImplTest : public ::testing::Test, public RendererClient { |
const AudioParameters& hardware_params) { |
hardware_params_ = hardware_params; |
sink_ = new FakeAudioRendererSink(hardware_params_); |
- decoder_ = new MockAudioDecoder(); |
- ConfigureDecoder(); |
- ScopedVector<AudioDecoder> decoders; |
- decoders.push_back(decoder_); |
- renderer_.reset(new AudioRendererImpl(message_loop_.task_runner(), |
- sink_.get(), std::move(decoders), |
- new MediaLog())); |
+ renderer_.reset(new AudioRendererImpl( |
+ message_loop_.task_runner(), sink_.get(), |
+ base::Bind(&AudioRendererImplTest::CreateAudioDecoderForTest, |
+ base::Unretained(this)), |
+ new MediaLog())); |
testing::Mock::VerifyAndClearExpectations(&demuxer_stream_); |
ConfigureDemuxerStream(true); |
} |
- void ExpectUnsupportedAudioDecoder() { |
- EXPECT_CALL(*decoder_, Initialize(_, _, _, _)) |
- .WillOnce(DoAll(SaveArg<3>(&output_cb_), RunCallback<2>(false))); |
- } |
- |
// RendererClient implementation. |
MOCK_METHOD1(OnError, void(PipelineStatus)); |
void OnEnded() override { |
@@ -173,16 +175,15 @@ class AudioRendererImplTest : public ::testing::Test, public RendererClient { |
MOCK_METHOD1(OnVideoOpacityChange, void(bool)); |
MOCK_METHOD1(OnDurationChange, void(base::TimeDelta)); |
- void InitializeRenderer(const PipelineStatusCB& pipeline_status_cb) { |
+ void InitializeRenderer(DemuxerStream* demuxer_stream, |
+ const PipelineStatusCB& pipeline_status_cb) { |
EXPECT_CALL(*this, OnWaitingForDecryptionKey()).Times(0); |
EXPECT_CALL(*this, OnVideoNaturalSizeChange(_)).Times(0); |
EXPECT_CALL(*this, OnVideoOpacityChange(_)).Times(0); |
- renderer_->Initialize(&demuxer_stream_, nullptr, this, pipeline_status_cb); |
+ renderer_->Initialize(demuxer_stream, nullptr, this, pipeline_status_cb); |
} |
void Initialize() { |
- EXPECT_CALL(*decoder_, Initialize(_, _, _, _)) |
- .WillOnce(DoAll(SaveArg<3>(&output_cb_), RunCallback<2>(true))); |
InitializeWithStatus(PIPELINE_OK); |
next_timestamp_.reset(new AudioTimestampHelper(kInputSamplesPerSecond)); |
@@ -192,7 +193,7 @@ class AudioRendererImplTest : public ::testing::Test, public RendererClient { |
SCOPED_TRACE(base::StringPrintf("InitializeWithStatus(%d)", expected)); |
WaitableMessageLoopEvent event; |
- InitializeRenderer(event.GetPipelineStatusCB()); |
+ InitializeRenderer(&demuxer_stream_, event.GetPipelineStatusCB()); |
event.RunAndWaitForStatus(expected); |
// We should have no reads. |
@@ -200,11 +201,8 @@ class AudioRendererImplTest : public ::testing::Test, public RendererClient { |
} |
void InitializeAndDestroy() { |
- EXPECT_CALL(*decoder_, Initialize(_, _, _, _)) |
- .WillOnce(RunCallback<2>(true)); |
- |
WaitableMessageLoopEvent event; |
- InitializeRenderer(event.GetPipelineStatusCB()); |
+ InitializeRenderer(&demuxer_stream_, event.GetPipelineStatusCB()); |
// Destroy the |renderer_| before we let the MessageLoop run, this simulates |
// an interleaving in which we end up destroying the |renderer_| while the |
@@ -214,11 +212,10 @@ class AudioRendererImplTest : public ::testing::Test, public RendererClient { |
} |
void InitializeAndDestroyDuringDecoderInit() { |
- EXPECT_CALL(*decoder_, Initialize(_, _, _, _)) |
- .WillOnce(EnterPendingDecoderInitStateAction(this)); |
+ enter_pending_decoder_init_ = true; |
WaitableMessageLoopEvent event; |
- InitializeRenderer(event.GetPipelineStatusCB()); |
+ InitializeRenderer(&demuxer_stream_, event.GetPipelineStatusCB()); |
base::RunLoop().RunUntilIdle(); |
DCHECK(!init_decoder_cb_.is_null()); |
@@ -457,7 +454,6 @@ class AudioRendererImplTest : public ::testing::Test, public RendererClient { |
PipelineStatistics last_statistics_; |
MockDemuxerStream demuxer_stream_; |
- MockAudioDecoder* decoder_; |
// Used for satisfying reads. |
AudioDecoder::OutputCB output_cb_; |
@@ -469,6 +465,8 @@ class AudioRendererImplTest : public ::testing::Test, public RendererClient { |
base::Closure wait_for_pending_decode_cb_; |
AudioDecoder::InitCB init_decoder_cb_; |
+ bool expected_init_result_; |
+ bool enter_pending_decoder_init_; |
bool ended_; |
DISALLOW_COPY_AND_ASSIGN(AudioRendererImplTest); |
@@ -479,10 +477,39 @@ TEST_F(AudioRendererImplTest, Initialize_Successful) { |
} |
TEST_F(AudioRendererImplTest, Initialize_DecoderInitFailure) { |
- ExpectUnsupportedAudioDecoder(); |
+ expected_init_result_ = false; |
InitializeWithStatus(DECODER_ERROR_NOT_SUPPORTED); |
} |
+TEST_F(AudioRendererImplTest, ReinitializeForDifferentStream) { |
+ // Initialize and start playback |
+ Initialize(); |
+ Preroll(); |
+ StartTicking(); |
+ EXPECT_TRUE(ConsumeBufferedData(OutputFrames(256))); |
+ WaitForPendingRead(); |
+ |
+ // Stop playback and flush |
+ StopTicking(); |
+ EXPECT_TRUE(IsReadPending()); |
+ // Flush and expect to be notified that we have nothing. |
+ EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_NOTHING)); |
+ FlushDuringPendingRead(); |
+ |
+ // Prepare a new demuxer stream. |
+ MockDemuxerStream new_stream(DemuxerStream::AUDIO); |
+ EXPECT_CALL(new_stream, SupportsConfigChanges()).WillOnce(Return(false)); |
+ AudioDecoderConfig audio_config(kCodec, kSampleFormat, kChannelLayout, |
+ kInputSamplesPerSecond, EmptyExtraData(), |
+ Unencrypted()); |
+ new_stream.set_audio_decoder_config(audio_config); |
+ |
+ // The renderer is now in the flushed state and can be reinitialized. |
+ WaitableMessageLoopEvent event; |
+ InitializeRenderer(&new_stream, event.GetPipelineStatusCB()); |
+ event.RunAndWaitForStatus(PIPELINE_OK); |
+} |
+ |
TEST_F(AudioRendererImplTest, Preroll) { |
Initialize(); |
Preroll(); |