Commit ddaaf850 authored by xhwang@chromium.org's avatar xhwang@chromium.org

Make DataSource::Stop() synchronous.

In a lot of filters in media code, Stop() has been folded into the dtor.
This model doesn't apply directly to DataSource because DataSource::Stop()
is called by the FFmpegDemuxer, but the DataSource is owned by
WebMediaPlayerImpl.

TBR=gbillock@chromium.org
BUG=349211
TEST=All existing tests pass.

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@285479 0039d316-1c4b-4281-b951-d872f2087c98
parent 6affe2cb
...@@ -21,9 +21,8 @@ IPCDataSource::~IPCDataSource() { ...@@ -21,9 +21,8 @@ IPCDataSource::~IPCDataSource() {
DCHECK(utility_thread_checker_.CalledOnValidThread()); DCHECK(utility_thread_checker_.CalledOnValidThread());
} }
void IPCDataSource::Stop(const base::Closure& callback) { void IPCDataSource::Stop() {
DCHECK(data_source_thread_checker_.CalledOnValidThread()); DCHECK(data_source_thread_checker_.CalledOnValidThread());
callback.Run();
} }
void IPCDataSource::Read(int64 position, int size, uint8* data, void IPCDataSource::Read(int64 position, int size, uint8* data,
......
...@@ -32,7 +32,7 @@ class IPCDataSource: public media::DataSource, ...@@ -32,7 +32,7 @@ class IPCDataSource: public media::DataSource,
// Implementation of DataSource. These methods may be called on any single // Implementation of DataSource. These methods may be called on any single
// thread. First usage of these methods attaches a thread checker. // thread. First usage of these methods attaches a thread checker.
virtual void Stop(const base::Closure& callback) OVERRIDE; virtual void Stop() OVERRIDE;
virtual void Read(int64 position, int size, uint8* data, virtual void Read(int64 position, int size, uint8* data,
const ReadCB& read_cb) OVERRIDE; const ReadCB& read_cb) OVERRIDE;
virtual bool GetSize(int64* size_out) OVERRIDE; virtual bool GetSize(int64* size_out) OVERRIDE;
......
...@@ -207,12 +207,11 @@ void BufferedDataSource::MediaIsPaused() { ...@@ -207,12 +207,11 @@ void BufferedDataSource::MediaIsPaused() {
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// media::DataSource implementation. // media::DataSource implementation.
void BufferedDataSource::Stop(const base::Closure& closure) { void BufferedDataSource::Stop() {
{ {
base::AutoLock auto_lock(lock_); base::AutoLock auto_lock(lock_);
StopInternal_Locked(); StopInternal_Locked();
} }
closure.Run();
render_loop_->PostTask( render_loop_->PostTask(
FROM_HERE, FROM_HERE,
......
...@@ -98,7 +98,7 @@ class CONTENT_EXPORT BufferedDataSource : public media::DataSource { ...@@ -98,7 +98,7 @@ class CONTENT_EXPORT BufferedDataSource : public media::DataSource {
// media::DataSource implementation. // media::DataSource implementation.
// Called from demuxer thread. // Called from demuxer thread.
virtual void Stop(const base::Closure& closure) OVERRIDE; virtual void Stop() OVERRIDE;
virtual void Read(int64 position, int size, uint8* data, virtual void Read(int64 position, int size, uint8* data,
const media::DataSource::ReadCB& read_cb) OVERRIDE; const media::DataSource::ReadCB& read_cb) OVERRIDE;
......
...@@ -178,7 +178,7 @@ class BufferedDataSourceTest : public testing::Test { ...@@ -178,7 +178,7 @@ class BufferedDataSourceTest : public testing::Test {
message_loop_.RunUntilIdle(); message_loop_.RunUntilIdle();
} }
data_source_->Stop(media::NewExpectedClosure()); data_source_->Stop();
message_loop_.RunUntilIdle(); message_loop_.RunUntilIdle();
} }
...@@ -505,31 +505,6 @@ TEST_F(BufferedDataSourceTest, File_Successful) { ...@@ -505,31 +505,6 @@ TEST_F(BufferedDataSourceTest, File_Successful) {
Stop(); Stop();
} }
static void SetTrue(bool* value) {
*value = true;
}
// This test makes sure that Stop() does not require a task to run on
// |message_loop_| before it calls its callback. This prevents accidental
// introduction of a pipeline teardown deadlock. The pipeline owner blocks
// the render message loop while waiting for Stop() to complete. Since this
// object runs on the render message loop, Stop() will not complete if it
// requires a task to run on the the message loop that is being blocked.
TEST_F(BufferedDataSourceTest, StopDoesNotUseMessageLoopForCallback) {
InitializeWith206Response();
// Stop() the data source, using a callback that lets us verify that it was
// called before Stop() returns. This is to make sure that the callback does
// not require |message_loop_| to execute tasks before being called.
bool stop_done_called = false;
EXPECT_TRUE(data_source_->loading());
data_source_->Stop(base::Bind(&SetTrue, &stop_done_called));
// Verify that the callback was called inside the Stop() call.
EXPECT_TRUE(stop_done_called);
message_loop_.RunUntilIdle();
}
TEST_F(BufferedDataSourceTest, StopDuringRead) { TEST_F(BufferedDataSourceTest, StopDuringRead) {
InitializeWith206Response(); InitializeWith206Response();
...@@ -541,7 +516,7 @@ TEST_F(BufferedDataSourceTest, StopDuringRead) { ...@@ -541,7 +516,7 @@ TEST_F(BufferedDataSourceTest, StopDuringRead) {
{ {
InSequence s; InSequence s;
EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError)); EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
data_source_->Stop(media::NewExpectedClosure()); data_source_->Stop();
} }
message_loop_.RunUntilIdle(); message_loop_.RunUntilIdle();
} }
......
...@@ -28,7 +28,7 @@ class MEDIA_EXPORT DataSource { ...@@ -28,7 +28,7 @@ class MEDIA_EXPORT DataSource {
// Stops the DataSource. Once this is called all future Read() calls will // Stops the DataSource. Once this is called all future Read() calls will
// return an error. // return an error.
virtual void Stop(const base::Closure& callback) = 0; virtual void Stop() = 0;
// Returns true and the file size, false if the file size could not be // Returns true and the file size, false if the file size could not be
// retrieved. // retrieved.
......
...@@ -24,10 +24,7 @@ class BlockingUrlProtocolTest : public testing::Test { ...@@ -24,10 +24,7 @@ class BlockingUrlProtocolTest : public testing::Test {
} }
virtual ~BlockingUrlProtocolTest() { virtual ~BlockingUrlProtocolTest() {
base::WaitableEvent stop_event(false, false); data_source_.Stop();
data_source_.Stop(base::Bind(
&base::WaitableEvent::Signal, base::Unretained(&stop_event)));
stop_event.Wait();
} }
MOCK_METHOD0(OnDataSourceError, void()); MOCK_METHOD0(OnDataSourceError, void());
......
...@@ -530,11 +530,22 @@ FFmpegDemuxer::~FFmpegDemuxer() {} ...@@ -530,11 +530,22 @@ FFmpegDemuxer::~FFmpegDemuxer() {}
void FFmpegDemuxer::Stop(const base::Closure& callback) { void FFmpegDemuxer::Stop(const base::Closure& callback) {
DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK(task_runner_->BelongsToCurrentThread());
url_protocol_->Abort(); url_protocol_->Abort();
data_source_->Stop( data_source_->Stop();
BindToCurrentLoop(base::Bind(&FFmpegDemuxer::OnDataSourceStopped,
weak_factory_.GetWeakPtr(), // This will block until all tasks complete. Note that after this returns it's
BindToCurrentLoop(callback)))); // possible for reply tasks (e.g., OnReadFrameDone()) to be queued on this
// thread. Each of the reply task methods must check whether we've stopped the
// thread and drop their results on the floor.
blocking_thread_.Stop();
StreamVector::iterator iter;
for (iter = streams_.begin(); iter != streams_.end(); ++iter) {
if (*iter)
(*iter)->Stop();
}
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) {
...@@ -1120,23 +1131,6 @@ void FFmpegDemuxer::OnReadFrameDone(ScopedAVPacket packet, int result) { ...@@ -1120,23 +1131,6 @@ void FFmpegDemuxer::OnReadFrameDone(ScopedAVPacket packet, int result) {
ReadFrameIfNeeded(); ReadFrameIfNeeded();
} }
void FFmpegDemuxer::OnDataSourceStopped(const base::Closure& callback) {
// This will block until all tasks complete. Note that after this returns it's
// possible for reply tasks (e.g., OnReadFrameDone()) to be queued on this
// thread. Each of the reply task methods must check whether we've stopped the
// thread and drop their results on the floor.
DCHECK(task_runner_->BelongsToCurrentThread());
blocking_thread_.Stop();
StreamVector::iterator iter;
for (iter = streams_.begin(); iter != streams_.end(); ++iter) {
if (*iter)
(*iter)->Stop();
}
callback.Run();
}
bool FFmpegDemuxer::StreamsHaveAvailableCapacity() { bool FFmpegDemuxer::StreamsHaveAvailableCapacity() {
DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK(task_runner_->BelongsToCurrentThread());
StreamVector::iterator iter; StreamVector::iterator iter;
......
...@@ -197,9 +197,6 @@ class MEDIA_EXPORT FFmpegDemuxer : public Demuxer { ...@@ -197,9 +197,6 @@ class MEDIA_EXPORT FFmpegDemuxer : public Demuxer {
void ReadFrameIfNeeded(); void ReadFrameIfNeeded();
void OnReadFrameDone(ScopedAVPacket packet, int result); void OnReadFrameDone(ScopedAVPacket packet, int result);
// DataSource callbacks during stopping.
void OnDataSourceStopped(const base::Closure& callback);
// Returns true iff any stream has additional capacity. Note that streams can // Returns true iff any stream has additional capacity. Note that streams can
// go over capacity depending on how the file is muxed. // go over capacity depending on how the file is muxed.
bool StreamsHaveAvailableCapacity(); bool StreamsHaveAvailableCapacity();
......
...@@ -26,8 +26,7 @@ bool FileDataSource::Initialize(const base::FilePath& file_path) { ...@@ -26,8 +26,7 @@ bool FileDataSource::Initialize(const base::FilePath& file_path) {
return file_.Initialize(file_path); return file_.Initialize(file_path);
} }
void FileDataSource::Stop(const base::Closure& callback) { void FileDataSource::Stop() {
callback.Run();
} }
void FileDataSource::Read(int64 position, int size, uint8* data, void FileDataSource::Read(int64 position, int size, uint8* data,
......
...@@ -25,7 +25,7 @@ class MEDIA_EXPORT FileDataSource : public DataSource { ...@@ -25,7 +25,7 @@ class MEDIA_EXPORT FileDataSource : public DataSource {
bool Initialize(const base::FilePath& file_path); bool Initialize(const base::FilePath& file_path);
// Implementation of DataSource. // Implementation of DataSource.
virtual void Stop(const base::Closure& callback) OVERRIDE; virtual void Stop() OVERRIDE;
virtual void Read(int64 position, int size, uint8* data, virtual void Read(int64 position, int size, uint8* data,
const DataSource::ReadCB& read_cb) OVERRIDE; const DataSource::ReadCB& read_cb) OVERRIDE;
virtual bool GetSize(int64* size_out) OVERRIDE; virtual bool GetSize(int64* size_out) OVERRIDE;
......
...@@ -77,7 +77,7 @@ TEST(FileDataSourceTest, ReadData) { ...@@ -77,7 +77,7 @@ TEST(FileDataSourceTest, ReadData) {
&ReadCBHandler::ReadCB, base::Unretained(&handler))); &ReadCBHandler::ReadCB, base::Unretained(&handler)));
EXPECT_EQ('5', ten_bytes[0]); EXPECT_EQ('5', ten_bytes[0]);
data_source.Stop(NewExpectedClosure()); data_source.Stop();
} }
} // namespace media } // namespace media
...@@ -6,11 +6,6 @@ ...@@ -6,11 +6,6 @@
#include "base/logging.h" #include "base/logging.h"
#include "media/tools/player_x11/data_source_logger.h" #include "media/tools/player_x11/data_source_logger.h"
static void LogAndRunStopClosure(const base::Closure& closure) {
VLOG(1) << "Stop() finished";
closure.Run();
}
static void LogAndRunReadCB( static void LogAndRunReadCB(
int64 position, int size, int64 position, int size,
const media::DataSource::ReadCB& read_cb, int result) { const media::DataSource::ReadCB& read_cb, int result) {
...@@ -25,9 +20,9 @@ DataSourceLogger::DataSourceLogger( ...@@ -25,9 +20,9 @@ DataSourceLogger::DataSourceLogger(
streaming_(streaming) { streaming_(streaming) {
} }
void DataSourceLogger::Stop(const base::Closure& closure) { void DataSourceLogger::Stop() {
VLOG(1) << "Stop() started"; VLOG(1) << "Stop()";
data_source_->Stop(base::Bind(&LogAndRunStopClosure, closure)); data_source_->Stop();
} }
void DataSourceLogger::Read( void DataSourceLogger::Read(
......
...@@ -22,7 +22,7 @@ class DataSourceLogger : public media::DataSource { ...@@ -22,7 +22,7 @@ class DataSourceLogger : public media::DataSource {
virtual ~DataSourceLogger(); virtual ~DataSourceLogger();
// media::DataSource implementation. // media::DataSource implementation.
virtual void Stop(const base::Closure& closure) OVERRIDE; virtual void Stop() OVERRIDE;
virtual void Read( virtual void Read(
int64 position, int size, uint8* data, int64 position, int size, uint8* data,
const media::DataSource::ReadCB& read_cb) OVERRIDE; const media::DataSource::ReadCB& read_cb) OVERRIDE;
......
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