| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 
|  | 2 // Use of this source code is governed by a BSD-style license that can be | 
|  | 3 // found in the LICENSE file. | 
|  | 4 | 
|  | 5 #include "config.h" | 
|  | 6 #include "core/html/track/AutomaticTrackSelection.h" | 
|  | 7 | 
|  | 8 #include "core/html/track/TextTrack.h" | 
|  | 9 #include "core/html/track/TextTrackList.h" | 
|  | 10 #include "platform/Language.h" | 
|  | 11 | 
|  | 12 namespace blink { | 
|  | 13 | 
|  | 14 class TrackGroup { | 
|  | 15     STACK_ALLOCATED(); | 
|  | 16 public: | 
|  | 17     enum GroupKind { | 
|  | 18         CaptionsAndSubtitles, | 
|  | 19         Description, | 
|  | 20         Chapter, | 
|  | 21         Metadata | 
|  | 22     }; | 
|  | 23 | 
|  | 24     explicit TrackGroup(GroupKind kind) | 
|  | 25         : visibleTrack(nullptr) | 
|  | 26         , defaultTrack(nullptr) | 
|  | 27         , kind(kind) | 
|  | 28         , hasSrcLang(false) | 
|  | 29     { | 
|  | 30     } | 
|  | 31 | 
|  | 32     WillBeHeapVector<RefPtrWillBeMember<TextTrack>> tracks; | 
|  | 33     RefPtrWillBeMember<TextTrack> visibleTrack; | 
|  | 34     RefPtrWillBeMember<TextTrack> defaultTrack; | 
|  | 35     GroupKind kind; | 
|  | 36     bool hasSrcLang; | 
|  | 37 }; | 
|  | 38 | 
|  | 39 static int textTrackLanguageSelectionScore(const TextTrack& track) | 
|  | 40 { | 
|  | 41     if (track.language().isEmpty()) | 
|  | 42         return 0; | 
|  | 43 | 
|  | 44     Vector<AtomicString> languages = userPreferredLanguages(); | 
|  | 45     size_t languageMatchIndex = indexOfBestMatchingLanguageInList(track.language
     (), languages); | 
|  | 46     if (languageMatchIndex >= languages.size()) | 
|  | 47         return 0; | 
|  | 48 | 
|  | 49     return languages.size() - languageMatchIndex; | 
|  | 50 } | 
|  | 51 | 
|  | 52 static int textTrackSelectionScore(const TextTrack& track) | 
|  | 53 { | 
|  | 54     if (track.kind() != TextTrack::captionsKeyword() && track.kind() != TextTrac
     k::subtitlesKeyword()) | 
|  | 55         return 0; | 
|  | 56 | 
|  | 57     return textTrackLanguageSelectionScore(track); | 
|  | 58 } | 
|  | 59 | 
|  | 60 AutomaticTrackSelection::AutomaticTrackSelection(const Configuration& configurat
     ion) | 
|  | 61     : m_configuration(configuration) | 
|  | 62 { | 
|  | 63 } | 
|  | 64 | 
|  | 65 void AutomaticTrackSelection::performAutomaticTextTrackSelection(const TrackGrou
     p& group) | 
|  | 66 { | 
|  | 67     ASSERT(group.tracks.size()); | 
|  | 68 | 
|  | 69     // First, find the track in the group that should be enabled (if any). | 
|  | 70     WillBeHeapVector<RefPtrWillBeMember<TextTrack>> currentlyEnabledTracks; | 
|  | 71     RefPtrWillBeRawPtr<TextTrack> trackToEnable = nullptr; | 
|  | 72     RefPtrWillBeRawPtr<TextTrack> defaultTrack = nullptr; | 
|  | 73     RefPtrWillBeRawPtr<TextTrack> fallbackTrack = nullptr; | 
|  | 74     int highestTrackScore = 0; | 
|  | 75     for (size_t i = 0; i < group.tracks.size(); ++i) { | 
|  | 76         RefPtrWillBeRawPtr<TextTrack> textTrack = group.tracks[i]; | 
|  | 77 | 
|  | 78         if (m_configuration.disableCurrentlyEnabledTracks && textTrack->mode() =
     = TextTrack::showingKeyword()) | 
|  | 79             currentlyEnabledTracks.append(textTrack); | 
|  | 80 | 
|  | 81         int trackScore = textTrackSelectionScore(*textTrack); | 
|  | 82         if (trackScore) { | 
|  | 83             // * If the text track kind is { [subtitles or captions] [descriptio
     ns] } and the user has indicated an interest in having a | 
|  | 84             // track with this text track kind, text track language, and text tr
     ack label enabled, and there is no | 
|  | 85             // other text track in the media element's list of text tracks with 
     a text track kind of either subtitles | 
|  | 86             // or captions whose text track mode is showing | 
|  | 87             // ... | 
|  | 88             // * If the text track kind is chapters and the text track language 
     is one that the user agent has reason | 
|  | 89             // to believe is appropriate for the user, and there is no other tex
     t track in the media element's list of | 
|  | 90             // text tracks with a text track kind of chapters whose text track m
     ode is showing | 
|  | 91             //    Let the text track mode be showing. | 
|  | 92             if (trackScore > highestTrackScore) { | 
|  | 93                 highestTrackScore = trackScore; | 
|  | 94                 trackToEnable = textTrack; | 
|  | 95             } | 
|  | 96 | 
|  | 97             if (!defaultTrack && textTrack->isDefault()) | 
|  | 98                 defaultTrack = textTrack; | 
|  | 99             if (!defaultTrack && !fallbackTrack) | 
|  | 100                 fallbackTrack = textTrack; | 
|  | 101         } else if (!group.visibleTrack && !defaultTrack && textTrack->isDefault(
     )) { | 
|  | 102             // * If the track element has a default attribute specified, and the
     re is no other text track in the media | 
|  | 103             // element's list of text tracks whose text track mode is showing or
      showing by default | 
|  | 104             //    Let the text track mode be showing by default. | 
|  | 105             defaultTrack = textTrack; | 
|  | 106         } | 
|  | 107     } | 
|  | 108 | 
|  | 109     if (!trackToEnable && defaultTrack) | 
|  | 110         trackToEnable = defaultTrack; | 
|  | 111 | 
|  | 112     // If no track matches the user's preferred language and non was marked 'def
     ault', enable the first track | 
|  | 113     // because the user has explicitly stated a preference for this kind of trac
     k. | 
|  | 114     if (!fallbackTrack && m_configuration.forceEnableSubtitleOrCaptionTrack && g
     roup.kind == TrackGroup::CaptionsAndSubtitles) | 
|  | 115         fallbackTrack = group.tracks[0]; | 
|  | 116 | 
|  | 117     if (!trackToEnable && fallbackTrack) | 
|  | 118         trackToEnable = fallbackTrack; | 
|  | 119 | 
|  | 120     if (currentlyEnabledTracks.size()) { | 
|  | 121         for (size_t i = 0; i < currentlyEnabledTracks.size(); ++i) { | 
|  | 122             RefPtrWillBeRawPtr<TextTrack> textTrack = currentlyEnabledTracks[i]; | 
|  | 123             if (textTrack != trackToEnable) | 
|  | 124                 textTrack->setMode(TextTrack::disabledKeyword()); | 
|  | 125         } | 
|  | 126     } | 
|  | 127 | 
|  | 128     if (trackToEnable) | 
|  | 129         trackToEnable->setMode(TextTrack::showingKeyword()); | 
|  | 130 } | 
|  | 131 | 
|  | 132 void AutomaticTrackSelection::enableDefaultMetadataTextTracks(const TrackGroup& 
     group) | 
|  | 133 { | 
|  | 134     ASSERT(group.tracks.size()); | 
|  | 135 | 
|  | 136     // https://html.spec.whatwg.org/multipage/embedded-content.html#honor-user-p
     references-for-automatic-text-track-selection | 
|  | 137 | 
|  | 138     // 4. If there are any text tracks in the media element's list of text | 
|  | 139     // tracks whose text track kind is metadata that correspond to track | 
|  | 140     // elements with a default attribute set whose text track mode is set to | 
|  | 141     // disabled, then set the text track mode of all such tracks to hidden | 
|  | 142     for (auto& textTrack : group.tracks) { | 
|  | 143         if (textTrack->mode() != TextTrack::disabledKeyword()) | 
|  | 144             continue; | 
|  | 145         if (!textTrack->isDefault()) | 
|  | 146             continue; | 
|  | 147         textTrack->setMode(TextTrack::hiddenKeyword()); | 
|  | 148     } | 
|  | 149 } | 
|  | 150 | 
|  | 151 void AutomaticTrackSelection::perform(TextTrackList& textTracks) | 
|  | 152 { | 
|  | 153     TrackGroup captionAndSubtitleTracks(TrackGroup::CaptionsAndSubtitles); | 
|  | 154     TrackGroup descriptionTracks(TrackGroup::Description); | 
|  | 155     TrackGroup chapterTracks(TrackGroup::Chapter); | 
|  | 156     TrackGroup metadataTracks(TrackGroup::Metadata); | 
|  | 157 | 
|  | 158     for (size_t i = 0; i < textTracks.length(); ++i) { | 
|  | 159         RefPtrWillBeRawPtr<TextTrack> textTrack = textTracks.item(i); | 
|  | 160         if (!textTrack) | 
|  | 161             continue; | 
|  | 162 | 
|  | 163         String kind = textTrack->kind(); | 
|  | 164         TrackGroup* currentGroup; | 
|  | 165         if (kind == TextTrack::subtitlesKeyword() || kind == TextTrack::captions
     Keyword()) { | 
|  | 166             currentGroup = &captionAndSubtitleTracks; | 
|  | 167         } else if (kind == TextTrack::descriptionsKeyword()) { | 
|  | 168             currentGroup = &descriptionTracks; | 
|  | 169         } else if (kind == TextTrack::chaptersKeyword()) { | 
|  | 170             currentGroup = &chapterTracks; | 
|  | 171         } else { | 
|  | 172             ASSERT(kind == TextTrack::metadataKeyword()); | 
|  | 173             currentGroup = &metadataTracks; | 
|  | 174         } | 
|  | 175 | 
|  | 176         if (!currentGroup->visibleTrack && textTrack->mode() == TextTrack::showi
     ngKeyword()) | 
|  | 177             currentGroup->visibleTrack = textTrack; | 
|  | 178         if (!currentGroup->defaultTrack && textTrack->isDefault()) | 
|  | 179             currentGroup->defaultTrack = textTrack; | 
|  | 180 | 
|  | 181         // Do not add this track to the group if it has already been automatical
     ly configured | 
|  | 182         // as we only want to perform selection once per track so that adding an
     other track | 
|  | 183         // after the initial configuration doesn't reconfigure every track - onl
     y those that | 
|  | 184         // should be changed by the new addition. For example all metadata track
     s are | 
|  | 185         // disabled by default, and we don't want a track that has been enabled 
     by script | 
|  | 186         // to be disabled automatically when a new metadata track is added later
     . | 
|  | 187         if (textTrack->hasBeenConfigured()) | 
|  | 188             continue; | 
|  | 189 | 
|  | 190         if (textTrack->language().length()) | 
|  | 191             currentGroup->hasSrcLang = true; | 
|  | 192         currentGroup->tracks.append(textTrack); | 
|  | 193     } | 
|  | 194 | 
|  | 195     if (captionAndSubtitleTracks.tracks.size()) | 
|  | 196         performAutomaticTextTrackSelection(captionAndSubtitleTracks); | 
|  | 197     if (descriptionTracks.tracks.size()) | 
|  | 198         performAutomaticTextTrackSelection(descriptionTracks); | 
|  | 199     if (chapterTracks.tracks.size()) | 
|  | 200         performAutomaticTextTrackSelection(chapterTracks); | 
|  | 201     if (metadataTracks.tracks.size()) | 
|  | 202         enableDefaultMetadataTextTracks(metadataTracks); | 
|  | 203 } | 
|  | 204 | 
|  | 205 } // namespace blink | 
| OLD | NEW | 
|---|