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

Unified Diff: media/filters/audio_renderer_impl_unittest.cc

Issue 140823012: Reland: Add Stop() to AudioDecoder. (https://codereview.chromium.org/126793002/) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: remove extra scope Created 6 years, 11 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/filters/audio_renderer_impl.cc ('k') | media/filters/decrypting_audio_decoder.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/filters/audio_renderer_impl_unittest.cc
diff --git a/media/filters/audio_renderer_impl_unittest.cc b/media/filters/audio_renderer_impl_unittest.cc
index 5adfbc499f7491f8176e71d4c801104f0fa1cf26..21bc3dcb34afc814a1a5999ec12ea5a0679b82c7 100644
--- a/media/filters/audio_renderer_impl_unittest.cc
+++ b/media/filters/audio_renderer_impl_unittest.cc
@@ -7,6 +7,7 @@
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_vector.h"
#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "media/base/audio_buffer.h"
@@ -46,7 +47,8 @@ class AudioRendererImplTest : public ::testing::Test {
public:
// Give the decoder some non-garbage media properties.
AudioRendererImplTest()
- : demuxer_stream_(DemuxerStream::AUDIO),
+ : needs_stop_(true),
+ demuxer_stream_(DemuxerStream::AUDIO),
decoder_(new MockAudioDecoder()) {
AudioDecoderConfig audio_config(kCodec,
kSampleFormat,
@@ -64,6 +66,9 @@ class AudioRendererImplTest : public ::testing::Test {
EXPECT_CALL(*decoder_, Reset(_))
.WillRepeatedly(Invoke(this, &AudioRendererImplTest::ResetDecoder));
+ EXPECT_CALL(*decoder_, Stop(_))
+ .WillRepeatedly(Invoke(this, &AudioRendererImplTest::StopDecoder));
+
// Set up audio properties.
EXPECT_CALL(*decoder_, bits_per_channel())
.WillRepeatedly(Return(audio_config.bits_per_channel()));
@@ -88,9 +93,11 @@ class AudioRendererImplTest : public ::testing::Test {
virtual ~AudioRendererImplTest() {
SCOPED_TRACE("~AudioRendererImplTest()");
- WaitableMessageLoopEvent event;
- renderer_->Stop(event.GetClosure());
- event.RunAndWait();
+ if (needs_stop_) {
+ WaitableMessageLoopEvent event;
+ renderer_->Stop(event.GetClosure());
+ event.RunAndWait();
+ }
}
void ExpectUnsupportedAudioDecoder() {
@@ -371,11 +378,25 @@ class AudioRendererImplTest : public ::testing::Test {
time_ += time;
}
+ void HoldStopDecoderCB() {
+ EXPECT_CALL(*decoder_, Stop(_)).WillRepeatedly(
+ Invoke(this, &AudioRendererImplTest::StopDecoderHoldCB));
+ }
+
+ void DispatchHeldStopDecoderCB() {
+ base::ResetAndReturn(&stop_decoder_cb_).Run();
+ }
+
+
// Fixture members.
base::MessageLoop message_loop_;
scoped_ptr<AudioRendererImpl> renderer_;
scoped_refptr<FakeAudioRendererSink> sink_;
+ // Whether or not the test needs the destructor to call Stop() on
+ // |renderer_| at destruction.
+ bool needs_stop_;
+
private:
TimeTicks GetTime() {
base::AutoLock auto_lock(lock_);
@@ -383,6 +404,9 @@ class AudioRendererImplTest : public ::testing::Test {
}
void ReadDecoder(const AudioDecoder::ReadCB& read_cb) {
+ // We shouldn't ever call Read() after Stop():
+ EXPECT_TRUE(stop_decoder_cb_.is_null());
+
// TODO(scherkus): Make this a DCHECK after threading semantics are fixed.
if (base::MessageLoop::current() != &message_loop_) {
message_loop_.PostTask(FROM_HERE, base::Bind(
@@ -406,6 +430,14 @@ class AudioRendererImplTest : public ::testing::Test {
message_loop_.PostTask(FROM_HERE, reset_cb);
}
+ void StopDecoder(const base::Closure& stop_cb) {
+ message_loop_.PostTask(FROM_HERE, stop_cb);
+ }
+
+ void StopDecoderHoldCB(const base::Closure& stop_cb) {
+ stop_decoder_cb_ = stop_cb;
+ }
+
void DeliverBuffer(AudioDecoder::Status status,
const scoped_refptr<AudioBuffer>& buffer) {
CHECK(!read_cb_.is_null());
@@ -428,6 +460,8 @@ class AudioRendererImplTest : public ::testing::Test {
// Run during ReadDecoder() to unblock WaitForPendingRead().
base::Closure wait_for_pending_read_cb_;
+ base::Closure stop_decoder_cb_;
+
DISALLOW_COPY_AND_ASSIGN(AudioRendererImplTest);
};
@@ -769,7 +803,6 @@ TEST_F(AudioRendererImplTest, PendingRead_Pause) {
Preroll(1000, PIPELINE_OK);
}
-
TEST_F(AudioRendererImplTest, PendingRead_Flush) {
Initialize();
@@ -798,7 +831,32 @@ TEST_F(AudioRendererImplTest, PendingRead_Flush) {
Preroll(1000, PIPELINE_OK);
}
-TEST_F(AudioRendererImplTest, StopDuringFlush) {
+TEST_F(AudioRendererImplTest, PendingRead_Stop) {
+ Initialize();
+
+ Preroll();
+ Play();
+
+ // Partially drain internal buffer so we get a pending read.
+ EXPECT_TRUE(ConsumeBufferedData(frames_buffered() / 2, NULL));
+ WaitForPendingRead();
+
+ Pause();
+
+ EXPECT_TRUE(IsReadPending());
+
+ WaitableMessageLoopEvent stop_event;
+ renderer_->Stop(stop_event.GetClosure());
+ needs_stop_ = false;
+
+ SatisfyPendingRead(kDataSize);
+
+ stop_event.RunAndWait();
+
+ EXPECT_FALSE(IsReadPending());
+}
+
+TEST_F(AudioRendererImplTest, PendingFlush_Stop) {
Initialize();
Preroll();
@@ -818,9 +876,40 @@ TEST_F(AudioRendererImplTest, StopDuringFlush) {
SatisfyPendingRead(kDataSize);
- // Request a Stop() before the flush completes.
+ WaitableMessageLoopEvent event;
+ renderer_->Stop(event.GetClosure());
+ event.RunAndWait();
+ needs_stop_ = false;
+}
+
+TEST_F(AudioRendererImplTest, PendingStop_Read) {
+ // This reproduces crbug.com/335181, basically an extra Read() call to the
+ // decoder can sneak into the gap between Stop() and its callback being run,
+ // which is potentially problematic if we wait until that callback runs to
+ // set the 'kStopped' state on the AudioRendererImpl.
+
+ Initialize();
+
+ Preroll();
+ Play();
+
+ // Delay calling the callback passed to AudioDecoder::Stop()
+ HoldStopDecoderCB();
+
+ // This will post at least one call to ARI::AttemptRead.
+ ConsumeAllBufferedData();
+
WaitableMessageLoopEvent stop_event;
renderer_->Stop(stop_event.GetClosure());
+ needs_stop_ = false;
+
+ // Now, after stopping, but before the callback is run, let some pending
+ // AttemptRead()'s go through... the AudioRendererImpl should ignore them,
+ // since the Stop() should have put us into the kStopped state.
+ base::RunLoop().RunUntilIdle();
+
+ // Now let the stop callback run.
+ DispatchHeldStopDecoderCB();
stop_event.RunAndWait();
}
« no previous file with comments | « media/filters/audio_renderer_impl.cc ('k') | media/filters/decrypting_audio_decoder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698