diff options
author | wjia@google.com <wjia@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-24 19:15:07 +0000 |
---|---|---|
committer | wjia@google.com <wjia@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-24 19:15:07 +0000 |
commit | 5e83826af14858fca1ebac8281afa75107281e7b (patch) | |
tree | 467fbad219ff625270ebe0455dabe4459f1c7e36 | |
parent | cc2de439d0fd34aac593b1fabc40f0626c5848e1 (diff) | |
download | chromium_src-5e83826af14858fca1ebac8281afa75107281e7b.zip chromium_src-5e83826af14858fca1ebac8281afa75107281e7b.tar.gz chromium_src-5e83826af14858fca1ebac8281afa75107281e7b.tar.bz2 |
1. remove initial rendering lag time for egl image decoding path
2. put all GLES operations in one thread
BUG=none
TEST=dev platform and desktop
Review URL: http://codereview.chromium.org/2836019
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@50749 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/renderer/media/ipc_video_renderer.cc | 10 | ||||
-rw-r--r-- | chrome/renderer/media/ipc_video_renderer.h | 4 | ||||
-rw-r--r-- | media/base/factory.h | 26 | ||||
-rw-r--r-- | media/filters/video_renderer_base.cc | 59 | ||||
-rw-r--r-- | media/filters/video_renderer_base.h | 7 | ||||
-rw-r--r-- | media/filters/video_renderer_base_unittest.cc | 10 | ||||
-rw-r--r-- | media/tools/player_wtl/player_wtl.cc | 2 | ||||
-rw-r--r-- | media/tools/player_wtl/wtl_renderer.cc | 6 | ||||
-rw-r--r-- | media/tools/player_wtl/wtl_renderer.h | 2 | ||||
-rw-r--r-- | media/tools/player_x11/gl_video_renderer.cc | 11 | ||||
-rw-r--r-- | media/tools/player_x11/gl_video_renderer.h | 17 | ||||
-rw-r--r-- | media/tools/player_x11/gles_video_renderer.cc | 30 | ||||
-rw-r--r-- | media/tools/player_x11/gles_video_renderer.h | 19 | ||||
-rw-r--r-- | media/tools/player_x11/player_x11.cc | 28 | ||||
-rw-r--r-- | media/tools/player_x11/x11_video_renderer.cc | 11 | ||||
-rw-r--r-- | media/tools/player_x11/x11_video_renderer.h | 17 | ||||
-rw-r--r-- | webkit/glue/media/video_renderer_impl.cc | 6 | ||||
-rw-r--r-- | webkit/glue/media/video_renderer_impl.h | 2 |
18 files changed, 161 insertions, 106 deletions
diff --git a/chrome/renderer/media/ipc_video_renderer.cc b/chrome/renderer/media/ipc_video_renderer.cc index 843869c..aa234ff 100644 --- a/chrome/renderer/media/ipc_video_renderer.cc +++ b/chrome/renderer/media/ipc_video_renderer.cc @@ -52,11 +52,11 @@ bool IPCVideoRenderer::OnInitialize(media::VideoDecoder* decoder) { return true; } -void IPCVideoRenderer::OnStop() { +void IPCVideoRenderer::OnStop(media::FilterCallback* callback) { stopped_.Signal(); proxy_->message_loop()->PostTask(FROM_HERE, - NewRunnableMethod(this, &IPCVideoRenderer::DoDestroyVideo)); + NewRunnableMethod(this, &IPCVideoRenderer::DoDestroyVideo, callback)); } void IPCVideoRenderer::OnFrameAvailable() { @@ -160,7 +160,7 @@ void IPCVideoRenderer::DoUpdateVideo() { video_rect_)); } -void IPCVideoRenderer::DoDestroyVideo() { +void IPCVideoRenderer::DoDestroyVideo(media::FilterCallback* callback) { DCHECK(MessageLoop::current() == proxy_->message_loop()); // We shouldn't receive any more messages after the browser receives this. @@ -169,4 +169,8 @@ void IPCVideoRenderer::DoDestroyVideo() { // Detach ourselves from the proxy. proxy_->SetVideoRenderer(NULL); proxy_ = NULL; + if (callback) { + callback->Run(); + delete callback; + } } diff --git a/chrome/renderer/media/ipc_video_renderer.h b/chrome/renderer/media/ipc_video_renderer.h index 070166b..943e0c9 100644 --- a/chrome/renderer/media/ipc_video_renderer.h +++ b/chrome/renderer/media/ipc_video_renderer.h @@ -59,7 +59,7 @@ class IPCVideoRenderer : public webkit_glue::WebVideoRenderer { protected: // VideoRendererBase implementation. virtual bool OnInitialize(media::VideoDecoder* decoder); - virtual void OnStop(); + virtual void OnStop(media::FilterCallback* callback); virtual void OnFrameAvailable(); private: @@ -80,7 +80,7 @@ class IPCVideoRenderer : public webkit_glue::WebVideoRenderer { void DoUpdateVideo(); // Handles destroying the video on the render thread. - void DoDestroyVideo(); + void DoDestroyVideo(media::FilterCallback* callback); // Pointer to our parent object that is called to request repaints. scoped_refptr<webkit_glue::WebMediaPlayerImpl::Proxy> proxy_; diff --git a/media/base/factory.h b/media/base/factory.h index ade8990..49bd868 100644 --- a/media/base/factory.h +++ b/media/base/factory.h @@ -187,6 +187,32 @@ class FilterFactoryImpl2 : public FilterFactory { DISALLOW_COPY_AND_ASSIGN(FilterFactoryImpl2); }; +template <class Filter, class A, class B, class C> +class FilterFactoryImpl3 : public FilterFactory { + public: + FilterFactoryImpl3(A a, B b, C c) : a_(a), b_(b), c_(c) {} + + protected: + virtual MediaFilter* Create(FilterType filter_type, + const MediaFormat& media_format) { + Filter* filter = NULL; + if (Filter::filter_type() == filter_type && + Filter::IsMediaFormatSupported(media_format)) { + filter = new Filter(a_, b_, c_); + } + return filter; + } + + private: + ~FilterFactoryImpl3() {} + + A const a_; + B const b_; + C const c_; + + DISALLOW_COPY_AND_ASSIGN(FilterFactoryImpl3); +}; + //------------------------------------------------------------------------------ // This specialized factory is typically used by test programs that create diff --git a/media/filters/video_renderer_base.cc b/media/filters/video_renderer_base.cc index 6eeed60..da80221 100644 --- a/media/filters/video_renderer_base.cc +++ b/media/filters/video_renderer_base.cc @@ -111,30 +111,25 @@ void VideoRendererBase::Pause(FilterCallback* callback) { } void VideoRendererBase::Stop(FilterCallback* callback) { - AutoLock auto_lock(lock_); - state_ = kStopped; - - // Signal the subclass we're stopping. - // TODO(scherkus): do we trust subclasses not to do something silly while - // we're holding the lock? - OnStop(); - - // Clean up our thread if present. - if (thread_) { - // Signal the thread since it's possible to get stopped with the video - // thread waiting for a read to complete. - frame_available_.Signal(); - { - AutoUnlock auto_unlock(lock_); - PlatformThread::Join(thread_); + { + AutoLock auto_lock(lock_); + state_ = kStopped; + + // Clean up our thread if present. + if (thread_) { + // Signal the thread since it's possible to get stopped with the video + // thread waiting for a read to complete. + frame_available_.Signal(); + { + AutoUnlock auto_unlock(lock_); + PlatformThread::Join(thread_); + } + thread_ = kNullThreadHandle; } - thread_ = kNullThreadHandle; - } - if (callback) { - callback->Run(); - delete callback; } + // Signal the subclass we're stopping. + OnStop(callback); } void VideoRendererBase::SetPlaybackRate(float playback_rate) { @@ -154,17 +149,6 @@ void VideoRendererBase::Seek(base::TimeDelta time, FilterCallback* callback) { for (size_t i = 0; i < kMaxFrames; ++i) { ScheduleRead_Locked(); } - - // TODO(wjia): This would be removed if "Paint" thread allows renderer to - // allocate EGL images before filters are in playing state. - if (uses_egl_image()) { - state_ = kPaused; - VideoFrame::CreateBlackFrame(width_, height_, ¤t_frame_); - DCHECK(current_frame_); - OnFrameAvailable(); - seek_callback_->Run(); - seek_callback_.reset(); - } } void VideoRendererBase::Initialize(VideoDecoder* decoder, @@ -283,6 +267,9 @@ void VideoRendererBase::ThreadMain() { if (!frames_.empty() && !frames_.front()->IsEndOfStream()) { DCHECK_EQ(current_frame_, frames_.front()); frames_.pop_front(); + // TODO(wjia): Make sure |current_frame_| is not used by renderer any + // more. Could use fence or delay recycle by one frame. But both have + // problems. if (uses_egl_image() && media::VideoFrame::TYPE_EGL_IMAGE == current_frame_->type()) { decoder_->FillThisBuffer(current_frame_); @@ -344,6 +331,11 @@ void VideoRendererBase::ThreadMain() { void VideoRendererBase::GetCurrentFrame(scoped_refptr<VideoFrame>* frame_out) { AutoLock auto_lock(lock_); + + if (state_ == kStopped) { + VideoFrame::CreateBlackFrame(width_, height_, frame_out); + return; + } // We should have initialized and have the current frame. DCHECK(state_ == kPaused || state_ == kSeeking || state_ == kPlaying || state_ == kEnded); @@ -367,9 +359,6 @@ void VideoRendererBase::OnFillBufferDone(scoped_refptr<VideoFrame> frame) { // Enqueue the frame. frames_.push_back(frame); - if (uses_egl_image() && - media::VideoFrame::TYPE_EGL_IMAGE != current_frame_->type()) - current_frame_ = frame; DCHECK_LE(frames_.size(), kMaxFrames); frame_available_.Signal(); diff --git a/media/filters/video_renderer_base.h b/media/filters/video_renderer_base.h index 9f9c865..a0bb0f4 100644 --- a/media/filters/video_renderer_base.h +++ b/media/filters/video_renderer_base.h @@ -68,10 +68,11 @@ class VideoRendererBase : public VideoRenderer, // output surfaces. Implementors should NOT call InitializationComplete(). virtual bool OnInitialize(VideoDecoder* decoder) = 0; - // Subclass interface. Called before any other stopping actions takes place. + // Subclass interface. Called after all other stopping actions take place. // - // Implementors should perform any necessary cleanup before returning. - virtual void OnStop() = 0; + // Implementors should perform any necessary cleanup before calling the + // callback. + virtual void OnStop(FilterCallback* callback) = 0; // Subclass interface. Called when a new frame is ready for display, which // can be accessed via GetCurrentFrame(). diff --git a/media/filters/video_renderer_base_unittest.cc b/media/filters/video_renderer_base_unittest.cc index 02b352a..ae21320 100644 --- a/media/filters/video_renderer_base_unittest.cc +++ b/media/filters/video_renderer_base_unittest.cc @@ -4,6 +4,7 @@ #include "base/callback.h" #include "base/stl_util-inl.h" +#include "media/base/callback.h" #include "media/base/data_buffer.h" #include "media/base/mock_filter_host.h" #include "media/base/mock_filters.h" @@ -21,6 +22,9 @@ using ::testing::ReturnRef; using ::testing::StrictMock; namespace media { +ACTION(OnStop) { + AutoCallbackRunner auto_runner(arg0); +} // Mocked subclass of VideoRendererBase for testing purposes. class MockVideoRendererBase : public VideoRendererBase { @@ -30,7 +34,7 @@ class MockVideoRendererBase : public VideoRendererBase { // VideoRendererBase implementation. MOCK_METHOD1(OnInitialize, bool(VideoDecoder* decoder)); - MOCK_METHOD0(OnStop, void()); + MOCK_METHOD1(OnStop, void(FilterCallback* callback)); MOCK_METHOD0(OnFrameAvailable, void()); // Used for verifying check points during tests. @@ -68,7 +72,9 @@ class VideoRendererBaseTest : public ::testing::Test { read_queue_.clear(); // Expect a call into the subclass. - EXPECT_CALL(*renderer_, OnStop()); + EXPECT_CALL(*renderer_, OnStop(NotNull())) + .WillOnce(DoAll(OnStop(), Return())) + .RetiresOnSaturation(); EXPECT_CALL(callback_, OnFilterCallback()); EXPECT_CALL(callback_, OnCallbackDestroyed()); renderer_->Stop(callback_.NewCallback()); diff --git a/media/tools/player_wtl/player_wtl.cc b/media/tools/player_wtl/player_wtl.cc index 73abc95..5df87a7 100644 --- a/media/tools/player_wtl/player_wtl.cc +++ b/media/tools/player_wtl/player_wtl.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. diff --git a/media/tools/player_wtl/wtl_renderer.cc b/media/tools/player_wtl/wtl_renderer.cc index 28a6f3e..73c97db 100644 --- a/media/tools/player_wtl/wtl_renderer.cc +++ b/media/tools/player_wtl/wtl_renderer.cc @@ -19,7 +19,11 @@ bool WtlVideoRenderer::IsMediaFormatSupported( return ParseMediaFormat(media_format, NULL, NULL, NULL, NULL); } -void WtlVideoRenderer::OnStop() { +void WtlVideoRenderer::OnStop(media::FilterCallback* callback) { + if (callback) { + callback->Run(); + delete callback; + } } bool WtlVideoRenderer::OnInitialize(media::VideoDecoder* decoder) { diff --git a/media/tools/player_wtl/wtl_renderer.h b/media/tools/player_wtl/wtl_renderer.h index 86aa61f..70fbe0e 100644 --- a/media/tools/player_wtl/wtl_renderer.h +++ b/media/tools/player_wtl/wtl_renderer.h @@ -20,7 +20,7 @@ class WtlVideoRenderer : public media::VideoRendererBase { protected: // VideoRendererBase implementation. virtual bool OnInitialize(media::VideoDecoder* decoder); - virtual void OnStop(); + virtual void OnStop(media::FilterCallback* callback); virtual void OnFrameAvailable(); private: diff --git a/media/tools/player_x11/gl_video_renderer.cc b/media/tools/player_x11/gl_video_renderer.cc index a828fbe..e2f4681 100644 --- a/media/tools/player_x11/gl_video_renderer.cc +++ b/media/tools/player_x11/gl_video_renderer.cc @@ -13,11 +13,12 @@ GlVideoRenderer* GlVideoRenderer::instance_ = NULL; -GlVideoRenderer::GlVideoRenderer(Display* display, Window window) +GlVideoRenderer::GlVideoRenderer(Display* display, Window window, + MessageLoop* message_loop) : display_(display), window_(window), gl_context_(NULL), - glx_thread_message_loop_(NULL) { + glx_thread_message_loop_(message_loop) { } GlVideoRenderer::~GlVideoRenderer() { @@ -29,9 +30,13 @@ bool GlVideoRenderer::IsMediaFormatSupported( return ParseMediaFormat(media_format, NULL, NULL, NULL, NULL); } -void GlVideoRenderer::OnStop() { +void GlVideoRenderer::OnStop(media::FilterCallback* callback) { glXMakeCurrent(display_, 0, NULL); glXDestroyContext(display_, gl_context_); + if (callback) { + callback->Run(); + delete callback; + } } static GLXContext InitGLContext(Display* display, Window window) { diff --git a/media/tools/player_x11/gl_video_renderer.h b/media/tools/player_x11/gl_video_renderer.h index 24599bf..71f8d77 100644 --- a/media/tools/player_x11/gl_video_renderer.h +++ b/media/tools/player_x11/gl_video_renderer.h @@ -9,17 +9,20 @@ #include "base/lock.h" #include "base/scoped_ptr.h" #include "media/base/factory.h" +#include "media/base/filters.h" #include "media/filters/video_renderer_base.h" class GlVideoRenderer : public media::VideoRendererBase { public: static media::FilterFactory* CreateFactory(Display* display, - Window window) { - return new media::FilterFactoryImpl2< - GlVideoRenderer, Display*, Window>(display, window); + Window window, + MessageLoop* message_loop) { + return new media::FilterFactoryImpl3< + GlVideoRenderer, Display*, Window, MessageLoop*>(display, window, + message_loop); } - GlVideoRenderer(Display* display, Window window); + GlVideoRenderer(Display* display, Window window, MessageLoop* message_loop); // This method is called to paint the current video frame to the assigned // window. @@ -30,10 +33,6 @@ class GlVideoRenderer : public media::VideoRendererBase { static GlVideoRenderer* instance() { return instance_; } - void set_glx_thread_message_loop(MessageLoop* message_loop) { - glx_thread_message_loop_ = message_loop; - } - MessageLoop* glx_thread_message_loop() { return glx_thread_message_loop_; } @@ -41,7 +40,7 @@ class GlVideoRenderer : public media::VideoRendererBase { protected: // VideoRendererBase implementation. virtual bool OnInitialize(media::VideoDecoder* decoder); - virtual void OnStop(); + virtual void OnStop(media::FilterCallback* callback); virtual void OnFrameAvailable(); private: diff --git a/media/tools/player_x11/gles_video_renderer.cc b/media/tools/player_x11/gles_video_renderer.cc index 4bca69c..0b36e74 100644 --- a/media/tools/player_x11/gles_video_renderer.cc +++ b/media/tools/player_x11/gles_video_renderer.cc @@ -11,14 +11,15 @@ #include <X11/extensions/Xcomposite.h> #include "media/base/buffers.h" -#include "media/base/pipeline.h" #include "media/base/filter_host.h" +#include "media/base/pipeline.h" #include "media/base/video_frame.h" #include "media/base/yuv_convert.h" GlesVideoRenderer* GlesVideoRenderer::instance_ = NULL; -GlesVideoRenderer::GlesVideoRenderer(Display* display, Window window) +GlesVideoRenderer::GlesVideoRenderer(Display* display, Window window, + MessageLoop* message_loop) : egl_create_image_khr_(NULL), egl_destroy_image_khr_(NULL), display_(display), @@ -26,7 +27,7 @@ GlesVideoRenderer::GlesVideoRenderer(Display* display, Window window) egl_display_(NULL), egl_surface_(NULL), egl_context_(NULL), - glx_thread_message_loop_(NULL) { + glx_thread_message_loop_(message_loop) { } GlesVideoRenderer::~GlesVideoRenderer() { @@ -38,11 +39,17 @@ bool GlesVideoRenderer::IsMediaFormatSupported( return ParseMediaFormat(media_format, NULL, NULL, NULL, NULL); } -void GlesVideoRenderer::OnStop() { - // TODO(hclam): Context switching seems to be broek so the following - // calls may fail. Need to fix them. - eglMakeCurrent(egl_display_, EGL_NO_SURFACE, - EGL_NO_SURFACE, EGL_NO_CONTEXT); +void GlesVideoRenderer::OnStop(media::FilterCallback* callback) { + if (glx_thread_message_loop()) { + glx_thread_message_loop()->PostTask(FROM_HERE, + NewRunnableMethod(this, &GlesVideoRenderer::DeInitializeGlesTask, + callback)); + } +} + +void GlesVideoRenderer::DeInitializeGlesTask(media::FilterCallback* callback) { + DCHECK_EQ(glx_thread_message_loop(), MessageLoop::current()); + for (size_t i = 0; i < egl_frames_.size(); ++i) { scoped_refptr<media::VideoFrame> frame = egl_frames_[i].first; if (frame->private_buffer()) @@ -51,8 +58,15 @@ void GlesVideoRenderer::OnStop() { glDeleteTextures(1, &egl_frames_[i].second); } egl_frames_.clear(); + eglMakeCurrent(egl_display_, EGL_NO_SURFACE, + EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroyContext(egl_display_, egl_context_); eglDestroySurface(egl_display_, egl_surface_); + + if (callback) { + callback->Run(); + delete callback; + } } // Matrix used for the YUV to RGB conversion. diff --git a/media/tools/player_x11/gles_video_renderer.h b/media/tools/player_x11/gles_video_renderer.h index 195f33e..27780b6 100644 --- a/media/tools/player_x11/gles_video_renderer.h +++ b/media/tools/player_x11/gles_video_renderer.h @@ -13,18 +13,21 @@ #include "base/lock.h" #include "base/scoped_ptr.h" #include "media/base/factory.h" +#include "media/base/filters.h" #include "media/base/video_frame.h" #include "media/filters/video_renderer_base.h" class GlesVideoRenderer : public media::VideoRendererBase { public: static media::FilterFactory* CreateFactory(Display* display, - Window window) { - return new media::FilterFactoryImpl2< - GlesVideoRenderer, Display*, Window>(display, window); + Window window, + MessageLoop* message_loop) { + return new media::FilterFactoryImpl3< + GlesVideoRenderer, Display*, Window, MessageLoop*>(display, window, + message_loop); } - GlesVideoRenderer(Display* display, Window window); + GlesVideoRenderer(Display* display, Window window, MessageLoop* message_loop); // This method is called to paint the current video frame to the assigned // window. @@ -35,10 +38,6 @@ class GlesVideoRenderer : public media::VideoRendererBase { static GlesVideoRenderer* instance() { return instance_; } - void set_glx_thread_message_loop(MessageLoop* message_loop) { - glx_thread_message_loop_ = message_loop; - } - MessageLoop* glx_thread_message_loop() { return glx_thread_message_loop_; } @@ -46,7 +45,7 @@ class GlesVideoRenderer : public media::VideoRendererBase { protected: // VideoRendererBase implementation. virtual bool OnInitialize(media::VideoDecoder* decoder); - virtual void OnStop(); + virtual void OnStop(media::FilterCallback* callback); virtual void OnFrameAvailable(); private: @@ -62,6 +61,8 @@ class GlesVideoRenderer : public media::VideoRendererBase { void CreateTextureAndProgramEgl(); void CreateTextureAndProgramYuv2Rgb(); + void DeInitializeGlesTask(media::FilterCallback* callback); + PFNEGLCREATEIMAGEKHRPROC egl_create_image_khr_; PFNEGLDESTROYIMAGEKHRPROC egl_destroy_image_khr_; diff --git a/media/tools/player_x11/player_x11.cc b/media/tools/player_x11/player_x11.cc index 3833b4e..8811b98 100644 --- a/media/tools/player_x11/player_x11.cc +++ b/media/tools/player_x11/player_x11.cc @@ -68,7 +68,8 @@ bool InitX11() { bool InitPipeline(MessageLoop* message_loop, const char* filename, bool enable_audio, - scoped_refptr<media::PipelineImpl>* pipeline) { + scoped_refptr<media::PipelineImpl>* pipeline, + MessageLoop* paint_message_loop) { // Initialize OpenMAX. if (CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableOpenMax) && @@ -94,7 +95,8 @@ bool InitPipeline(MessageLoop* message_loop, factories->AddFactory(media::OmxVideoDecoder::CreateFactory()); } factories->AddFactory(media::FFmpegVideoDecoder::CreateFactory()); - factories->AddFactory(Renderer::CreateFactory(g_display, g_window)); + factories->AddFactory(Renderer::CreateFactory(g_display, g_window, + paint_message_loop)); if (enable_audio) { factories->AddFactory(media::AudioRendererImpl::CreateFilterFactory()); @@ -129,6 +131,7 @@ void TerminateHandler(int signal) { void PeriodicalUpdate( media::PipelineImpl* pipeline, MessageLoop* message_loop, + base::WaitableEvent* stop_event, bool audio_only) { if (!g_running) { message_loop->Quit(); @@ -172,7 +175,9 @@ void PeriodicalUpdate( g_running = false; // QuitNow is more responsive than Quit since renderer_base is till // posting paint messages. - message_loop->QuitNow(); + pipeline->Stop(NewCallback(stop_event, + &base::WaitableEvent::Signal)); + message_loop->Quit(); return; } else if (key == XK_space) { if (pipeline->GetPlaybackRate() < 0.01f) // paused @@ -189,7 +194,7 @@ void PeriodicalUpdate( message_loop->PostDelayedTask(FROM_HERE, NewRunnableFunction(PeriodicalUpdate, pipeline, - message_loop, audio_only), 10); + message_loop, stop_event, audio_only), 10); } int main(int argc, char** argv) { @@ -227,31 +232,24 @@ int main(int argc, char** argv) { scoped_ptr<base::Thread> thread; scoped_refptr<media::PipelineImpl> pipeline; MessageLoop message_loop; + base::WaitableEvent stop_event(false, false); thread.reset(new base::Thread("PipelineThread")); thread->Start(); if (InitPipeline(thread->message_loop(), filename.c_str(), - enable_audio, &pipeline)) { + enable_audio, &pipeline, &message_loop)) { // Main loop of the application. g_running = true; // Check if video is present. audio_only = !pipeline->IsRendered(media::mime_type::kMajorTypeVideo); - if (!audio_only) { - // Tell the renderer to paint. - DCHECK(Renderer::instance()); - Renderer::instance()->set_glx_thread_message_loop(&message_loop); - } - message_loop.PostTask(FROM_HERE, NewRunnableFunction(PeriodicalUpdate, pipeline.get(), - &message_loop, audio_only)); + &message_loop, &stop_event, audio_only)); message_loop.Run(); // Need to wait for pipeline to be fully stopped before stopping the thread. - base::WaitableEvent event(false, false); - pipeline->Stop(NewCallback(&event, &base::WaitableEvent::Signal)); - event.Wait(); + stop_event.Wait(); } else{ std::cout << "Pipeline initialization failed..." << std::endl; } diff --git a/media/tools/player_x11/x11_video_renderer.cc b/media/tools/player_x11/x11_video_renderer.cc index a1a9f15..881a719 100644 --- a/media/tools/player_x11/x11_video_renderer.cc +++ b/media/tools/player_x11/x11_video_renderer.cc @@ -53,13 +53,14 @@ static XRenderPictFormat* GetRenderARGB32Format(Display* dpy) { return pictformat; } -X11VideoRenderer::X11VideoRenderer(Display* display, Window window) +X11VideoRenderer::X11VideoRenderer(Display* display, Window window, + MessageLoop* message_loop) : display_(display), window_(window), image_(NULL), picture_(0), use_render_(false), - glx_thread_message_loop_(NULL) { + glx_thread_message_loop_(message_loop) { } X11VideoRenderer::~X11VideoRenderer() { @@ -71,11 +72,15 @@ bool X11VideoRenderer::IsMediaFormatSupported( return ParseMediaFormat(media_format, NULL, NULL, NULL, NULL); } -void X11VideoRenderer::OnStop() { +void X11VideoRenderer::OnStop(media::FilterCallback* callback) { if (image_) { XDestroyImage(image_); } XRenderFreePicture(display_, picture_); + if (callback) { + callback->Run(); + delete callback; + } } bool X11VideoRenderer::OnInitialize(media::VideoDecoder* decoder) { diff --git a/media/tools/player_x11/x11_video_renderer.h b/media/tools/player_x11/x11_video_renderer.h index 5b7a954..2bd9dc4 100644 --- a/media/tools/player_x11/x11_video_renderer.h +++ b/media/tools/player_x11/x11_video_renderer.h @@ -10,17 +10,20 @@ #include "base/lock.h" #include "base/scoped_ptr.h" #include "media/base/factory.h" +#include "media/base/filters.h" #include "media/filters/video_renderer_base.h" class X11VideoRenderer : public media::VideoRendererBase { public: static media::FilterFactory* CreateFactory(Display* display, - Window window) { - return new media::FilterFactoryImpl2< - X11VideoRenderer, Display*, Window>(display, window); + Window window, + MessageLoop* message_loop) { + return new media::FilterFactoryImpl3< + X11VideoRenderer, Display*, Window, MessageLoop*>(display, window, + message_loop); } - X11VideoRenderer(Display* display, Window window); + X11VideoRenderer(Display* display, Window window, MessageLoop* message_loop); // This method is called to paint the current video frame to the assigned // window. @@ -31,10 +34,6 @@ class X11VideoRenderer : public media::VideoRendererBase { static X11VideoRenderer* instance() { return instance_; } - void set_glx_thread_message_loop(MessageLoop* message_loop) { - glx_thread_message_loop_ = message_loop; - } - MessageLoop* glx_thread_message_loop() { return glx_thread_message_loop_; } @@ -42,7 +41,7 @@ class X11VideoRenderer : public media::VideoRendererBase { protected: // VideoRendererBase implementation. virtual bool OnInitialize(media::VideoDecoder* decoder); - virtual void OnStop(); + virtual void OnStop(media::FilterCallback* callback); virtual void OnFrameAvailable(); private: diff --git a/webkit/glue/media/video_renderer_impl.cc b/webkit/glue/media/video_renderer_impl.cc index 3fd8299..d1a4fdc 100644 --- a/webkit/glue/media/video_renderer_impl.cc +++ b/webkit/glue/media/video_renderer_impl.cc @@ -47,7 +47,11 @@ bool VideoRendererImpl::OnInitialize(media::VideoDecoder* decoder) { return false; } -void VideoRendererImpl::OnStop() { +void VideoRendererImpl::OnStop(media::FilterCallback* callback) { + if (callback) { + callback->Run(); + delete callback; + } } void VideoRendererImpl::OnFrameAvailable() { diff --git a/webkit/glue/media/video_renderer_impl.h b/webkit/glue/media/video_renderer_impl.h index 61e6ea1..30f2e38 100644 --- a/webkit/glue/media/video_renderer_impl.h +++ b/webkit/glue/media/video_renderer_impl.h @@ -60,7 +60,7 @@ class VideoRendererImpl : public WebVideoRenderer { virtual bool OnInitialize(media::VideoDecoder* decoder); // Method called by the VideoRendererBase when stopping. - virtual void OnStop(); + virtual void OnStop(media::FilterCallback* callback); // Method called by the VideoRendererBase when a frame is available. virtual void OnFrameAvailable(); |