| // Copyright 2015 Google Inc. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #ifndef COBALT_DOM_HTML_MEDIA_ELEMENT_H_ |
| #define COBALT_DOM_HTML_MEDIA_ELEMENT_H_ |
| |
| #include <string> |
| |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/optional.h" |
| #include "base/threading/thread_checker.h" |
| #include "base/timer.h" |
| #include "cobalt/dom/event_queue.h" |
| #include "cobalt/dom/html_element.h" |
| #include "cobalt/dom/media_error.h" |
| #include "cobalt/dom/time_ranges.h" |
| #include "cobalt/dom/uint8_array.h" |
| #include "cobalt/loader/image/image_cache.h" |
| #include "cobalt/script/exception_state.h" |
| #include "googleurl/src/gurl.h" |
| #if defined(COBALT_MEDIA_SOURCE_2016) |
| #include "cobalt/dom/eme/media_keys.h" |
| #include "cobalt/media/player/web_media_player.h" |
| #else // defined(COBALT_MEDIA_SOURCE_2016) |
| #include "cobalt/dom/media_source.h" |
| #include "media/player/web_media_player.h" |
| #endif // defined(COBALT_MEDIA_SOURCE_2016) |
| |
| namespace cobalt { |
| namespace dom { |
| |
| class MediaSource; |
| |
| #if defined(COBALT_MEDIA_SOURCE_2016) |
| typedef media::ChunkDemuxer ChunkDemuxer; |
| typedef media::WebMediaPlayer WebMediaPlayer; |
| typedef media::WebMediaPlayerClient WebMediaPlayerClient; |
| #else // defined(COBALT_MEDIA_SOURCE_2016) |
| typedef ::media::WebMediaPlayer WebMediaPlayer; |
| typedef ::media::WebMediaPlayerClient WebMediaPlayerClient; |
| #endif // defined(COBALT_MEDIA_SOURCE_2016) |
| |
| // The HTMLMediaElement is the base of HTMLAudioElement and HTMLVideoElement. |
| // https://www.w3.org/TR/html5/embedded-content-0.html#media-element |
| class HTMLMediaElement : public HTMLElement, private WebMediaPlayerClient { |
| public: |
| HTMLMediaElement(Document* document, base::Token tag_name); |
| ~HTMLMediaElement() OVERRIDE; |
| |
| // Web API: HTMLMediaElement |
| // |
| // Error state |
| scoped_refptr<MediaError> error() const; |
| |
| // Network state |
| std::string src() const; |
| void set_src(const std::string& src); |
| const std::string& current_src() const { return current_src_; } |
| |
| enum NetworkState { |
| kNetworkEmpty, |
| kNetworkIdle, |
| kNetworkLoading, |
| kNetworkNoSource |
| }; |
| uint16_t network_state() const; |
| |
| scoped_refptr<TimeRanges> buffered() const; |
| void Load(); |
| std::string CanPlayType(const std::string& mimeType); |
| std::string CanPlayType(const std::string& mimeType, |
| const std::string& key_system); |
| |
| #if defined(COBALT_MEDIA_SOURCE_2016) |
| const EventListenerScriptValue* onencrypted() const; |
| void set_onencrypted(const EventListenerScriptValue& event_listener); |
| |
| const scoped_refptr<eme::MediaKeys>& media_keys() const { |
| return media_keys_; |
| } |
| typedef script::ScriptValue<script::Promise<void> > VoidPromiseValue; |
| scoped_ptr<VoidPromiseValue> SetMediaKeys( |
| const scoped_refptr<eme::MediaKeys>& media_keys); |
| #else // defined(COBALT_MEDIA_SOURCE_2016) |
| void GenerateKeyRequest( |
| const std::string& key_system, |
| const base::optional<scoped_refptr<Uint8Array> >& init_data, |
| script::ExceptionState* exception_state); |
| void AddKey(const std::string& key_system, |
| const scoped_refptr<const Uint8Array>& key, |
| const base::optional<scoped_refptr<Uint8Array> >& init_data, |
| const base::optional<std::string>& session_id, |
| script::ExceptionState* exception_state); |
| void CancelKeyRequest(const std::string& key_system, |
| const base::optional<std::string>& session_id, |
| script::ExceptionState* exception_state); |
| #endif // defined(COBALT_MEDIA_SOURCE_2016) |
| |
| // Ready state |
| enum ReadyState { |
| kHaveNothing = WebMediaPlayer::kReadyStateHaveNothing, |
| kHaveMetadata = WebMediaPlayer::kReadyStateHaveMetadata, |
| kHaveCurrentData = WebMediaPlayer::kReadyStateHaveCurrentData, |
| kHaveFutureData = WebMediaPlayer::kReadyStateHaveFutureData, |
| kHaveEnoughData = WebMediaPlayer::kReadyStateHaveEnoughData, |
| }; |
| |
| uint16_t ready_state() const; |
| bool seeking() const; |
| |
| // Playback state |
| float current_time(script::ExceptionState* exception_state) const; |
| void set_current_time(float time, script::ExceptionState* exception_state); |
| float duration() const; |
| bool paused() const; |
| float default_playback_rate() const; |
| void set_default_playback_rate(float rate); |
| float playback_rate() const; |
| void set_playback_rate(float rate); |
| const scoped_refptr<TimeRanges>& played(); |
| scoped_refptr<TimeRanges> seekable() const; |
| bool ended() const; |
| bool autoplay() const; |
| void set_autoplay(bool autoplay); |
| bool loop() const; |
| void set_loop(bool loop); |
| void Play(); |
| void Pause(); |
| |
| // Controls |
| bool controls() const; |
| void set_controls(bool controls); |
| float volume(script::ExceptionState* exception_state) const; |
| void set_volume(float volume, script::ExceptionState* exception_state); |
| bool muted() const; |
| void set_muted(bool muted); |
| |
| // Custom, not in any spec |
| // |
| // From Node |
| void OnInsertedIntoDocument() OVERRIDE; |
| |
| #if defined(COBALT_MEDIA_SOURCE_2016) |
| // Called by MediaSource |
| void DurationChanged(double duration, bool request_seek); |
| #endif // defined(COBALT_MEDIA_SOURCE_2016) |
| |
| // Let other objects add event to the EventQueue of HTMLMediaElement. This |
| // function won't modify the target of the |event| passed in. |
| void ScheduleEvent(const scoped_refptr<Event>& event); |
| |
| DEFINE_WRAPPABLE_TYPE(HTMLMediaElement); |
| |
| protected: |
| WebMediaPlayer* player() { return player_.get(); } |
| const WebMediaPlayer* player() const { return player_.get(); } |
| |
| private: |
| static const char kMediaSourceUrlProtocol[]; |
| static const double kMaxTimeupdateEventFrequency; |
| |
| // Loading |
| void CreateMediaPlayer(); |
| void ScheduleLoad(); |
| void PrepareForLoad(); |
| void LoadInternal(); |
| void LoadResource(const GURL& initial_url, const std::string& content_type, |
| const std::string& key_system); |
| void ClearMediaPlayer(); |
| void NoneSupported(); |
| void MediaLoadingFailed(WebMediaPlayer::NetworkState error); |
| |
| // Timers |
| void OnLoadTimer(); |
| void OnProgressEventTimer(); |
| void OnPlaybackProgressTimer(); |
| void StartPlaybackProgressTimer(); |
| void StartProgressEventTimer(); |
| void StopPeriodicTimers(); |
| |
| // Events |
| void ScheduleTimeupdateEvent(bool periodic_event); |
| void ScheduleOwnEvent(base::Token event_name); |
| void CancelPendingEventsAndCallbacks(); |
| bool ProcessingMediaPlayerCallback() const { |
| return processing_media_player_callback_ > 0; |
| } |
| void BeginProcessingMediaPlayerCallback() { |
| ++processing_media_player_callback_; |
| } |
| void EndProcessingMediaPlayerCallback() { |
| DCHECK(processing_media_player_callback_); |
| --processing_media_player_callback_; |
| } |
| |
| // States |
| void SetReadyState(WebMediaPlayer::ReadyState state); |
| void SetNetworkState(WebMediaPlayer::NetworkState state); |
| void ChangeNetworkStateFromLoadingToIdle(); |
| |
| // Playback |
| void Seek(float time); |
| void FinishSeek(); |
| |
| void AddPlayedRange(float start, float end); |
| |
| void UpdateVolume(); |
| void UpdatePlayState(); |
| bool PotentiallyPlaying() const; |
| bool EndedPlayback() const; |
| bool StoppedDueToErrors() const; |
| bool CouldPlayIfEnoughData() const; |
| |
| void ConfigureMediaControls(); |
| |
| // Error report |
| void MediaEngineError(scoped_refptr<MediaError> error); |
| |
| // WebMediaPlayerClient methods |
| void NetworkStateChanged() OVERRIDE; |
| void ReadyStateChanged() OVERRIDE; |
| void TimeChanged() OVERRIDE; |
| void DurationChanged() OVERRIDE; |
| void OutputModeChanged() OVERRIDE; |
| void PlaybackStateChanged() OVERRIDE; |
| void SawUnsupportedTracks() OVERRIDE; |
| float Volume() const OVERRIDE; |
| #if defined(COBALT_MEDIA_SOURCE_2016) |
| void SourceOpened(ChunkDemuxer* chunk_demuxer) OVERRIDE; |
| #else // defined(COBALT_MEDIA_SOURCE_2016) |
| void SourceOpened() OVERRIDE; |
| #endif // defined(COBALT_MEDIA_SOURCE_2016) |
| std::string SourceURL() const OVERRIDE; |
| bool PreferDecodeToTexture() OVERRIDE; |
| #if defined(COBALT_MEDIA_SOURCE_2016) |
| void EncryptedMediaInitDataEncountered( |
| media::EmeInitDataType init_data_type, const unsigned char* init_data, |
| unsigned int init_data_length) OVERRIDE; |
| #else // defined(COBALT_MEDIA_SOURCE_2016) |
| void KeyAdded(const std::string& key_system, |
| const std::string& session_id) OVERRIDE; |
| void KeyError(const std::string& key_system, const std::string& session_id, |
| MediaKeyErrorCode error_code, uint16 system_code) OVERRIDE; |
| void KeyMessage(const std::string& key_system, const std::string& session_id, |
| const unsigned char* message, unsigned int message_length, |
| const std::string& default_url) OVERRIDE; |
| void KeyNeeded(const std::string& key_system, const std::string& session_id, |
| const unsigned char* init_data, |
| unsigned int init_data_length) OVERRIDE; |
| #endif // !defined(COBALT_MEDIA_SOURCE_2016) |
| void ClearMediaSource(); |
| #if !defined(COBALT_MEDIA_SOURCE_2016) |
| void SetSourceState(MediaSourceReadyState ready_state); |
| #endif // !defined(COBALT_MEDIA_SOURCE_2016) |
| |
| scoped_ptr<WebMediaPlayer> player_; |
| |
| std::string current_src_; |
| // Loading state. |
| enum LoadState { kWaitingForSource, kLoadingFromSrcAttr }; |
| LoadState load_state_; |
| |
| EventQueue event_queue_; |
| |
| base::OneShotTimer<HTMLMediaElement> load_timer_; |
| base::RepeatingTimer<HTMLMediaElement> progress_event_timer_; |
| base::RepeatingTimer<HTMLMediaElement> playback_progress_timer_; |
| scoped_refptr<TimeRanges> played_time_ranges_; |
| float playback_rate_; |
| float default_playback_rate_; |
| NetworkState network_state_; |
| WebMediaPlayer::ReadyState ready_state_; |
| WebMediaPlayer::ReadyState ready_state_maximum_; |
| |
| float volume_; |
| float last_seek_time_; |
| double previous_progress_time_; |
| |
| double duration_; |
| |
| bool playing_; |
| bool have_fired_loaded_data_; |
| bool autoplaying_; |
| bool muted_; |
| bool paused_; |
| bool seeking_; |
| bool loop_; |
| bool controls_; |
| |
| // The last time a timeupdate event was sent (wall clock). |
| double last_time_update_event_wall_time_; |
| // The last time a timeupdate event was sent in movie time. |
| double last_time_update_event_movie_time_; |
| |
| // Counter incremented while processing a callback from the media player, so |
| // we can avoid calling the low level player recursively. |
| int processing_media_player_callback_; |
| |
| GURL media_source_url_; |
| scoped_refptr<MediaSource> media_source_; |
| |
| bool pending_load_; |
| |
| // Data has not been loaded since sending a "stalled" event. |
| bool sent_stalled_event_; |
| // Time has not changed since sending an "ended" event. |
| bool sent_end_event_; |
| |
| scoped_refptr<MediaError> error_; |
| |
| // Helper object to reduce the image capacity while a video is playing. |
| base::optional<loader::image::ReducedCacheCapacityManager::Request> |
| reduced_image_cache_capacity_request_; |
| |
| #if defined(COBALT_MEDIA_SOURCE_2016) |
| scoped_refptr<eme::MediaKeys> media_keys_; |
| #endif // defined(COBALT_MEDIA_SOURCE_2016) |
| |
| DISALLOW_COPY_AND_ASSIGN(HTMLMediaElement); |
| }; |
| |
| } // namespace dom |
| } // namespace cobalt |
| |
| #endif // COBALT_DOM_HTML_MEDIA_ELEMENT_H_ |