Commit fcdacaf9 authored by xhwang's avatar xhwang Committed by Commit bot

Make Demuxer::Stop() synchronous.

BUG=349211
TEST=All existing tests pass.

Review URL: https://codereview.chromium.org/416393003

Cr-Commit-Position: refs/heads/master@{#292958}
parent a75ac029
...@@ -139,10 +139,14 @@ void MediaSourceDelegate::StopDemuxer() { ...@@ -139,10 +139,14 @@ void MediaSourceDelegate::StopDemuxer() {
media_weak_factory_.InvalidateWeakPtrs(); media_weak_factory_.InvalidateWeakPtrs();
DCHECK(!media_weak_factory_.HasWeakPtrs()); DCHECK(!media_weak_factory_.HasWeakPtrs());
// The callback OnDemuxerStopDone() owns |this| and will delete it when chunk_demuxer_->Stop();
// called. Hence using base::Unretained(this) is safe here. chunk_demuxer_.reset();
chunk_demuxer_->Stop(base::Bind(&MediaSourceDelegate::OnDemuxerStopDone,
base::Unretained(this))); // The callback DeleteSelf() owns |this| and will delete it when called.
// Hence using base::Unretained(this) is safe here.
media_task_runner_->PostTask(
FROM_HERE,
base::Bind(&MediaSourceDelegate::DeleteSelf, base::Unretained(this)));
} }
void MediaSourceDelegate::InitializeMediaSource( void MediaSourceDelegate::InitializeMediaSource(
...@@ -626,18 +630,9 @@ void MediaSourceDelegate::FinishResettingDecryptingDemuxerStreams() { ...@@ -626,18 +630,9 @@ void MediaSourceDelegate::FinishResettingDecryptingDemuxerStreams() {
demuxer_client_->DemuxerSeekDone(demuxer_client_id_, browser_seek_time_); demuxer_client_->DemuxerSeekDone(demuxer_client_id_, browser_seek_time_);
} }
void MediaSourceDelegate::OnDemuxerStopDone() {
DCHECK(media_task_runner_->BelongsToCurrentThread());
DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
main_task_runner_->PostTask(
FROM_HERE,
base::Bind(&MediaSourceDelegate::DeleteSelf, base::Unretained(this)));
}
void MediaSourceDelegate::DeleteSelf() { void MediaSourceDelegate::DeleteSelf() {
DCHECK(main_task_runner_->BelongsToCurrentThread()); DCHECK(main_task_runner_->BelongsToCurrentThread());
DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
chunk_demuxer_.reset();
delete this; delete this;
} }
......
...@@ -146,9 +146,7 @@ class MediaSourceDelegate : public media::DemuxerHost { ...@@ -146,9 +146,7 @@ class MediaSourceDelegate : public media::DemuxerHost {
void ResetVideoDecryptingDemuxerStream(); void ResetVideoDecryptingDemuxerStream();
void FinishResettingDecryptingDemuxerStreams(); void FinishResettingDecryptingDemuxerStreams();
// Callback for ChunkDemuxer::Stop() and helper for deleting |this| on the // Helper for deleting |this| on the main thread.
// main thread.
void OnDemuxerStopDone();
void DeleteSelf(); void DeleteSelf();
void OnDemuxerOpened(); void OnDemuxerOpened();
......
...@@ -72,11 +72,11 @@ class MEDIA_EXPORT Demuxer { ...@@ -72,11 +72,11 @@ class MEDIA_EXPORT Demuxer {
virtual void Seek(base::TimeDelta time, virtual void Seek(base::TimeDelta time,
const PipelineStatusCB& status_cb) = 0; const PipelineStatusCB& status_cb) = 0;
// Starts stopping this demuxer, executing the callback upon completion. // Stops this demuxer.
// //
// After the callback completes the demuxer may be destroyed. It is illegal to // After this call the demuxer may be destroyed. It is illegal to call any
// call any method (including Stop()) after a demuxer has stopped. // method (including Stop()) after a demuxer has stopped.
virtual void Stop(const base::Closure& callback) = 0; virtual void Stop() = 0;
// Returns the first stream of the given stream type (which is not allowed // Returns the first stream of the given stream type (which is not allowed
// to be DemuxerStream::TEXT), or NULL if that type of stream is not present. // to be DemuxerStream::TEXT), or NULL if that type of stream is not present.
......
...@@ -38,7 +38,7 @@ class DemuxerHostImpl : public media::DemuxerHost { ...@@ -38,7 +38,7 @@ class DemuxerHostImpl : public media::DemuxerHost {
}; };
static void QuitLoopWithStatus(base::MessageLoop* message_loop, static void QuitLoopWithStatus(base::MessageLoop* message_loop,
media::PipelineStatus status) { media::PipelineStatus status) {
CHECK_EQ(status, media::PIPELINE_OK); CHECK_EQ(status, media::PIPELINE_OK);
message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
} }
...@@ -194,8 +194,8 @@ static void RunDemuxerBenchmark(const std::string& filename) { ...@@ -194,8 +194,8 @@ static void RunDemuxerBenchmark(const std::string& filename) {
} }
base::TimeTicks end = base::TimeTicks::HighResNow(); base::TimeTicks end = base::TimeTicks::HighResNow();
total_time += (end - start).InSecondsF(); total_time += (end - start).InSecondsF();
demuxer.Stop(base::Bind( demuxer.Stop();
&QuitLoopWithStatus, &message_loop, PIPELINE_OK)); QuitLoopWithStatus(&message_loop, PIPELINE_OK);
message_loop.Run(); message_loop.Run();
} }
......
...@@ -36,7 +36,7 @@ class MockDemuxer : public Demuxer { ...@@ -36,7 +36,7 @@ class MockDemuxer : public Demuxer {
void(DemuxerHost* host, const PipelineStatusCB& cb, bool)); void(DemuxerHost* host, const PipelineStatusCB& cb, bool));
MOCK_METHOD1(SetPlaybackRate, void(float playback_rate)); MOCK_METHOD1(SetPlaybackRate, void(float playback_rate));
MOCK_METHOD2(Seek, void(base::TimeDelta time, const PipelineStatusCB& cb)); MOCK_METHOD2(Seek, void(base::TimeDelta time, const PipelineStatusCB& cb));
MOCK_METHOD1(Stop, void(const base::Closure& callback)); MOCK_METHOD0(Stop, void());
MOCK_METHOD0(OnAudioRendererDisabled, void()); MOCK_METHOD0(OnAudioRendererDisabled, void());
MOCK_METHOD1(GetStream, DemuxerStream*(DemuxerStream::Type)); MOCK_METHOD1(GetStream, DemuxerStream*(DemuxerStream::Type));
MOCK_CONST_METHOD0(GetTimelineOffset, base::Time()); MOCK_CONST_METHOD0(GetTimelineOffset, base::Time());
......
...@@ -410,8 +410,8 @@ void Pipeline::DoStop(const PipelineStatusCB& done_cb) { ...@@ -410,8 +410,8 @@ void Pipeline::DoStop(const PipelineStatusCB& done_cb) {
text_renderer_.reset(); text_renderer_.reset();
if (demuxer_) { if (demuxer_) {
demuxer_->Stop(base::Bind(done_cb, PIPELINE_OK)); demuxer_->Stop();
return; demuxer_ = NULL;
} }
task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK)); task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK));
......
...@@ -276,7 +276,7 @@ class PipelineTest : public ::testing::Test { ...@@ -276,7 +276,7 @@ class PipelineTest : public ::testing::Test {
void ExpectDemuxerStop() { void ExpectDemuxerStop() {
if (demuxer_) if (demuxer_)
EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>()); EXPECT_CALL(*demuxer_, Stop());
} }
void ExpectPipelineStopAndDestroyPipeline() { void ExpectPipelineStopAndDestroyPipeline() {
...@@ -371,8 +371,7 @@ TEST_F(PipelineTest, StopWithoutStart) { ...@@ -371,8 +371,7 @@ TEST_F(PipelineTest, StopWithoutStart) {
TEST_F(PipelineTest, StartThenStopImmediately) { TEST_F(PipelineTest, StartThenStopImmediately) {
EXPECT_CALL(*demuxer_, Initialize(_, _, _)) EXPECT_CALL(*demuxer_, Initialize(_, _, _))
.WillOnce(RunCallback<1>(PIPELINE_OK)); .WillOnce(RunCallback<1>(PIPELINE_OK));
EXPECT_CALL(*demuxer_, Stop(_)) EXPECT_CALL(*demuxer_, Stop());
.WillOnce(RunClosure<0>());
EXPECT_CALL(callbacks_, OnStart(_)); EXPECT_CALL(callbacks_, OnStart(_));
StartPipeline(); StartPipeline();
...@@ -394,9 +393,8 @@ TEST_F(PipelineTest, DemuxerErrorDuringStop) { ...@@ -394,9 +393,8 @@ TEST_F(PipelineTest, DemuxerErrorDuringStop) {
StartPipelineAndExpect(PIPELINE_OK); StartPipelineAndExpect(PIPELINE_OK);
EXPECT_CALL(*demuxer_, Stop(_)) EXPECT_CALL(*demuxer_, Stop())
.WillOnce(DoAll(InvokeWithoutArgs(this, &PipelineTest::OnDemuxerError), .WillOnce(InvokeWithoutArgs(this, &PipelineTest::OnDemuxerError));
RunClosure<0>()));
ExpectPipelineStopAndDestroyPipeline(); ExpectPipelineStopAndDestroyPipeline();
pipeline_->Stop( pipeline_->Stop(
...@@ -407,8 +405,7 @@ TEST_F(PipelineTest, DemuxerErrorDuringStop) { ...@@ -407,8 +405,7 @@ TEST_F(PipelineTest, DemuxerErrorDuringStop) {
TEST_F(PipelineTest, URLNotFound) { TEST_F(PipelineTest, URLNotFound) {
EXPECT_CALL(*demuxer_, Initialize(_, _, _)) EXPECT_CALL(*demuxer_, Initialize(_, _, _))
.WillOnce(RunCallback<1>(PIPELINE_ERROR_URL_NOT_FOUND)); .WillOnce(RunCallback<1>(PIPELINE_ERROR_URL_NOT_FOUND));
EXPECT_CALL(*demuxer_, Stop(_)) EXPECT_CALL(*demuxer_, Stop());
.WillOnce(RunClosure<0>());
StartPipelineAndExpect(PIPELINE_ERROR_URL_NOT_FOUND); StartPipelineAndExpect(PIPELINE_ERROR_URL_NOT_FOUND);
} }
...@@ -416,8 +413,7 @@ TEST_F(PipelineTest, URLNotFound) { ...@@ -416,8 +413,7 @@ TEST_F(PipelineTest, URLNotFound) {
TEST_F(PipelineTest, NoStreams) { TEST_F(PipelineTest, NoStreams) {
EXPECT_CALL(*demuxer_, Initialize(_, _, _)) EXPECT_CALL(*demuxer_, Initialize(_, _, _))
.WillOnce(RunCallback<1>(PIPELINE_OK)); .WillOnce(RunCallback<1>(PIPELINE_OK));
EXPECT_CALL(*demuxer_, Stop(_)) EXPECT_CALL(*demuxer_, Stop());
.WillOnce(RunClosure<0>());
StartPipelineAndExpect(PIPELINE_ERROR_COULD_NOT_RENDER); StartPipelineAndExpect(PIPELINE_ERROR_COULD_NOT_RENDER);
} }
...@@ -528,8 +524,7 @@ TEST_F(PipelineTest, SeekAfterError) { ...@@ -528,8 +524,7 @@ TEST_F(PipelineTest, SeekAfterError) {
// Initialize then seek! // Initialize then seek!
StartPipelineAndExpect(PIPELINE_OK); StartPipelineAndExpect(PIPELINE_OK);
EXPECT_CALL(*demuxer_, Stop(_)) EXPECT_CALL(*demuxer_, Stop());
.WillOnce(RunClosure<0>());
EXPECT_CALL(callbacks_, OnError(_)); EXPECT_CALL(callbacks_, OnError(_));
static_cast<DemuxerHost*>(pipeline_.get()) static_cast<DemuxerHost*>(pipeline_.get())
...@@ -649,8 +644,7 @@ TEST_F(PipelineTest, ErrorDuringSeek) { ...@@ -649,8 +644,7 @@ TEST_F(PipelineTest, ErrorDuringSeek) {
EXPECT_CALL(*demuxer_, Seek(seek_time, _)) EXPECT_CALL(*demuxer_, Seek(seek_time, _))
.WillOnce(RunCallback<1>(PIPELINE_ERROR_READ)); .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
EXPECT_CALL(*demuxer_, Stop(_)) EXPECT_CALL(*demuxer_, Stop());
.WillOnce(RunClosure<0>());
pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek, pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
base::Unretained(&callbacks_))); base::Unretained(&callbacks_)));
...@@ -703,8 +697,7 @@ TEST_F(PipelineTest, NoMessageDuringTearDownFromError) { ...@@ -703,8 +697,7 @@ TEST_F(PipelineTest, NoMessageDuringTearDownFromError) {
EXPECT_CALL(*demuxer_, Seek(seek_time, _)) EXPECT_CALL(*demuxer_, Seek(seek_time, _))
.WillOnce(RunCallback<1>(PIPELINE_ERROR_READ)); .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
EXPECT_CALL(*demuxer_, Stop(_)) EXPECT_CALL(*demuxer_, Stop());
.WillOnce(RunClosure<0>());
pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek, pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
base::Unretained(&callbacks_))); base::Unretained(&callbacks_)));
...@@ -819,7 +812,7 @@ class PipelineTeardownTest : public PipelineTest { ...@@ -819,7 +812,7 @@ class PipelineTeardownTest : public PipelineTest {
.WillOnce(RunCallback<1>(status)); .WillOnce(RunCallback<1>(status));
} }
EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>()); EXPECT_CALL(*demuxer_, Stop());
return status; return status;
} }
...@@ -845,7 +838,7 @@ class PipelineTeardownTest : public PipelineTest { ...@@ -845,7 +838,7 @@ class PipelineTeardownTest : public PipelineTest {
.WillOnce(RunCallback<0>(status)); .WillOnce(RunCallback<0>(status));
} }
EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>()); EXPECT_CALL(*demuxer_, Stop());
return status; return status;
} }
...@@ -872,7 +865,7 @@ class PipelineTeardownTest : public PipelineTest { ...@@ -872,7 +865,7 @@ class PipelineTeardownTest : public PipelineTest {
InSequence s; InSequence s;
PipelineStatus status = SetSeekExpectations(state, stop_or_error); PipelineStatus status = SetSeekExpectations(state, stop_or_error);
EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>()); EXPECT_CALL(*demuxer_, Stop());
EXPECT_CALL(callbacks_, OnSeek(status)); EXPECT_CALL(callbacks_, OnSeek(status));
if (status == PIPELINE_OK) { if (status == PIPELINE_OK) {
...@@ -938,7 +931,7 @@ class PipelineTeardownTest : public PipelineTest { ...@@ -938,7 +931,7 @@ class PipelineTeardownTest : public PipelineTest {
void DoStopOrError(StopOrError stop_or_error) { void DoStopOrError(StopOrError stop_or_error) {
InSequence s; InSequence s;
EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>()); EXPECT_CALL(*demuxer_, Stop());
switch (stop_or_error) { switch (stop_or_error) {
case kStop: case kStop:
...@@ -956,6 +949,7 @@ class PipelineTeardownTest : public PipelineTest { ...@@ -956,6 +949,7 @@ class PipelineTeardownTest : public PipelineTest {
EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ)); EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ));
ExpectPipelineStopAndDestroyPipeline(); ExpectPipelineStopAndDestroyPipeline();
pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ); pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ);
message_loop_.RunUntilIdle();
pipeline_->Stop(base::Bind( pipeline_->Stop(base::Bind(
&CallbackHelper::OnStop, base::Unretained(&callbacks_))); &CallbackHelper::OnStop, base::Unretained(&callbacks_)));
break; break;
......
...@@ -1057,10 +1057,9 @@ void ChunkDemuxer::Initialize( ...@@ -1057,10 +1057,9 @@ void ChunkDemuxer::Initialize(
base::ResetAndReturn(&open_cb_).Run(); base::ResetAndReturn(&open_cb_).Run();
} }
void ChunkDemuxer::Stop(const base::Closure& callback) { void ChunkDemuxer::Stop() {
DVLOG(1) << "Stop()"; DVLOG(1) << "Stop()";
Shutdown(); Shutdown();
callback.Run();
} }
void ChunkDemuxer::Seek(TimeDelta time, const PipelineStatusCB& cb) { void ChunkDemuxer::Seek(TimeDelta time, const PipelineStatusCB& cb) {
......
...@@ -159,7 +159,7 @@ class MEDIA_EXPORT ChunkDemuxer : public Demuxer { ...@@ -159,7 +159,7 @@ class MEDIA_EXPORT ChunkDemuxer : public Demuxer {
virtual void Initialize(DemuxerHost* host, virtual void Initialize(DemuxerHost* host,
const PipelineStatusCB& cb, const PipelineStatusCB& cb,
bool enable_text_tracks) OVERRIDE; bool enable_text_tracks) OVERRIDE;
virtual void Stop(const base::Closure& callback) OVERRIDE; virtual void Stop() OVERRIDE;
virtual void Seek(base::TimeDelta time, const PipelineStatusCB& cb) OVERRIDE; virtual void Seek(base::TimeDelta time, const PipelineStatusCB& cb) OVERRIDE;
virtual DemuxerStream* GetStream(DemuxerStream::Type type) OVERRIDE; virtual DemuxerStream* GetStream(DemuxerStream::Type type) OVERRIDE;
virtual base::Time GetTimelineOffset() const OVERRIDE; virtual base::Time GetTimelineOffset() const OVERRIDE;
......
...@@ -555,7 +555,7 @@ FFmpegDemuxer::FFmpegDemuxer( ...@@ -555,7 +555,7 @@ FFmpegDemuxer::FFmpegDemuxer(
FFmpegDemuxer::~FFmpegDemuxer() {} FFmpegDemuxer::~FFmpegDemuxer() {}
void FFmpegDemuxer::Stop(const base::Closure& callback) { void FFmpegDemuxer::Stop() {
DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK(task_runner_->BelongsToCurrentThread());
url_protocol_->Abort(); url_protocol_->Abort();
data_source_->Stop(); data_source_->Stop();
...@@ -573,7 +573,6 @@ void FFmpegDemuxer::Stop(const base::Closure& callback) { ...@@ -573,7 +573,6 @@ void FFmpegDemuxer::Stop(const base::Closure& callback) {
} }
data_source_ = NULL; data_source_ = NULL;
task_runner_->PostTask(FROM_HERE, callback);
} }
void FFmpegDemuxer::Seek(base::TimeDelta time, const PipelineStatusCB& cb) { void FFmpegDemuxer::Seek(base::TimeDelta time, const PipelineStatusCB& cb) {
......
...@@ -164,7 +164,7 @@ class MEDIA_EXPORT FFmpegDemuxer : public Demuxer { ...@@ -164,7 +164,7 @@ class MEDIA_EXPORT FFmpegDemuxer : public Demuxer {
virtual void Initialize(DemuxerHost* host, virtual void Initialize(DemuxerHost* host,
const PipelineStatusCB& status_cb, const PipelineStatusCB& status_cb,
bool enable_text_tracks) OVERRIDE; bool enable_text_tracks) OVERRIDE;
virtual void Stop(const base::Closure& callback) OVERRIDE; virtual void Stop() OVERRIDE;
virtual void Seek(base::TimeDelta time, const PipelineStatusCB& cb) OVERRIDE; virtual void Seek(base::TimeDelta time, const PipelineStatusCB& cb) OVERRIDE;
virtual DemuxerStream* GetStream(DemuxerStream::Type type) OVERRIDE; virtual DemuxerStream* GetStream(DemuxerStream::Type type) OVERRIDE;
virtual base::Time GetTimelineOffset() const OVERRIDE; virtual base::Time GetTimelineOffset() const OVERRIDE;
......
...@@ -67,11 +67,8 @@ class FFmpegDemuxerTest : public testing::Test { ...@@ -67,11 +67,8 @@ class FFmpegDemuxerTest : public testing::Test {
FFmpegDemuxerTest() {} FFmpegDemuxerTest() {}
virtual ~FFmpegDemuxerTest() { virtual ~FFmpegDemuxerTest() {
if (demuxer_) { if (demuxer_)
WaitableMessageLoopEvent event; demuxer_->Stop();
demuxer_->Stop(event.GetClosure());
event.RunAndWait();
}
} }
void CreateDemuxer(const std::string& name) { void CreateDemuxer(const std::string& name) {
...@@ -753,9 +750,7 @@ TEST_F(FFmpegDemuxerTest, Stop) { ...@@ -753,9 +750,7 @@ TEST_F(FFmpegDemuxerTest, Stop) {
DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO); DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
ASSERT_TRUE(audio); ASSERT_TRUE(audio);
WaitableMessageLoopEvent event; demuxer_->Stop();
demuxer_->Stop(event.GetClosure());
event.RunAndWait();
// Reads after being stopped are all EOS buffers. // Reads after being stopped are all EOS buffers.
StrictMock<MockReadCB> callback; StrictMock<MockReadCB> callback;
...@@ -914,9 +909,7 @@ TEST_F(FFmpegDemuxerTest, IsValidAnnexB) { ...@@ -914,9 +909,7 @@ TEST_F(FFmpegDemuxerTest, IsValidAnnexB) {
stream->Read(base::Bind(&ValidateAnnexB, stream)); stream->Read(base::Bind(&ValidateAnnexB, stream));
message_loop_.Run(); message_loop_.Run();
WaitableMessageLoopEvent event; demuxer_->Stop();
demuxer_->Stop(event.GetClosure());
event.RunAndWait();
demuxer_.reset(); demuxer_.reset();
data_source_.reset(); data_source_.reset();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment