Changeset 108241 in webkit


Ignore:
Timestamp:
Feb 20, 2012 7:02:09 AM (12 years ago)
Author:
commit-queue@webkit.org
Message:

Source/WebCore: Added code to support dispatching of missed cues in case of normal playback
and event sorting in case of simultaneous event triggering.

<track>-related events cuechange, enter, and exit should be sorted and filtered before dispatching
https://bugs.webkit.org/show_bug.cgi?id=72171

Patch by Victor Carbune <victor@rosedu.org> on 2012-02-20
Reviewed by Eric Carlson.

Tests: media/track/track-cues-missed.html

media/track/track-cues-sorted-before-dispatch.html

  • html/HTMLMediaElement.cpp:

(WebCore::HTMLMediaElement::HTMLMediaElement): Added initialization code
for newly added state variables.
(WebCore::trackIndexCompare): Static boolean compare function between
the index of two tracks.
(WebCore):
(WebCore::eventTimeCueCompare): Static boolean compare function between
events associated with text track cues.
(WebCore::HTMLMediaElement::updateActiveTextTrackCues): Added code to
sort the events associated with text track cues before dispatching.
Each step from the specification is commented within the code.
(WebCore::HTMLMediaElement::finishSeek): Added a boolean variable that
is needed within the text track update function, to know whether a seek
event has occured before or not.
(WebCore::HTMLMediaElement::mediaPlayerTimeChanged): Moved the update
call for text tracks at the beginning of the function instead of the end.
'ended' events for video should be dispatched after track specific events.

  • html/HTMLMediaElement.h: Added variables to keep

state information required by the text track update algorithm (last time
the algorithm was run, and whether a seeking event has occured)
(HTMLMediaElement):

  • html/LoadableTextTrack.cpp: Refactored fireCueChangeEvent method

(WebCore::LoadableTextTrack::fireCueChangeEvent): The method dispatches a
synchronous cue change event for the track element.

  • html/LoadableTextTrack.h:

(LoadableTextTrack):

  • html/TextTrack.cpp: Modified the fireCueChange method, cached track index.

(WebCore::TextTrack::TextTrack):
(WebCore::TextTrack::trackIndex): Cached the track index.
(WebCore):
(WebCore::TextTrack::invalidateTrackIndex): Invalidates the track. Used
when a new track is added in a TextTrackList instance.

  • html/TextTrack.h:

(TextTrack):
(WebCore::TextTrack::fireCueChangeEvent): The fireCueChangeEvent has been changed,
as events need to be fired asyncronously.

  • html/TextTrackCue.cpp: Added internal variables to keep the current index

position in the track cue order. This is invalidated when an element is
inserted before.
(WebCore::TextTrackCue::TextTrackCue):
(WebCore::TextTrackCue::cueIndex): Getter for the cueIndex.
(WebCore):
(WebCore::TextTrackCue::invalidateCueIndex): Invalidates the currently stored
cue index.
(WebCore::TextTrackCue::dispatchEvent): Event dispatching is done asynchronously
now. This should be the only method used for event dispatching.
(WebCore::TextTrackCue::setIsActive): The setIsActive method no longer dispatches
events, but rather just changes the m_isActive variable.

  • html/TextTrackCue.h:

(TextTrackCue):

  • html/TextTrackCueList.cpp:

(WebCore::TextTrackCueList::getCueIndex): Retrieves the cue index, in the track cue
order, of a given cue.
(WebCore):
(WebCore::TextTrackCueList::add): Modified the add method such that all the next cue
indexes are invalidated.
(WebCore::TextTrackCueList::invalidateCueIndexes): Invalidates all cue indexes starting
with a specific position.

  • html/TextTrackCueList.h:

(TextTrackCueList):

  • html/track/TextTrackList.cpp:

(TextTrackList::getTrackIndex): Retrieves the track index position.
(TextTrackList::append): Added method for invalidating the text track index in case of
changing the list contents.

  • html/track/TextTrackList.h:

(TextTrackList):

LayoutTests: <track>-related events cuechange, enter, and exit should be sorted and filtered before dispatching
https://bugs.webkit.org/show_bug.cgi?id=72171

Patch by Victor Carbune <victor@rosedu.org> on 2012-02-20
Reviewed by Eric Carlson.

  • media/track/captions-webvtt/missed-cues.vtt: Added.
  • media/track/captions-webvtt/sorted-dispatch.vtt: Added.
  • media/track/track-cues-cuechange-expected.txt: This test had to be changed because

the synchronous dispatch of the events against the HTMLTrackElement doesn't mean that
the text track actually has any active cues at the dispatch moment.

  • media/track/track-cues-cuechange.html: Changed tests structure to guide the entering and

exit events according to the asynchronous dispatch done by TextTrack.

  • media/track/track-cues-missed-expected.txt: Added.
  • media/track/track-cues-missed.html: Added.
  • media/track/track-cues-sorted-before-dispatch-expected.txt: Added.
  • media/track/track-cues-sorted-before-dispatch.html: Added.
Location:
trunk
Files:
6 added
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r108237 r108241  
     12012-02-20  Victor Carbune  <victor@rosedu.org>
     2
     3        <track>-related events cuechange, enter, and exit should be sorted and filtered before dispatching
     4        https://bugs.webkit.org/show_bug.cgi?id=72171
     5
     6        Reviewed by Eric Carlson.
     7
     8        * media/track/captions-webvtt/missed-cues.vtt: Added.
     9        * media/track/captions-webvtt/sorted-dispatch.vtt: Added.
     10        * media/track/track-cues-cuechange-expected.txt: This test had to be changed because
     11        the synchronous dispatch of the events against the HTMLTrackElement doesn't mean that
     12        the text track actually has any active cues at the dispatch moment.
     13        * media/track/track-cues-cuechange.html: Changed tests structure to guide the entering and
     14        exit events according to the asynchronous dispatch done by TextTrack.
     15        * media/track/track-cues-missed-expected.txt: Added.
     16        * media/track/track-cues-missed.html: Added.
     17        * media/track/track-cues-sorted-before-dispatch-expected.txt: Added.
     18        * media/track/track-cues-sorted-before-dispatch.html: Added.
     19
    1202012-02-20  Vsevolod Vlasov  <vsevik@chromium.org>
    221
  • trunk/LayoutTests/media/track/track-cues-cuechange-expected.txt

    r100296 r108241  
    55RUN(video.play())
    66
     7EVENT(cuechange) from <track>
    78EVENT(cuechange) from TextTrack
    89Cue entered
     
    1112
    1213EVENT(cuechange) from <track>
    13 Cue entered
    14 EXPECTED ([object TextTrackCue] == '[object TextTrackCue]') OK
    15 EXPECTED (currentCue.id == '1') OK
    16 
    1714EVENT(cuechange) from TextTrack
    1815Cue exited
    1916
    2017EVENT(cuechange) from <track>
    21 Cue exited
    22 
    2318EVENT(cuechange) from TextTrack
    2419Cue entered
     
    2722
    2823EVENT(cuechange) from <track>
    29 Cue entered
    30 EXPECTED ([object TextTrackCue] == '[object TextTrackCue]') OK
    31 EXPECTED (currentCue.id == '2') OK
    32 
    3324EVENT(cuechange) from TextTrack
    3425Cue exited
    3526
    3627EVENT(cuechange) from <track>
    37 Cue exited
    38 
    3928EVENT(cuechange) from TextTrack
    4029Cue entered
     
    4332
    4433EVENT(cuechange) from <track>
    45 Cue entered
    46 EXPECTED ([object TextTrackCue] == '[object TextTrackCue]') OK
    47 EXPECTED (currentCue.id == '3') OK
    48 
    4934EVENT(cuechange) from TextTrack
    50 Cue exited
    51 
    52 EVENT(cuechange) from <track>
    5335Cue exited
    5436
  • trunk/LayoutTests/media/track/track-cues-cuechange.html

    r102212 r108241  
    3232        {
    3333            consoleWrite("EVENT(cuechange) from &lt;track&gt;");
    34            
    35             currentCueIndex = Math.floor(cueChangeCount/2);
    36             currentCue = event.target.track.cues[currentCueIndex];
     34        }
     35
     36        function cueChangedFromTextTrack()
     37        {
     38            consoleWrite("EVENT(cuechange) from TextTrack");
     39
     40            currentCueIndex = Math.floor(cueChangeCount / 2);
     41            currentCue = event.target.cues[currentCueIndex];
    3742            checkCue();
    3843
     
    4247        }
    4348
    44         function cueChangedFromTextTrack()
    45         {
    46             consoleWrite("EVENT(cuechange) from TextTrack");
    47            
    48             currentCueIndex = Math.floor(cueChangeCount/2);
    49             currentCue = event.target.cues[currentCueIndex];
    50             checkCue();
    51         }
    52        
    5349        function checkCue()
    5450        {
  • trunk/Source/WebCore/ChangeLog

    r108240 r108241  
     12012-02-20  Victor Carbune  <victor@rosedu.org>
     2
     3        Added code to support dispatching of missed cues in case of normal playback
     4        and event sorting in case of simultaneous event triggering.
     5
     6        <track>-related events cuechange, enter, and exit should be sorted and filtered before dispatching
     7        https://bugs.webkit.org/show_bug.cgi?id=72171
     8
     9        Reviewed by Eric Carlson.
     10
     11        Tests: media/track/track-cues-missed.html
     12               media/track/track-cues-sorted-before-dispatch.html
     13
     14        * html/HTMLMediaElement.cpp:
     15        (WebCore::HTMLMediaElement::HTMLMediaElement): Added initialization code
     16        for newly added state variables.
     17        (WebCore::trackIndexCompare): Static boolean compare function between
     18        the index of two tracks.
     19        (WebCore):
     20        (WebCore::eventTimeCueCompare): Static boolean compare function between
     21        events associated with text track cues.
     22        (WebCore::HTMLMediaElement::updateActiveTextTrackCues): Added code to
     23        sort the events associated with text track cues before dispatching.
     24        Each step from the specification is commented within the code.
     25        (WebCore::HTMLMediaElement::finishSeek): Added a boolean variable that
     26        is needed within the text track update function, to know whether a seek
     27        event has occured before or not.
     28        (WebCore::HTMLMediaElement::mediaPlayerTimeChanged): Moved the update
     29        call for text tracks at the beginning of the function instead of the end.
     30        'ended' events for video should be dispatched after track specific events.
     31        * html/HTMLMediaElement.h: Added variables to keep
     32        state information required by the text track update algorithm (last time
     33        the algorithm was run, and whether a seeking event has occured)
     34        (HTMLMediaElement):
     35
     36        * html/LoadableTextTrack.cpp: Refactored fireCueChangeEvent method
     37        (WebCore::LoadableTextTrack::fireCueChangeEvent): The method dispatches a
     38        synchronous cue change event for the track element.
     39        * html/LoadableTextTrack.h:
     40        (LoadableTextTrack):
     41        * html/TextTrack.cpp: Modified the fireCueChange method, cached track index.
     42        (WebCore::TextTrack::TextTrack):
     43        (WebCore::TextTrack::trackIndex): Cached the track index.
     44        (WebCore):
     45        (WebCore::TextTrack::invalidateTrackIndex): Invalidates the track. Used
     46        when a new track is added in a TextTrackList instance.
     47        * html/TextTrack.h:
     48        (TextTrack):
     49        (WebCore::TextTrack::fireCueChangeEvent): The fireCueChangeEvent has been changed,
     50        as events need to be fired asyncronously.
     51        * html/TextTrackCue.cpp: Added internal variables to keep the current index
     52        position in the track cue order. This is invalidated when an element is
     53        inserted before.
     54        (WebCore::TextTrackCue::TextTrackCue):
     55        (WebCore::TextTrackCue::cueIndex): Getter for the cueIndex.
     56        (WebCore):
     57        (WebCore::TextTrackCue::invalidateCueIndex): Invalidates the currently stored
     58        cue index.
     59        (WebCore::TextTrackCue::dispatchEvent): Event dispatching is done asynchronously
     60        now. This should be the only method used for event dispatching.
     61        (WebCore::TextTrackCue::setIsActive): The setIsActive method no longer dispatches
     62        events, but rather just changes the m_isActive variable.
     63        * html/TextTrackCue.h:
     64        (TextTrackCue):
     65
     66        * html/TextTrackCueList.cpp:
     67        (WebCore::TextTrackCueList::getCueIndex): Retrieves the cue index, in the track cue
     68        order, of a given cue.
     69        (WebCore):
     70        (WebCore::TextTrackCueList::add): Modified the add method such that all the next cue
     71        indexes are invalidated.
     72        (WebCore::TextTrackCueList::invalidateCueIndexes): Invalidates all cue indexes starting
     73        with a specific position.
     74        * html/TextTrackCueList.h:
     75        (TextTrackCueList):
     76        * html/track/TextTrackList.cpp:
     77        (TextTrackList::getTrackIndex): Retrieves the track index position.
     78        (TextTrackList::append): Added method for invalidating the text track index in case of
     79        changing the list contents.
     80        * html/track/TextTrackList.h:
     81        (TextTrackList):
     82
    1832012-02-20  Kenichi Ishibashi  <bashi@chromium.org>
    284
  • trunk/Source/WebCore/html/HTMLMediaElement.cpp

    r108165 r108241  
    7878#include <wtf/CurrentTime.h>
    7979#include <wtf/MathExtras.h>
     80#include <wtf/NonCopyingSort.h>
    8081#include <wtf/Uint8Array.h>
    8182#include <wtf/text/CString.h>
     
    237238    , m_tracksAreReady(true)
    238239    , m_haveVisibleTextTrack(false)
     240    , m_lastTextTrackUpdateTime(-1)
    239241    , m_textTracks(0)
    240242    , m_ignoreTrackDisplayUpdate(0)
     
    935937
    936938#if ENABLE(VIDEO_TRACK)
     939static bool trackIndexCompare(TextTrack* a,
     940                              TextTrack* b)
     941{
     942    return a->trackIndex() - b->trackIndex() < 0;
     943}
     944
     945static bool eventTimeCueCompare(const std::pair<double, TextTrackCue*>& a,
     946                                const std::pair<double, TextTrackCue*>& b)
     947{
     948    // 12 - Sort the tasks in events in ascending time order (tasks with earlier
     949    // times first).
     950    if (a.first != b.first)
     951        return a.first - b.first < 0;
     952
     953    // If the cues belong to different text tracks, it doesn't make sense to
     954    // compare the two tracks by the relative cue order, so return the relative
     955    // track order.
     956    if (a.second->track() != b.second->track())
     957        return trackIndexCompare(a.second->track(), b.second->track());
     958
     959    // 12 - Further sort tasks in events that have the same time by the
     960    // relative text track cue order of the text track cues associated
     961    // with these tasks.
     962    return a.second->cueIndex() - b.second->cueIndex() < 0;
     963}
     964
     965
    937966void HTMLMediaElement::updateActiveTextTrackCues(float movieTime)
    938967{
     968    LOG(Media, "HTMLMediaElement::updateActiveTextTracks");
     969
     970    // 4.8.10.8 Playing the media resource
     971
     972    //  If the current playback position changes while the steps are running,
     973    //  then the user agent must wait for the steps to complete, and then must
     974    //  immediately rerun the steps.
    939975    if (ignoreTrackDisplayUpdateRequests())
    940976        return;
    941977
    942     CueList previouslyActiveCues = m_currentlyActiveCues;
    943     bool activeSetChanged = false;
    944 
    945     // The user agent must synchronously unset [the text track cue active] flag whenever ... the media
    946     // element's readyState is changed back to HAVE_NOTHING.
    947     if (m_readyState == HAVE_NOTHING || !m_player)
    948         m_currentlyActiveCues.shrink(0);
    949     else
    950         m_currentlyActiveCues = m_cueTree.allOverlaps(m_cueTree.createInterval(movieTime, movieTime));
    951    
    952     // FIXME(72171): Events need to be sorted and filtered before dispatching.
    953 
    954     for (size_t i = 0; i < previouslyActiveCues.size(); ++i) {
    955         if (!m_currentlyActiveCues.contains(previouslyActiveCues[i])) {
    956             previouslyActiveCues[i].data()->setIsActive(false);
     978    // 1 - Let current cues be a list of cues, initialized to contain all the
     979    // cues of all the hidden, showing, or showing by default text tracks of the
     980    // media element (not the disabled ones) whose start times are less than or
     981    // equal to the current playback position and whose end times are greater
     982    // than the current playback position.
     983    Vector<CueIntervalTree::IntervalType> currentCues;
     984
     985    // The user agent must synchronously unset [the text track cue active] flag
     986    // whenever ... the media element's readyState is changed back to HAVE_NOTHING.
     987    if (m_readyState != HAVE_NOTHING && m_player)
     988        currentCues = m_cueTree.allOverlaps(m_cueTree.createInterval(movieTime, movieTime));
     989
     990    Vector<CueIntervalTree::IntervalType> affectedCues;
     991    Vector<CueIntervalTree::IntervalType> previousCues;
     992    Vector<CueIntervalTree::IntervalType> missedCues;
     993
     994    // 2 - Let other cues be a list of cues, initialized to contain all the cues
     995    // of hidden, showing, and showing by default text tracks of the media
     996    // element that are not present in current cues.
     997    previousCues = m_currentlyActiveCues;
     998
     999    // 3 - Let last time be the current playback position at the time this
     1000    // algorithm was last run for this media element, if this is not the first
     1001    // time it has run.
     1002    float lastTime = m_lastTextTrackUpdateTime;
     1003
     1004    // 4 - If the current playback position has, since the last time this
     1005    // algorithm was run, only changed through its usual monotonic increase
     1006    // during normal playback, then let missed cues be the list of cues in other
     1007    // cues whose start times are greater than or equal to last time and whose
     1008    // end times are less than or equal to the current playback position.
     1009    // Otherwise, let missed cues be an empty list.
     1010    if (lastTime >= 0 && m_lastSeekTime <= lastTime) {
     1011        Vector<CueIntervalTree::IntervalType> potentiallySkippedCues =
     1012            m_cueTree.allOverlaps(m_cueTree.createInterval(lastTime, movieTime));
     1013
     1014        for (size_t i = 0; i < potentiallySkippedCues.size(); ++i) {
     1015            float cueStartTime = potentiallySkippedCues[i].low();
     1016            float cueEndTime = potentiallySkippedCues[i].high();
     1017
     1018            if (cueStartTime > lastTime && cueEndTime < movieTime)
     1019                missedCues.append(potentiallySkippedCues[i]);
     1020        }
     1021    }
     1022
     1023    m_lastTextTrackUpdateTime = movieTime;
     1024
     1025    // 5 - If the time was reached through the usual monotonic increase of the
     1026    // current playback position during normal playback, and if the user agent
     1027    // has not fired a timeupdate event at the element in the past 15 to 250ms
     1028    // and is not still running event handlers for such an event, then the user
     1029    // agent must queue a task to fire a simple event named timeupdate at the
     1030    // element. (In the other cases, such as explicit seeks, relevant events get
     1031    // fired as part of the overall process of changing the current playback
     1032    // position.)
     1033    if (m_lastSeekTime <= lastTime)
     1034        scheduleTimeupdateEvent(false);
     1035
     1036    // 6 - If all of the cues in current cues have their text track cue active
     1037    // flag set, none of the cues in other cues have their text track cue active
     1038    // flag set, and missed cues is empty, then abort these steps.
     1039    bool activeSetChanged = missedCues.size();
     1040
     1041    size_t previousCuesSize = previousCues.size();
     1042    for (size_t i = 0; !activeSetChanged && i < previousCuesSize; ++i)
     1043        if (!currentCues.contains(previousCues[i]) && previousCues[i].data()->isActive())
    9571044            activeSetChanged = true;
    958         }
    959     }
    960     for (size_t i = 0; i < m_currentlyActiveCues.size(); ++i) {
    961         if (!previouslyActiveCues.contains(m_currentlyActiveCues[i])) {
    962             m_currentlyActiveCues[i].data()->setIsActive(true);
     1045
     1046    size_t currentCuesSize = currentCues.size();
     1047    for (size_t i = 0; !activeSetChanged && i < currentCuesSize; ++i) {
     1048        if (!currentCues[i].data()->isActive())
    9631049            activeSetChanged = true;
    964         }
    965     }
    966    
    967     // FIXME(72173): Pause the media element for cues going past their endTime
    968     // during a monotonic time increase.
     1050    }
     1051
     1052    if (!activeSetChanged)
     1053        return;
     1054
     1055    // FIXME(72173): 7 - If the time was reached through the usual monotonic
     1056    // increase of the current playback position during normal playback, and
     1057    // there are cues in other cues that have their text track cue pause-on-exit
     1058    // flag set and that either have their text track cue active flag set or are
     1059    // also in missed cues, then immediately pause the media element.
     1060
     1061    // 8 - Let events be a list of tasks, initially empty. Each task in this
     1062    // list will be associated with a text track, a text track cue, and a time,
     1063    // which are used to sort the list before the tasks are queued.
     1064    Vector<std::pair<double, TextTrackCue*> > eventTasks;
     1065
     1066    // 8 - Let affected tracks be a list of text tracks, initially empty.
     1067    Vector<TextTrack*> affectedTracks;
     1068
     1069    for (size_t i = 0; i < missedCues.size(); ++i) {
     1070        // 9 - For each text track cue in missed cues, prepare an event named enter
     1071        // for the TextTrackCue object with the text track cue start time.
     1072        eventTasks.append(std::make_pair(missedCues[i].data()->startTime(),
     1073                                         missedCues[i].data()));
     1074
     1075        // 10 - For each text track in missed cues, prepare an event
     1076        // named exit for the TextTrackCue object with the text track cue end
     1077        // time.
     1078        eventTasks.append(std::make_pair(missedCues[i].data()->endTime(),
     1079                                         missedCues[i].data()));
     1080    }
     1081
     1082    for (size_t i = 0; i < previousCues.size(); ++i) {
     1083        // 10 - For each text track cue in other cues that has its text
     1084        // track cue active flag set prepare an event named exit for the
     1085        // TextTrackCue object with the text track cue end time.
     1086        if (!currentCues.contains(previousCues[i]))
     1087            eventTasks.append(std::make_pair(previousCues[i].data()->endTime(),
     1088                                             previousCues[i].data()));
     1089    }
     1090
     1091    for (size_t i = 0; i < currentCues.size(); ++i) {
     1092        // 11 - For each text track cue in current cues that does not have its
     1093        // text track cue active flag set, prepare an event named enter for the
     1094        // TextTrackCue object with the text track cue start time.
     1095        if (!previousCues.contains(currentCues[i]))
     1096            eventTasks.append(std::make_pair(currentCues[i].data()->startTime(),
     1097                                             currentCues[i].data()));
     1098    }
     1099
     1100    // 12 - Sort the tasks in events in ascending time order (tasks with earlier
     1101    // times first).
     1102    nonCopyingSort(eventTasks.begin(), eventTasks.end(), eventTimeCueCompare);
     1103
     1104    for (size_t i = 0; i < eventTasks.size(); ++i) {
     1105        if (!affectedTracks.contains(eventTasks[i].second->track()))
     1106            affectedTracks.append(eventTasks[i].second->track());
     1107
     1108        // 13 - Queue each task in events, in list order.
     1109        RefPtr<Event> event;
     1110
     1111        // Each event in eventTasks may be either an enterEvent or an exitEvent,
     1112        // depending on the time that is associated with the event. This
     1113        // correctly identifies the type of the event, since the startTime is
     1114        // always less than the endTime.
     1115        if (eventTasks[i].first == eventTasks[i].second->startTime())
     1116            event = Event::create(eventNames().enterEvent, false, false);
     1117        else
     1118            event = Event::create(eventNames().exitEvent, false, false);
     1119
     1120        event->setTarget(eventTasks[i].second);
     1121        m_asyncEventQueue.enqueueEvent(event.release());
     1122    }
     1123
     1124    // 14 - Sort affected tracks in the same order as the text tracks appear in
     1125    // the media element's list of text tracks, and remove duplicates.
     1126    nonCopyingSort(affectedTracks.begin(), affectedTracks.end(), trackIndexCompare);
     1127
     1128    // 15 - For each text track in affected tracks, in the list order, queue a
     1129    // task to fire a simple event named cuechange at the TextTrack object, and,
     1130    // if the text track has a corresponding track element, to then fire a
     1131    // simple event named cuechange at the track element as well.
     1132    for (size_t i = 0; i < affectedTracks.size(); ++i) {
     1133        RefPtr<Event> event = Event::create(eventNames().cuechangeEvent, false, false);
     1134        event->setTarget(affectedTracks[i]);
     1135
     1136        m_asyncEventQueue.enqueueEvent(event.release());
     1137
     1138        // Fire syncronous cue change event for track elements.
     1139        if (affectedTracks[i]->trackType() == TextTrack::TrackElement)
     1140            affectedTracks[i]->fireCueChangeEvent();
     1141    }
     1142
     1143    // 16 - Set the text track cue active flag of all the cues in the current
     1144    // cues, and unset the text track cue active flag of all the cues in the
     1145    // other cues.
     1146    for (size_t i = 0; i < currentCues.size(); ++i)
     1147        currentCues[i].data()->setIsActive(true);
     1148
     1149    for (size_t i = 0; i < previousCues.size(); ++i)
     1150        if (!currentCues.contains(previousCues[i]))
     1151            previousCues[i].data()->setIsActive(false);
     1152
     1153    // Update the current active cues.
     1154    m_currentlyActiveCues = currentCues;
    9691155
    9701156    if (activeSetChanged && hasMediaControls())
     
    26962882{
    26972883    LOG(Media, "HTMLMediaElement::mediaPlayerTimeChanged");
     2884
     2885#if ENABLE(VIDEO_TRACK)
     2886    updateActiveTextTrackCues(currentTime());
     2887#endif
    26982888
    26992889    beginProcessingMediaPlayerCallback();
     
    27452935
    27462936    updatePlayState();
    2747 #if ENABLE(VIDEO_TRACK)
    2748     updateActiveTextTrackCues(now);
    2749 #endif
    27502937    endProcessingMediaPlayerCallback();
    27512938}
  • trunk/Source/WebCore/html/HTMLMediaElement.h

    r108165 r108241  
    595595    bool m_tracksAreReady : 1;
    596596    bool m_haveVisibleTextTrack : 1;
     597    float m_lastTextTrackUpdateTime;
    597598
    598599    RefPtr<TextTrackList> m_textTracks;
    599600    Vector<RefPtr<TextTrack> > m_textTracksWhenResourceSelectionBegan;
     601
    600602    CueIntervalTree m_cueTree;
     603
    601604    CueList m_currentlyActiveCues;
    602605    int m_ignoreTrackDisplayUpdate;
  • trunk/Source/WebCore/html/LoadableTextTrack.cpp

    r101999 r108241  
    126126void LoadableTextTrack::fireCueChangeEvent()
    127127{
    128     TextTrack::fireCueChangeEvent();
     128    RefPtr<Event> event = Event::create(eventNames().cuechangeEvent, false, false);
    129129    ExceptionCode ec = 0;
    130     m_trackElement->dispatchEvent(Event::create(eventNames().cuechangeEvent, false, false), ec);
     130
     131    m_trackElement->dispatchEvent(event, ec);
    131132}
    132133
  • trunk/Source/WebCore/html/LoadableTextTrack.h

    r102471 r108241  
    5858
    5959    virtual void clearClient();
    60    
     60
    6161    size_t trackElementIndex();
    6262    HTMLTrackElement* trackElement() { return m_trackElement; }
     63
     64    virtual void fireCueChangeEvent();
    6365
    6466private:
     
    7274
    7375    void loadTimerFired(Timer<LoadableTextTrack>*);
    74    
    75     virtual void fireCueChangeEvent();
    7676
    7777    HTMLTrackElement* m_trackElement;
  • trunk/Source/WebCore/html/TextTrack.cpp

    r107632 r108241  
    3838#include "Event.h"
    3939#include "ExceptionCode.h"
     40#include "HTMLMediaElement.h"
    4041#include "TextTrackCueList.h"
     42#include "TextTrackList.h"
    4143#include "TrackBase.h"
    4244
    4345namespace WebCore {
     46
     47static const int invalidTrackIndex = -1;
    4448
    4549const AtomicString& TextTrack::subtitlesKeyword()
     
    8387    , m_readinessState(NotLoaded)
    8488    , m_showingByDefault(false)
     89    , m_trackIndex(invalidTrackIndex)
    8590{
    8691    setKind(kind);
     
    244249}
    245250
    246 void TextTrack::fireCueChangeEvent()
    247 {
    248     ExceptionCode ec = 0;
    249     dispatchEvent(Event::create(eventNames().cuechangeEvent, false, false), ec);
    250 }
    251    
    252251void TextTrack::cueWillChange(TextTrackCue* cue)
    253252{
     
    269268}
    270269
     270int TextTrack::trackIndex()
     271{
     272    ASSERT(m_mediaElement);
     273
     274    if (m_trackIndex == invalidTrackIndex)
     275        m_trackIndex = m_mediaElement->textTracks()->getTrackIndex(this);
     276
     277    return m_trackIndex;
     278}
     279
     280void TextTrack::invalidateTrackIndex()
     281{
     282    m_trackIndex = invalidTrackIndex;
     283}
     284
    271285TextTrackCueList* TextTrack::ensureTextTrackCueList()
    272286{
  • trunk/Source/WebCore/html/TextTrack.h

    r107632 r108241  
    6060    }
    6161    virtual ~TextTrack();
    62    
     62
    6363    void setMediaElement(HTMLMediaElement* element) { m_mediaElement = element; }
    6464    HTMLMediaElement* mediaElement() { return m_mediaElement; }
     
    100100    void removeCue(TextTrackCue*, ExceptionCode&);
    101101
     102    virtual void fireCueChangeEvent() { };
     103
    102104    void cueWillChange(TextTrackCue*);
    103105    void cueDidChange(TextTrackCue*);
    104    
    105     virtual void fireCueChangeEvent();
     106
    106107    DEFINE_ATTRIBUTE_EVENT_LISTENER(cuechange);
    107108
    108109    enum TextTrackType { TrackElement, AddTrack, InBand };
    109110    TextTrackType trackType() const { return m_trackType; }
     111
     112    int trackIndex();
     113    void invalidateTrackIndex();
    110114
    111115protected:
     
    125129    ReadinessState m_readinessState;
    126130    bool m_showingByDefault;
     131    int m_trackIndex;
    127132};
    128133
  • trunk/Source/WebCore/html/TextTrackCue.cpp

    r104624 r108241  
    3939#include "DocumentFragment.h"
    4040#include "TextTrack.h"
     41#include "TextTrackCueList.h"
    4142#include "WebVTTParser.h"
    4243#include <wtf/text/StringBuilder.h>
    4344
    4445namespace WebCore {
     46
     47static const int invalidCueIndex = -1;
    4548
    4649static const AtomicString& startKeyword()
     
    8891    , m_textPosition(50)
    8992    , m_cueSize(100)
     93    , m_cueIndex(invalidCueIndex)
    9094    , m_cueAlignment(Middle)
    9195    , m_scriptExecutionContext(context)
     
    325329}
    326330
     331int TextTrackCue::cueIndex()
     332{
     333    if (m_cueIndex == invalidCueIndex)
     334        m_cueIndex = track()->cues()->getCueIndex(this);
     335
     336    return m_cueIndex;
     337}
     338
     339void TextTrackCue::invalidateCueIndex()
     340{
     341    m_cueIndex = invalidCueIndex;
     342}
     343
    327344PassRefPtr<DocumentFragment> TextTrackCue::getCueAsHTML()
    328345{
     
    338355}
    339356
     357bool TextTrackCue::dispatchEvent(PassRefPtr<Event> event)
     358{
     359    // When a TextTrack's mode is disabled: no cues are active, no events fired.
     360    if (!track() || track()->mode() == TextTrack::DISABLED)
     361        return false;
     362
     363    return EventTarget::dispatchEvent(event);
     364}
     365
     366bool TextTrackCue::dispatchEvent(PassRefPtr<Event> event, ExceptionCode &ec)
     367{
     368    return EventTarget::dispatchEvent(event, ec);
     369}
     370
    340371bool TextTrackCue::isActive()
    341372{
     
    346377{
    347378    m_isActive = active;
    348 
    349     // When a TextTrack's mode is disabled: No cues are active, no events are fired ...
    350     if (!track() || track()->mode() == TextTrack::DISABLED)
    351         return;
    352 
    353     ExceptionCode ec = 0;
    354     if (active)
    355         dispatchEvent(Event::create(eventNames().enterEvent, false, false), ec);
    356     else
    357         dispatchEvent(Event::create(eventNames().exitEvent, false, false), ec);
    358 
    359     if (m_track)
    360         m_track->fireCueChangeEvent();
    361379}
    362380
  • trunk/Source/WebCore/html/TextTrackCue.h

    r104624 r108241  
    5151        return adoptRef(new TextTrackCue(context, id, start, end, content, settings, pauseOnExit));
    5252    }
    53    
     53
    5454    enum Direction { Horizontal, VerticalGrowingLeft, VerticalGrowingRight };
    5555    enum Alignment { Start, Middle, End };
     
    9393    void setText(const String&);
    9494
     95    int cueIndex();
     96    void invalidateCueIndex();
     97
    9598    PassRefPtr<DocumentFragment> getCueAsHTML();
    9699    void setCueHTML(PassRefPtr<DocumentFragment>);
    97100
     101    virtual bool dispatchEvent(PassRefPtr<Event>);
     102    bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&);
     103
    98104    bool isActive();
    99105    void setIsActive(bool);
    100    
     106
    101107    virtual const AtomicString& interfaceName() const;
    102108    virtual ScriptExecutionContext* scriptExecutionContext() const;
     
    119125    void cueWillChange();
    120126    void cueDidChange();
    121    
     127
    122128    virtual void refEventTarget() { ref(); }
    123129    virtual void derefEventTarget() { deref(); }
    124    
     130
    125131    String m_id;
    126132    double m_startTime;
     
    131137    int m_textPosition;
    132138    int m_cueSize;
     139    int m_cueIndex;
     140
    133141    Alignment m_cueAlignment;
    134142    RefPtr<DocumentFragment> m_documentFragment;
  • trunk/Source/WebCore/html/TextTrackCueList.cpp

    r101185 r108241  
    3939{
    4040    return m_list.size();
     41}
     42
     43unsigned long TextTrackCueList::getCueIndex(TextTrackCue* cue) const
     44{
     45    return m_list.find(cue);
    4146}
    4247
     
    8994
    9095       m_list.insert(start, cue);
     96       invalidateCueIndexes(start);
    9197       return true;
    9298    }
     
    120126}
    121127
     128void TextTrackCueList::invalidateCueIndexes(size_t start)
     129{
     130    for (size_t i = start; i < m_list.size(); ++i)
     131        m_list[i]->invalidateCueIndex();
     132}
     133
    122134} // namespace WebCore
    123135
  • trunk/Source/WebCore/html/TextTrackCueList.h

    r101185 r108241  
    4646
    4747    unsigned long length() const;
     48    unsigned long getCueIndex(TextTrackCue*) const;
     49
    4850    TextTrackCue* item(unsigned index) const;
    4951    TextTrackCue* getCueById(const String&) const;
     
    5860    bool add(PassRefPtr<TextTrackCue>, size_t, size_t);
    5961    void clear();
    60    
     62    void invalidateCueIndexes(size_t);
     63
    6164    Vector<RefPtr<TextTrackCue> > m_list;
    6265    RefPtr<TextTrackCueList> m_activeCues;
    63    
     66
    6467};
    6568
  • trunk/Source/WebCore/html/track/TextTrackList.cpp

    r102471 r108241  
    5656}
    5757
     58unsigned TextTrackList::getTrackIndex(TextTrack *textTrack)
     59{
     60    if (textTrack->trackType() == TextTrack::TrackElement)
     61        return static_cast<LoadableTextTrack*>(textTrack)->trackElementIndex();
     62
     63    if (textTrack->trackType() == TextTrack::AddTrack)
     64        return m_elementTracks.size() + m_addTrackTracks.find(textTrack);
     65
     66    ASSERT_NOT_REACHED();
     67
     68    return -1;
     69}
     70
    5871TextTrack* TextTrackList::item(unsigned index)
    5972{
     
    7891{
    7992    RefPtr<TextTrack> track = prpTrack;
    80    
     93
    8194    if (track->trackType() == TextTrack::AddTrack)
    8295        m_addTrackTracks.append(track);
     
    8598        size_t index = static_cast<LoadableTextTrack*>(track.get())->trackElementIndex();
    8699        m_elementTracks.insert(index, track);
     100
     101        // Invalidate the cached index for all the following tracks.
     102        for (size_t i = index; i < m_elementTracks.size(); ++i)
     103            m_elementTracks[i]->invalidateTrackIndex();
     104
     105        for (size_t i = 0; i < m_addTrackTracks.size(); ++i)
     106            m_addTrackTracks[i]->invalidateTrackIndex();
     107
    87108    } else
    88109        ASSERT_NOT_REACHED();
  • trunk/Source/WebCore/html/track/TextTrackList.h

    r102471 r108241  
    5252
    5353    unsigned length() const;
     54    unsigned getTrackIndex(TextTrack*);
     55
    5456    TextTrack* item(unsigned index);
    5557    void append(PassRefPtr<TextTrack>);
Note: See TracChangeset for help on using the changeset viewer.