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 |