// 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 #include #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/public/renderer/render_view_observer.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/platform/WebMediaPlayer.h" #include "third_party/WebKit/public/platform/WebMediaPlayerClient.h" #include "url/gurl.h" class RenderAudioSourceProvider; namespace blink { class WebFrame; } namespace base { class MessageLoopProxy; } namespace media { class ChunkDemuxer; class GpuVideoAcceleratorFactories; class MediaLog; } namespace webkit { class WebLayerImpl; } namespace content { class BufferedDataSource; class WebAudioSourceProviderImpl; class WebMediaPlayerDelegate; class WebMediaPlayerParams; class WebTextTrackImpl; class WebMediaPlayerImpl : public blink::WebMediaPlayer, public cc::VideoFrameProvider, public content::RenderViewObserver, public base::SupportsWeakPtr { public: // Constructs a WebMediaPlayer implementation using Chromium's media stack. // |render_view| is passed only for the purpose of registering |this| as an // observer of it. // |delegate| may be null. WebMediaPlayerImpl( content::RenderView* render_view, blink::WebFrame* frame, blink::WebMediaPlayerClient* client, base::WeakPtr delegate, const WebMediaPlayerParams& params); virtual ~WebMediaPlayerImpl(); virtual void load(LoadType load_type, const blink::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(blink::WebMediaPlayer::Preload preload); virtual const blink::WebTimeRanges& buffered(); virtual double maxTimeSeekable() const; // Methods for painting. virtual void paint(blink::WebCanvas* canvas, const blink::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 blink::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 blink::WebMediaPlayer::NetworkState networkState() const; virtual blink::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 GetCurrentFrame() OVERRIDE; virtual void PutCurrentFrame(const scoped_refptr& frame) OVERRIDE; virtual bool copyVideoTextureToPlatformTexture( blink::WebGraphicsContext3D* web_graphics_context, unsigned int texture, unsigned int level, unsigned int internal_format, unsigned int type, bool premultiply_alpha, bool flip_y); virtual blink::WebAudioSourceProvider* audioSourceProvider(); virtual MediaKeyException generateKeyRequest( const blink::WebString& key_system, const unsigned char* init_data, unsigned init_data_length); virtual MediaKeyException addKey(const blink::WebString& key_system, const unsigned char* key, unsigned key_length, const unsigned char* init_data, unsigned init_data_length, const blink::WebString& session_id); virtual MediaKeyException cancelKeyRequest( const blink::WebString& key_system, const blink::WebString& session_id); // content::RenderViewObserver implementation. virtual void OnDestruct() 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& message, const std::string& default_url); void OnNeedKey(const std::string& type, const std::vector& init_data); void OnAddTextTrack(const media::TextTrackConfig& config, const media::AddTextTrackDoneCB& done_cb); 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 blink::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(blink::WebMediaPlayer::NetworkState state); void SetReadyState(blink::WebMediaPlayer::ReadyState state); // Destroy resources held. void Destroy(); // Getter method to |client_|. blink::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 blink::WebString& key_system, const unsigned char* init_data, unsigned init_data_length); MediaKeyException AddKeyInternal(const blink::WebString& key_system, const unsigned char* key, unsigned key_length, const unsigned char* init_data, unsigned init_data_length, const blink::WebString& session_id); MediaKeyException CancelKeyRequestInternal( const blink::WebString& key_system, const blink::WebString& session_id); // Gets the duration value reported by the pipeline. double GetPipelineDuration() const; // Notifies WebKit of the duration change. void OnDurationChange(); // Called by VideoRendererImpl on its internal thread with the new frame to be // painted. void FrameReady(const scoped_refptr& 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); blink::WebFrame* frame_; // TODO(hclam): get rid of these members and read from the pipeline directly. blink::WebMediaPlayer::NetworkState network_state_; blink::WebMediaPlayer::ReadyState ready_state_; // Keep a list of buffered time ranges. blink::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 main_loop_; scoped_ptr pipeline_; scoped_refptr media_loop_; // The currently selected key system. Empty string means that no key system // has been selected. blink::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_; blink::WebMediaPlayerClient* client_; base::WeakPtr delegate_; base::Callback defer_load_cb_; scoped_refptr 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 gpu_factories_; // Routes audio playback to either AudioRendererSink or WebAudio. scoped_refptr audio_source_provider_; bool is_local_source_; bool supports_save_; // The decryptor that manages decryption keys and decrypts encrypted frames. scoped_ptr 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 data_source_; scoped_ptr 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 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 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_