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

Side by Side Diff: media/filters/audio_renderer_impl_unittest.cc

Issue 297553002: Add callback in VideoDecoder and AudioDecoder to return decoded frames. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 6 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/bind.h" 5 #include "base/bind.h"
6 #include "base/callback_helpers.h" 6 #include "base/callback_helpers.h"
7 #include "base/gtest_prod_util.h" 7 #include "base/gtest_prod_util.h"
8 #include "base/memory/scoped_vector.h" 8 #include "base/memory/scoped_vector.h"
9 #include "base/message_loop/message_loop.h" 9 #include "base/message_loop/message_loop.h"
10 #include "base/run_loop.h" 10 #include "base/run_loop.h"
(...skipping 11 matching lines...) Expand all
22 #include "media/filters/audio_renderer_impl.h" 22 #include "media/filters/audio_renderer_impl.h"
23 #include "testing/gtest/include/gtest/gtest.h" 23 #include "testing/gtest/include/gtest/gtest.h"
24 24
25 using ::base::Time; 25 using ::base::Time;
26 using ::base::TimeTicks; 26 using ::base::TimeTicks;
27 using ::base::TimeDelta; 27 using ::base::TimeDelta;
28 using ::testing::_; 28 using ::testing::_;
29 using ::testing::AnyNumber; 29 using ::testing::AnyNumber;
30 using ::testing::Invoke; 30 using ::testing::Invoke;
31 using ::testing::Return; 31 using ::testing::Return;
32 using ::testing::SaveArg;
32 33
33 namespace media { 34 namespace media {
34 35
35 // Constants to specify the type of audio data used. 36 // Constants to specify the type of audio data used.
36 static AudioCodec kCodec = kCodecVorbis; 37 static AudioCodec kCodec = kCodecVorbis;
37 static SampleFormat kSampleFormat = kSampleFormatPlanarF32; 38 static SampleFormat kSampleFormat = kSampleFormatPlanarF32;
38 static ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO; 39 static ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
39 static int kChannelCount = 2; 40 static int kChannelCount = 2;
40 static int kChannels = ChannelLayoutToChannelCount(kChannelLayout); 41 static int kChannels = ChannelLayoutToChannelCount(kChannelLayout);
41 static int kSamplesPerSecond = 44100; 42 static int kSamplesPerSecond = 44100;
(...skipping 28 matching lines...) Expand all
70 0, 71 0,
71 false); 72 false);
72 demuxer_stream_.set_audio_decoder_config(audio_config); 73 demuxer_stream_.set_audio_decoder_config(audio_config);
73 74
74 // Used to save callbacks and run them at a later time. 75 // Used to save callbacks and run them at a later time.
75 EXPECT_CALL(*decoder_, Decode(_, _)) 76 EXPECT_CALL(*decoder_, Decode(_, _))
76 .WillRepeatedly(Invoke(this, &AudioRendererImplTest::DecodeDecoder)); 77 .WillRepeatedly(Invoke(this, &AudioRendererImplTest::DecodeDecoder));
77 EXPECT_CALL(*decoder_, Reset(_)) 78 EXPECT_CALL(*decoder_, Reset(_))
78 .WillRepeatedly(Invoke(this, &AudioRendererImplTest::ResetDecoder)); 79 .WillRepeatedly(Invoke(this, &AudioRendererImplTest::ResetDecoder));
79 80
80 // Mock out demuxer reads 81 // Mock out demuxer reads.
81 EXPECT_CALL(demuxer_stream_, Read(_)).WillRepeatedly( 82 EXPECT_CALL(demuxer_stream_, Read(_)).WillRepeatedly(
82 RunCallback<0>(DemuxerStream::kOk, DecoderBuffer::CreateEOSBuffer())); 83 RunCallback<0>(DemuxerStream::kOk,
84 scoped_refptr<DecoderBuffer>(new DecoderBuffer(0))));
xhwang 2014/06/05 21:53:49 why making this change?
Sergey Ulanov 2014/06/06 22:49:39 DecoderStream<StreamType>::OnBufferReady() stops r
83 EXPECT_CALL(demuxer_stream_, SupportsConfigChanges()) 85 EXPECT_CALL(demuxer_stream_, SupportsConfigChanges())
84 .WillRepeatedly(Return(true)); 86 .WillRepeatedly(Return(true));
85 AudioParameters out_params(AudioParameters::AUDIO_PCM_LOW_LATENCY, 87 AudioParameters out_params(AudioParameters::AUDIO_PCM_LOW_LATENCY,
86 kChannelLayout, 88 kChannelLayout,
87 kOutputSamplesPerSecond, 89 kOutputSamplesPerSecond,
88 SampleFormatToBytesPerChannel(kSampleFormat) * 8, 90 SampleFormatToBytesPerChannel(kSampleFormat) * 8,
89 512); 91 512);
90 hardware_config_.UpdateOutputConfig(out_params); 92 hardware_config_.UpdateOutputConfig(out_params);
91 ScopedVector<AudioDecoder> decoders; 93 ScopedVector<AudioDecoder> decoders;
92 decoders.push_back(decoder_); 94 decoders.push_back(decoder_);
(...skipping 12 matching lines...) Expand all
105 virtual ~AudioRendererImplTest() { 107 virtual ~AudioRendererImplTest() {
106 SCOPED_TRACE("~AudioRendererImplTest()"); 108 SCOPED_TRACE("~AudioRendererImplTest()");
107 if (needs_stop_) { 109 if (needs_stop_) {
108 WaitableMessageLoopEvent event; 110 WaitableMessageLoopEvent event;
109 renderer_->Stop(event.GetClosure()); 111 renderer_->Stop(event.GetClosure());
110 event.RunAndWait(); 112 event.RunAndWait();
111 } 113 }
112 } 114 }
113 115
114 void ExpectUnsupportedAudioDecoder() { 116 void ExpectUnsupportedAudioDecoder() {
115 EXPECT_CALL(*decoder_, Initialize(_, _)) 117 EXPECT_CALL(*decoder_, Initialize(_, _, _))
116 .WillOnce(RunCallback<1>(DECODER_ERROR_NOT_SUPPORTED)); 118 .WillOnce(DoAll(SaveArg<2>(&output_cb_),
119 RunCallback<1>(DECODER_ERROR_NOT_SUPPORTED)));
117 } 120 }
118 121
119 MOCK_METHOD1(OnStatistics, void(const PipelineStatistics&)); 122 MOCK_METHOD1(OnStatistics, void(const PipelineStatistics&));
120 MOCK_METHOD0(OnUnderflow, void()); 123 MOCK_METHOD0(OnUnderflow, void());
121 MOCK_METHOD1(OnError, void(PipelineStatus)); 124 MOCK_METHOD1(OnError, void(PipelineStatus));
122 125
123 void OnAudioTimeCallback(TimeDelta current_time, TimeDelta max_time) { 126 void OnAudioTimeCallback(TimeDelta current_time, TimeDelta max_time) {
124 CHECK(current_time <= max_time); 127 CHECK(current_time <= max_time);
125 last_time_update_ = current_time; 128 last_time_update_ = current_time;
126 } 129 }
127 130
128 void InitializeRenderer(const PipelineStatusCB& pipeline_status_cb) { 131 void InitializeRenderer(const PipelineStatusCB& pipeline_status_cb) {
129 renderer_->Initialize( 132 renderer_->Initialize(
130 &demuxer_stream_, 133 &demuxer_stream_,
131 pipeline_status_cb, 134 pipeline_status_cb,
132 base::Bind(&AudioRendererImplTest::OnStatistics, 135 base::Bind(&AudioRendererImplTest::OnStatistics,
133 base::Unretained(this)), 136 base::Unretained(this)),
134 base::Bind(&AudioRendererImplTest::OnUnderflow, 137 base::Bind(&AudioRendererImplTest::OnUnderflow,
135 base::Unretained(this)), 138 base::Unretained(this)),
136 base::Bind(&AudioRendererImplTest::OnAudioTimeCallback, 139 base::Bind(&AudioRendererImplTest::OnAudioTimeCallback,
137 base::Unretained(this)), 140 base::Unretained(this)),
138 ended_event_.GetClosure(), 141 ended_event_.GetClosure(),
139 base::Bind(&AudioRendererImplTest::OnError, 142 base::Bind(&AudioRendererImplTest::OnError,
140 base::Unretained(this))); 143 base::Unretained(this)));
141 } 144 }
142 145
143 void Initialize() { 146 void Initialize() {
144 EXPECT_CALL(*decoder_, Initialize(_, _)) 147 EXPECT_CALL(*decoder_, Initialize(_, _, _))
145 .WillOnce(RunCallback<1>(PIPELINE_OK)); 148 .WillOnce(DoAll(SaveArg<2>(&output_cb_),
149 RunCallback<1>(PIPELINE_OK)));
146 EXPECT_CALL(*decoder_, Stop()); 150 EXPECT_CALL(*decoder_, Stop());
147 InitializeWithStatus(PIPELINE_OK); 151 InitializeWithStatus(PIPELINE_OK);
148 152
149 next_timestamp_.reset(new AudioTimestampHelper( 153 next_timestamp_.reset(new AudioTimestampHelper(
150 hardware_config_.GetOutputConfig().sample_rate())); 154 hardware_config_.GetOutputConfig().sample_rate()));
151 } 155 }
152 156
153 void InitializeWithStatus(PipelineStatus expected) { 157 void InitializeWithStatus(PipelineStatus expected) {
154 SCOPED_TRACE(base::StringPrintf("InitializeWithStatus(%d)", expected)); 158 SCOPED_TRACE(base::StringPrintf("InitializeWithStatus(%d)", expected));
155 159
156 WaitableMessageLoopEvent event; 160 WaitableMessageLoopEvent event;
157 InitializeRenderer(event.GetPipelineStatusCB()); 161 InitializeRenderer(event.GetPipelineStatusCB());
158 event.RunAndWaitForStatus(expected); 162 event.RunAndWaitForStatus(expected);
159 163
160 // We should have no reads. 164 // We should have no reads.
161 EXPECT_TRUE(decode_cb_.is_null()); 165 EXPECT_TRUE(decode_cb_.is_null());
162 } 166 }
163 167
164 void InitializeAndStop() { 168 void InitializeAndStop() {
165 EXPECT_CALL(*decoder_, Initialize(_, _)) 169 EXPECT_CALL(*decoder_, Initialize(_, _, _))
166 .WillOnce(RunCallback<1>(PIPELINE_OK)); 170 .WillOnce(DoAll(SaveArg<2>(&output_cb_),
171 RunCallback<1>(PIPELINE_OK)));
167 EXPECT_CALL(*decoder_, Stop()); 172 EXPECT_CALL(*decoder_, Stop());
168 173
169 WaitableMessageLoopEvent event; 174 WaitableMessageLoopEvent event;
170 InitializeRenderer(event.GetPipelineStatusCB()); 175 InitializeRenderer(event.GetPipelineStatusCB());
171 176
172 // Stop before we let the MessageLoop run, this simulates an interleaving 177 // Stop before we let the MessageLoop run, this simulates an interleaving
173 // in which we end up calling Stop() while the OnDecoderSelected callback 178 // in which we end up calling Stop() while the OnDecoderSelected callback
174 // is in flight. 179 // is in flight.
175 renderer_->Stop(NewExpectedClosure()); 180 renderer_->Stop(NewExpectedClosure());
176 event.RunAndWaitForStatus(PIPELINE_ERROR_ABORT); 181 event.RunAndWaitForStatus(PIPELINE_ERROR_ABORT);
177 EXPECT_EQ(renderer_->state_, AudioRendererImpl::kStopped); 182 EXPECT_EQ(renderer_->state_, AudioRendererImpl::kStopped);
178 } 183 }
179 184
180 void InitializeAndStopDuringDecoderInit() { 185 void InitializeAndStopDuringDecoderInit() {
181 EXPECT_CALL(*decoder_, Initialize(_, _)) 186 EXPECT_CALL(*decoder_, Initialize(_, _, _))
182 .WillOnce(EnterPendingDecoderInitStateAction(this)); 187 .WillOnce(DoAll(SaveArg<2>(&output_cb_),
188 EnterPendingDecoderInitStateAction(this)));
183 EXPECT_CALL(*decoder_, Stop()); 189 EXPECT_CALL(*decoder_, Stop());
184 190
185 WaitableMessageLoopEvent event; 191 WaitableMessageLoopEvent event;
186 InitializeRenderer(event.GetPipelineStatusCB()); 192 InitializeRenderer(event.GetPipelineStatusCB());
187 193
188 base::RunLoop().RunUntilIdle(); 194 base::RunLoop().RunUntilIdle();
189 DCHECK(!init_decoder_cb_.is_null()); 195 DCHECK(!init_decoder_cb_.is_null());
190 196
191 renderer_->Stop(NewExpectedClosure()); 197 renderer_->Stop(NewExpectedClosure());
192 base::ResetAndReturn(&init_decoder_cb_).Run(PIPELINE_OK); 198 base::ResetAndReturn(&init_decoder_cb_).Run(PIPELINE_OK);
(...skipping 23 matching lines...) Expand all
216 222
217 TimeDelta timestamp = TimeDelta::FromMilliseconds(timestamp_ms); 223 TimeDelta timestamp = TimeDelta::FromMilliseconds(timestamp_ms);
218 next_timestamp_->SetBaseTimestamp(timestamp); 224 next_timestamp_->SetBaseTimestamp(timestamp);
219 225
220 // Fill entire buffer to complete prerolling. 226 // Fill entire buffer to complete prerolling.
221 WaitableMessageLoopEvent event; 227 WaitableMessageLoopEvent event;
222 renderer_->Preroll(timestamp, event.GetPipelineStatusCB()); 228 renderer_->Preroll(timestamp, event.GetPipelineStatusCB());
223 WaitForPendingRead(); 229 WaitForPendingRead();
224 DeliverRemainingAudio(); 230 DeliverRemainingAudio();
225 event.RunAndWaitForStatus(PIPELINE_OK); 231 event.RunAndWaitForStatus(PIPELINE_OK);
226
227 // We should have no reads.
228 EXPECT_TRUE(decode_cb_.is_null());
229 } 232 }
230 233
231 void StartRendering() { 234 void StartRendering() {
232 renderer_->StartRendering(); 235 renderer_->StartRendering();
233 renderer_->SetPlaybackRate(1.0f); 236 renderer_->SetPlaybackRate(1.0f);
234 } 237 }
235 238
236 void StopRendering() { 239 void StopRendering() {
237 renderer_->StopRendering(); 240 renderer_->StopRendering();
238 } 241 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 kChannelLayout, 280 kChannelLayout,
278 kChannelCount, 281 kChannelCount,
279 kSamplesPerSecond, 282 kSamplesPerSecond,
280 kPlayingAudio, 283 kPlayingAudio,
281 0.0f, 284 0.0f,
282 size, 285 size,
283 next_timestamp_->GetTimestamp()); 286 next_timestamp_->GetTimestamp());
284 next_timestamp_->AddFrames(size); 287 next_timestamp_->AddFrames(size);
285 288
286 DeliverBuffer(AudioDecoder::kOk, buffer); 289 DeliverBuffer(AudioDecoder::kOk, buffer);
290 message_loop_.RunUntilIdle();
287 } 291 }
288 292
289 void AbortPendingRead() { 293 void AbortPendingRead() {
290 DeliverBuffer(AudioDecoder::kAborted, NULL); 294 DeliverBuffer(AudioDecoder::kAborted, NULL);
291 } 295 }
292 296
293 void DeliverEndOfStream() { 297 void DeliverEndOfStream() {
294 DeliverBuffer(AudioDecoder::kOk, AudioBuffer::CreateEOSBuffer()); 298 while (!decode_cb_.is_null()) {
299 DeliverBuffer(AudioDecoder::kOk, AudioBuffer::CreateEOSBuffer());
300 message_loop_.RunUntilIdle();
xhwang 2014/06/05 21:53:49 Run the message loop in DeliverBuffer()?
Sergey Ulanov 2014/06/06 22:49:40 Done.
301 }
xhwang 2014/06/05 21:53:49 why "while" loop? There could be only one pending
Sergey Ulanov 2014/06/06 22:49:40 DecoderStream::OnDecodeDone() may get another buff
295 } 302 }
296 303
297 // Delivers frames until |renderer_|'s internal buffer is full and no longer 304 // Delivers frames until |renderer_|'s internal buffer is full and no longer
298 // has pending reads. 305 // has pending reads.
299 void DeliverRemainingAudio() { 306 void DeliverRemainingAudio() {
300 SatisfyPendingRead(frames_remaining_in_buffer()); 307 SatisfyPendingRead(frames_remaining_in_buffer());
308 message_loop_.RunUntilIdle();
xhwang 2014/06/05 21:53:49 SatisfyPendingRead() already runs the message loop
Sergey Ulanov 2014/06/06 22:49:39 Done.
301 } 309 }
302 310
303 // Attempts to consume |requested_frames| frames from |renderer_|'s internal 311 // Attempts to consume |requested_frames| frames from |renderer_|'s internal
304 // buffer, returning true if all |requested_frames| frames were consumed, 312 // buffer, returning true if all |requested_frames| frames were consumed,
305 // false if less than |requested_frames| frames were consumed. 313 // false if less than |requested_frames| frames were consumed.
306 // 314 //
307 // |muted| is optional and if passed will get set if the value of 315 // |muted| is optional and if passed will get set if the value of
308 // the consumed data is muted audio. 316 // the consumed data is muted audio.
309 bool ConsumeBufferedData(int requested_frames, bool* muted) { 317 bool ConsumeBufferedData(int requested_frames, bool* muted) {
310 scoped_ptr<AudioBus> bus = 318 scoped_ptr<AudioBus> bus =
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
458 466
459 CHECK(decode_cb_.is_null()) << "Overlapping decodes are not permitted"; 467 CHECK(decode_cb_.is_null()) << "Overlapping decodes are not permitted";
460 decode_cb_ = decode_cb; 468 decode_cb_ = decode_cb;
461 469
462 // Wake up WaitForPendingRead() if needed. 470 // Wake up WaitForPendingRead() if needed.
463 if (!wait_for_pending_decode_cb_.is_null()) 471 if (!wait_for_pending_decode_cb_.is_null())
464 base::ResetAndReturn(&wait_for_pending_decode_cb_).Run(); 472 base::ResetAndReturn(&wait_for_pending_decode_cb_).Run();
465 } 473 }
466 474
467 void ResetDecoder(const base::Closure& reset_cb) { 475 void ResetDecoder(const base::Closure& reset_cb) {
468 CHECK(decode_cb_.is_null()) 476 if (!decode_cb_.is_null()) {
469 << "Reset overlapping with reads is not permitted"; 477 reset_cb_ = reset_cb;
xhwang 2014/06/05 21:53:49 Add a comment that in this case the |reset_cb| is
Sergey Ulanov 2014/06/06 22:49:39 Done.
478 return;
479 }
470 480
471 message_loop_.PostTask(FROM_HERE, reset_cb); 481 message_loop_.PostTask(FROM_HERE, reset_cb);
472 } 482 }
473 483
474 void DeliverBuffer(AudioDecoder::Status status, 484 void DeliverBuffer(AudioDecoder::Status status,
475 const scoped_refptr<AudioBuffer>& buffer) { 485 const scoped_refptr<AudioBuffer>& buffer) {
476 CHECK(!decode_cb_.is_null()); 486 CHECK(!decode_cb_.is_null());
477 base::ResetAndReturn(&decode_cb_).Run(status, buffer); 487 if (buffer)
488 output_cb_.Run(buffer);
489 base::ResetAndReturn(&decode_cb_).Run(status);
490
491 if (!reset_cb_.is_null())
492 base::ResetAndReturn(&reset_cb_).Run();
478 } 493 }
479 494
480 MockDemuxerStream demuxer_stream_; 495 MockDemuxerStream demuxer_stream_;
481 MockAudioDecoder* decoder_; 496 MockAudioDecoder* decoder_;
482 497
483 // Used for stubbing out time in the audio callback thread. 498 // Used for stubbing out time in the audio callback thread.
484 base::Lock lock_; 499 base::Lock lock_;
485 TimeTicks time_; 500 TimeTicks time_;
486 501
487 // Used for satisfying reads. 502 // Used for satisfying reads.
503 AudioDecoder::OutputCB output_cb_;
488 AudioDecoder::DecodeCB decode_cb_; 504 AudioDecoder::DecodeCB decode_cb_;
505 base::Closure reset_cb_;
489 scoped_ptr<AudioTimestampHelper> next_timestamp_; 506 scoped_ptr<AudioTimestampHelper> next_timestamp_;
490 507
491 WaitableMessageLoopEvent ended_event_; 508 WaitableMessageLoopEvent ended_event_;
492 509
493 // Run during DecodeDecoder() to unblock WaitForPendingRead(). 510 // Run during DecodeDecoder() to unblock WaitForPendingRead().
494 base::Closure wait_for_pending_decode_cb_; 511 base::Closure wait_for_pending_decode_cb_;
495 base::Closure stop_decoder_cb_; 512 base::Closure stop_decoder_cb_;
496 513
497 PipelineStatusCB init_decoder_cb_; 514 PipelineStatusCB init_decoder_cb_;
498 base::TimeDelta last_time_update_; 515 base::TimeDelta last_time_update_;
(...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after
993 // Start rendering with zero playback rate. Sink should be paused until 1010 // Start rendering with zero playback rate. Sink should be paused until
994 // non-zero rate is set. 1011 // non-zero rate is set.
995 renderer_->SetPlaybackRate(0.0f); 1012 renderer_->SetPlaybackRate(0.0f);
996 renderer_->StartRendering(); 1013 renderer_->StartRendering();
997 EXPECT_EQ(FakeAudioRendererSink::kPaused, sink_->state()); 1014 EXPECT_EQ(FakeAudioRendererSink::kPaused, sink_->state());
998 renderer_->SetPlaybackRate(1.0f); 1015 renderer_->SetPlaybackRate(1.0f);
999 EXPECT_EQ(FakeAudioRendererSink::kPlaying, sink_->state()); 1016 EXPECT_EQ(FakeAudioRendererSink::kPlaying, sink_->state());
1000 } 1017 }
1001 1018
1002 } // namespace media 1019 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698