Changeset 206350 in webkit
- Timestamp:
- Sep 23, 2016, 6:38:52 PM (9 years ago)
- Location:
- trunk/Source
- Files:
-
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r206343 r206350 1 2016-09-23 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 Media controls playhead does not animate smoothly while playing 4 https://bugs.webkit.org/show_bug.cgi?id=162399 5 <rdar://problem/28115680> 6 7 Reviewed by Beth Dakin. 8 9 The media controls playhead currently does not animate smoothly during playback because we don't specify a 10 playback rate when updating the WebPlaybackControlsManager's timing value. However, simply setting this timing 11 value to the current playback rate (as known to the UI process) results in the UI process receiving multiple 12 updates from the web process where the current time is equal (or even less than) the time at which media began 13 to play, which results in the playhead seeking backwards to the start time multiple times when playing or 14 resuming media. 15 16 To address this, in WebCore, we inform the playback session model of the media time when playback begins (i.e. 17 a `playing` or `play` event is fired). This message precedes both the "rate changed" and "current time changed" 18 messages. 19 20 Unit tests to be added in a future patch. 21 22 * html/HTMLMediaElement.cpp: 23 (WebCore::HTMLMediaElement::notifyAboutPlaying): 24 (WebCore::HTMLMediaElement::setReadyState): 25 (WebCore::HTMLMediaElement::playInternal): 26 * html/HTMLMediaElement.h: 27 (WebCore::HTMLMediaElement::playbackStartedTime): 28 * platform/cocoa/WebPlaybackSessionModel.h: 29 (WebCore::WebPlaybackSessionModelClient::playbackStartedTimeChanged): 30 (WebCore::WebPlaybackSessionModelClient::bufferedTimeChanged): Deleted. 31 * platform/cocoa/WebPlaybackSessionModelMediaElement.h: 32 * platform/cocoa/WebPlaybackSessionModelMediaElement.mm: 33 (WebPlaybackSessionModelMediaElement::updateForEventName): 34 (WebPlaybackSessionModelMediaElement::playbackStartedTime): 35 * platform/ios/WebVideoFullscreenControllerAVKit.mm: 36 * platform/mac/WebPlaybackSessionInterfaceMac.h: 37 * platform/mac/WebPlaybackSessionInterfaceMac.mm: 38 (WebCore::WebPlaybackSessionInterfaceMac::currentTimeChanged): 39 (WebCore::WebPlaybackSessionInterfaceMac::rateChanged): 40 (WebCore::WebPlaybackSessionInterfaceMac::beginScrubbing): 41 (WebCore::WebPlaybackSessionInterfaceMac::endScrubbing): 42 (WebCore::WebPlaybackSessionInterfaceMac::updatePlaybackControlsManagerTiming): 43 1 44 2016-09-23 Zalan Bujtas <zalan@apple.com> 2 45 -
trunk/Source/WebCore/html/HTMLMediaElement.cpp
r206315 r206350 1029 1029 void HTMLMediaElement::notifyAboutPlaying() 1030 1030 { 1031 m_playbackStartedTime = currentMediaTime().toDouble(); 1031 1032 dispatchEvent(Event::create(eventNames().playingEvent, false, true)); 1032 1033 resolvePendingPlayPromises(); … … 2422 2423 m_paused = false; 2423 2424 invalidateCachedTime(); 2425 m_playbackStartedTime = currentMediaTime().toDouble(); 2424 2426 scheduleEvent(eventNames().playEvent); 2425 2427 scheduleNotifyAboutPlaying(); … … 3211 3213 m_paused = false; 3212 3214 invalidateCachedTime(); 3215 m_playbackStartedTime = currentMediaTime().toDouble(); 3213 3216 scheduleEvent(eventNames().playEvent); 3214 3217 -
trunk/Source/WebCore/html/HTMLMediaElement.h
r206315 r206350 479 479 bool hasEverHadVideo() const { return m_hasEverHadVideo; } 480 480 481 double playbackStartedTime() const { return m_playbackStartedTime; } 482 481 483 protected: 482 484 HTMLMediaElement(const QualifiedName&, Document&, bool createdByParser); … … 859 861 860 862 double m_previousProgressTime; 863 double m_playbackStartedTime { 0 }; 861 864 862 865 // The last time a timeupdate event was sent (based on monotonic clock). -
trunk/Source/WebCore/platform/cocoa/WebPlaybackSessionModel.h
r205365 r206350 60 60 enum ExternalPlaybackTargetType { TargetTypeNone, TargetTypeAirPlay, TargetTypeTVOut }; 61 61 62 virtual double playbackStartedTime() const = 0; 62 63 virtual double duration() const = 0; 63 64 virtual double currentTime() const = 0; 64 65 virtual double bufferedTime() const = 0; 65 66 virtual bool isPlaying() const = 0; 67 virtual bool isScrubbing() const = 0; 66 68 virtual float playbackRate() const = 0; 67 69 virtual Ref<TimeRanges> seekableRanges() const = 0; … … 83 85 virtual void currentTimeChanged(double /* currentTime */, double /* anchorTime */) { } 84 86 virtual void bufferedTimeChanged(double) { } 87 virtual void playbackStartedTimeChanged(double /* playbackStartedTime */) { } 85 88 virtual void rateChanged(bool /* isPlaying */, float /* playbackRate */) { } 86 89 virtual void seekableRangesChanged(const TimeRanges&) { } -
trunk/Source/WebCore/platform/cocoa/WebPlaybackSessionModelMediaElement.h
r206245 r206350 74 74 double bufferedTime() const final; 75 75 bool isPlaying() const final; 76 bool isScrubbing() const final { return false; } 76 77 float playbackRate() const final; 77 78 Ref<TimeRanges> seekableRanges() const final; … … 99 100 Vector<RefPtr<AudioTrack>> m_audioTracksForMenu; 100 101 102 double playbackStartedTime() const; 101 103 void updateLegibleOptions(); 102 104 }; -
trunk/Source/WebCore/platform/cocoa/WebPlaybackSessionModelMediaElement.mm
r205412 r206350 107 107 108 108 if (all 109 || eventName == eventNames().playEvent 110 || eventName == eventNames().playingEvent) { 111 for (auto client : m_clients) 112 client->playbackStartedTimeChanged(playbackStartedTime()); 113 } 114 115 if (all 109 116 || eventName == eventNames().pauseEvent 110 117 || eventName == eventNames().playEvent … … 286 293 client->legibleMediaSelectionOptionsChanged(legibleOptions, legibleIndex); 287 294 } 295 } 296 297 double WebPlaybackSessionModelMediaElement::playbackStartedTime() const 298 { 299 if (!m_mediaElement) 300 return 0; 301 302 return m_mediaElement->playbackStartedTime(); 288 303 } 289 304 -
trunk/Source/WebCore/platform/ios/WebVideoFullscreenControllerAVKit.mm
r205365 r206350 148 148 void selectLegibleMediaOption(uint64_t) override; 149 149 double duration() const override; 150 double playbackStartedTime() const override { return 0; } 150 151 double currentTime() const override; 151 152 double bufferedTime() const override; 152 153 bool isPlaying() const override; 154 bool isScrubbing() const override { return false; } 153 155 float playbackRate() const override; 154 156 Ref<TimeRanges> seekableRanges() const override; -
trunk/Source/WebCore/platform/mac/WebPlaybackSessionInterfaceMac.h
r205365 r206350 64 64 WEBCORE_EXPORT void ensureControlsManager(); 65 65 WEBCORE_EXPORT void setPlayBackControlsManager(WebPlaybackControlsManager *); 66 WEBCORE_EXPORT void beginScrubbing(); 67 WEBCORE_EXPORT void endScrubbing(); 66 68 WEBCORE_EXPORT WebPlaybackControlsManager *playBackControlsManager(); 67 69 … … 70 72 WebPlaybackSessionModel* m_playbackSessionModel { nullptr }; 71 73 WebPlaybackControlsManager *m_playbackControlsManager { nullptr }; 74 75 void updatePlaybackControlsManagerTiming(double currentTime, double anchorTime, double playbackRate, bool isPlaying); 72 76 }; 73 77 -
trunk/Source/WebCore/platform/mac/WebPlaybackSessionInterfaceMac.mm
r205365 r206350 77 77 { 78 78 WebPlaybackControlsManager* controlsManager = playBackControlsManager(); 79 80 NSTimeInterval anchorTimeStamp = ![controlsManager rate] ? NAN : anchorTime; 81 AVValueTiming *timing = [getAVValueTimingClass() valueTimingWithAnchorValue:currentTime 82 anchorTimeStamp:anchorTimeStamp rate:0]; 83 84 [controlsManager setTiming:timing]; 79 updatePlaybackControlsManagerTiming(currentTime, anchorTime, controlsManager.rate, controlsManager.playing); 85 80 } 86 81 … … 90 85 [controlsManager setRate:isPlaying ? playbackRate : 0.]; 91 86 [controlsManager setPlaying:isPlaying]; 87 updatePlaybackControlsManagerTiming(m_playbackSessionModel ? m_playbackSessionModel->currentTime() : 0, [[NSProcessInfo processInfo] systemUptime], playbackRate, isPlaying); 88 } 89 90 void WebPlaybackSessionInterfaceMac::beginScrubbing() 91 { 92 updatePlaybackControlsManagerTiming(m_playbackSessionModel ? m_playbackSessionModel->currentTime() : 0, [[NSProcessInfo processInfo] systemUptime], 0, false); 93 webPlaybackSessionModel()->beginScrubbing(); 94 } 95 96 void WebPlaybackSessionInterfaceMac::endScrubbing() 97 { 98 webPlaybackSessionModel()->endScrubbing(); 92 99 } 93 100 … … 164 171 } 165 172 173 void WebPlaybackSessionInterfaceMac::updatePlaybackControlsManagerTiming(double currentTime, double anchorTime, double playbackRate, bool isPlaying) 174 { 175 WebPlaybackControlsManager *manager = playBackControlsManager(); 176 if (!manager) 177 return; 178 179 WebPlaybackSessionModel *model = webPlaybackSessionModel(); 180 if (!model) 181 return; 182 183 double effectiveAnchorTime = playbackRate ? anchorTime : NAN; 184 double effectivePlaybackRate = playbackRate; 185 if (!isPlaying 186 || model->isScrubbing() 187 || (manager.rate > 0 && model->playbackStartedTime() >= currentTime) 188 || (manager.rate < 0 && model->playbackStartedTime() <= currentTime)) 189 effectivePlaybackRate = 0; 190 191 manager.timing = [getAVValueTimingClass() valueTimingWithAnchorValue:currentTime anchorTimeStamp:effectiveAnchorTime rate:effectivePlaybackRate]; 192 } 193 166 194 } 167 195 -
trunk/Source/WebKit2/ChangeLog
r206333 r206350 1 2016-09-23 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 Media controls playhead does not animate smoothly while playing 4 https://bugs.webkit.org/show_bug.cgi?id=162399 5 <rdar://problem/28115680> 6 7 Reviewed by Beth Dakin. 8 9 See WebCore ChangeLog for more details. 10 11 In the UI process, we update the WebPlaybackSessionManager's timing value when the rate or current time changes. 12 Each AVValueTiming is generated from the current time, system anchor time, and playback rate. The behavior of 13 the first two properties is unaffected. However, the rate used to update the timing value is the effective 14 playback rate, which is equal to the playback rate unless we are (1) not playing, (2) interacting with the media 15 controls in such a way that the media is essentially not playing, or (3) the current time precedes the playback 16 start time, accounting for playback direction. In these cases, our effective playback rate is 0, which means 17 that we do not animate the playhead. 18 19 * UIProcess/Cocoa/WebPlaybackSessionManagerProxy.h: 20 * UIProcess/Cocoa/WebPlaybackSessionManagerProxy.messages.in: 21 * UIProcess/Cocoa/WebPlaybackSessionManagerProxy.mm: 22 (WebKit::WebPlaybackSessionModelContext::beginScrubbing): 23 (WebKit::WebPlaybackSessionModelContext::endScrubbing): 24 (WebKit::WebPlaybackSessionModelContext::setPlaybackStartedTime): 25 (WebKit::WebPlaybackSessionModelContext::setCurrentTime): 26 (WebKit::WebPlaybackSessionManagerProxy::setPlaybackStartedTime): 27 * WebProcess/cocoa/WebPlaybackSessionManager.h: 28 * WebProcess/cocoa/WebPlaybackSessionManager.mm: 29 (WebKit::WebPlaybackSessionInterfaceContext::playbackStartedTimeChanged): 30 (WebKit::WebPlaybackSessionManager::playbackStartedTimeChanged): 31 1 32 2016-09-23 Caitlin Potter <caitp@igalia.com> 2 33 -
trunk/Source/WebKit2/UIProcess/Cocoa/WebPlaybackSessionManagerProxy.h
r205412 r206350 72 72 void setCurrentTime(double); 73 73 void setBufferedTime(double); 74 void setPlaybackStartedTime(double); 74 75 void setRate(bool isPlaying, float playbackRate); 75 76 void setSeekableRanges(WebCore::TimeRanges&); … … 103 104 void selectLegibleMediaOption(uint64_t) final; 104 105 106 double playbackStartedTime() const final { return m_playbackStartedTime; } 105 107 double duration() const final { return m_duration; } 106 108 double currentTime() const final { return m_currentTime; } 107 109 double bufferedTime() const final { return m_bufferedTime; } 108 110 bool isPlaying() const final { return m_isPlaying; } 111 bool isScrubbing() const final { return m_isScrubbing; } 109 112 float playbackRate() const final { return m_playbackRate; } 110 113 Ref<WebCore::TimeRanges> seekableRanges() const final { return m_seekableRanges.copyRef(); } … … 122 125 uint64_t m_contextId; 123 126 HashSet<WebCore::WebPlaybackSessionModelClient*> m_clients; 127 double m_playbackStartedTime { 0 }; 128 bool m_playbackStartedTimeNeedsUpdate { false }; 124 129 double m_duration { 0 }; 125 130 double m_currentTime { 0 }; 126 131 double m_bufferedTime { 0 }; 127 132 bool m_isPlaying { false }; 133 bool m_isScrubbing { false }; 128 134 float m_playbackRate { 0 }; 129 135 Ref<WebCore::TimeRanges> m_seekableRanges { WebCore::TimeRanges::create() }; … … 177 183 void setWirelessVideoPlaybackDisabled(uint64_t contextId, bool); 178 184 void setDuration(uint64_t contextId, double duration); 185 void setPlaybackStartedTime(uint64_t contextId, double playbackStartedTime); 179 186 void setRate(uint64_t contextId, bool isPlaying, double rate); 180 187 void handleControlledElementIDResponse(uint64_t, String) const; -
trunk/Source/WebKit2/UIProcess/Cocoa/WebPlaybackSessionManagerProxy.messages.in
r205412 r206350 33 33 SetWirelessVideoPlaybackDisabled(uint64_t contextId, bool disabled) 34 34 SetDuration(uint64_t contextId, double duration) 35 SetPlaybackStartedTime(uint64_t contextId, double playbackStartedTime) 35 36 SetRate(uint64_t contextId, bool isPlaying, double rate) 36 37 SetUpPlaybackControlsManagerWithID(uint64_t contextId) -
trunk/Source/WebKit2/UIProcess/Cocoa/WebPlaybackSessionManagerProxy.mm
r205412 r206350 75 75 if (m_manager) 76 76 m_manager->beginScrubbing(m_contextId); 77 78 m_isScrubbing = true; 77 79 } 78 80 … … 81 83 if (m_manager) 82 84 m_manager->endScrubbing(m_contextId); 85 86 m_isScrubbing = false; 87 m_playbackStartedTimeNeedsUpdate = isPlaying(); 83 88 } 84 89 … … 123 128 if (m_manager) 124 129 m_manager->selectLegibleMediaOption(m_contextId, optionId); 130 } 131 132 void WebPlaybackSessionModelContext::setPlaybackStartedTime(double playbackStartedTime) 133 { 134 m_playbackStartedTime = playbackStartedTime; 135 m_playbackStartedTimeNeedsUpdate = false; 125 136 } 126 137 … … 136 147 m_currentTime = currentTime; 137 148 auto anchorTime = [[NSProcessInfo processInfo] systemUptime]; 149 if (m_playbackStartedTimeNeedsUpdate) 150 setPlaybackStartedTime(currentTime); 138 151 139 152 for (auto* client : m_clients) … … 390 403 } 391 404 405 void WebPlaybackSessionManagerProxy::setPlaybackStartedTime(uint64_t contextId, double playbackStartedTime) 406 { 407 ensureModel(contextId).setPlaybackStartedTime(playbackStartedTime); 408 } 409 392 410 void WebPlaybackSessionManagerProxy::setRate(uint64_t contextId, bool isPlaying, double rate) 393 411 { -
trunk/Source/WebKit2/WebProcess/cocoa/WebPlaybackSessionManager.h
r205412 r206350 78 78 void currentTimeChanged(double currentTime, double anchorTime) final; 79 79 void bufferedTimeChanged(double) final; 80 void playbackStartedTimeChanged(double playbackStartedTime) final; 80 81 void rateChanged(bool isPlaying, float playbackRate) final; 81 82 void seekableRangesChanged(const WebCore::TimeRanges&) final; … … 123 124 void currentTimeChanged(uint64_t contextId, double currentTime, double anchorTime); 124 125 void bufferedTimeChanged(uint64_t contextId, double bufferedTime); 126 void playbackStartedTimeChanged(uint64_t contextId, double playbackStartedTime); 125 127 void rateChanged(uint64_t contextId, bool isPlaying, float playbackRate); 126 128 void seekableRangesChanged(uint64_t contextId, const WebCore::TimeRanges&); -
trunk/Source/WebKit2/WebProcess/cocoa/WebPlaybackSessionManager.mm
r205412 r206350 97 97 } 98 98 99 void WebPlaybackSessionInterfaceContext::playbackStartedTimeChanged(double playbackStartedTime) 100 { 101 if (m_manager) 102 m_manager->playbackStartedTimeChanged(m_contextId, playbackStartedTime); 103 } 104 99 105 void WebPlaybackSessionInterfaceContext::seekableRangesChanged(const WebCore::TimeRanges& ranges) 100 106 { … … 298 304 } 299 305 306 void WebPlaybackSessionManager::playbackStartedTimeChanged(uint64_t contextId, double playbackStartedTime) 307 { 308 m_page->send(Messages::WebPlaybackSessionManagerProxy::SetPlaybackStartedTime(contextId, playbackStartedTime), m_page->pageID()); 309 } 310 300 311 void WebPlaybackSessionManager::rateChanged(uint64_t contextId, bool isPlaying, float playbackRate) 301 312 {
Note:
See TracChangeset
for help on using the changeset viewer.