| // Copyright 2013 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. |
| |
| // Delegate calls from WebCore::MediaPlayerPrivate to Chrome's video player. |
| // It contains Pipeline which is the actual media player pipeline, it glues |
| // the media player pipeline, data source, audio renderer and renderer. |
| // Pipeline would creates multiple threads and access some public methods |
| // of this class, so we need to be extra careful about concurrent access of |
| // methods and members. |
| // |
| // Other issues: |
| // During tear down of the whole browser or a tab, the DOM tree may not be |
| // destructed nicely, and there will be some dangling media threads trying to |
| // the main thread, so we need this class to listen to destruction event of the |
| // main thread and cleanup the media threads when the even is received. Also |
| // at destruction of this class we will need to unhook it from destruction event |
| // list of the main thread. |
| |
| #ifndef CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_IMPL_H_ |
| #define CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_IMPL_H_ |
| |
| #include <string> |
| #include <vector> |
| |
| #include "base/basictypes.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/threading/thread.h" |
| #include "cc/layers/video_frame_provider.h" |
| #include "content/renderer/media/crypto/proxy_decryptor.h" |
| #include "media/base/audio_renderer_sink.h" |
| #include "media/base/decryptor.h" |
| #include "media/base/media_keys.h" |
| #include "media/base/pipeline.h" |
| #include "media/base/text_track.h" |
| #include "media/filters/skcanvas_video_renderer.h" |
| #include "skia/ext/platform_canvas.h" |
| #include "third_party/WebKit/public/platform/WebAudioSourceProvider.h" |
| #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" |
| #include "third_party/WebKit/public/web/WebMediaPlayer.h" |
| #include "third_party/WebKit/public/web/WebMediaPlayerClient.h" |
| #include "url/gurl.h" |
| |
| class RenderAudioSourceProvider; |
| |
| namespace WebKit { |
| class WebFrame; |
| } |
| |
| namespace base { |
| class MessageLoopProxy; |
| } |
| |
| namespace media { |
| class ChunkDemuxer; |
| class FFmpegDemuxer; |
| class GpuVideoAcceleratorFactories; |
| class MediaLog; |
| } |
| |
| namespace webkit { |
| class WebLayerImpl; |
| } |
| |
| namespace content { |
| class BufferedDataSource; |
| class WebAudioSourceProviderImpl; |
| class WebMediaPlayerDelegate; |
| class WebMediaPlayerParams; |
| class WebTextTrackImpl; |
| |
| class WebMediaPlayerImpl |
| : public WebKit::WebMediaPlayer, |
| public cc::VideoFrameProvider, |
| public base::MessageLoop::DestructionObserver, |
| public base::SupportsWeakPtr<WebMediaPlayerImpl> { |
| public: |
| // Constructs a WebMediaPlayer implementation using Chromium's media stack. |
| // |
| // |delegate| may be null. |
| WebMediaPlayerImpl( |
| WebKit::WebFrame* frame, |
| WebKit::WebMediaPlayerClient* client, |
| base::WeakPtr<WebMediaPlayerDelegate> delegate, |
| const WebMediaPlayerParams& params); |
| virtual ~WebMediaPlayerImpl(); |
| |
| virtual void load(LoadType load_type, |
| const WebKit::WebURL& url, |
| CORSMode cors_mode) OVERRIDE; |
| |
| // Playback controls. |
| virtual void play(); |
| virtual void pause(); |
| virtual bool supportsFullscreen() const; |
| virtual bool supportsSave() const; |
| virtual void seek(double seconds); |
| virtual void setRate(double rate); |
| virtual void setVolume(double volume); |
| virtual void setPreload(WebKit::WebMediaPlayer::Preload preload); |
| virtual const WebKit::WebTimeRanges& buffered(); |
| virtual double maxTimeSeekable() const; |
| |
| // Methods for painting. |
| virtual void paint(WebKit::WebCanvas* canvas, |
| const WebKit::WebRect& rect, |
| unsigned char alpha); |
| |
| // True if the loaded media has a playable video/audio track. |
| virtual bool hasVideo() const; |
| virtual bool hasAudio() const; |
| |
| // Dimensions of the video. |
| virtual WebKit::WebSize naturalSize() const; |
| |
| // Getters of playback state. |
| virtual bool paused() const; |
| virtual bool seeking() const; |
| virtual double duration() const; |
| virtual double currentTime() const; |
| |
| // Internal states of loading and network. |
| // TODO(hclam): Ask the pipeline about the state rather than having reading |
| // them from members which would cause race conditions. |
| virtual WebKit::WebMediaPlayer::NetworkState networkState() const; |
| virtual WebKit::WebMediaPlayer::ReadyState readyState() const; |
| |
| virtual bool didLoadingProgress() const; |
| |
| virtual bool hasSingleSecurityOrigin() const; |
| virtual bool didPassCORSAccessCheck() const; |
| |
| virtual double mediaTimeForTimeValue(double timeValue) const; |
| |
| virtual unsigned decodedFrameCount() const; |
| virtual unsigned droppedFrameCount() const; |
| virtual unsigned audioDecodedByteCount() const; |
| virtual unsigned videoDecodedByteCount() const; |
| |
| // cc::VideoFrameProvider implementation. |
| virtual void SetVideoFrameProviderClient( |
| cc::VideoFrameProvider::Client* client) OVERRIDE; |
| virtual scoped_refptr<media::VideoFrame> GetCurrentFrame() OVERRIDE; |
| virtual void PutCurrentFrame(const scoped_refptr<media::VideoFrame>& frame) |
| OVERRIDE; |
| |
| virtual bool copyVideoTextureToPlatformTexture( |
| WebKit::WebGraphicsContext3D* web_graphics_context, |
| unsigned int texture, |
| unsigned int level, |
| unsigned int internal_format, |
| unsigned int type, |
| bool premultiply_alpha, |
| bool flip_y); |
| |
| virtual WebKit::WebAudioSourceProvider* audioSourceProvider(); |
| |
| virtual MediaKeyException generateKeyRequest( |
| const WebKit::WebString& key_system, |
| const unsigned char* init_data, |
| unsigned init_data_length); |
| |
| virtual MediaKeyException addKey(const WebKit::WebString& key_system, |
| const unsigned char* key, |
| unsigned key_length, |
| const unsigned char* init_data, |
| unsigned init_data_length, |
| const WebKit::WebString& session_id); |
| |
| virtual MediaKeyException cancelKeyRequest( |
| const WebKit::WebString& key_system, |
| const WebKit::WebString& session_id); |
| |
| // As we are closing the tab or even the browser, |main_loop_| is destroyed |
| // even before this object gets destructed, so we need to know when |
| // |main_loop_| is being destroyed and we can stop posting repaint task |
| // to it. |
| virtual void WillDestroyCurrentMessageLoop() OVERRIDE; |
| |
| void Repaint(); |
| |
| void OnPipelineSeek(media::PipelineStatus status); |
| void OnPipelineEnded(); |
| void OnPipelineError(media::PipelineStatus error); |
| void OnPipelineBufferingState( |
| media::Pipeline::BufferingState buffering_state); |
| void OnDemuxerOpened(); |
| void OnKeyAdded(const std::string& session_id); |
| void OnKeyError(const std::string& session_id, |
| media::MediaKeys::KeyError error_code, |
| int system_code); |
| void OnKeyMessage(const std::string& session_id, |
| const std::vector<uint8>& message, |
| const std::string& default_url); |
| void OnNeedKey(const std::string& type, |
| const std::vector<uint8>& init_data); |
| scoped_ptr<media::TextTrack> OnTextTrack(media::TextKind kind, |
| const std::string& label, |
| const std::string& language); |
| void SetOpaque(bool); |
| |
| private: |
| // Called after |defer_load_cb_| has decided to allow the load. If |
| // |defer_load_cb_| is null this is called immediately. |
| void DoLoad(LoadType load_type, |
| const WebKit::WebURL& url, |
| CORSMode cors_mode); |
| |
| // Called after asynchronous initialization of a data source completed. |
| void DataSourceInitialized(const GURL& gurl, bool success); |
| |
| // Called when the data source is downloading or paused. |
| void NotifyDownloading(bool is_downloading); |
| |
| // Finishes starting the pipeline due to a call to load(). |
| void StartPipeline(); |
| |
| // Helpers that set the network/ready state and notifies the client if |
| // they've changed. |
| void SetNetworkState(WebKit::WebMediaPlayer::NetworkState state); |
| void SetReadyState(WebKit::WebMediaPlayer::ReadyState state); |
| |
| // Destroy resources held. |
| void Destroy(); |
| |
| // Getter method to |client_|. |
| WebKit::WebMediaPlayerClient* GetClient(); |
| |
| // Lets V8 know that player uses extra resources not managed by V8. |
| void IncrementExternallyAllocatedMemory(); |
| |
| // Actually do the work for generateKeyRequest/addKey so they can easily |
| // report results to UMA. |
| MediaKeyException GenerateKeyRequestInternal( |
| const WebKit::WebString& key_system, |
| const unsigned char* init_data, |
| unsigned init_data_length); |
| MediaKeyException AddKeyInternal(const WebKit::WebString& key_system, |
| const unsigned char* key, |
| unsigned key_length, |
| const unsigned char* init_data, |
| unsigned init_data_length, |
| const WebKit::WebString& session_id); |
| MediaKeyException CancelKeyRequestInternal( |
| const WebKit::WebString& key_system, |
| const WebKit::WebString& session_id); |
| |
| // Gets the duration value reported by the pipeline. |
| double GetPipelineDuration() const; |
| |
| // Notifies WebKit of the duration change. |
| void OnDurationChange(); |
| |
| // Called by VideoRendererBase on its internal thread with the new frame to be |
| // painted. |
| void FrameReady(const scoped_refptr<media::VideoFrame>& frame); |
| |
| // Called when a paint or a new frame arrives to indicate that we are |
| // no longer waiting for |current_frame_| to be painted. |
| // |painting_frame| is set to true if |current_frame_| is being painted. |
| // False indicates |current_frame_| is being replaced with a new frame. |
| void DoneWaitingForPaint(bool painting_frame); |
| |
| WebKit::WebFrame* frame_; |
| |
| // TODO(hclam): get rid of these members and read from the pipeline directly. |
| WebKit::WebMediaPlayer::NetworkState network_state_; |
| WebKit::WebMediaPlayer::ReadyState ready_state_; |
| |
| // Keep a list of buffered time ranges. |
| WebKit::WebTimeRanges buffered_; |
| |
| // Message loops for posting tasks on Chrome's main thread. Also used |
| // for DCHECKs so methods calls won't execute in the wrong thread. |
| const scoped_refptr<base::MessageLoopProxy> main_loop_; |
| |
| scoped_ptr<media::Pipeline> pipeline_; |
| scoped_refptr<base::MessageLoopProxy> media_loop_; |
| |
| // The currently selected key system. Empty string means that no key system |
| // has been selected. |
| WebKit::WebString current_key_system_; |
| |
| // The LoadType passed in the |load_type| parameter of the load() call. |
| LoadType load_type_; |
| |
| // Playback state. |
| // |
| // TODO(scherkus): we have these because Pipeline favours the simplicity of a |
| // single "playback rate" over worrying about paused/stopped etc... It forces |
| // all clients to manage the pause+playback rate externally, but is that |
| // really a bad thing? |
| // |
| // TODO(scherkus): since SetPlaybackRate(0) is asynchronous and we don't want |
| // to hang the render thread during pause(), we record the time at the same |
| // time we pause and then return that value in currentTime(). Otherwise our |
| // clock can creep forward a little bit while the asynchronous |
| // SetPlaybackRate(0) is being executed. |
| bool paused_; |
| bool seeking_; |
| double playback_rate_; |
| base::TimeDelta paused_time_; |
| |
| // Seek gets pending if another seek is in progress. Only last pending seek |
| // will have effect. |
| bool pending_seek_; |
| double pending_seek_seconds_; |
| |
| WebKit::WebMediaPlayerClient* client_; |
| |
| base::WeakPtr<WebMediaPlayerDelegate> delegate_; |
| |
| base::Callback<void(const base::Closure&)> defer_load_cb_; |
| |
| scoped_refptr<media::MediaLog> media_log_; |
| |
| // Since accelerated compositing status is only known after the first layout, |
| // we delay reporting it to UMA until that time. |
| bool accelerated_compositing_reported_; |
| |
| bool incremented_externally_allocated_memory_; |
| |
| // Factories for supporting video accelerators. May be null. |
| scoped_refptr<media::GpuVideoAcceleratorFactories> gpu_factories_; |
| |
| // Routes audio playback to either AudioRendererSink or WebAudio. |
| scoped_refptr<WebAudioSourceProviderImpl> audio_source_provider_; |
| |
| bool is_local_source_; |
| bool supports_save_; |
| |
| // The decryptor that manages decryption keys and decrypts encrypted frames. |
| scoped_ptr<ProxyDecryptor> decryptor_; |
| |
| bool starting_; |
| |
| // These two are mutually exclusive: |
| // |data_source_| is used for regular resource loads. |
| // |chunk_demuxer_| is used for Media Source resource loads. |
| // |
| // |demuxer_| will contain the appropriate demuxer based on which resource |
| // load strategy we're using. |
| scoped_ptr<BufferedDataSource> data_source_; |
| scoped_ptr<media::Demuxer> demuxer_; |
| media::ChunkDemuxer* chunk_demuxer_; |
| |
| // Temporary for EME v0.1. In the future the init data type should be passed |
| // through GenerateKeyRequest() directly from WebKit. |
| std::string init_data_type_; |
| |
| // Video frame rendering members. |
| // |
| // |lock_| protects |current_frame_|, |current_frame_painted_|, and |
| // |frames_dropped_before_paint_| since new frames arrive on the video |
| // rendering thread, yet are accessed for rendering on either the main thread |
| // or compositing thread depending on whether accelerated compositing is used. |
| mutable base::Lock lock_; |
| media::SkCanvasVideoRenderer skcanvas_video_renderer_; |
| scoped_refptr<media::VideoFrame> current_frame_; |
| bool current_frame_painted_; |
| uint32 frames_dropped_before_paint_; |
| bool pending_repaint_; |
| bool pending_size_change_; |
| |
| // The compositor layer for displaying the video content when using composited |
| // playback. |
| scoped_ptr<webkit::WebLayerImpl> video_weblayer_; |
| |
| // A pointer back to the compositor to inform it about state changes. This is |
| // not NULL while the compositor is actively using this webmediaplayer. |
| cc::VideoFrameProvider::Client* video_frame_provider_client_; |
| |
| // Text track objects get a unique index value when they're created. |
| int text_track_index_; |
| |
| DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerImpl); |
| }; |
| |
| } // namespace content |
| |
| #endif // CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_IMPL_H_ |