Chromium Code Reviews| 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(TextTrackList* textTracks, cons t Configuration& configuration) | |
| 61 : m_textTracks(textTracks) | |
| 62 , m_configuration(configuration) | |
| 63 { | |
| 64 ASSERT(textTracks); | |
| 65 } | |
| 66 | |
| 67 void AutomaticTrackSelection::performAutomaticTextTrackSelection(const TrackGrou p& group) | |
| 68 { | |
| 69 ASSERT(group.tracks.size()); | |
| 70 | |
| 71 WTF_LOG(Media, "TrackSelection::configureTextTrackGroup(%p, %d)", this, grou p.kind); | |
|
philipj_slow
2015/02/11 03:00:24
All the bots seem to be upset about this.
fs
2015/02/11 10:02:26
Yes, this is unpleasant... Some components of this
| |
| 72 | |
| 73 // First, find the track in the group that should be enabled (if any). | |
| 74 WillBeHeapVector<RefPtrWillBeMember<TextTrack>> currentlyEnabledTracks; | |
| 75 RefPtrWillBeRawPtr<TextTrack> trackToEnable = nullptr; | |
| 76 RefPtrWillBeRawPtr<TextTrack> defaultTrack = nullptr; | |
| 77 RefPtrWillBeRawPtr<TextTrack> fallbackTrack = nullptr; | |
| 78 int highestTrackScore = 0; | |
| 79 for (size_t i = 0; i < group.tracks.size(); ++i) { | |
| 80 RefPtrWillBeRawPtr<TextTrack> textTrack = group.tracks[i]; | |
| 81 | |
| 82 if (m_configuration.disableCurrentlyEnabledTracks && textTrack->mode() = = TextTrack::showingKeyword()) | |
| 83 currentlyEnabledTracks.append(textTrack); | |
| 84 | |
| 85 int trackScore = textTrackSelectionScore(*textTrack); | |
| 86 if (trackScore) { | |
| 87 // * If the text track kind is { [subtitles or captions] [descriptio ns] } and the user has indicated an interest in having a | |
| 88 // track with this text track kind, text track language, and text tr ack label enabled, and there is no | |
| 89 // other text track in the media element's list of text tracks with a text track kind of either subtitles | |
| 90 // or captions whose text track mode is showing | |
| 91 // ... | |
| 92 // * If the text track kind is chapters and the text track language is one that the user agent has reason | |
| 93 // to believe is appropriate for the user, and there is no other tex t track in the media element's list of | |
| 94 // text tracks with a text track kind of chapters whose text track m ode is showing | |
| 95 // Let the text track mode be showing. | |
| 96 if (trackScore > highestTrackScore) { | |
| 97 highestTrackScore = trackScore; | |
| 98 trackToEnable = textTrack; | |
| 99 } | |
| 100 | |
| 101 if (!defaultTrack && textTrack->isDefault()) | |
| 102 defaultTrack = textTrack; | |
| 103 if (!defaultTrack && !fallbackTrack) | |
| 104 fallbackTrack = textTrack; | |
| 105 } else if (!group.visibleTrack && !defaultTrack && textTrack->isDefault( )) { | |
| 106 // * If the track element has a default attribute specified, and the re is no other text track in the media | |
| 107 // element's list of text tracks whose text track mode is showing or showing by default | |
| 108 // Let the text track mode be showing by default. | |
| 109 defaultTrack = textTrack; | |
| 110 } | |
| 111 } | |
| 112 | |
| 113 if (!trackToEnable && defaultTrack) | |
| 114 trackToEnable = defaultTrack; | |
| 115 | |
| 116 // If no track matches the user's preferred language and non was marked 'def ault', enable the first track | |
| 117 // because the user has explicitly stated a preference for this kind of trac k. | |
| 118 if (!fallbackTrack && m_configuration.forceEnableSubtitleOrCaptionTrack && g roup.kind == TrackGroup::CaptionsAndSubtitles) | |
| 119 fallbackTrack = group.tracks[0]; | |
| 120 | |
| 121 if (!trackToEnable && fallbackTrack) | |
| 122 trackToEnable = fallbackTrack; | |
| 123 | |
| 124 if (currentlyEnabledTracks.size()) { | |
| 125 for (size_t i = 0; i < currentlyEnabledTracks.size(); ++i) { | |
| 126 RefPtrWillBeRawPtr<TextTrack> textTrack = currentlyEnabledTracks[i]; | |
| 127 if (textTrack != trackToEnable) | |
| 128 textTrack->setMode(TextTrack::disabledKeyword()); | |
| 129 } | |
| 130 } | |
| 131 | |
| 132 if (trackToEnable) | |
| 133 trackToEnable->setMode(TextTrack::showingKeyword()); | |
| 134 } | |
| 135 | |
| 136 void AutomaticTrackSelection::enableDefaultMetadataTextTracks(const TrackGroup& group) | |
| 137 { | |
| 138 ASSERT(group.tracks.size()); | |
| 139 | |
| 140 // https://html.spec.whatwg.org/multipage/embedded-content.html#honor-user-p references-for-automatic-text-track-selection | |
| 141 | |
| 142 // 4. If there are any text tracks in the media element's list of text | |
| 143 // tracks whose text track kind is metadata that correspond to track | |
| 144 // elements with a default attribute set whose text track mode is set to | |
| 145 // disabled, then set the text track mode of all such tracks to hidden | |
| 146 for (auto& textTrack : group.tracks) { | |
| 147 if (textTrack->mode() != TextTrack::disabledKeyword()) | |
| 148 continue; | |
| 149 if (!textTrack->isDefault()) | |
| 150 continue; | |
| 151 textTrack->setMode(TextTrack::hiddenKeyword()); | |
| 152 } | |
| 153 } | |
| 154 | |
| 155 void AutomaticTrackSelection::perform() | |
| 156 { | |
| 157 TrackGroup captionAndSubtitleTracks(TrackGroup::CaptionsAndSubtitles); | |
| 158 TrackGroup descriptionTracks(TrackGroup::Description); | |
| 159 TrackGroup chapterTracks(TrackGroup::Chapter); | |
| 160 TrackGroup metadataTracks(TrackGroup::Metadata); | |
| 161 | |
| 162 for (size_t i = 0; i < m_textTracks->length(); ++i) { | |
| 163 RefPtrWillBeRawPtr<TextTrack> textTrack = m_textTracks->item(i); | |
| 164 if (!textTrack) | |
| 165 continue; | |
| 166 | |
| 167 String kind = textTrack->kind(); | |
| 168 TrackGroup* currentGroup; | |
| 169 if (kind == TextTrack::subtitlesKeyword() || kind == TextTrack::captions Keyword()) { | |
| 170 currentGroup = &captionAndSubtitleTracks; | |
| 171 } else if (kind == TextTrack::descriptionsKeyword()) { | |
| 172 currentGroup = &descriptionTracks; | |
| 173 } else if (kind == TextTrack::chaptersKeyword()) { | |
| 174 currentGroup = &chapterTracks; | |
| 175 } else { | |
| 176 ASSERT(kind == TextTrack::metadataKeyword()); | |
| 177 currentGroup = &metadataTracks; | |
| 178 } | |
| 179 | |
| 180 if (!currentGroup->visibleTrack && textTrack->mode() == TextTrack::showi ngKeyword()) | |
| 181 currentGroup->visibleTrack = textTrack; | |
| 182 if (!currentGroup->defaultTrack && textTrack->isDefault()) | |
| 183 currentGroup->defaultTrack = textTrack; | |
| 184 | |
| 185 // Do not add this track to the group if it has already been automatical ly configured | |
| 186 // as we only want to perform selection once per track so that adding an other track | |
| 187 // after the initial configuration doesn't reconfigure every track - onl y those that | |
| 188 // should be changed by the new addition. For example all metadata track s are | |
| 189 // disabled by default, and we don't want a track that has been enabled by script | |
| 190 // to be disabled automatically when a new metadata track is added later . | |
| 191 if (textTrack->hasBeenConfigured()) | |
| 192 continue; | |
| 193 | |
| 194 if (textTrack->language().length()) | |
| 195 currentGroup->hasSrcLang = true; | |
| 196 currentGroup->tracks.append(textTrack); | |
| 197 } | |
| 198 | |
| 199 if (captionAndSubtitleTracks.tracks.size()) | |
| 200 performAutomaticTextTrackSelection(captionAndSubtitleTracks); | |
| 201 if (descriptionTracks.tracks.size()) | |
| 202 performAutomaticTextTrackSelection(descriptionTracks); | |
| 203 if (chapterTracks.tracks.size()) | |
| 204 performAutomaticTextTrackSelection(chapterTracks); | |
| 205 if (metadataTracks.tracks.size()) | |
| 206 enableDefaultMetadataTextTracks(metadataTracks); | |
| 207 } | |
| 208 | |
| 209 } // namespace blink | |
| OLD | NEW |