[email protected] | add5177 | 2009-06-11 18:25:17 | [diff] [blame] | 1 | // Copyright (c) 2008-2009 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be found |
| 3 | // 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 | // |
[email protected] | 8931c41a | 2009-07-07 17:31:49 | [diff] [blame] | 12 | // WebMediaPlayerImpl works with multiple objects, the most important ones are: |
[email protected] | add5177 | 2009-06-11 18:25:17 | [diff] [blame] | 13 | // |
[email protected] | 8931c41a | 2009-07-07 17:31:49 | [diff] [blame] | 14 | // media::PipelineImpl |
| 15 | // The media playback pipeline. |
[email protected] | add5177 | 2009-06-11 18:25:17 | [diff] [blame] | 16 | // |
[email protected] | 8931c41a | 2009-07-07 17:31:49 | [diff] [blame] | 17 | // VideoRendererImpl |
| 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 | // | | VideoRendererImpl |
| 33 | // | | ^ r |
| 34 | // | | | |
| 35 | // | r | r | |
| 36 | // .------> Proxy <-----. |
| 37 | // | |
| 38 | // | |
| 39 | // v |
| 40 | // WebMediaPlayerClient |
| 41 | // |
| 42 | // Notice that Proxy and VideoRendererImpl are referencing each other. This |
| 43 | // interdependency has to be treated carefully. |
[email protected] | add5177 | 2009-06-11 18:25:17 | [diff] [blame] | 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_ |
[email protected] | 8931c41a | 2009-07-07 17:31:49 | [diff] [blame] | 54 | #define WEBKIT_GLUE_WEBMEDIAPLAYER_IMPL_H_ |
[email protected] | add5177 | 2009-06-11 18:25:17 | [diff] [blame] | 55 | |
| 56 | #include <vector> |
| 57 | |
[email protected] | 8931c41a | 2009-07-07 17:31:49 | [diff] [blame] | 58 | #include "base/gfx/rect.h" |
| 59 | #include "base/gfx/size.h" |
[email protected] | add5177 | 2009-06-11 18:25:17 | [diff] [blame] | 60 | #include "base/lock.h" |
| 61 | #include "base/message_loop.h" |
[email protected] | 8931c41a | 2009-07-07 17:31:49 | [diff] [blame] | 62 | #include "base/ref_counted.h" |
[email protected] | add5177 | 2009-06-11 18:25:17 | [diff] [blame] | 63 | #include "media/base/filters.h" |
| 64 | #include "media/base/pipeline_impl.h" |
[email protected] | 66a473c | 2009-07-22 02:12:50 | [diff] [blame] | 65 | #include "skia/ext/platform_canvas.h" |
[email protected] | add5177 | 2009-06-11 18:25:17 | [diff] [blame] | 66 | #include "webkit/api/public/WebMediaPlayer.h" |
| 67 | #include "webkit/api/public/WebMediaPlayerClient.h" |
| 68 | |
[email protected] | add5177 | 2009-06-11 18:25:17 | [diff] [blame] | 69 | class GURL; |
[email protected] | add5177 | 2009-06-11 18:25:17 | [diff] [blame] | 70 | |
| 71 | namespace media { |
| 72 | class FilterFactoryCollection; |
| 73 | } |
| 74 | |
| 75 | namespace webkit_glue { |
| 76 | |
[email protected] | 8931c41a | 2009-07-07 17:31:49 | [diff] [blame] | 77 | class VideoRendererImpl; |
[email protected] | add5177 | 2009-06-11 18:25:17 | [diff] [blame] | 78 | |
| 79 | class WebMediaPlayerImpl : public WebKit::WebMediaPlayer, |
| 80 | public MessageLoop::DestructionObserver { |
| 81 | public: |
[email protected] | 8931c41a | 2009-07-07 17:31:49 | [diff] [blame] | 82 | // A proxy class that dispatches method calls from the media pipeline to |
| 83 | // WebKit. Since there are multiple threads in the media pipeline and there's |
| 84 | // need for the media pipeline to call to WebKit, e.g. repaint requests, |
| 85 | // initialization events, etc, we have this class to bridge all method calls |
| 86 | // from the media pipeline on different threads and serialize these calls |
| 87 | // on the render thread. |
| 88 | // Because of the nature of this object that it works with different threads, |
| 89 | // it is made ref-counted. |
| 90 | class Proxy : public base::RefCountedThreadSafe<Proxy> { |
| 91 | public: |
| 92 | Proxy(MessageLoop* render_loop, |
| 93 | WebMediaPlayerImpl* webmediaplayer); |
| 94 | virtual ~Proxy(); |
| 95 | |
[email protected] | 9670691 | 2009-07-15 17:18:05 | [diff] [blame] | 96 | // Public methods called from the video renderer. |
[email protected] | 8931c41a | 2009-07-07 17:31:49 | [diff] [blame] | 97 | void Repaint(); |
[email protected] | 8931c41a | 2009-07-07 17:31:49 | [diff] [blame] | 98 | void SetVideoRenderer(VideoRendererImpl* video_renderer); |
| 99 | |
[email protected] | 9670691 | 2009-07-15 17:18:05 | [diff] [blame] | 100 | // Public methods called from WebMediaPlayerImpl. |
| 101 | void Paint(skia::PlatformCanvas* canvas, const gfx::Rect& dest_rect); |
| 102 | void SetSize(const gfx::Rect& rect); |
| 103 | void Detach(); |
[email protected] | 8931c41a | 2009-07-07 17:31:49 | [diff] [blame] | 104 | |
[email protected] | 9670691 | 2009-07-15 17:18:05 | [diff] [blame] | 105 | // Public methods called from the pipeline via callback issued by |
| 106 | // WebMediaPlayerImpl. |
| 107 | void PipelineInitializationCallback(); |
| 108 | void PipelineSeekCallback(); |
[email protected] | 57653784 | 2009-08-12 23:52:05 | [diff] [blame^] | 109 | void PipelineEndedCallback(); |
[email protected] | db190487d | 2009-07-30 18:51:52 | [diff] [blame] | 110 | void PipelineErrorCallback(); |
[email protected] | 9670691 | 2009-07-15 17:18:05 | [diff] [blame] | 111 | |
| 112 | private: |
[email protected] | 8931c41a | 2009-07-07 17:31:49 | [diff] [blame] | 113 | // Invoke |webmediaplayer_| to perform a repaint. |
| 114 | void RepaintTask(); |
| 115 | |
[email protected] | 9670691 | 2009-07-15 17:18:05 | [diff] [blame] | 116 | // Notify |webmediaplayer_| that initialization has finished. |
| 117 | void PipelineInitializationTask(); |
[email protected] | 8931c41a | 2009-07-07 17:31:49 | [diff] [blame] | 118 | |
[email protected] | 9670691 | 2009-07-15 17:18:05 | [diff] [blame] | 119 | // Notify |webmediaplayer_| that a seek has finished. |
| 120 | void PipelineSeekTask(); |
[email protected] | 8931c41a | 2009-07-07 17:31:49 | [diff] [blame] | 121 | |
[email protected] | 57653784 | 2009-08-12 23:52:05 | [diff] [blame^] | 122 | // Notify |webmediaplayer_| that the media has ended. |
| 123 | void PipelineEndedTask(); |
| 124 | |
[email protected] | db190487d | 2009-07-30 18:51:52 | [diff] [blame] | 125 | // Notify |webmediaplayer_| that a pipeline error has been set. |
| 126 | void PipelineErrorTask(); |
| 127 | |
[email protected] | 8931c41a | 2009-07-07 17:31:49 | [diff] [blame] | 128 | // The render message loop where WebKit lives. |
| 129 | MessageLoop* render_loop_; |
| 130 | WebMediaPlayerImpl* webmediaplayer_; |
| 131 | scoped_refptr<VideoRendererImpl> video_renderer_; |
| 132 | |
| 133 | Lock lock_; |
| 134 | int outstanding_repaints_; |
| 135 | }; |
| 136 | |
[email protected] | add5177 | 2009-06-11 18:25:17 | [diff] [blame] | 137 | // Construct a WebMediaPlayerImpl with reference to the client, and media |
| 138 | // filter factory collection. By providing the filter factory collection |
| 139 | // the implementor can provide more specific media filters that does resource |
| 140 | // loading and rendering. |factory| should contain filter factories for: |
| 141 | // 1. Data source |
| 142 | // 2. Audio renderer |
| 143 | // 3. Video renderer (optional) |
| 144 | // |
| 145 | // There are some default filters provided by this method: |
| 146 | // 1. FFmpeg demuxer |
| 147 | // 2. FFmpeg audio decoder |
| 148 | // 3. FFmpeg video decoder |
| 149 | // 4. Video renderer |
[email protected] | 8380c09 | 2009-06-25 17:45:51 | [diff] [blame] | 150 | // 5. Null audio renderer |
[email protected] | add5177 | 2009-06-11 18:25:17 | [diff] [blame] | 151 | // The video renderer provided by this class is using the graphics context |
| 152 | // provided by WebKit to perform renderering. The simple data source does |
| 153 | // resource loading by loading the whole resource object into memory. Null |
| 154 | // audio renderer is a fake audio device that plays silence. Provider of the |
| 155 | // |factory| can override the default filters by adding extra filters to |
| 156 | // |factory| before calling this method. |
| 157 | WebMediaPlayerImpl(WebKit::WebMediaPlayerClient* client, |
| 158 | media::FilterFactoryCollection* factory); |
| 159 | virtual ~WebMediaPlayerImpl(); |
| 160 | |
| 161 | virtual void load(const WebKit::WebURL& url); |
| 162 | virtual void cancelLoad(); |
| 163 | |
| 164 | // Playback controls. |
| 165 | virtual void play(); |
| 166 | virtual void pause(); |
[email protected] | 574a1d6 | 2009-07-17 03:23:46 | [diff] [blame] | 167 | virtual bool supportsFullscreen() const; |
| 168 | virtual bool supportsSave() const; |
[email protected] | add5177 | 2009-06-11 18:25:17 | [diff] [blame] | 169 | virtual void seek(float seconds); |
| 170 | virtual void setEndTime(float seconds); |
| 171 | virtual void setRate(float rate); |
| 172 | virtual void setVolume(float volume); |
| 173 | virtual void setVisible(bool visible); |
| 174 | virtual bool setAutoBuffer(bool autoBuffer); |
| 175 | virtual bool totalBytesKnown(); |
| 176 | virtual float maxTimeBuffered() const; |
| 177 | virtual float maxTimeSeekable() const; |
| 178 | |
| 179 | // Methods for painting. |
| 180 | virtual void setSize(const WebKit::WebSize& size); |
| 181 | |
[email protected] | add5177 | 2009-06-11 18:25:17 | [diff] [blame] | 182 | virtual void paint(WebKit::WebCanvas* canvas, const WebKit::WebRect& rect); |
[email protected] | add5177 | 2009-06-11 18:25:17 | [diff] [blame] | 183 | |
| 184 | // True if a video is loaded. |
| 185 | virtual bool hasVideo() const; |
| 186 | |
| 187 | // Dimensions of the video. |
| 188 | virtual WebKit::WebSize naturalSize() const; |
| 189 | |
| 190 | // Getters of playback state. |
| 191 | virtual bool paused() const; |
| 192 | virtual bool seeking() const; |
| 193 | virtual float duration() const; |
| 194 | virtual float currentTime() const; |
| 195 | |
| 196 | // Get rate of loading the resource. |
| 197 | virtual int32 dataRate() const; |
| 198 | |
| 199 | // Internal states of loading and network. |
| 200 | // TODO(hclam): Ask the pipeline about the state rather than having reading |
| 201 | // them from members which would cause race conditions. |
| 202 | virtual WebKit::WebMediaPlayer::NetworkState networkState() const { |
| 203 | return network_state_; |
| 204 | } |
| 205 | virtual WebKit::WebMediaPlayer::ReadyState readyState() const { |
| 206 | return ready_state_; |
| 207 | } |
| 208 | |
| 209 | virtual unsigned long long bytesLoaded() const; |
| 210 | virtual unsigned long long totalBytes() const; |
| 211 | |
[email protected] | 38259a7a8 | 2009-07-29 21:49:49 | [diff] [blame] | 212 | virtual bool hasSingleSecurityOrigin() const; |
| 213 | virtual WebKit::WebMediaPlayer::MovieLoadType movieLoadType() const; |
| 214 | |
[email protected] | add5177 | 2009-06-11 18:25:17 | [diff] [blame] | 215 | // As we are closing the tab or even the browser, |main_loop_| is destroyed |
| 216 | // even before this object gets destructed, so we need to know when |
| 217 | // |main_loop_| is being destroyed and we can stop posting repaint task |
| 218 | // to it. |
| 219 | virtual void WillDestroyCurrentMessageLoop(); |
| 220 | |
[email protected] | 8931c41a | 2009-07-07 17:31:49 | [diff] [blame] | 221 | void Repaint(); |
[email protected] | add5177 | 2009-06-11 18:25:17 | [diff] [blame] | 222 | |
[email protected] | 9670691 | 2009-07-15 17:18:05 | [diff] [blame] | 223 | void OnPipelineInitialize(); |
[email protected] | add5177 | 2009-06-11 18:25:17 | [diff] [blame] | 224 | |
[email protected] | 9670691 | 2009-07-15 17:18:05 | [diff] [blame] | 225 | void OnPipelineSeek(); |
[email protected] | add5177 | 2009-06-11 18:25:17 | [diff] [blame] | 226 | |
[email protected] | 57653784 | 2009-08-12 23:52:05 | [diff] [blame^] | 227 | void OnPipelineEnded(); |
| 228 | |
[email protected] | db190487d | 2009-07-30 18:51:52 | [diff] [blame] | 229 | void OnPipelineError(); |
| 230 | |
[email protected] | add5177 | 2009-06-11 18:25:17 | [diff] [blame] | 231 | private: |
[email protected] | 9670691 | 2009-07-15 17:18:05 | [diff] [blame] | 232 | // Helpers that set the network/ready state and notifies the client if |
| 233 | // they've changed. |
| 234 | void SetNetworkState(WebKit::WebMediaPlayer::NetworkState state); |
| 235 | void SetReadyState(WebKit::WebMediaPlayer::ReadyState state); |
| 236 | |
[email protected] | 8931c41a | 2009-07-07 17:31:49 | [diff] [blame] | 237 | // Destroy resources held. |
| 238 | void Destroy(); |
[email protected] | add5177 | 2009-06-11 18:25:17 | [diff] [blame] | 239 | |
[email protected] | 8931c41a | 2009-07-07 17:31:49 | [diff] [blame] | 240 | // Getter method to |client_|. |
| 241 | WebKit::WebMediaPlayerClient* GetClient(); |
[email protected] | add5177 | 2009-06-11 18:25:17 | [diff] [blame] | 242 | |
| 243 | // TODO(hclam): get rid of these members and read from the pipeline directly. |
| 244 | WebKit::WebMediaPlayer::NetworkState network_state_; |
| 245 | WebKit::WebMediaPlayer::ReadyState ready_state_; |
| 246 | |
| 247 | // Message loops for posting tasks between Chrome's main thread. Also used |
| 248 | // for DCHECKs so methods calls won't execute in the wrong thread. |
| 249 | MessageLoop* main_loop_; |
| 250 | |
| 251 | // A collection of factories for creating filters. |
| 252 | scoped_refptr<media::FilterFactoryCollection> filter_factory_; |
| 253 | |
[email protected] | 3b4cbbf | 2009-07-11 00:16:19 | [diff] [blame] | 254 | // The actual pipeline and the thread it runs on. |
[email protected] | a564815 | 2009-07-18 03:37:43 | [diff] [blame] | 255 | scoped_refptr<media::PipelineImpl> pipeline_; |
[email protected] | 3b4cbbf | 2009-07-11 00:16:19 | [diff] [blame] | 256 | base::Thread pipeline_thread_; |
[email protected] | add5177 | 2009-06-11 18:25:17 | [diff] [blame] | 257 | |
[email protected] | 4948090 | 2009-07-14 20:23:43 | [diff] [blame] | 258 | // Playback state. |
| 259 | // |
| 260 | // TODO(scherkus): we have these because Pipeline favours the simplicity of a |
| 261 | // single "playback rate" over worrying about paused/stopped etc... It forces |
| 262 | // all clients to manage the pause+playback rate externally, but is that |
| 263 | // really a bad thing? |
| 264 | bool paused_; |
| 265 | float playback_rate_; |
| 266 | |
[email protected] | add5177 | 2009-06-11 18:25:17 | [diff] [blame] | 267 | WebKit::WebMediaPlayerClient* client_; |
| 268 | |
[email protected] | 8931c41a | 2009-07-07 17:31:49 | [diff] [blame] | 269 | scoped_refptr<Proxy> proxy_; |
[email protected] | add5177 | 2009-06-11 18:25:17 | [diff] [blame] | 270 | |
| 271 | DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerImpl); |
| 272 | }; |
| 273 | |
| 274 | } // namespace webkit_glue |
| 275 | |
| 276 | #endif // WEBKIT_GLUE_WEBMEDIAPLAYER_IMPL_H_ |