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

Unified Diff: content/renderer/media/webmediaplayer_ms_unittest.cc

Issue 1417533006: Unit test for WebMediaPlayerMS (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Unittest Created 5 years, 2 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
Index: content/renderer/media/webmediaplayer_ms_unittest.cc
diff --git a/content/renderer/media/webmediaplayer_ms_unittest.cc b/content/renderer/media/webmediaplayer_ms_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..eeb8df0dcddf5b1a823a12a0f6a9d869e10a86a2
--- /dev/null
+++ b/content/renderer/media/webmediaplayer_ms_unittest.cc
@@ -0,0 +1,700 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "cc/layers/video_frame_provider.h"
+#include "content/public/renderer/media_stream_renderer_factory.h"
+#include "content/public/renderer/video_frame_provider.h"
+#include "content/renderer/media/mock_media_constraint_factory.h"
+#include "content/renderer/media/render_media_log.h"
+#include "content/renderer/media/webmediaplayer_ms.h"
+#include "content/renderer/media/webrtc_audio_renderer.h"
+#include "content/renderer/render_frame_impl.h"
+#include "media/base/gmock_callback_support.h"
+#include "media/base/mock_filters.h"
+#include "media/base/test_helpers.h"
+#include "media/base/video_frame.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
+#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
+#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
mcasas 2015/10/21 19:54:02 Needed? (check all header please).
qiangchen 2015/10/22 17:22:58 Done. Looks like many includes are included in te
+
+namespace content {
+
+class WebMediaPlayerMSTest;
+
+class MockCB {
mcasas 2015/10/21 19:54:02 There's indeed plenty of Mock/Test dependent class
qiangchen 2015/10/22 17:22:58 My investigation shows only content::VideoFramePro
+ public:
+ MOCK_METHOD0(StartRendering, void());
+ MOCK_METHOD0(StopRendering, void());
+
+ MOCK_METHOD1(NetworkStateChanged, void(blink::WebMediaPlayer::NetworkState));
+ MOCK_METHOD1(ReadyStateChanged, void(blink::WebMediaPlayer::ReadyState));
+ void VerifyAndClearExpectations() {
+ // Note: the raw value of "this" could be different from &mock_cb_.
+ // So this is not equivalent with calling
+ // VerifyAndClearExpectations(&mock_cb_) outside.
+ testing::Mock::VerifyAndClearExpectations(this);
+ }
+};
+
+struct TestFrame {
+ enum TestFrameType {
+ NORMAL_FRAME,
+ BROKEN_FRAME,
+ TEST_BRAKE // Signal to pause message loop.
+ };
+ TestFrame(TestFrameType input_category,
+ const scoped_refptr<media::VideoFrame>& input_frame)
+ : category(input_category), frame(input_frame) {}
+
+ TestFrameType category;
+ scoped_refptr<media::VideoFrame> frame;
+};
+
+class ReusableMessageLoopEvent {
+ public:
+ ReusableMessageLoopEvent() : event_(new media::WaitableMessageLoopEvent()) {}
+
+ base::Closure GetClosure() { return event_->GetClosure(); }
+
+ media::PipelineStatusCB GetPipelineStatusCB() {
+ return event_->GetPipelineStatusCB();
+ }
+
+ void RunAndWait() {
+ event_->RunAndWait();
+ event_.reset(new media::WaitableMessageLoopEvent());
+ }
+
+ void RunAndWaitForStatus(media::PipelineStatus expected) {
+ event_->RunAndWaitForStatus(expected);
+ event_.reset(new media::WaitableMessageLoopEvent());
+ }
+
+ private:
+ scoped_ptr<media::WaitableMessageLoopEvent> event_;
+};
+
+// The class mainly used to inject VideoFrames into WebMediaPlayerMS.
+class MockVideoFrameProvider : public VideoFrameProvider {
+ public:
+ MockVideoFrameProvider(base::MessageLoop* message_loop,
+ ReusableMessageLoopEvent* message_loop_controller,
+ const base::Closure& error_cb,
+ const VideoFrameProvider::RepaintCB& repaint_cb)
+ : started_(false),
+ message_loop_(message_loop),
+ message_loop_controller_(message_loop_controller),
+ error_cb_(error_cb),
+ repaint_cb_(repaint_cb),
+ delay_(base::TimeDelta::FromSecondsD(1.0 / 30.0)) {}
+
+ // Implementation of VideoFrameProvider
+ void Start() override;
+ void Stop() override;
+ void Play() override;
+ void Pause() override;
+
+ // Methods for test use
+ void QueueFrames(const std::string& str);
mcasas 2015/10/21 19:54:02 I don't see much added value in creating/passing t
qiangchen 2015/10/22 17:22:58 Done.
+ void PrepareFrame(TestFrame::TestFrameType category,
+ const scoped_refptr<media::VideoFrame>& frame);
+ bool Started();
+ bool Paused();
+
+ private:
+ ~MockVideoFrameProvider() override {}
+
+ // Main function that pushes frame into WebMediaPlayerMS
+ void InjectFrame();
+
+ bool started_;
+ bool paused_;
+
+ base::MessageLoop* message_loop_;
+ ReusableMessageLoopEvent* message_loop_controller_;
+ base::Closure error_cb_;
+ VideoFrameProvider::RepaintCB repaint_cb_;
+
+ std::deque<TestFrame> frames_;
+ base::TimeDelta delay_;
+};
+
+// The class is used to generate MockVideoProvider
+class MockRenderFactory : public MediaStreamRendererFactory {
+ public:
+ MockRenderFactory(base::MessageLoop* message_loop,
+ ReusableMessageLoopEvent* message_loop_controller)
+ : message_loop_(message_loop),
+ message_loop_controller_(message_loop_controller) {}
+
+ scoped_refptr<VideoFrameProvider> GetVideoFrameProvider(
+ const GURL& url,
+ const base::Closure& error_cb,
+ const VideoFrameProvider::RepaintCB& repaint_cb,
+ const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
+ const scoped_refptr<base::TaskRunner>& worker_task_runner,
+ media::GpuVideoAcceleratorFactories* gpu_factories) override;
+
+ MockVideoFrameProvider* GetVideoFrameProvider();
+
+ scoped_refptr<MediaStreamAudioRenderer> GetAudioRenderer(
+ const GURL& url,
+ int render_frame_id,
+ const std::string& device_id,
+ const url::Origin& security_origin) override;
+
+ private:
+ base::MessageLoop* message_loop_;
+ scoped_refptr<VideoFrameProvider> provider_;
+ ReusableMessageLoopEvent* message_loop_controller_;
+};
+
+// The class is responsible to pull frames from WebMediaPlayerMS
+class MockVideoFrameProviderClient : public cc::VideoFrameProvider::Client {
+ public:
+ MockVideoFrameProviderClient(base::MessageLoop* message_loop,
+ cc::VideoFrameProvider* compositor,
+ MockCB* mock_cb)
+ : rendering_(false),
+ background_rendering_(false),
+ message_loop_(message_loop),
+ compositor_(compositor),
+ mock_cb_(mock_cb) {}
+
+ // Implementation of cc::VideoFrameProvider::Client
+ void StopUsingProvider() override;
+ void StartRendering() override;
+ void StopRendering() override;
+ void DidReceiveFrame() override {}
+ void DidUpdateMatrix(const float* matrix) override {}
+
+ // For test use
+ void SetBackgroundRendering(bool background_rendering);
+
+ private:
+ // Main function trying to ask WebMediaPlayerMS to submit a frame for
+ // rendering.
+ void RenderFrame();
+
+ bool rendering_;
+ bool background_rendering_;
+ base::MessageLoop* message_loop_;
+ cc::VideoFrameProvider* compositor_;
+ MockCB* mock_cb_;
+};
+
+// This class is used to respond to WebMediaPlayerMS status change.
+class MockClient : public blink::WebMediaPlayerClient {
+ public:
+ MockClient(WebMediaPlayerMSTest* test,
+ WebMediaPlayerMS* player,
+ base::MessageLoop* message_loop,
+ ReusableMessageLoopEvent* message_loop_controller)
+ : test_(test),
+ player_(player),
+ message_loop_(message_loop),
+ message_loop_controller_(message_loop_controller),
+ compositor_(nullptr) {}
+ ~MockClient() {}
+
+ // Implementation of WebMediaPlayerClient
+ void networkStateChanged() override;
+ void readyStateChanged() override;
+ void timeChanged() override {}
+ void repaint() override {}
+ void durationChanged() override {}
+ void sizeChanged() override {}
+ void playbackStateChanged() override {}
+ void setWebLayer(blink::WebLayer* layer) override;
+ blink::WebMediaPlayer::TrackId addAudioTrack(const blink::WebString& id,
+ AudioTrackKind,
+ const blink::WebString& label,
+ const blink::WebString& language,
+ bool enabled) override;
+ void removeAudioTrack(blink::WebMediaPlayer::TrackId) override {}
+ blink::WebMediaPlayer::TrackId addVideoTrack(const blink::WebString& id,
+ VideoTrackKind,
+ const blink::WebString& label,
+ const blink::WebString& language,
+ bool selected) override;
+ void removeVideoTrack(blink::WebMediaPlayer::TrackId) override {}
+ void addTextTrack(blink::WebInbandTextTrack*) override {}
+ void removeTextTrack(blink::WebInbandTextTrack*) override {}
+ void mediaSourceOpened(blink::WebMediaSource*) override {}
+ void requestSeek(double) override {}
+ void remoteRouteAvailabilityChanged(bool) override {}
+ void connectedToRemoteDevice() override {}
+ void disconnectedFromRemoteDevice() override {}
+
+ // For test use
+ MockVideoFrameProviderClient* GetVideoFrameProviderClient();
+
+ private:
+ WebMediaPlayerMSTest* test_;
+ WebMediaPlayerMS* player_;
+ base::MessageLoop* message_loop_;
+ ReusableMessageLoopEvent* message_loop_controller_;
+ cc::VideoFrameProvider* compositor_;
+ scoped_ptr<MockVideoFrameProviderClient> video_frame_provider_client_;
+};
+
+class WebMediaPlayerMSTest : public testing::Test {
+ public:
+ WebMediaPlayerMSTest()
+ : client_(this, &player_, &message_loop_, &message_loop_controller_),
+ render_factory_(
+ new MockRenderFactory(&message_loop_, &message_loop_controller_)),
+ player_(nullptr,
+ &client_,
+ base::WeakPtr<RenderFrameImpl>(),
+ new media::MediaLog(),
+ scoped_ptr<MediaStreamRendererFactory>(render_factory_),
+ message_loop_.task_runner(),
+ message_loop_.task_runner(),
+ message_loop_.task_runner(),
+ nullptr) {}
+ ~WebMediaPlayerMSTest() override {}
+
+ MockVideoFrameProvider* LoadAndGetFrameProvider(bool algorithm_enabled);
+ cc::VideoFrameProvider* GetCompositorForTest();
+ MockCB* GetMockCB();
+
+ protected:
+ // Use StrictMock<T> to catch missing/extra callbacks.
+ testing::StrictMock<MockCB> mock_cb_;
+
+ base::MessageLoop message_loop_;
+ MockClient client_;
+ MockRenderFactory* render_factory_;
+ WebMediaPlayerMS player_;
+ cc::VideoFrameProvider* compositor_;
+
+ ReusableMessageLoopEvent message_loop_controller_;
+};
+
+MockVideoFrameProvider* WebMediaPlayerMSTest::LoadAndGetFrameProvider(
+ bool algorithm_enabled) {
+ MockVideoFrameProvider* provider = render_factory_->GetVideoFrameProvider();
+ EXPECT_EQ(nullptr, provider);
+
+ EXPECT_CALL(mock_cb_,
+ NetworkStateChanged(blink::WebMediaPlayer::NetworkStateLoading));
+ EXPECT_CALL(mock_cb_,
+ ReadyStateChanged(blink::WebMediaPlayer::ReadyStateHaveNothing));
+ compositor_ = player_.LoadForTesting(algorithm_enabled);
+
+ provider = render_factory_->GetVideoFrameProvider();
+ EXPECT_NE(nullptr, provider);
+ EXPECT_TRUE(provider->Started());
+
+ mock_cb_.VerifyAndClearExpectations();
+ return provider;
+}
+
+cc::VideoFrameProvider* WebMediaPlayerMSTest::GetCompositorForTest() {
+ return compositor_;
+}
+
+MockCB* WebMediaPlayerMSTest::GetMockCB() {
+ return &mock_cb_;
+}
+
+void MockVideoFrameProvider::Start() {
+ started_ = true;
+ paused_ = false;
+ message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&MockVideoFrameProvider::InjectFrame, base::Unretained(this)));
+}
+
+void MockVideoFrameProvider::Stop() {
+ started_ = false;
+ frames_.clear();
+}
+
+void MockVideoFrameProvider::Play() {
+ CHECK(started_);
+ paused_ = false;
+}
+
+void MockVideoFrameProvider::Pause() {
+ CHECK(started_);
+ paused_ = true;
+}
+
+void MockVideoFrameProvider::PrepareFrame(
+ TestFrame::TestFrameType category,
+ const scoped_refptr<media::VideoFrame>& frame) {
+ frames_.push_back(TestFrame(category, frame));
+}
+
+void MockVideoFrameProvider::QueueFrames(const std::string& str) {
+ for (const std::string& token : base::SplitString(
+ str, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) {
+ if (token == "error") {
+ PrepareFrame(TestFrame::TestFrameType::BROKEN_FRAME, nullptr);
+ continue;
+ }
+ if (token == "brake") {
+ PrepareFrame(TestFrame::TestFrameType::TEST_BRAKE, nullptr);
+ continue;
+ }
+
+ int timestamp_in_ms = 0;
+ if (base::StringToInt(token, &timestamp_in_ms)) {
+ gfx::Size natural_size = media::TestVideoConfig::NormalCodedSize();
+ auto frame = media::VideoFrame::CreateFrame(
+ media::PIXEL_FORMAT_YV12, natural_size, gfx::Rect(natural_size),
+ natural_size, base::TimeDelta::FromMilliseconds(timestamp_in_ms));
+
+ frame->metadata()->SetTimeTicks(
+ media::VideoFrameMetadata::Key::REFERENCE_TIME,
+ base::TimeTicks::Now() +
+ base::TimeDelta::FromMilliseconds(timestamp_in_ms));
+
+ PrepareFrame(TestFrame::TestFrameType::NORMAL_FRAME, frame);
+ continue;
+ }
+
+ CHECK(false) << "Unrecognized token: " << token;
+ }
+}
+
+bool MockVideoFrameProvider::Started() {
+ return started_;
+}
+
+bool MockVideoFrameProvider::Paused() {
+ return paused_;
+}
+
+void MockVideoFrameProvider::InjectFrame() {
+ if (!started_)
+ return;
+
+ if (frames_.empty()) {
+ message_loop_controller_->GetClosure().Run();
+ return;
+ }
+
+ auto frame = frames_.front();
+ frames_.pop_front();
+
+ if (frame.category == TestFrame::TestFrameType::BROKEN_FRAME) {
+ error_cb_.Run();
+ return;
+ }
+
+ // For pause case, the provider will still let the stream continue, but
+ // not send the frames to the player. As is the same case in reality.
+ if (frame.category == TestFrame::TestFrameType::NORMAL_FRAME) {
+ if (!paused_)
+ repaint_cb_.Run(frame.frame);
+
+ size_t i = 0;
+ while (i < frames_.size() &&
+ frames_[i].category != TestFrame::TestFrameType::NORMAL_FRAME) {
+ ++i;
+ }
+
+ if (i < frames_.size()) {
+ delay_ =
+ (frames_[i].frame->timestamp() - frame.frame->timestamp()) / (i + 1);
+ }
+ }
+
+ message_loop_->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&MockVideoFrameProvider::InjectFrame, base::Unretained(this)),
+ delay_);
+
+ if (frame.category == TestFrame::TestFrameType::TEST_BRAKE)
+ message_loop_controller_->GetClosure().Run();
+}
+
+scoped_refptr<VideoFrameProvider> MockRenderFactory::GetVideoFrameProvider(
+ const GURL& url,
+ const base::Closure& error_cb,
+ const VideoFrameProvider::RepaintCB& repaint_cb,
+ const scoped_refptr<base::SingleThreadTaskRunner>& /*media_task_runner*/,
+ const scoped_refptr<base::TaskRunner>& /*worker_task_runner*/,
+ media::GpuVideoAcceleratorFactories* /*gpu_factories*/) {
+ provider_ = new MockVideoFrameProvider(
+ message_loop_, message_loop_controller_, error_cb, repaint_cb);
+
+ return provider_;
+}
+
+MockVideoFrameProvider* MockRenderFactory::GetVideoFrameProvider() {
+ return static_cast<MockVideoFrameProvider*>(provider_.get());
+}
+
+scoped_refptr<MediaStreamAudioRenderer> MockRenderFactory::GetAudioRenderer(
+ const GURL& url,
+ int render_frame_id,
+ const std::string& device_id,
+ const url::Origin& security_origin) {
+ return nullptr;
+}
+
+void MockClient::networkStateChanged() {
+ blink::WebMediaPlayer::NetworkState state = player_->networkState();
+ test_->GetMockCB()->NetworkStateChanged(state);
+ if (state == blink::WebMediaPlayer::NetworkState::NetworkStateFormatError ||
+ state == blink::WebMediaPlayer::NetworkState::NetworkStateDecodeError ||
+ state == blink::WebMediaPlayer::NetworkState::NetworkStateNetworkError)
+ message_loop_controller_->GetPipelineStatusCB().Run(
+ media::PipelineStatus::PIPELINE_ERROR_NETWORK);
+}
+
+void MockClient::readyStateChanged() {
+ blink::WebMediaPlayer::ReadyState state = player_->readyState();
+ test_->GetMockCB()->ReadyStateChanged(state);
+ if (state == blink::WebMediaPlayer::ReadyState::ReadyStateHaveEnoughData)
+ player_->play();
+}
+
+blink::WebMediaPlayer::TrackId MockClient::addAudioTrack(
+ const blink::WebString& id,
+ AudioTrackKind,
+ const blink::WebString& label,
+ const blink::WebString& language,
+ bool enabled) {
+ return 0;
+}
+
+blink::WebMediaPlayer::TrackId MockClient::addVideoTrack(
+ const blink::WebString& id,
+ VideoTrackKind,
+ const blink::WebString& label,
+ const blink::WebString& language,
+ bool selected) {
+ return 0;
+}
+
+void MockVideoFrameProviderClient::StopUsingProvider() {
+ if (rendering_)
+ StopRendering();
+ compositor_ = nullptr;
+}
+
+void MockVideoFrameProviderClient::StartRendering() {
+ if (!rendering_) {
+ rendering_ = true;
+ message_loop_->PostTask(
+ FROM_HERE, base::Bind(&MockVideoFrameProviderClient::RenderFrame,
+ base::Unretained(this)));
+ }
+ mock_cb_->StartRendering();
+}
+
+void MockVideoFrameProviderClient::StopRendering() {
+ rendering_ = false;
+ mock_cb_->StopRendering();
+}
+
+void MockVideoFrameProviderClient::SetBackgroundRendering(
+ bool background_rendering) {
+ background_rendering_ = background_rendering;
+}
+
+void MockVideoFrameProviderClient::RenderFrame() {
+ if (!rendering_ || !compositor_)
+ return;
+
+ base::TimeTicks now = base::TimeTicks::Now();
+ base::TimeTicks deadline_min =
+ now + base::TimeDelta::FromSecondsD(1.0 / 60.0);
+ base::TimeTicks deadline_max =
+ deadline_min + base::TimeDelta::FromSecondsD(1.0 / 60.0);
+
+ // Background rendering is different from stop rendering. The rendering loop
+ // is still running but we do not ask frames from compositor_. And background
+ // rendering is not initiated from compositor_.
+ if (!background_rendering_) {
+ compositor_->UpdateCurrentFrame(deadline_min, deadline_max);
+ auto frame = compositor_->GetCurrentFrame();
+ compositor_->PutCurrentFrame();
+ }
+ message_loop_->PostDelayedTask(
+ FROM_HERE, base::Bind(&MockVideoFrameProviderClient::RenderFrame,
+ base::Unretained(this)),
+ base::TimeDelta::FromSecondsD(1.0 / 60.0));
+}
+
+void MockClient::setWebLayer(blink::WebLayer* layer) {
+ if (layer) {
+ compositor_ = test_->GetCompositorForTest();
+ video_frame_provider_client_.reset(new MockVideoFrameProviderClient(
+ message_loop_, compositor_, test_->GetMockCB()));
+ compositor_->SetVideoFrameProviderClient(
+ video_frame_provider_client_.get());
+ }
+}
+
+MockVideoFrameProviderClient* MockClient::GetVideoFrameProviderClient() {
+ return video_frame_provider_client_.get();
+}
+
+TEST_F(WebMediaPlayerMSTest, Playing_Normal) {
+ // Workflow:
+ // 1. WMPMS::Load will generate and start content::VideoFrameProvider.
+ // 2. content::VideoFrameProvider will start pushing frames into WMPMS
+ // repeatedly.
+ // 3. On WMPMS receiving the first frame, a WebLayer will be created.
+ // 4. The WebLayer will call WMPMSCompositor::SetVideoFrameProviderClient,
+ // which in turn will trigger cc::VideoFrameProviderClient::StartRendering.
+ // 5. Then cc::VideoFrameProviderClient will start calling
+ // WMPMSCompositor::UpdateCurrentFrame, GetCurrentFrame for rendering
+ // repeatedly.
+ // 6. When WMPSMS::pause gets called, it should trigger
+ // content::VideoFrameProvider::Pause, and then the provider will stop
+ // pushing frames into WMPMS, but instead digesting them; simultanously, it
+ // should call cc::VideoFrameProviderClient::StopRendering, so the client
+ // will stop asking frames from WMPMSCompositor.
+ // 7. When WMPMS::play gets called, evething paused in step 6 should be
+ // resumed.
+ MockVideoFrameProvider* provider = LoadAndGetFrameProvider(true);
+
+ provider->QueueFrames(
+ "0 33 66 100 133 166 200 233 266 300 333 366 400 433 "
+ "466 500 533 566 600");
+
+ EXPECT_CALL(mock_cb_, StartRendering());
+ EXPECT_CALL(mock_cb_,
+ ReadyStateChanged(blink::WebMediaPlayer::ReadyStateHaveMetadata));
+ EXPECT_CALL(mock_cb_, ReadyStateChanged(
+ blink::WebMediaPlayer::ReadyStateHaveEnoughData));
+ message_loop_controller_.RunAndWaitForStatus(
+ media::PipelineStatus::PIPELINE_OK);
+}
+
+TEST_F(WebMediaPlayerMSTest, Playing_ErrorFrame) {
+ MockVideoFrameProvider* provider = LoadAndGetFrameProvider(false);
+
+ provider->QueueFrames(
+ "0 33 66 100 133 166 200 233 266 300 333 366 400 433 "
+ "466 500 533 566 600 error");
+
+ EXPECT_CALL(mock_cb_, StartRendering());
+ EXPECT_CALL(mock_cb_,
+ ReadyStateChanged(blink::WebMediaPlayer::ReadyStateHaveMetadata));
+ EXPECT_CALL(mock_cb_, ReadyStateChanged(
+ blink::WebMediaPlayer::ReadyStateHaveEnoughData));
+ EXPECT_CALL(mock_cb_, NetworkStateChanged(
+ blink::WebMediaPlayer::NetworkStateFormatError));
+ message_loop_controller_.RunAndWaitForStatus(
+ media::PipelineStatus::PIPELINE_ERROR_NETWORK);
+}
+
+TEST_F(WebMediaPlayerMSTest, PlayThenPause) {
+ MockVideoFrameProvider* provider = LoadAndGetFrameProvider(false);
+
+ provider->QueueFrames(
+ "0 33 66 100 133 brake 166 200 233 266 300 333 366 400 "
+ "433 466 500 533 566 600");
+
+ EXPECT_CALL(mock_cb_, StartRendering());
+ EXPECT_CALL(mock_cb_,
+ ReadyStateChanged(blink::WebMediaPlayer::ReadyStateHaveMetadata));
+ EXPECT_CALL(mock_cb_, ReadyStateChanged(
+ blink::WebMediaPlayer::ReadyStateHaveEnoughData));
+ // Rendering will be "paused" at the TestBrake.
+ message_loop_controller_.RunAndWaitForStatus(
+ media::PipelineStatus::PIPELINE_OK);
+ mock_cb_.VerifyAndClearExpectations();
+
+ // Here No more rendering. 1. Render should not be called, 2. Frame freeze.
+ EXPECT_CALL(mock_cb_, StopRendering());
+ player_.pause();
+ cc::VideoFrameProvider* compositor = GetCompositorForTest();
+ auto prev_frame = compositor->GetCurrentFrame();
+ message_loop_controller_.RunAndWaitForStatus(
+ media::PipelineStatus::PIPELINE_OK);
+ auto after_frame = compositor->GetCurrentFrame();
+ EXPECT_EQ(prev_frame->timestamp(), after_frame->timestamp());
+}
+
+TEST_F(WebMediaPlayerMSTest, PlayThenPauseThenPlay) {
+ MockVideoFrameProvider* provider = LoadAndGetFrameProvider(false);
+
+ provider->QueueFrames(
+ "0 33 66 100 133 brake 166 200 233 266 300 333 366 400 "
+ "433 brake 466 500 533 566 600");
+
+ EXPECT_CALL(mock_cb_, StartRendering());
+ EXPECT_CALL(mock_cb_,
+ ReadyStateChanged(blink::WebMediaPlayer::ReadyStateHaveMetadata));
+ EXPECT_CALL(mock_cb_, ReadyStateChanged(
+ blink::WebMediaPlayer::ReadyStateHaveEnoughData));
+ // Rendering will be "paused" at the TestBrake.
+ message_loop_controller_.RunAndWaitForStatus(
+ media::PipelineStatus::PIPELINE_OK);
+ mock_cb_.VerifyAndClearExpectations();
+
+ // Here No more rendering. 1. Render should not be called, 2. Frame freeze.
+ EXPECT_CALL(mock_cb_, StopRendering());
+ player_.pause();
+ cc::VideoFrameProvider* compositor = GetCompositorForTest();
+ auto prev_frame = compositor->GetCurrentFrame();
+ message_loop_controller_.RunAndWaitForStatus(
+ media::PipelineStatus::PIPELINE_OK);
+ auto after_frame = compositor->GetCurrentFrame();
+ EXPECT_EQ(prev_frame->timestamp(), after_frame->timestamp());
+ mock_cb_.VerifyAndClearExpectations();
+
+ // We resume the player
+ EXPECT_CALL(mock_cb_, StartRendering());
+ player_.play();
+ prev_frame = compositor->GetCurrentFrame();
+ message_loop_controller_.RunAndWaitForStatus(
+ media::PipelineStatus::PIPELINE_OK);
+ after_frame = compositor->GetCurrentFrame();
+ EXPECT_NE(prev_frame->timestamp(), after_frame->timestamp());
+}
+
+TEST_F(WebMediaPlayerMSTest, BackgroudRendering) {
+ MockVideoFrameProvider* provider = LoadAndGetFrameProvider(true);
+
+ provider->QueueFrames(
+ "0 33 66 100 133 brake 166 200 233 266 300 333 366 400 "
+ "433 brake 466 500 533 566 600");
+
+ EXPECT_CALL(mock_cb_, StartRendering());
+ EXPECT_CALL(mock_cb_,
+ ReadyStateChanged(blink::WebMediaPlayer::ReadyStateHaveMetadata));
+ EXPECT_CALL(mock_cb_, ReadyStateChanged(
+ blink::WebMediaPlayer::ReadyStateHaveEnoughData));
+ // Rendering will be "paused" at the TestBrake.
+ message_loop_controller_.RunAndWaitForStatus(
+ media::PipelineStatus::PIPELINE_OK);
+ mock_cb_.VerifyAndClearExpectations();
+
+ // Switch to background rendering, expect rendering to continue
+ MockVideoFrameProviderClient* client = client_.GetVideoFrameProviderClient();
+ client->SetBackgroundRendering(true);
+ cc::VideoFrameProvider* compositor = GetCompositorForTest();
+ auto prev_frame = compositor->GetCurrentFrame();
+ message_loop_controller_.RunAndWaitForStatus(
+ media::PipelineStatus::PIPELINE_OK);
+ auto after_frame = compositor->GetCurrentFrame();
+ EXPECT_NE(prev_frame->timestamp(), after_frame->timestamp());
+
+ // Switch to foreground rendering
+ client->SetBackgroundRendering(false);
+ prev_frame = compositor->GetCurrentFrame();
+ message_loop_controller_.RunAndWaitForStatus(
+ media::PipelineStatus::PIPELINE_OK);
+ after_frame = compositor->GetCurrentFrame();
+ EXPECT_NE(prev_frame->timestamp(), after_frame->timestamp());
+}
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698