summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--content/public/test/layouttest_support.h11
-rw-r--r--content/renderer/render_thread_impl.cc10
-rw-r--r--content/renderer/render_thread_impl.h8
-rw-r--r--content/renderer/render_view_impl.cc1
-rw-r--r--content/shell/renderer/DEPS3
-rw-r--r--content/shell/renderer/webkit_test_runner.cc29
-rw-r--r--content/test/layouttest_support.cc4
-rw-r--r--media/base/pipeline.cc6
-rw-r--r--media/base/pipeline.h2
-rw-r--r--media/base/pipeline_unittest.cc48
-rw-r--r--webkit/mocks/test_media_stream_client.cc30
-rw-r--r--webkit/mocks/test_media_stream_client.h14
-rw-r--r--webkit/renderer/media/webmediaplayer_impl.cc30
-rw-r--r--webkit/renderer/media/webmediaplayer_impl.h2
-rw-r--r--webkit/renderer/media/webmediaplayer_params.cc7
-rw-r--r--webkit/renderer/media/webmediaplayer_params.h13
-rw-r--r--webkit/support/webkit_support.cc11
17 files changed, 144 insertions, 85 deletions
diff --git a/content/public/test/layouttest_support.h b/content/public/test/layouttest_support.h
index ed490ec..21a34503 100644
--- a/content/public/test/layouttest_support.h
+++ b/content/public/test/layouttest_support.h
@@ -6,6 +6,7 @@
#define CONTENT_PUBLIC_TEST_LAYOUTTEST_SUPPORT_H_
#include "base/callback_forward.h"
+#include "base/memory/ref_counted.h"
namespace WebKit {
class WebGamepads;
@@ -16,6 +17,10 @@ namespace WebTestRunner {
class WebTestProxyBase;
}
+namespace base {
+class MessageLoopProxy;
+}
+
namespace content {
class RenderView;
@@ -64,6 +69,12 @@ void EnableAutoResizeMode(RenderView* render_view,
void DisableAutoResizeMode(RenderView* render_view,
const WebKit::WebSize& new_size);
+// Return the thread on which media operations should run.
+//
+// TODO(scherkus): We should be using RenderViewImpl::createMediaPlayer(), see
+// http://crbug.com/239826
+scoped_refptr<base::MessageLoopProxy> GetMediaThreadMessageLoopProxy();
+
} // namespace content
#endif // CONTENT_PUBLIC_TEST_LAYOUTTEST_SUPPORT_H_
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 0f86870..ed8cbd2 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -1330,6 +1330,16 @@ RenderThreadImpl::GetFileThreadMessageLoopProxy() {
return file_thread_->message_loop_proxy();
}
+scoped_refptr<base::MessageLoopProxy>
+RenderThreadImpl::GetMediaThreadMessageLoopProxy() {
+ DCHECK(message_loop() == base::MessageLoop::current());
+ if (!media_thread_) {
+ media_thread_.reset(new base::Thread("Media"));
+ media_thread_->Start();
+ }
+ return media_thread_->message_loop_proxy();
+}
+
void RenderThreadImpl::SetFlingCurveParameters(
const std::vector<float>& new_touchpad,
const std::vector<float>& new_touchscreen) {
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index 50d1362..127c687 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -257,6 +257,11 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
// on the renderer's main thread.
scoped_refptr<base::MessageLoopProxy> GetFileThreadMessageLoopProxy();
+ // Returns a MessageLoopProxy instance corresponding to the message loop
+ // of the thread on which media operations should be run. Must be called
+ // on the renderer's main thread.
+ scoped_refptr<base::MessageLoopProxy> GetMediaThreadMessageLoopProxy();
+
// Causes the idle handler to skip sending idle notifications
// on the two next scheduled calls, so idle notifications are
// not sent for at least one notification delay.
@@ -425,6 +430,9 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
// May be null if overridden by ContentRendererClient.
scoped_ptr<base::Thread> compositor_thread_;
+ // Thread for running multimedia operations (e.g., video decoding).
+ scoped_ptr<base::Thread> media_thread_;
+
// Will point to appropriate MessageLoopProxy after initialization,
// regardless of whether |compositor_thread_| is overriden.
scoped_refptr<base::MessageLoopProxy> compositor_message_loop_proxy_;
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 2a33782..df21065 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -2912,6 +2912,7 @@ WebMediaPlayer* RenderViewImpl::createMediaPlayer(
}
webkit_media::WebMediaPlayerParams params(
+ RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy(),
sink, gpu_factories, new RenderMediaLog());
WebMediaPlayer* media_player =
GetContentClient()->renderer()->OverrideCreateWebMediaPlayer(
diff --git a/content/shell/renderer/DEPS b/content/shell/renderer/DEPS
new file mode 100644
index 0000000..47de12f
--- /dev/null
+++ b/content/shell/renderer/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+media/base", # For media::MediaLog.
+]
diff --git a/content/shell/renderer/webkit_test_runner.cc b/content/shell/renderer/webkit_test_runner.cc
index 03c3c4f..a6bd657 100644
--- a/content/shell/renderer/webkit_test_runner.cc
+++ b/content/shell/renderer/webkit_test_runner.cc
@@ -25,6 +25,7 @@
#include "content/shell/common/shell_messages.h"
#include "content/shell/common/webkit_test_helpers.h"
#include "content/shell/renderer/shell_render_process_observer.h"
+#include "media/base/media_log.h"
#include "net/base/net_errors.h"
#include "net/base/net_util.h"
#include "skia/ext/platform_canvas.h"
@@ -60,6 +61,9 @@
#include "webkit/common/webpreferences.h"
#include "webkit/glue/webkit_glue.h"
#include "webkit/mocks/test_media_stream_client.h"
+#include "webkit/renderer/media/webmediaplayer_impl.h"
+#include "webkit/renderer/media/webmediaplayer_ms.h"
+#include "webkit/renderer/media/webmediaplayer_params.h"
using WebKit::Platform;
using WebKit::WebArrayBufferView;
@@ -518,8 +522,29 @@ WebMediaPlayer* WebKitTestRunner::createWebMediaPlayer(
test_media_stream_client_.reset(
new webkit_glue::TestMediaStreamClient());
}
- return webkit_glue::CreateMediaPlayer(
- frame, url, client, test_media_stream_client_.get());
+
+ if (test_media_stream_client_->IsMediaStream(url)) {
+ return new webkit_media::WebMediaPlayerMS(
+ frame,
+ client,
+ base::WeakPtr<webkit_media::WebMediaPlayerDelegate>(),
+ test_media_stream_client_.get(),
+ new media::MediaLog());
+ }
+
+#if defined(OS_ANDROID)
+ return NULL;
+#else
+ // TODO(scherkus): Use RenderViewImpl::createMediaPlayer() instead of
+ // duplicating code here, see http://crbug.com/239826
+ webkit_media::WebMediaPlayerParams params(
+ GetMediaThreadMessageLoopProxy(), NULL, NULL, new media::MediaLog());
+ return new webkit_media::WebMediaPlayerImpl(
+ frame,
+ client,
+ base::WeakPtr<webkit_media::WebMediaPlayerDelegate>(),
+ params);
+#endif
}
// RenderViewObserver --------------------------------------------------------
diff --git a/content/test/layouttest_support.cc b/content/test/layouttest_support.cc
index 100ce3d..15251ed 100644
--- a/content/test/layouttest_support.cc
+++ b/content/test/layouttest_support.cc
@@ -111,4 +111,8 @@ void DisableAutoResizeMode(RenderView* render_view, const WebSize& new_size) {
->DisableAutoResizeForTesting(new_size);
}
+scoped_refptr<base::MessageLoopProxy> GetMediaThreadMessageLoopProxy() {
+ return RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy();
+}
+
} // namespace content
diff --git a/media/base/pipeline.cc b/media/base/pipeline.cc
index 67cc0f3..a81adc6 100644
--- a/media/base/pipeline.cc
+++ b/media/base/pipeline.cc
@@ -634,8 +634,12 @@ void Pipeline::OnStopCompleted(PipelineStatus status) {
error_cb_.Reset();
}
if (!stop_cb_.is_null()) {
- base::ResetAndReturn(&stop_cb_).Run();
error_cb_.Reset();
+ base::ResetAndReturn(&stop_cb_).Run();
+
+ // NOTE: pipeline may be deleted at this point in time as a result of
+ // executing |stop_cb_|.
+ return;
}
if (!error_cb_.is_null()) {
DCHECK_NE(status_, PIPELINE_OK);
diff --git a/media/base/pipeline.h b/media/base/pipeline.h
index a91176e..0ca7d62 100644
--- a/media/base/pipeline.h
+++ b/media/base/pipeline.h
@@ -114,6 +114,8 @@ class MEDIA_EXPORT Pipeline : public DemuxerHost {
//
// Stop() must complete before destroying the pipeline. It it permissible to
// call Stop() at any point during the lifetime of the pipeline.
+ //
+ // It is safe to delete the pipeline during the execution of |stop_cb|.
void Stop(const base::Closure& stop_cb);
// Attempt to seek to the position specified by time. |seek_cb| will be
diff --git a/media/base/pipeline_unittest.cc b/media/base/pipeline_unittest.cc
index 725695f..778a036 100644
--- a/media/base/pipeline_unittest.cc
+++ b/media/base/pipeline_unittest.cc
@@ -105,28 +105,16 @@ class PipelineTest : public ::testing::Test {
}
virtual ~PipelineTest() {
- // Shutdown sequence.
- if (pipeline_->IsRunning()) {
- EXPECT_CALL(*demuxer_, Stop(_))
- .WillOnce(RunClosure<0>());
+ if (!pipeline_ || !pipeline_->IsRunning())
+ return;
- if (audio_stream_)
- EXPECT_CALL(*audio_renderer_, Stop(_))
- .WillOnce(RunClosure<0>());
-
- if (video_stream_)
- EXPECT_CALL(*video_renderer_, Stop(_))
- .WillOnce(RunClosure<0>());
- }
+ ExpectStop();
// Expect a stop callback if we were started.
EXPECT_CALL(callbacks_, OnStop());
pipeline_->Stop(base::Bind(&CallbackHelper::OnStop,
base::Unretained(&callbacks_)));
message_loop_.RunUntilIdle();
-
- filter_collection_.reset();
- pipeline_.reset();
}
protected:
@@ -285,6 +273,17 @@ class PipelineTest : public ::testing::Test {
EXPECT_EQ(seek_time, pipeline_->GetMediaTime());
}
+ void ExpectStop() {
+ if (demuxer_)
+ EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
+
+ if (audio_stream_)
+ EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
+
+ if (video_stream_)
+ EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>());
+ }
+
// Fixture members.
StrictMock<CallbackHelper> callbacks_;
base::SimpleTestClock test_clock_;
@@ -836,6 +835,25 @@ TEST_F(PipelineTest, AudioTimeUpdateDuringSeek) {
EXPECT_EQ(pipeline_->GetMediaTime(), new_time);
}
+static void DeletePipeline(scoped_ptr<Pipeline> pipeline) {
+ // |pipeline| will go out of scope.
+}
+
+TEST_F(PipelineTest, DeleteAfterStop) {
+ CreateAudioStream();
+ MockDemuxerStreamVector streams;
+ streams.push_back(audio_stream());
+ InitializeDemuxer(&streams);
+ InitializeAudioRenderer(audio_stream(), false);
+ InitializePipeline(PIPELINE_OK);
+
+ ExpectStop();
+
+ Pipeline* pipeline = pipeline_.get();
+ pipeline->Stop(base::Bind(&DeletePipeline, base::Passed(&pipeline_)));
+ message_loop_.RunUntilIdle();
+}
+
class PipelineTeardownTest : public PipelineTest {
public:
enum TeardownState {
diff --git a/webkit/mocks/test_media_stream_client.cc b/webkit/mocks/test_media_stream_client.cc
index 632f6b39..3065612 100644
--- a/webkit/mocks/test_media_stream_client.cc
+++ b/webkit/mocks/test_media_stream_client.cc
@@ -13,9 +13,6 @@
#include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaStreamRegistry.h"
#include "webkit/renderer/media/media_stream_audio_renderer.h"
#include "webkit/renderer/media/simple_video_frame_provider.h"
-#include "webkit/renderer/media/webmediaplayer_impl.h"
-#include "webkit/renderer/media/webmediaplayer_ms.h"
-#include "webkit/renderer/media/webmediaplayer_params.h"
using namespace WebKit;
@@ -43,33 +40,6 @@ bool IsMockMediaStreamWithVideo(const WebURL& url) {
namespace webkit_glue {
-WebKit::WebMediaPlayer* CreateMediaPlayer(
- WebFrame* frame,
- const WebURL& url,
- WebMediaPlayerClient* client,
- webkit_media::MediaStreamClient* media_stream_client) {
- if (media_stream_client && media_stream_client->IsMediaStream(url)) {
- return new webkit_media::WebMediaPlayerMS(
- frame,
- client,
- base::WeakPtr<webkit_media::WebMediaPlayerDelegate>(),
- media_stream_client,
- new media::MediaLog());
- }
-
-#if defined(OS_ANDROID)
- return NULL;
-#else
- webkit_media::WebMediaPlayerParams params(
- NULL, NULL, new media::MediaLog());
- return new webkit_media::WebMediaPlayerImpl(
- frame,
- client,
- base::WeakPtr<webkit_media::WebMediaPlayerDelegate>(),
- params);
-#endif
-}
-
TestMediaStreamClient::TestMediaStreamClient() {}
TestMediaStreamClient::~TestMediaStreamClient() {}
diff --git a/webkit/mocks/test_media_stream_client.h b/webkit/mocks/test_media_stream_client.h
index b759f49..60fa4aa 100644
--- a/webkit/mocks/test_media_stream_client.h
+++ b/webkit/mocks/test_media_stream_client.h
@@ -13,26 +13,12 @@
#include "third_party/WebKit/public/platform/WebURL.h"
#include "webkit/renderer/media/media_stream_client.h"
-namespace WebKit {
-class WebFrame;
-class WebMediaPlayer;
-class WebMediaPlayerClient;
-}
-
namespace webkit_media {
class MediaStreamAudioRenderer;
-class MediaStreamClient;
}
namespace webkit_glue {
-// This is used by WebFrameClient::createMediaPlayer().
-WebKit::WebMediaPlayer* CreateMediaPlayer(
- WebKit::WebFrame* frame,
- const WebKit::WebURL& url,
- WebKit::WebMediaPlayerClient* client,
- webkit_media::MediaStreamClient* media_stream_client);
-
class TestMediaStreamClient : public webkit_media::MediaStreamClient {
public:
TestMediaStreamClient();
diff --git a/webkit/renderer/media/webmediaplayer_impl.cc b/webkit/renderer/media/webmediaplayer_impl.cc
index fb78842..13d8b52 100644
--- a/webkit/renderer/media/webmediaplayer_impl.cc
+++ b/webkit/renderer/media/webmediaplayer_impl.cc
@@ -130,7 +130,7 @@ WebMediaPlayerImpl::WebMediaPlayerImpl(
network_state_(WebMediaPlayer::NetworkStateEmpty),
ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
main_loop_(base::MessageLoopProxy::current()),
- media_thread_("MediaPipeline"),
+ media_loop_(params.message_loop_proxy()),
paused_(true),
seeking_(false),
playback_rate_(0.0f),
@@ -153,9 +153,7 @@ WebMediaPlayerImpl::WebMediaPlayerImpl(
media_log_->AddEvent(
media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_CREATED));
- CHECK(media_thread_.Start());
- pipeline_.reset(new media::Pipeline(media_thread_.message_loop_proxy(),
- media_log_.get()));
+ pipeline_.reset(new media::Pipeline(media_loop_, media_log_));
// Let V8 know we started new thread if we did not do it yet.
// Made separate task to avoid deletion of player currently being created.
@@ -185,7 +183,7 @@ WebMediaPlayerImpl::WebMediaPlayerImpl(
audio_source_provider_ = new WebAudioSourceProviderImpl(
params.audio_renderer_sink().get()
? params.audio_renderer_sink()
- : new media::NullAudioSink(media_thread_.message_loop_proxy()));
+ : new media::NullAudioSink(media_loop_));
}
WebMediaPlayerImpl::~WebMediaPlayerImpl() {
@@ -1061,7 +1059,7 @@ void WebMediaPlayerImpl::StartPipeline(WebKit::WebMediaSource* media_source) {
DCHECK(data_source_);
demuxer_.reset(new media::FFmpegDemuxer(
- media_thread_.message_loop_proxy(), data_source_.get(),
+ media_loop_, data_source_.get(),
BIND_TO_RENDER_LOOP_2(&WebMediaPlayerImpl::OnNeedKey, "", "")));
} else {
DCHECK(!chunk_demuxer_);
@@ -1100,15 +1098,13 @@ void WebMediaPlayerImpl::StartPipeline(WebKit::WebMediaSource* media_source) {
// Create our audio decoders and renderer.
ScopedVector<media::AudioDecoder> audio_decoders;
- audio_decoders.push_back(new media::FFmpegAudioDecoder(
- media_thread_.message_loop_proxy()));
+ audio_decoders.push_back(new media::FFmpegAudioDecoder(media_loop_));
if (cmd_line->HasSwitch(switches::kEnableOpusPlayback)) {
- audio_decoders.push_back(new media::OpusAudioDecoder(
- media_thread_.message_loop_proxy()));
+ audio_decoders.push_back(new media::OpusAudioDecoder(media_loop_));
}
scoped_ptr<media::AudioRenderer> audio_renderer(
- new media::AudioRendererImpl(media_thread_.message_loop_proxy(),
+ new media::AudioRendererImpl(media_loop_,
audio_source_provider_.get(),
audio_decoders.Pass(),
set_decryptor_ready_cb,
@@ -1120,7 +1116,7 @@ void WebMediaPlayerImpl::StartPipeline(WebKit::WebMediaSource* media_source) {
if (gpu_factories_.get()) {
video_decoders.push_back(new media::GpuVideoDecoder(
- media_thread_.message_loop_proxy(), gpu_factories_));
+ media_loop_, gpu_factories_));
}
// TODO(phajdan.jr): Remove ifdefs when libvpx with vp9 support is released
@@ -1128,17 +1124,15 @@ void WebMediaPlayerImpl::StartPipeline(WebKit::WebMediaSource* media_source) {
#if !defined(MEDIA_DISABLE_LIBVPX)
if (cmd_line->HasSwitch(switches::kEnableVp9Playback) ||
cmd_line->HasSwitch(switches::kEnableVp8AlphaPlayback)) {
- video_decoders.push_back(new media::VpxVideoDecoder(
- media_thread_.message_loop_proxy()));
+ video_decoders.push_back(new media::VpxVideoDecoder(media_loop_));
}
#endif // !defined(MEDIA_DISABLE_LIBVPX)
- video_decoders.push_back(new media::FFmpegVideoDecoder(
- media_thread_.message_loop_proxy()));
+ video_decoders.push_back(new media::FFmpegVideoDecoder(media_loop_));
scoped_ptr<media::VideoRenderer> video_renderer(
new media::VideoRendererBase(
- media_thread_.message_loop_proxy(),
+ media_loop_,
video_decoders.Pass(),
set_decryptor_ready_cb,
base::Bind(&WebMediaPlayerImpl::FrameReady, base::Unretained(this)),
@@ -1208,8 +1202,6 @@ void WebMediaPlayerImpl::Destroy() {
incremented_externally_allocated_memory_ = false;
}
- media_thread_.Stop();
-
// Release any final references now that everything has stopped.
pipeline_.reset();
demuxer_.reset();
diff --git a/webkit/renderer/media/webmediaplayer_impl.h b/webkit/renderer/media/webmediaplayer_impl.h
index 04c0fb4..0049369 100644
--- a/webkit/renderer/media/webmediaplayer_impl.h
+++ b/webkit/renderer/media/webmediaplayer_impl.h
@@ -287,7 +287,7 @@ class WebMediaPlayerImpl
const scoped_refptr<base::MessageLoopProxy> main_loop_;
scoped_ptr<media::Pipeline> pipeline_;
- base::Thread media_thread_;
+ scoped_refptr<base::MessageLoopProxy> media_loop_;
// The currently selected key system. Empty string means that no key system
// has been selected.
diff --git a/webkit/renderer/media/webmediaplayer_params.cc b/webkit/renderer/media/webmediaplayer_params.cc
index 7c6335a..91769d8 100644
--- a/webkit/renderer/media/webmediaplayer_params.cc
+++ b/webkit/renderer/media/webmediaplayer_params.cc
@@ -4,19 +4,22 @@
#include "webkit/renderer/media/webmediaplayer_params.h"
+#include "base/message_loop_proxy.h"
#include "media/base/audio_renderer_sink.h"
#include "media/base/media_log.h"
namespace webkit_media {
WebMediaPlayerParams::WebMediaPlayerParams(
+ const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy,
const scoped_refptr<media::AudioRendererSink>& audio_renderer_sink,
const scoped_refptr<media::GpuVideoDecoder::Factories>& gpu_factories,
const scoped_refptr<media::MediaLog>& media_log)
- : audio_renderer_sink_(audio_renderer_sink),
+ : message_loop_proxy_(message_loop_proxy),
+ audio_renderer_sink_(audio_renderer_sink),
gpu_factories_(gpu_factories),
media_log_(media_log) {
- DCHECK(media_log_.get());
+ DCHECK(media_log_);
}
WebMediaPlayerParams::~WebMediaPlayerParams() {}
diff --git a/webkit/renderer/media/webmediaplayer_params.h b/webkit/renderer/media/webmediaplayer_params.h
index 893cae7..62a5ce1 100644
--- a/webkit/renderer/media/webmediaplayer_params.h
+++ b/webkit/renderer/media/webmediaplayer_params.h
@@ -8,6 +8,10 @@
#include "base/memory/ref_counted.h"
#include "media/filters/gpu_video_decoder.h"
+namespace base {
+class MessageLoopProxy;
+}
+
namespace media {
class AudioRendererSink;
class MediaLog;
@@ -19,13 +23,19 @@ namespace webkit_media {
// to plumb arguments through various abstraction layers.
class WebMediaPlayerParams {
public:
- // |media_log| is the only required parameter; all others may be null.
+ // |message_loop_proxy| and |media_log| are the only required parameters;
+ // all others may be null.
WebMediaPlayerParams(
+ const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy,
const scoped_refptr<media::AudioRendererSink>& audio_renderer_sink,
const scoped_refptr<media::GpuVideoDecoder::Factories>& gpu_factories,
const scoped_refptr<media::MediaLog>& media_log);
~WebMediaPlayerParams();
+ const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy() const {
+ return message_loop_proxy_;
+ }
+
const scoped_refptr<media::AudioRendererSink>& audio_renderer_sink() const {
return audio_renderer_sink_;
}
@@ -40,6 +50,7 @@ class WebMediaPlayerParams {
}
private:
+ scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
scoped_refptr<media::AudioRendererSink> audio_renderer_sink_;
scoped_refptr<media::GpuVideoDecoder::Factories> gpu_factories_;
scoped_refptr<media::MediaLog> media_log_;
diff --git a/webkit/support/webkit_support.cc b/webkit/support/webkit_support.cc
index ba537a8..51997ec 100644
--- a/webkit/support/webkit_support.cc
+++ b/webkit/support/webkit_support.cc
@@ -206,6 +206,14 @@ class TestEnvironment {
}
#endif
+ scoped_refptr<base::MessageLoopProxy> GetMediaThreadMessageLoopProxy() {
+ if (!media_thread_) {
+ media_thread_.reset(new base::Thread("Media"));
+ CHECK(media_thread_->Start());
+ }
+ return media_thread_->message_loop_proxy();
+ }
+
private:
// Data member at_exit_manager_ will take the ownership of the input
// AtExitManager and manage its lifecycle.
@@ -213,6 +221,8 @@ class TestEnvironment {
scoped_ptr<MessageLoopType> main_message_loop_;
scoped_ptr<TestWebKitPlatformSupport> webkit_platform_support_;
+ scoped_ptr<base::Thread> media_thread_;
+
#if defined(OS_ANDROID)
base::FilePath mock_current_directory_;
#endif
@@ -404,6 +414,7 @@ WebKit::WebMediaPlayer* CreateMediaPlayer(
return NULL;
#else
webkit_media::WebMediaPlayerParams params(
+ test_environment->GetMediaThreadMessageLoopProxy(),
NULL, NULL, new media::MediaLog());
return new webkit_media::WebMediaPlayerImpl(
frame,