Reviewed by Adele.
Fix that 'timeupdate' and 'waiting' events were never dispatched.
Add explicit m_paused attribute instead of trying to derive paused state from
underlying media. Call updatePlayState() to start/stop media playback
when any attribute that affects active playback state changes. This matches
specification text.
Test: http/tests/media/video-play-stall.html
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::HTMLMediaElement):
(WebCore::HTMLMediaElement::setReadyState):
(WebCore::HTMLMediaElement::paused):
(WebCore::HTMLMediaElement::play):
(WebCore::HTMLMediaElement::pause):
(WebCore::HTMLMediaElement::checkIfSeekNeeded):
(WebCore::HTMLMediaElement::movieDidEnd):
(WebCore::HTMLMediaElement::updatePlayState):
* html/HTMLMediaElement.h:
LayoutTests:
Reviewed by Adele.
- add HTTP media test for stalling load
- update tests that don't specifically test autoplay feature to not use autoplay
attribute since playback may start before event listeners are registered
* http/tests/media: Added.
* http/tests/media/video-load-and-stall.cgi: Added.
* http/tests/media/video-play-stall-expected.txt: Added.
* http/tests/media/video-play-stall.html: Added.
* media/video-autoplay.html:
* media/video-dom-loopstart.html:
* media/video-end.html:
* media/video-loopcount.html:
* media/video-loopend.html:
* media/video-loopstart.html:
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@27758
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2007-11-12 Antti Koivisto <antti@apple.com>
+
+ Reviewed by Adele.
+
+ - add HTTP media test for stalling load
+ - update tests that don't specifically test autoplay feature to not use autoplay
+ attribute since playback may start before event listeners are registered
+
+ * http/tests/media: Added.
+ * http/tests/media/video-load-and-stall.cgi: Added.
+ * http/tests/media/video-play-stall-expected.txt: Added.
+ * http/tests/media/video-play-stall.html: Added.
+ * media/video-autoplay.html:
+ * media/video-dom-loopstart.html:
+ * media/video-end.html:
+ * media/video-loopcount.html:
+ * media/video-loopend.html:
+ * media/video-loopstart.html:
+
2007-11-13 Darin Adler <darin@apple.com>
Reviewed by Geoff.
--- /dev/null
+#!/usr/bin/perl -w
+
+use CGI;
+use File::stat;
+
+$query = new CGI;
+$name = $query->param('name');
+$stallAt = $query->param('stallAt');
+
+my $filesize = stat($name)->size;
+print "Content-type: video/mp4\n";
+print "Content-Length: " . $filesize . "\n\n";
+
+open FILE, $name or die;
+binmode FILE;
+$total = 0;
+my ($buf, $data, $n);
+while (($n = read FILE, $data, 1024) != 0) {
+ $total += $n;
+ if ($total > $stallAt) {
+ close(FILE);
+ return;
+ }
+ print $data;
+}
+close(FILE);
--- /dev/null
+Test that dataunavailable, timeupdate and waiting events are sent when media load stalls in the middle.
+
+EVENT(durationchange)
+EVENT(loadedmetadata)
+EVENT(loadedfirstframe)
+EVENT(canshowcurrentframe)
+EVENT(canplay)
+EVENT(dataunavailable)
+EVENT(timeupdate)
+EVENT(waiting)
+END OF TEST
+
--- /dev/null
+<video src="http://127.0.0.1:8000/media/video-load-and-stall.cgi?name=../../../media/content/test.mp4&stallAt=80000"></video>
+<p>Test that dataunavailable, timeupdate and waiting events are sent when media load stalls in the middle.</p>
+<script src=../../../media/video-test.js></script>
+<script>
+waitForEvent('durationchange');
+waitForEvent('loadedmetadata');
+waitForEvent('loadedfirstframe');
+waitForEvent('canshowcurrentframe');
+waitForEvent('canplay', function () {
+ waitForEvent('dataunavailable');
+ waitForEvent('timeupdate');
+ waitForEventAndEnd('waiting');
+} );
+video.play();
+</script>
-<video src=content/test.mp4 autoplay></video>
+<video autoplay></video>
<script src=video-test.js></script>
<script>
test("video.autoplay");
test("video.getAttribute('autoplay') != null");
waitForEventTestAndEnd('play', "!video.paused");
+video.src = "content/test.mp4";
</script>
-<video src=content/test.mp4 loopcount=2 autoplay></video>
+<video src=content/test.mp4 loopcount=2></video>
<script src=video-test.js></script>
<script>
video.loopStart = 1.0;
test("video.getAttribute('loopstart') == '1s'");
waitForEvent('play', function () { video.currentTime = 500; });
waitForEventTestAndEnd('timeupdate', "video.currentTime.toFixed(1) && video.currentLoop==1");
+video.play();
</script>
-<video autoplay src=content/test.mp4 end=0.5s></video>
+<video src=content/test.mp4 end=0.5s></video>
<script src=video-test.js></script>
<script>
test("!video.ended");
endTest();
}
);
+video.play();
</script>
-<video src=content/test.mp4 loopcount=2 loopend=0.2s end=0.2s autoplay></video>
+<video src=content/test.mp4 loopcount=2 loopend=0.2s end=0.2s></video>
<script src=video-test.js></script>
<script>
test("video.loopCount == 2");
test("video.currentLoop == 0");
waitForEventTestAndEnd('ended', "video.currentLoop == 1");
+video.play();
</script>
-<video src=content/test.mp4 loopcount=2 autoplay></video>
+<video src=content/test.mp4 loopcount=2></video>
<script src=video-test.js></script>
<script>
video.loopEnd = 0.5;
test("video.loopEnd==0.5");
setTimeout(function () { test("video.currentTime<=0.5"); }, 2000);
waitForEventTestAndEnd('timeupdate', "video.currentTime.toFixed(1) == 0 && video.currentLoop==1");
+video.play();
</script>
-<video src=content/test.mp4 loopcount=2 loopstart=1s autoplay></video>
+<video src=content/test.mp4 loopcount=2 loopstart=1s></video>
<script src=video-test.js></script>
<script>
test("video.loopStart==1.0");
waitForEvent('play', function () { video.currentTime = 500; });
waitForEventTestAndEnd('timeupdate', "video.currentTime.toFixed(1) == 1.0 && video.currentLoop==1");
+video.play();
</script>
+2007-11-12 Antti Koivisto <antti@apple.com>
+
+ Reviewed by Adele.
+
+ Fix that 'timeupdate' and 'waiting' events were never dispatched.
+
+ Add explicit m_paused attribute instead of trying to derive paused state from
+ underlying media. Call updatePlayState() to start/stop media playback
+ when any attribute that affects active playback state changes. This matches
+ specification text.
+
+ Test: http/tests/media/video-play-stall.html
+
+ * html/HTMLMediaElement.cpp:
+ (WebCore::HTMLMediaElement::HTMLMediaElement):
+ (WebCore::HTMLMediaElement::setReadyState):
+ (WebCore::HTMLMediaElement::paused):
+ (WebCore::HTMLMediaElement::play):
+ (WebCore::HTMLMediaElement::pause):
+ (WebCore::HTMLMediaElement::checkIfSeekNeeded):
+ (WebCore::HTMLMediaElement::movieDidEnd):
+ (WebCore::HTMLMediaElement::updatePlayState):
+ * html/HTMLMediaElement.h:
+
2007-11-13 John Sullivan <sullivan@apple.com>
Reviewed by Darin.
, m_currentLoop(0)
, m_volume(0.5f)
, m_muted(false)
+ , m_paused(true)
, m_previousProgress(0)
, m_previousProgressTime(numeric_limits<double>::max())
, m_sentStalledEvent(false)
if (networkState() != EMPTY) {
m_networkState = EMPTY;
m_readyState = DATA_UNAVAILABLE;
+ m_paused = true;
if (m_movie) {
m_movie->pause();
m_movie->seek(0);
dispatchHTMLEvent(canplayEvent, false, true);
} else if (state == CAN_PLAY_THROUGH) {
dispatchHTMLEvent(canplaythroughEvent, false, true);
- if (m_autoplaying && paused() && autoplay()) {
- m_movie->play();
+ if (m_autoplaying && m_paused && autoplay()) {
+ m_paused = false;
dispatchHTMLEvent(playEvent, false, true);
}
}
+ updatePlayState();
}
void HTMLMediaElement::progressEventTimerFired(Timer<HTMLMediaElement>*)
bool HTMLMediaElement::paused() const
{
- return m_movie ? m_movie->paused() : true;
+ return m_paused;
}
float HTMLMediaElement::defaultPlaybackRate() const
}
setPlaybackRate(defaultPlaybackRate(), unused);
- if (m_movie->paused()) {
- m_movie->play();
+ if (m_paused) {
+ m_paused = false;
+ updatePlayState();
dispatchEventAsync(playEvent);
}
return;
}
- if (!m_movie->paused()) {
- m_movie->pause();
+ if (!m_paused) {
+ m_paused = true;
+ updatePlayState();
dispatchEventAsync(timeupdateEvent);
dispatchEventAsync(pauseEvent);
}
// 6
if (m_currentLoop == loopCount() - 1 && time > effectiveEnd())
seek(effectiveEnd(), ec);
+
+ updatePlayState();
}
void HTMLMediaElement::movieVolumeChanged(Movie*)
m_movie->seek(effectiveLoopStart());
m_currentLoop++;
m_movie->setEndTime(m_currentLoop == loopCount() - 1 ? effectiveEnd() : effectiveLoopEnd());
- if (m_movie)
- m_movie->play();
+ updatePlayState();
dispatchHTMLEvent(timeupdateEvent, false, true);
}
return networkState() >= LOADED_METADATA && currentTime() >= effectiveEnd() && currentLoop() == loopCount() - 1;
}
+void HTMLMediaElement::updatePlayState()
+{
+ if (!m_movie)
+ return;
+ bool shouldBePlaying = activelyPlaying();
+ if (shouldBePlaying && m_movie->paused())
+ m_movie->play();
+ else if (!shouldBePlaying && !m_movie->paused())
+ m_movie->pause();
+}
+
void HTMLMediaElement::willSaveToCache()
{
// 3.14.9.4. Loading the media resource
void checkIfSeekNeeded();
String pickMedia();
+ void updatePlayState();
float effectiveStart() const;
float effectiveEnd() const;
float effectiveLoopStart() const;
float m_volume;
bool m_muted;
+ bool m_paused;
bool m_seeking;
unsigned m_previousProgress;