Changeset 27866 in webkit
- Timestamp:
- Nov 16, 2007, 6:10:16 PM (18 years ago)
- Location:
- trunk
- Files:
-
- 8 added
- 29 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r27865 r27866 1 2007-11-16 Antti Koivisto <antti@apple.com> 2 3 Reviewed by Adele. 4 5 Seeking related test updates 6 - update to match specificiation 7 - rename loopCount to playCount everywhere 8 - timeupdate events during seek 9 - fix that some tests (like audio ones) depended on timing sensitive ordering of play and load events 10 - add text about what is being tested 11 12 Add new tests for seeking past end, seeking past loaded position and 'seeking' DOM attribute. 13 14 * http/tests/media/video-seekable-stall-expected.txt: Added. 15 * http/tests/media/video-seekable-stall.html: Added. 16 * media/audio-constructor-expected.txt: 17 * media/audio-constructor-src-expected.txt: 18 * media/audio-constructor-src.html: 19 * media/audio-constructor.html: 20 * media/video-dom-loopcount-expected.txt: 21 * media/video-dom-loopcount.html: 22 * media/video-dom-loopend-expected.txt: 23 * media/video-dom-loopend.html: 24 * media/video-dom-loopstart-expected.txt: 25 * media/video-dom-loopstart.html: 26 * media/video-dom-start-expected.txt: 27 * media/video-dom-start.html: 28 * media/video-loopcount-expected.txt: 29 * media/video-loopcount.html: 30 * media/video-loopend-expected.txt: 31 * media/video-loopend.html: 32 * media/video-loopstart-expected.txt: 33 * media/video-loopstart.html: 34 * media/video-seek-past-end-paused-expected.txt: Added. 35 * media/video-seek-past-end-paused.html: Added. 36 * media/video-seek-past-end-playing-expected.txt: Added. 37 * media/video-seek-past-end-playing.html: Added. 38 * media/video-seeking-expected.txt: Added. 39 * media/video-seeking.html: Added. 40 * media/video-test.js: 41 1 42 2007-11-16 Anders Carlsson <andersca@apple.com> 2 43 -
trunk/LayoutTests/media/audio-constructor-expected.txt
r27286 r27866 1 Test that Audio() object loads the resource after src attribute is set and load() is called. 2 1 3 TEST(audio instanceof HTMLAudioElement) OK 2 EVENT(load) TEST(relativeURL(audio.currentSrc)=='content/test.wav') OK 3 EVENT(play) 4 RUN(audio.load()) 5 EVENT(begin) TEST(relativeURL(audio.currentSrc)=='content/test.wav') OK 6 EVENT(load) 4 7 END OF TEST 5 8 -
trunk/LayoutTests/media/audio-constructor-src-expected.txt
r27286 r27866 1 Test that Audio("url") constructor loads the specified resource. 2 1 3 TEST(audio instanceof HTMLAudioElement) OK 2 EVENT( load) TEST(relativeURL(audio.currentSrc)=='content/test.wav') OK3 EVENT( play)4 EVENT(begin) TEST(relativeURL(audio.currentSrc)=='content/test.wav') OK 5 EVENT(load) 4 6 END OF TEST 5 7 -
trunk/LayoutTests/media/audio-constructor-src.html
r27286 r27866 1 1 <body> 2 <p>Test that Audio("url") constructor loads the specified resource.</p> 2 3 <script src=video-test.js></script> 3 4 <script> 4 5 var audio = new Audio("content/test.wav"); 5 6 media = audio; 6 7 7 test("audio instanceof HTMLAudioElement"); 8 waitForEventAndTest("load", "relativeURL(audio.currentSrc)=='content/test.wav'"); 9 waitForEventAndEnd("play"); 10 audio.play(); 8 waitForEventAndTest("begin", "relativeURL(audio.currentSrc)=='content/test.wav'"); 9 waitForEventAndEnd("load"); 11 10 </script> -
trunk/LayoutTests/media/audio-constructor.html
r27286 r27866 1 1 <body> 2 <p>Test that Audio() object loads the resource after src attribute is set and load() is called.</p> 2 3 <script src=video-test.js></script> 3 4 <script> 4 5 var audio = new Audio(); 5 6 media = audio; 6 7 7 test("audio instanceof HTMLAudioElement"); 8 waitForEventAndTest(" load", "relativeURL(audio.currentSrc)=='content/test.wav'");9 waitForEventAndEnd(" play");8 waitForEventAndTest("begin", "relativeURL(audio.currentSrc)=='content/test.wav'"); 9 waitForEventAndEnd("load"); 10 10 audio.src = "content/test.wav"; 11 audio.play();11 run("audio.load()"); 12 12 </script> -
trunk/LayoutTests/media/video-dom-loopcount-expected.txt
r27286 r27866 1 TEST(video.loopCount == 2) OK 1 Test that playcount DOM attribute causes playback to end after right number of repeats. 2 3 TEST(video.playCount == 3) OK 2 4 TEST(video.currentLoop == 0) OK 3 TEST(video.getAttribute('loopCount') == 2) OK 4 EVENT(ended) TEST(video.currentLoop == 1) OK 5 TEST(video.getAttribute('playCount') == 3) OK 6 RUN(video.play()) 7 EVENT(ended) TEST(video.currentLoop == 2) OK 5 8 END OF TEST 6 9 -
trunk/LayoutTests/media/video-dom-loopcount.html
r27286 r27866 1 <video src=content/test.mp4 loopend=0.2s end=0.2s autoplay></video> 1 <video src=content/test.mp4 loopend=0.2s end=0.2s></video> 2 <p>Test that playcount DOM attribute causes playback to end after right number of repeats.</p> 2 3 <script src=video-test.js></script> 3 4 <script> 4 video. loopCount = 2;5 test("video. loopCount == 2");5 video.playCount = 3; 6 test("video.playCount == 3"); 6 7 test("video.currentLoop == 0"); 7 test("video.getAttribute('loopCount') == 2"); 8 waitForEventTestAndEnd('ended', "video.currentLoop == 1"); 8 test("video.getAttribute('playCount') == 3"); 9 waitForEventTestAndEnd('ended', "video.currentLoop == 2"); 10 run("video.play()"); 9 11 </script> -
trunk/LayoutTests/media/video-dom-loopend-expected.txt
r27286 r27866 1 Test that video loops when time reaches the value specified by the loopEnd DOM attribute. 2 1 3 TEST(video.loopEnd==0.5) OK 2 4 TEST(video.getAttribute('loopend') == '0.5s') OK 3 EVENT(timeupdate) TEST(video.currentTime.toFixed(1) == 0 && video.currentLoop==1) OK 5 RUN(video.play()) 6 EVENT(timeupdate) 7 EVENT(timeupdate) 8 TEST(video.currentLoop == 1) OK 9 TEST(video.currentTime.toFixed(1) == 0) OK 4 10 END OF TEST 5 11 -
trunk/LayoutTests/media/video-dom-loopend.html
r27286 r27866 1 <video src=content/test.mp4 loopcount=2 autoplay></video> 1 <video src=content/test.mp4 playcount=2></video> 2 <p>Test that video loops when time reaches the value specified by the loopEnd DOM attribute.</p> 2 3 <script src=video-test.js></script> 3 4 <script> … … 6 7 test("video.getAttribute('loopend') == '0.5s'"); 7 8 setTimeout(function () { test("video.currentTime<=0.5"); }, 2000); 8 waitForEventTestAndEnd('timeupdate', "video.currentTime.toFixed(1) == 0 && video.currentLoop==1"); 9 waitForEvent('timeupdate', function () { 10 if (video.currentLoop == 1) { 11 test("video.currentLoop == 1"); 12 test("video.currentTime.toFixed(1) == 0"); 13 endTest(); 14 } 15 }); 16 run("video.play()"); 9 17 </script> -
trunk/LayoutTests/media/video-dom-loopstart-expected.txt
r27286 r27866 1 Test that playing video rewinds to time specified by the loopStart DOM attribute when it loops. 2 1 3 TEST(video.loopStart==1.0) OK 2 4 TEST(video.getAttribute('loopstart') == '1s') OK 3 EVENT(play) 4 EVENT(timeupdate) TEST(video.currentTime.toFixed(1) && video.currentLoop==1) OK 5 RUN(video.play()) 6 EVENT(load) 7 EVENT(timeupdate) 8 EVENT(timeupdate) 9 EVENT(timeupdate) 10 TEST(video.currentLoop == 1) OK 11 TEST(video.currentTime.toFixed(1) == 1.0) OK 5 12 END OF TEST 6 13 -
trunk/LayoutTests/media/video-dom-loopstart.html
r27758 r27866 1 <video src=content/test.mp4 loopcount=2></video> 1 <video playcount=2></video> 2 <p>Test that playing video rewinds to time specified by the loopStart DOM attribute when it loops.</p> 2 3 <script src=video-test.js></script> 3 4 <script> … … 5 6 test("video.loopStart==1.0"); 6 7 test("video.getAttribute('loopstart') == '1s'"); 7 waitForEvent('play', function () { video.currentTime = 500; }); 8 waitForEventTestAndEnd('timeupdate', "video.currentTime.toFixed(1) && video.currentLoop==1"); 9 video.play(); 8 waitForEvent('load', function () { 9 waitForEvent('timeupdate', function () { 10 failTestIn(1000); 11 if (video.currentLoop == 1) { 12 test("video.currentLoop == 1"); 13 test("video.currentTime.toFixed(1) == 1.0"); 14 endTest(); 15 } 16 }); 17 video.currentTime = video.duration - 0.2; 18 }); 19 video.src = "content/test.mp4"; 20 run("video.play()"); 10 21 </script> -
trunk/LayoutTests/media/video-dom-start-expected.txt
r27286 r27866 1 Test that when start DOM attribute is set, playback starts from that time. 2 1 3 TEST(video.start == 1.0) OK 2 4 TEST(video.getAttribute('start') == '1s') OK 5 RUN(video.load()) 3 6 EVENT(canplaythrough) TEST(video.currentTime == 1.0) OK 4 7 END OF TEST -
trunk/LayoutTests/media/video-dom-start.html
r27286 r27866 1 <video src=content/test.mp4></video> 1 <video></video> 2 <p>Test that when start DOM attribute is set, playback starts from that time.</p> 2 3 <script src=video-test.js></script> 3 4 <script> … … 6 7 test("video.getAttribute('start') == '1s'"); 7 8 waitForEventTestAndEnd('canplaythrough', "video.currentTime == 1.0"); 9 video.src = "content/test.mp4"; 10 run("video.load()"); 8 11 </script> -
trunk/LayoutTests/media/video-loopcount-expected.txt
r27286 r27866 1 TEST(video.loopCount == 2) OK 1 Test that playcount attribute causes playback to end after right number of repeats. 2 3 TEST(video.playCount == 3) OK 2 4 TEST(video.currentLoop == 0) OK 3 EVENT(ended) TEST(video.currentLoop == 1) OK5 EVENT(ended) TEST(video.currentLoop == 2) OK 4 6 END OF TEST 5 7 -
trunk/LayoutTests/media/video-loopcount.html
r27758 r27866 1 <video src=content/test.mp4 loopcount=2 loopend=0.2s end=0.2s></video> 1 <video src=content/test.mp4 playcount=3 loopend=0.2s end=0.2s></video> 2 <p>Test that playcount attribute causes playback to end after right number of repeats.</p> 2 3 <script src=video-test.js></script> 3 4 <script> 4 test("video. loopCount == 2");5 test("video.playCount == 3"); 5 6 test("video.currentLoop == 0"); 6 waitForEventTestAndEnd('ended', "video.currentLoop == 1");7 waitForEventTestAndEnd('ended', "video.currentLoop == 2"); 7 8 video.play(); 8 9 </script> -
trunk/LayoutTests/media/video-loopend-expected.txt
r27286 r27866 1 Test that video loops when time reaches the value specified by the loopEnd attribute. 2 1 3 TEST(video.loopEnd==0.5) OK 2 EVENT(timeupdate) TEST(video.currentTime.toFixed(1) == 0 && video.currentLoop==1) OK 4 RUN(video.play()) 5 EVENT(timeupdate) 6 EVENT(timeupdate) 7 TEST(video.currentLoop == 1) OK 8 TEST(video.currentTime.toFixed(1) == 0) OK 3 9 END OF TEST 4 10 -
trunk/LayoutTests/media/video-loopend.html
r27758 r27866 1 <video src=content/test.mp4 loopcount=2></video> 1 <video src=content/test.mp4 playcount=2 loopend=0.5s></video> 2 <p>Test that video loops when time reaches the value specified by the loopEnd attribute.</p> 2 3 <script src=video-test.js></script> 3 4 <script> 4 video.loopEnd = 0.5;5 5 test("video.loopEnd==0.5"); 6 6 setTimeout(function () { test("video.currentTime<=0.5"); }, 2000); 7 waitForEventTestAndEnd('timeupdate', "video.currentTime.toFixed(1) == 0 && video.currentLoop==1"); 8 video.play(); 7 waitForEvent('timeupdate', function () { 8 if (video.currentLoop == 1) { 9 test("video.currentLoop == 1"); 10 test("video.currentTime.toFixed(1) == 0"); 11 endTest(); 12 } 13 }); 14 run("video.play()"); 9 15 </script> -
trunk/LayoutTests/media/video-loopstart-expected.txt
r27286 r27866 1 Test that playing video rewinds to time specified by the loopstart attribute when it loops. 2 1 3 TEST(video.loopStart==1.0) OK 2 EVENT(play) 3 EVENT(timeupdate) TEST(video.currentTime.toFixed(1) == 1.0 && video.currentLoop==1) OK 4 RUN(video.play()) 5 EVENT(load) 6 EVENT(timeupdate) 7 EVENT(timeupdate) 8 EVENT(timeupdate) 9 TEST(video.currentLoop == 1) OK 10 TEST(video.currentTime.toFixed(1) == 1.0) OK 4 11 END OF TEST 5 12 -
trunk/LayoutTests/media/video-loopstart.html
r27758 r27866 1 <video src=content/test.mp4 loopcount=2 loopstart=1s></video> 1 <video playcount=2 loopstart=1s></video> 2 <p>Test that playing video rewinds to time specified by the loopstart attribute when it loops.</p> 2 3 <script src=video-test.js></script> 3 4 <script> 4 5 test("video.loopStart==1.0"); 5 waitForEvent('play', function () { video.currentTime = 500; }); 6 waitForEventTestAndEnd('timeupdate', "video.currentTime.toFixed(1) == 1.0 && video.currentLoop==1"); 7 video.play(); 6 waitForEvent('load', function () { 7 waitForEvent('timeupdate', function () { 8 failTestIn(1000); 9 if (video.currentLoop == 1) { 10 test("video.currentLoop == 1"); 11 test("video.currentTime.toFixed(1) == 1.0"); 12 endTest(); 13 } 14 }); 15 video.currentTime = video.duration - 0.2; 16 }); 17 video.src = "content/test.mp4"; 18 run("video.play()"); 8 19 </script> -
trunk/LayoutTests/media/video-test.js
r27696 r27866 119 119 } 120 120 121 function failTestIn(ms) 122 { 123 setTimeout(function () { 124 consoleWrite("FAIL: did not end fast enough"); 125 endTest(); 126 }, ms); 127 } 128 121 129 function consoleWrite(text) 122 130 { -
trunk/WebCore/ChangeLog
r27865 r27866 1 2007-11-16 Antti Koivisto <antti@apple.com> 2 3 Reviewed by Adele. 4 5 Seeking related fixes, updates match to the latest specification 6 - rename loopCount of HTMLMediaElement to playCount 7 - add explicit seeking attribute to HTMLMediaElement to get semantics right 8 - implement the specification behavior that currentTime must immediately return seeked position in HTMLMediaElement 9 instead of MoviePrivateQTKit 10 - fix broken behavior when seeking past end of the media, add tests 11 - replace Movie didEnd callback with broader timeChanged callback (which gets called in didEnd case too) 12 - use setDelayCallbacks: in various MoviePrivateQTKit methods to avoid bug prone synchronous callbacks from QT, make 13 HTMLMediaElement not depend on synchronous callbacks 14 - do some cleanups and simplifications in MoviePrivateQTKit, get rid of m_rateBeforeSeek and m_blockStateUpdate variables 15 16 Tests: http/tests/media/video-seekable-stall.html 17 media/video-seeking.html 18 media/video-seek-past-end-paused.html 19 media/video-seek-past-end-playing.html 20 21 * html/HTMLAttributeNames.in: 22 * html/HTMLMediaElement.cpp: 23 (WebCore::HTMLMediaElement::HTMLMediaElement): 24 (WebCore::HTMLMediaElement::load): 25 (WebCore::HTMLMediaElement::movieNetworkStateChanged): 26 (WebCore::HTMLMediaElement::setReadyState): 27 (WebCore::HTMLMediaElement::seek): 28 (WebCore::HTMLMediaElement::seeking): 29 (WebCore::HTMLMediaElement::currentTime): 30 (WebCore::HTMLMediaElement::ended): 31 (WebCore::HTMLMediaElement::play): 32 (WebCore::HTMLMediaElement::pause): 33 (WebCore::HTMLMediaElement::playCount): 34 (WebCore::HTMLMediaElement::setPlayCount): 35 (WebCore::HTMLMediaElement::checkIfSeekNeeded): 36 (WebCore::HTMLMediaElement::movieTimeChanged): 37 (WebCore::HTMLMediaElement::endedPlayback): 38 (WebCore::HTMLMediaElement::updateMovie): 39 * html/HTMLMediaElement.h: 40 * html/HTMLMediaElement.idl: 41 * platform/graphics/Movie.cpp: 42 (WebCore::Movie::timeChanged): 43 * platform/graphics/Movie.h: 44 (WebCore::MovieClient::movieTimeChanged): 45 * platform/graphics/mac/MoviePrivateQTKit.h: 46 * platform/graphics/mac/MoviePrivateQTKit.mm: 47 (WebCore::MoviePrivate::MoviePrivate): 48 (WebCore::MoviePrivate::load): 49 (WebCore::MoviePrivate::play): 50 (WebCore::MoviePrivate::pause): 51 (WebCore::MoviePrivate::currentTime): 52 (WebCore::MoviePrivate::seek): 53 (WebCore::MoviePrivate::doSeek): 54 (WebCore::MoviePrivate::cancelSeek): 55 (WebCore::MoviePrivate::seekTimerFired): 56 (WebCore::MoviePrivate::startCuePointTimerIfNeeded): 57 (WebCore::MoviePrivate::paused): 58 (WebCore::MoviePrivate::updateStates): 59 (WebCore::MoviePrivate::timeChanged): 60 (WebCore::MoviePrivate::didEnd): 61 1 62 2007-11-16 Anders Carlsson <andersca@apple.com> 2 63 -
trunk/WebCore/html/HTMLAttributeNames.in
r27465 r27866 74 74 longdesc 75 75 loop 76 loopcount76 playcount 77 77 loopend 78 78 loopstart -
trunk/WebCore/html/HTMLMediaElement.cpp
r27826 r27866 73 73 , m_muted(false) 74 74 , m_paused(true) 75 , m_seeking(false) 76 , m_currentTimeDuringSeek(0) 75 77 , m_previousProgress(0) 76 78 , m_previousProgressTime(numeric_limits<double>::max()) … … 262 264 m_readyState = DATA_UNAVAILABLE; 263 265 m_paused = true; 266 m_seeking = false; 264 267 if (m_movie) { 265 268 m_movie->pause(); … … 355 358 if (state >= Movie::LoadedMetaData && m_networkState < LOADED_METADATA) { 356 359 m_movie->seek(effectiveStart()); 357 m_movie->setEndTime(currentLoop() == loopCount() - 1 ? effectiveEnd() : effectiveLoopEnd());358 360 m_networkState = LOADED_METADATA; 359 361 … … 417 419 bool wasActivelyPlaying = activelyPlaying(); 418 420 m_readyState = state; 421 422 if (state >= CAN_PLAY) 423 m_seeking = false; 419 424 420 425 if (networkState() == EMPTY) … … 443 448 } 444 449 } 445 update PlayState();450 updateMovie(); 446 451 } 447 452 … … 486 491 487 492 // 3 488 float maxTime = currentLoop() == loopCount() - 1 ? effectiveEnd() : effectiveLoopEnd();493 float maxTime = currentLoop() == playCount() - 1 ? effectiveEnd() : effectiveLoopEnd(); 489 494 490 495 // 4 … … 502 507 503 508 // 7 504 if (m_movie) { 505 m_movie->seek(time); 506 m_movie->setEndTime(maxTime); 507 } 508 509 m_currentTimeDuringSeek = time; 510 509 511 // 8 510 // The seeking DOM attribute is implicitly set to true512 m_seeking = true; 511 513 512 514 // 9 … … 516 518 // As soon as the user agent has established whether or not the media data for the new playback position is available, 517 519 // and, if it is, decoded enough data to play back that position, the seeking DOM attribute must be set to false. 520 if (m_movie) { 521 m_movie->setEndTime(maxTime); 522 m_movie->seek(time); 523 } 518 524 } 519 525 … … 525 531 bool HTMLMediaElement::seeking() const 526 532 { 527 if (!m_movie) 528 return false; 529 RefPtr<TimeRanges> seekableRanges = seekable(); 530 return m_movie->seeking() && seekableRanges->contain(currentTime()); 533 return m_seeking; 531 534 } 532 535 … … 534 537 float HTMLMediaElement::currentTime() const 535 538 { 536 return m_movie ? m_movie->currentTime() : 0; 539 if (!m_movie) 540 return 0; 541 if (m_seeking) 542 return m_currentTimeDuringSeek; 543 return m_movie->currentTime(); 537 544 } 538 545 … … 588 595 bool HTMLMediaElement::ended() 589 596 { 590 return networkState() >= LOADED_METADATA && currentTime() >= effectiveEnd() && currentLoop() == loopCount() - 1;597 return endedPlayback(); 591 598 } 592 599 … … 619 626 if (m_paused) { 620 627 m_paused = false; 621 updatePlayState();622 628 dispatchEventAsync(playEvent); 623 629 } 624 630 625 631 m_autoplaying = false; 632 633 updateMovie(); 626 634 } 627 635 … … 638 646 if (!m_paused) { 639 647 m_paused = true; 640 updatePlayState();641 648 dispatchEventAsync(timeupdateEvent); 642 649 dispatchEventAsync(pauseEvent); … … 644 651 645 652 m_autoplaying = false; 646 } 647 648 unsigned HTMLMediaElement::loopCount() const 649 { 650 String val = getAttribute(loopcountAttr); 653 654 updateMovie(); 655 } 656 657 unsigned HTMLMediaElement::playCount() const 658 { 659 String val = getAttribute(playcountAttr); 651 660 int count = val.toInt(); 652 661 return max(count, 1); 653 662 } 654 663 655 void HTMLMediaElement::set LoopCount(unsigned count, ExceptionCode& ec)664 void HTMLMediaElement::setPlayCount(unsigned count, ExceptionCode& ec) 656 665 { 657 666 if (!count) { … … 659 668 return; 660 669 } 661 setAttribute( loopcountAttr, String::number(count));670 setAttribute(playcountAttr, String::number(count)); 662 671 checkIfSeekNeeded(); 663 672 } … … 798 807 // 3.14.9.5. Offsets into the media resource 799 808 // 1 800 if ( loopCount() - 1 <m_currentLoop)801 m_currentLoop = loopCount() - 1;809 if (playCount() <= m_currentLoop) 810 m_currentLoop = playCount() - 1; 802 811 803 812 // 2 … … 816 825 817 826 // 5 818 if (m_currentLoop < loopCount() - 1 && time > effectiveLoopEnd()) {827 if (m_currentLoop < playCount() - 1 && time > effectiveLoopEnd()) { 819 828 seek(effectiveLoopStart(), ec); 820 829 m_currentLoop++; … … 822 831 823 832 // 6 824 if (m_currentLoop == loopCount() - 1 && time > effectiveEnd())833 if (m_currentLoop == playCount() - 1 && time > effectiveEnd()) 825 834 seek(effectiveEnd(), ec); 826 835 827 update PlayState();836 updateMovie(); 828 837 } 829 838 … … 839 848 } 840 849 841 void HTMLMediaElement::movieDidEnd(Movie*) 842 { 843 if (m_currentLoop < loopCount() - 1 && currentTime() >= effectiveLoopEnd()) { 844 m_movie->seek(effectiveLoopStart()); 850 void HTMLMediaElement::movieTimeChanged(Movie*) 851 { 852 if (readyState() >= CAN_PLAY) 853 m_seeking = false; 854 855 if (m_currentLoop < playCount() - 1 && currentTime() >= effectiveLoopEnd()) { 856 ExceptionCode ec; 857 seek(effectiveLoopStart(), ec); 845 858 m_currentLoop++; 846 m_movie->setEndTime(m_currentLoop == loopCount() - 1 ? effectiveEnd() : effectiveLoopEnd());847 updatePlayState();848 859 dispatchHTMLEvent(timeupdateEvent, false, true); 849 860 } 850 861 851 if (m_currentLoop == loopCount() - 1 && currentTime() >= effectiveEnd()) {862 if (m_currentLoop == playCount() - 1 && currentTime() >= effectiveEnd()) { 852 863 dispatchHTMLEvent(timeupdateEvent, false, true); 853 864 dispatchHTMLEvent(endedEvent, false, true); 854 865 } 866 867 updateMovie(); 855 868 } 856 869 … … 957 970 bool HTMLMediaElement::endedPlayback() const 958 971 { 959 return networkState() >= LOADED_METADATA && currentTime() >= effectiveEnd() && currentLoop() == loopCount() - 1;960 } 961 962 void HTMLMediaElement::update PlayState()972 return networkState() >= LOADED_METADATA && currentTime() >= effectiveEnd() && currentLoop() == playCount() - 1; 973 } 974 975 void HTMLMediaElement::updateMovie() 963 976 { 964 977 if (!m_movie) 965 978 return; 966 bool shouldBePlaying = activelyPlaying(); 979 980 m_movie->setEndTime(currentLoop() == playCount() - 1 ? effectiveEnd() : effectiveLoopEnd()); 981 982 bool shouldBePlaying = activelyPlaying() && currentTime() < effectiveEnd(); 967 983 if (shouldBePlaying && m_movie->paused()) 968 984 m_movie->play(); -
trunk/WebCore/html/HTMLMediaElement.h
r27758 r27866 109 109 float loopEnd() const; 110 110 void setLoopEnd(float time); 111 unsigned loopCount() const;112 void set LoopCount(unsigned, ExceptionCode&);111 unsigned playCount() const; 112 void setPlayCount(unsigned, ExceptionCode&); 113 113 unsigned currentLoop() const; 114 114 void setCurrentLoop(unsigned); … … 141 141 virtual void movieNetworkStateChanged(Movie*); 142 142 virtual void movieReadyStateChanged(Movie*); 143 virtual void movieTimeChanged(Movie*); 143 144 virtual void movieVolumeChanged(Movie*); 144 virtual void movieDidEnd(Movie*);145 145 virtual void movieCuePointReached(Movie*, float cueTime); 146 146 … … 153 153 154 154 String pickMedia(); 155 void update PlayState();155 void updateMovie(); 156 156 float effectiveStart() const; 157 157 float effectiveEnd() const; … … 186 186 bool m_paused; 187 187 bool m_seeking; 188 189 float m_currentTimeDuringSeek; 188 190 189 191 unsigned m_previousProgress; -
trunk/WebCore/html/HTMLMediaElement.idl
r27277 r27866 76 76 attribute float loopStart; 77 77 attribute float loopEnd; 78 attribute unsigned long loopCount78 attribute unsigned long playCount 79 79 setter raises (DOMException); 80 80 attribute unsigned long currentLoop; -
trunk/WebCore/platform/graphics/Movie.cpp
r27597 r27866 264 264 } 265 265 266 void Movie:: didEnd()267 { 268 if (m_movieClient) 269 m_movieClient->movie DidEnd(this);266 void Movie::timeChanged() 267 { 268 if (m_movieClient) 269 m_movieClient->movieTimeChanged(this); 270 270 } 271 271 -
trunk/WebCore/platform/graphics/Movie.h
r27277 r27866 50 50 virtual void movieReadyStateChanged(Movie*) { } 51 51 virtual void movieVolumeChanged(Movie*) { } 52 virtual void movie DidEnd(Movie*) { }52 virtual void movieTimeChanged(Movie*) { } 53 53 virtual void movieCuePointReached(Movie*, float cueTime) { } 54 54 }; … … 120 120 void readyStateChanged(); 121 121 void volumeChanged(); 122 void didEnd();122 void timeChanged(); 123 123 void cuePointReached(float cueTime); 124 124 -
trunk/WebCore/platform/graphics/mac/MoviePrivateQTKit.h
r27277 r27866 114 114 115 115 private: 116 117 116 void updateStates(); 117 void doSeek(); 118 118 void cancelSeek(); 119 119 void seekTimerFired(Timer<MoviePrivate>*); … … 132 132 Timer<MoviePrivate> m_cuePointTimer; 133 133 float m_previousTimeCueTimerFired; 134 float m_rateBeforeSeek;135 134 Movie::NetworkState m_networkState; 136 135 Movie::ReadyState m_readyState; 137 136 bool m_startedPlaying; 138 bool m_blockStateUpdate;139 137 bool m_isStreaming; 140 138 }; -
trunk/WebCore/platform/graphics/mac/MoviePrivateQTKit.mm
r27600 r27866 71 71 , m_cuePointTimer(this, &MoviePrivate::cuePointTimerFired) 72 72 , m_previousTimeCueTimerFired(0) 73 , m_rateBeforeSeek(0)74 73 , m_networkState(Movie::Empty) 75 74 , m_readyState(Movie::DataUnavailable) 76 75 , m_startedPlaying(false) 77 , m_blockStateUpdate(false)78 76 , m_isStreaming(false) 79 77 { … … 170 168 cancelSeek(); 171 169 m_cuePointTimer.stop(); 170 171 [m_objcObserver.get() setDelayCallbacks:YES]; 172 172 173 createQTMovie(url); 173 174 if (m_movie->visible()) 174 175 createQTMovieView(); 175 176 updateStates(); 176 177 [m_objcObserver.get() loadStateChanged:nil]; 178 [m_objcObserver.get() setDelayCallbacks:NO]; 177 179 } 178 180 179 181 void MoviePrivate::play() 180 182 { 181 cancelSeek();182 183 if (!m_qtMovie) 183 184 return; 184 185 m_startedPlaying = true; 186 [m_objcObserver.get() setDelayCallbacks:YES]; 185 187 [m_qtMovie.get() setRate: m_movie->rate()]; 188 [m_objcObserver.get() setDelayCallbacks:NO]; 186 189 startCuePointTimerIfNeeded(); 187 190 } … … 189 192 void MoviePrivate::pause() 190 193 { 191 cancelSeek();192 194 if (!m_qtMovie) 193 195 return; 194 196 m_startedPlaying = false; 197 [m_objcObserver.get() setDelayCallbacks:YES]; 195 198 [m_qtMovie.get() stop]; 199 [m_objcObserver.get() setDelayCallbacks:NO]; 196 200 m_cuePointTimer.stop(); 197 201 } … … 211 215 if (!m_qtMovie) 212 216 return 0; 213 if (seeking())214 return m_seekTo;215 217 QTTime time = [m_qtMovie.get() currentTime]; 216 218 float current = (float)time.timeValue / time.timeScale; … … 229 231 time = duration(); 230 232 231 if (maxTimeLoaded() < time) { 232 m_seekTo = time; 233 m_seekTimer.startRepeating(0.5f); 234 m_rateBeforeSeek = [m_qtMovie.get() rate]; 235 [m_qtMovie.get() setRate:0.0f]; 233 m_seekTo = time; 234 if (maxTimeLoaded() >= m_seekTo) 235 doSeek(); 236 else 237 m_seekTimer.start(0, 0.5f); 238 } 239 240 void MoviePrivate::doSeek() 241 { 242 QTTime qttime = createQTTime(m_seekTo); 243 // setCurrentTime generates several event callbacks, update afterwards 244 [m_objcObserver.get() setDelayCallbacks:YES]; 245 float oldRate = [m_qtMovie.get() rate]; 246 [m_qtMovie.get() setRate:0]; 247 [m_qtMovie.get() setCurrentTime: qttime]; 248 float timeAfterSeek = currentTime(); 249 // restore playback only if not at end, othewise QTMovie will loop 250 if (timeAfterSeek < duration() && timeAfterSeek < m_endTime) 251 [m_qtMovie.get() setRate:oldRate]; 252 cancelSeek(); 253 [m_objcObserver.get() setDelayCallbacks:NO]; 254 } 255 256 void MoviePrivate::cancelSeek() 257 { 258 m_seekTo = -1; 259 m_seekTimer.stop(); 260 } 261 262 void MoviePrivate::seekTimerFired(Timer<MoviePrivate>*) 263 { 264 if (!m_qtMovie || !seeking() || currentTime() == m_seekTo) { 265 cancelSeek(); 236 266 updateStates(); 237 } else { 238 QTTime qttime = createQTTime(time); 239 // setCurrentTime generates several event callbacks, update afterwards 240 m_blockStateUpdate = true; 241 [m_qtMovie.get() setCurrentTime: qttime]; 242 m_blockStateUpdate = false; 243 updateStates(); 267 m_movie->timeChanged(); 268 return; 269 } 270 271 if (maxTimeLoaded() >= m_seekTo) 272 doSeek(); 273 else { 274 Movie::NetworkState state = networkState(); 275 if (state == Movie::Empty || state == Movie::Loaded) { 276 cancelSeek(); 277 updateStates(); 278 m_movie->timeChanged(); 279 } 244 280 } 245 281 } … … 267 303 void MoviePrivate::startCuePointTimerIfNeeded() 268 304 { 269 270 305 if ((m_endTime < duration() || !m_movie->m_cuePoints.isEmpty()) 271 306 && m_startedPlaying && !m_cuePointTimer.isActive()) { 272 307 m_previousTimeCueTimerFired = currentTime(); 273 308 m_cuePointTimer.startRepeating(0.020f); 274 }275 }276 277 void MoviePrivate::cancelSeek()278 {279 if (m_seekTo > -1) {280 m_seekTo = -1;281 if (m_qtMovie)282 [m_qtMovie.get() setRate:m_rateBeforeSeek];283 }284 m_rateBeforeSeek = 0.0f;285 m_seekTimer.stop();286 }287 288 void MoviePrivate::seekTimerFired(Timer<MoviePrivate>*)289 {290 if (!m_qtMovie) {291 cancelSeek();292 return;293 }294 if (!seeking()) {295 updateStates();296 return;297 }298 299 if (maxTimeLoaded() > m_seekTo) {300 QTTime qttime = createQTTime(m_seekTo);301 // setCurrentTime generates several event callbacks, update afterwards302 m_blockStateUpdate = true;303 [m_qtMovie.get() setCurrentTime: qttime];304 m_blockStateUpdate = false;305 cancelSeek();306 updateStates();307 }308 309 Movie::NetworkState state = networkState();310 if (state == Movie::Empty || state == Movie::Loaded) {311 cancelSeek();312 updateStates();313 309 } 314 310 } … … 337 333 if (!m_qtMovie) 338 334 return true; 339 return [m_qtMovie.get() rate] == 0.0f && (!seeking() || m_rateBeforeSeek == 0.0f);335 return [m_qtMovie.get() rate] == 0.0f; 340 336 } 341 337 … … 462 458 void MoviePrivate::updateStates() 463 459 { 464 if (m_blockStateUpdate)465 return;466 467 460 Movie::NetworkState oldNetworkState = m_networkState; 468 461 Movie::ReadyState oldReadyState = m_readyState; … … 474 467 if (m_networkState < Movie::Loaded) 475 468 m_networkState = Movie::Loaded; 476 469 m_readyState = Movie::CanPlayThrough; 477 470 } else if (loadState >= 20000) { 478 471 // 20000 is kMovieLoadStatePlaythroughOK … … 498 491 m_readyState = Movie::DataUnavailable; 499 492 } 500 493 501 494 if (seeking()) 502 495 m_readyState = Movie::DataUnavailable; … … 526 519 m_previousTimeCueTimerFired = -1; 527 520 updateStates(); 521 m_movie->timeChanged(); 528 522 } 529 523 … … 537 531 m_cuePointTimer.stop(); 538 532 m_startedPlaying = false; 539 m_movie->didEnd(); 533 updateStates(); 534 m_movie->timeChanged(); 540 535 } 541 536
Note:
See TracChangeset
for help on using the changeset viewer.