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

Unified Diff: media/filters/video_renderer_base_unittest.cc

Issue 9295020: Fix ChunkDemuxer seek deadlock (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix copyright year. Created 8 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/video_renderer_base.cc ('k') | media/webm/webm_cluster_parser.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/filters/video_renderer_base_unittest.cc
diff --git a/media/filters/video_renderer_base_unittest.cc b/media/filters/video_renderer_base_unittest.cc
index 88a1b1a8551b3dcc0d50504fc51337a5b551e07f..7ff3f411c0d93e4d21b7fd6da1f83cd8bdba4234 100644
--- a/media/filters/video_renderer_base_unittest.cc
+++ b/media/filters/video_renderer_base_unittest.cc
@@ -48,10 +48,11 @@ class VideoRendererBaseTest : public ::testing::Test {
event_(false, false),
timeout_(base::TimeDelta::FromMilliseconds(
TestTimeouts::action_timeout_ms())),
- seeking_(false) {
+ seeking_(false),
+ paint_cv_(&lock_),
+ paint_was_called_(false) {
renderer_ = new VideoRendererBase(
- base::Bind(&VideoRendererBaseTest::PaintCBWasCalled,
- base::Unretained(this)),
+ base::Bind(&VideoRendererBaseTest::Paint, base::Unretained(this)),
base::Bind(&VideoRendererBaseTest::SetOpaqueCBWasCalled,
base::Unretained(this)));
renderer_->set_host(&host_);
@@ -74,8 +75,6 @@ class VideoRendererBaseTest : public ::testing::Test {
}
}
- MOCK_METHOD0(PaintCBWasCalled, void());
-
MOCK_CONST_METHOD1(SetOpaqueCBWasCalled, void(bool));
void Initialize() {
@@ -178,6 +177,18 @@ class VideoRendererBaseTest : public ::testing::Test {
}
}
+ void AbortRead() {
+ // Lock+swap to avoid re-entrancy issues.
+ VideoDecoder::ReadCB read_cb;
+ {
+ base::AutoLock l(lock_);
+ CHECK(!read_cb_.is_null()) << "Can't deliver a frame without a callback";
+ std::swap(read_cb, read_cb_);
+ }
+
+ read_cb.Run(NULL);
+ }
+
void ExpectCurrentFrame(bool present) {
scoped_refptr<VideoFrame> frame;
renderer_->GetCurrentFrame(&frame);
@@ -220,10 +231,12 @@ class VideoRendererBaseTest : public ::testing::Test {
void RenderFrame(int64 timestamp) {
base::AutoLock l(lock_);
time_ = base::TimeDelta::FromMicroseconds(timestamp);
+ paint_was_called_ = false;
if (read_cb_.is_null()) {
cv_.TimedWait(timeout_);
CHECK(!read_cb_.is_null()) << "Timed out waiting for read to occur.";
}
+ WaitForPaint_Locked();
}
// Advances clock to |timestamp| (which should be the timestamp of the last
@@ -241,6 +254,11 @@ class VideoRendererBaseTest : public ::testing::Test {
base::WaitableEvent* event() { return &event_; }
const base::TimeDelta& timeout() { return timeout_; }
+ void VerifyNotSeeking() {
+ base::AutoLock l(lock_);
+ ASSERT_FALSE(seeking_);
+ }
+
protected:
StatisticsCallback NewStatisticsCallback() {
return base::Bind(&MockStatisticsCallback::OnStatistics,
@@ -280,13 +298,12 @@ class VideoRendererBaseTest : public ::testing::Test {
}
void FinishSeeking(int64 timestamp) {
- EXPECT_CALL(*this, PaintCBWasCalled());
- EXPECT_TRUE(seeking_);
-
// Satisfy the read requests. The callback must be executed in order
// to exit the loop since VideoRendererBase can read a few extra frames
// after |timestamp| in order to preroll.
base::AutoLock l(lock_);
+ EXPECT_TRUE(seeking_);
+ paint_was_called_ = false;
int i = 0;
while (seeking_) {
if (!read_cb_.is_null()) {
@@ -310,6 +327,21 @@ class VideoRendererBaseTest : public ::testing::Test {
}
EXPECT_TRUE(read_cb_.is_null());
+ WaitForPaint_Locked();
+ }
+
+ void Paint() {
+ base::AutoLock l(lock_);
+ paint_was_called_ = true;
+ paint_cv_.Signal();
+ }
+
+ void WaitForPaint_Locked() {
+ lock_.AssertAcquired();
+ if (paint_was_called_)
+ return;
+ paint_cv_.TimedWait(timeout_);
+ EXPECT_TRUE(paint_was_called_);
}
base::Lock lock_;
@@ -322,6 +354,10 @@ class VideoRendererBaseTest : public ::testing::Test {
VideoDecoder::ReadCB read_cb_;
base::TimeDelta time_;
+ // Used in conjunction with |lock_| to wait for Paint() calls.
+ base::ConditionVariable paint_cv_;
+ bool paint_was_called_;
+
DISALLOW_COPY_AND_ASSIGN(VideoRendererBaseTest);
};
@@ -342,13 +378,8 @@ TEST_F(VideoRendererBaseTest, EndOfStream) {
Play();
// Finish rendering up to the next-to-last frame.
- //
- // Put the gmock expectation here to avoid racing with the rendering thread.
- EXPECT_CALL(*this, PaintCBWasCalled())
- .Times(limits::kMaxVideoFrames - 1);
- for (int i = 1; i < limits::kMaxVideoFrames; ++i) {
+ for (int i = 1; i < limits::kMaxVideoFrames; ++i)
RenderFrame(kFrameDuration * i);
- }
// Finish rendering the last frame, we should NOT get a new frame but instead
// get notified of end of stream.
@@ -475,4 +506,44 @@ TEST_F(VideoRendererBaseTest, Shutdown_DuringPaint) {
Stop();
}
+TEST_F(VideoRendererBaseTest, AbortPendingRead_Playing) {
+ Initialize();
+ Play();
+
+ // Render a frame to trigger a Read().
+ RenderFrame(kFrameDuration);
+
+ AbortRead();
+
+ Pause();
+ Flush();
+ Seek(kFrameDuration * 6);
+ ExpectCurrentTimestamp(kFrameDuration * 6);
+ Shutdown();
+}
+
+TEST_F(VideoRendererBaseTest, AbortPendingRead_Flush) {
+ Initialize();
+ Play();
+
+ // Render a frame to trigger a Read().
+ RenderFrame(kFrameDuration);
+
+ Pause();
+ renderer_->Flush(NewWaitableClosure());
+ AbortRead();
+ WaitForClosure();
+ Shutdown();
+}
+
+TEST_F(VideoRendererBaseTest, AbortPendingRead_Seek) {
+ Initialize();
+ Pause();
+ Flush();
+ StartSeeking(kFrameDuration * 6);
+ AbortRead();
+ VerifyNotSeeking();
+ Shutdown();
+}
+
} // namespace media
« no previous file with comments | « media/filters/video_renderer_base.cc ('k') | media/webm/webm_cluster_parser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698