webmediaplayer_impl.h revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
1// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5// Delegate calls from WebCore::MediaPlayerPrivate to Chrome's video player. 6// It contains PipelineImpl which is the actual media player pipeline, it glues 7// the media player pipeline, data source, audio renderer and renderer. 8// PipelineImpl would creates multiple threads and access some public methods 9// of this class, so we need to be extra careful about concurrent access of 10// methods and members. 11// 12// WebMediaPlayerImpl works with multiple objects, the most important ones are: 13// 14// media::PipelineImpl 15// The media playback pipeline. 16// 17// WebVideoRenderer 18// Video renderer object. 19// 20// WebMediaPlayerImpl::Proxy 21// Proxies methods calls from the media pipeline to WebKit. 22// 23// WebKit::WebMediaPlayerClient 24// WebKit client of this media player object. 25// 26// The following diagram shows the relationship of these objects: 27// (note: ref-counted reference is marked by a "r".) 28// 29// WebMediaPlayerImpl ------> PipelineImpl 30// | ^ | r 31// | | v 32// | | WebVideoRenderer 33// | | ^ r 34// | | | 35// | r | r | 36// .------> Proxy <-----. 37// | 38// | 39// v 40// WebMediaPlayerClient 41// 42// Notice that Proxy and WebVideoRenderer are referencing each other. This 43// interdependency has to be treated carefully. 44// 45// Other issues: 46// During tear down of the whole browser or a tab, the DOM tree may not be 47// destructed nicely, and there will be some dangling media threads trying to 48// the main thread, so we need this class to listen to destruction event of the 49// main thread and cleanup the media threads when the even is received. Also 50// at destruction of this class we will need to unhook it from destruction event 51// list of the main thread. 52 53#ifndef WEBKIT_GLUE_WEBMEDIAPLAYER_IMPL_H_ 54#define WEBKIT_GLUE_WEBMEDIAPLAYER_IMPL_H_ 55 56#include "base/lock.h" 57#include "base/message_loop.h" 58#include "base/ref_counted.h" 59#include "base/scoped_ptr.h" 60#include "base/thread.h" 61#include "base/waitable_event.h" 62#include "gfx/rect.h" 63#include "gfx/size.h" 64#include "media/base/filters.h" 65#include "media/base/pipeline.h" 66#include "skia/ext/platform_canvas.h" 67#include "third_party/WebKit/WebKit/chromium/public/WebMediaPlayer.h" 68#include "third_party/WebKit/WebKit/chromium/public/WebMediaPlayerClient.h" 69 70class GURL; 71 72namespace WebKit { 73class WebFrame; 74} 75 76namespace webkit_glue { 77 78class MediaResourceLoaderBridgeFactory; 79class WebDataSource; 80class WebVideoRenderer; 81 82class WebMediaPlayerImpl : public WebKit::WebMediaPlayer, 83 public MessageLoop::DestructionObserver { 84 public: 85 // A proxy class that dispatches method calls from the media pipeline to 86 // WebKit. Since there are multiple threads in the media pipeline and there's 87 // need for the media pipeline to call to WebKit, e.g. repaint requests, 88 // initialization events, etc, we have this class to bridge all method calls 89 // from the media pipeline on different threads and serialize these calls 90 // on the render thread. 91 // Because of the nature of this object that it works with different threads, 92 // it is made ref-counted. 93 class Proxy : public base::RefCountedThreadSafe<Proxy> { 94 public: 95 Proxy(MessageLoop* render_loop, 96 WebMediaPlayerImpl* webmediaplayer); 97 98 // Methods for Filter -> WebMediaPlayerImpl communication. 99 void Repaint(); 100 void SetVideoRenderer(scoped_refptr<WebVideoRenderer> video_renderer); 101 void SetDataSource(scoped_refptr<WebDataSource> data_source); 102 103 // Methods for WebMediaPlayerImpl -> Filter communication. 104 void Paint(skia::PlatformCanvas* canvas, const gfx::Rect& dest_rect); 105 void SetSize(const gfx::Rect& rect); 106 void Detach(); 107 void GetCurrentFrame(scoped_refptr<media::VideoFrame>* frame_out); 108 void PutCurrentFrame(scoped_refptr<media::VideoFrame> frame); 109 bool HasSingleOrigin(); 110 void AbortDataSource(); 111 112 // Methods for PipelineImpl -> WebMediaPlayerImpl communication. 113 void PipelineInitializationCallback(); 114 void PipelineSeekCallback(); 115 void PipelineEndedCallback(); 116 void PipelineErrorCallback(); 117 void NetworkEventCallback(); 118 119 // Returns the message loop used by the proxy. 120 MessageLoop* message_loop() { return render_loop_; } 121 122 private: 123 friend class base::RefCountedThreadSafe<Proxy>; 124 125 virtual ~Proxy(); 126 127 // Invoke |webmediaplayer_| to perform a repaint. 128 void RepaintTask(); 129 130 // Notify |webmediaplayer_| that initialization has finished. 131 void PipelineInitializationTask(); 132 133 // Notify |webmediaplayer_| that a seek has finished. 134 void PipelineSeekTask(); 135 136 // Notify |webmediaplayer_| that the media has ended. 137 void PipelineEndedTask(); 138 139 // Notify |webmediaplayer_| that a pipeline error has been set. 140 void PipelineErrorTask(); 141 142 // Notify |webmediaplayer_| that there's a network event. 143 void NetworkEventTask(); 144 145 // The render message loop where WebKit lives. 146 MessageLoop* render_loop_; 147 WebMediaPlayerImpl* webmediaplayer_; 148 scoped_refptr<WebDataSource> data_source_; 149 scoped_refptr<WebVideoRenderer> video_renderer_; 150 151 Lock lock_; 152 int outstanding_repaints_; 153 }; 154 155 // Construct a WebMediaPlayerImpl with reference to the client, and media 156 // filter collection. By providing the filter collection the implementor can 157 // provide more specific media filters that does resource loading and 158 // rendering. |collection| should contain filter factories for: 159 // 1. Data source 160 // 2. Audio renderer 161 // 3. Video renderer (optional) 162 // 163 // There are some default filters provided by this method: 164 // 1. FFmpeg demuxer 165 // 2. FFmpeg audio decoder 166 // 3. FFmpeg video decoder 167 // 4. Video renderer 168 // 5. Null audio renderer 169 // The video renderer provided by this class is using the graphics context 170 // provided by WebKit to perform renderering. The simple data source does 171 // resource loading by loading the whole resource object into memory. Null 172 // audio renderer is a fake audio device that plays silence. Provider of the 173 // |collection| can override the default filters by adding extra filters to 174 // |collection| before calling this method. 175 // 176 // Callers must call |Initialize()| before they can use the object. 177 WebMediaPlayerImpl(WebKit::WebMediaPlayerClient* client, 178 media::FilterCollection* collection); 179 virtual ~WebMediaPlayerImpl(); 180 181 // Finalizes initialization of the object. 182 bool Initialize( 183 WebKit::WebFrame* frame, 184 bool use_simple_data_source, 185 scoped_refptr<WebVideoRenderer> web_video_renderer); 186 187 virtual void load(const WebKit::WebURL& url); 188 virtual void cancelLoad(); 189 190 // Playback controls. 191 virtual void play(); 192 virtual void pause(); 193 virtual bool supportsFullscreen() const; 194 virtual bool supportsSave() const; 195 virtual void seek(float seconds); 196 virtual void setEndTime(float seconds); 197 virtual void setRate(float rate); 198 virtual void setVolume(float volume); 199 virtual void setVisible(bool visible); 200 virtual bool setAutoBuffer(bool autoBuffer); 201 virtual bool totalBytesKnown(); 202 virtual const WebKit::WebTimeRanges& buffered(); 203 virtual float maxTimeSeekable() const; 204 205 // Methods for painting. 206 virtual void setSize(const WebKit::WebSize& size); 207 208 virtual void paint(WebKit::WebCanvas* canvas, const WebKit::WebRect& rect); 209 210 // True if the loaded media has a playable video/audio track. 211 virtual bool hasVideo() const; 212 virtual bool hasAudio() const; 213 214 // Dimensions of the video. 215 virtual WebKit::WebSize naturalSize() const; 216 217 // Getters of playback state. 218 virtual bool paused() const; 219 virtual bool seeking() const; 220 virtual float duration() const; 221 virtual float currentTime() const; 222 223 // Get rate of loading the resource. 224 virtual int32 dataRate() const; 225 226 // Internal states of loading and network. 227 // TODO(hclam): Ask the pipeline about the state rather than having reading 228 // them from members which would cause race conditions. 229 virtual WebKit::WebMediaPlayer::NetworkState networkState() const; 230 virtual WebKit::WebMediaPlayer::ReadyState readyState() const; 231 232 virtual unsigned long long bytesLoaded() const; 233 virtual unsigned long long totalBytes() const; 234 235 virtual bool hasSingleSecurityOrigin() const; 236 virtual WebKit::WebMediaPlayer::MovieLoadType movieLoadType() const; 237 238 virtual WebKit::WebVideoFrame* getCurrentFrame(); 239 virtual void putCurrentFrame(WebKit::WebVideoFrame* web_video_frame); 240 241 // As we are closing the tab or even the browser, |main_loop_| is destroyed 242 // even before this object gets destructed, so we need to know when 243 // |main_loop_| is being destroyed and we can stop posting repaint task 244 // to it. 245 virtual void WillDestroyCurrentMessageLoop(); 246 247 void Repaint(); 248 249 void OnPipelineInitialize(); 250 251 void OnPipelineSeek(); 252 253 void OnPipelineEnded(); 254 255 void OnPipelineError(); 256 257 void OnNetworkEvent(); 258 259 private: 260 // Helpers that set the network/ready state and notifies the client if 261 // they've changed. 262 void SetNetworkState(WebKit::WebMediaPlayer::NetworkState state); 263 void SetReadyState(WebKit::WebMediaPlayer::ReadyState state); 264 265 // Destroy resources held. 266 void Destroy(); 267 268 // Callback executed after |pipeline_| stops which signals Destroy() 269 // to continue. 270 void PipelineStoppedCallback(); 271 272 // Getter method to |client_|. 273 WebKit::WebMediaPlayerClient* GetClient(); 274 275 // TODO(hclam): get rid of these members and read from the pipeline directly. 276 WebKit::WebMediaPlayer::NetworkState network_state_; 277 WebKit::WebMediaPlayer::ReadyState ready_state_; 278 279 // Keep a list of buffered time ranges. 280 WebKit::WebTimeRanges buffered_; 281 282 // Message loops for posting tasks between Chrome's main thread. Also used 283 // for DCHECKs so methods calls won't execute in the wrong thread. 284 MessageLoop* main_loop_; 285 286 // A collection of filters. 287 scoped_ptr<media::FilterCollection> filter_collection_; 288 289 // The actual pipeline and the thread it runs on. 290 scoped_refptr<media::Pipeline> pipeline_; 291 base::Thread pipeline_thread_; 292 293 // Playback state. 294 // 295 // TODO(scherkus): we have these because Pipeline favours the simplicity of a 296 // single "playback rate" over worrying about paused/stopped etc... It forces 297 // all clients to manage the pause+playback rate externally, but is that 298 // really a bad thing? 299 // 300 // TODO(scherkus): since SetPlaybackRate(0) is asynchronous and we don't want 301 // to hang the render thread during pause(), we record the time at the same 302 // time we pause and then return that value in currentTime(). Otherwise our 303 // clock can creep forward a little bit while the asynchronous 304 // SetPlaybackRate(0) is being executed. 305 bool paused_; 306 bool seeking_; 307 float playback_rate_; 308 base::TimeDelta paused_time_; 309 310 WebKit::WebMediaPlayerClient* client_; 311 312 scoped_refptr<Proxy> proxy_; 313 314 // Used to block Destroy() until Pipeline::Stop() is completed. 315 base::WaitableEvent pipeline_stopped_; 316 317#if WEBKIT_USING_CG 318 scoped_ptr<skia::PlatformCanvas> skia_canvas_; 319#endif 320 321 DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerImpl); 322}; 323 324} // namespace webkit_glue 325 326#endif // WEBKIT_GLUE_WEBMEDIAPLAYER_IMPL_H_ 327