Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(189)

Side by Side Diff: sky/engine/core/html/MediaFragmentURIParser.cpp

Issue 689373003: Remove most of the media stack. (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sky/engine/core/html/MediaFragmentURIParser.h ('k') | sky/engine/core/html/MediaKeyError.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27 #include "core/html/MediaFragmentURIParser.h"
28
29 #include "platform/graphics/media/MediaPlayer.h"
30 #include "wtf/text/CString.h"
31 #include "wtf/text/StringBuilder.h"
32 #include "wtf/text/WTFString.h"
33
34 namespace blink {
35
36 const int secondsPerHour = 3600;
37 const int secondsPerMinute = 60;
38 const unsigned nptIdentiferLength = 4; // "npt:"
39
40 static String collectDigits(const LChar* input, unsigned length, unsigned& posit ion)
41 {
42 StringBuilder digits;
43
44 // http://www.ietf.org/rfc/rfc2326.txt
45 // DIGIT ; any positive number
46 while (position < length && isASCIIDigit(input[position]))
47 digits.append(input[position++]);
48 return digits.toString();
49 }
50
51 static String collectFraction(const LChar* input, unsigned length, unsigned& pos ition)
52 {
53 StringBuilder digits;
54
55 // http://www.ietf.org/rfc/rfc2326.txt
56 // [ "." *DIGIT ]
57 if (input[position] != '.')
58 return String();
59
60 digits.append(input[position++]);
61 while (position < length && isASCIIDigit(input[position]))
62 digits.append(input[position++]);
63 return digits.toString();
64 }
65
66 double MediaFragmentURIParser::invalidTimeValue()
67 {
68 return MediaPlayer::invalidTime();
69 }
70
71 MediaFragmentURIParser::MediaFragmentURIParser(const KURL& url)
72 : m_url(url)
73 , m_timeFormat(None)
74 , m_startTime(MediaPlayer::invalidTime())
75 , m_endTime(MediaPlayer::invalidTime())
76 {
77 }
78
79 double MediaFragmentURIParser::startTime()
80 {
81 if (!m_url.isValid())
82 return MediaPlayer::invalidTime();
83 if (m_timeFormat == None)
84 parseTimeFragment();
85 return m_startTime;
86 }
87
88 double MediaFragmentURIParser::endTime()
89 {
90 if (!m_url.isValid())
91 return MediaPlayer::invalidTime();
92 if (m_timeFormat == None)
93 parseTimeFragment();
94 return m_endTime;
95 }
96
97 void MediaFragmentURIParser::parseFragments()
98 {
99 if (!m_url.hasFragmentIdentifier())
100 return;
101 String fragmentString = m_url.fragmentIdentifier();
102 if (fragmentString.isEmpty())
103 return;
104
105 unsigned offset = 0;
106 unsigned end = fragmentString.length();
107 while (offset < end) {
108 // http://www.w3.org/2008/WebVideo/Fragments/WD-media-fragments-spec/#pr ocessing-name-value-components
109 // 1. Parse the octet string according to the namevalues syntax, yieldin g a list of
110 // name-value pairs, where name and value are both octet string. In a ccordance
111 // with RFC 3986, the name and value components must be parsed and se parated before
112 // percent-encoded octets are decoded.
113 size_t parameterStart = offset;
114 size_t parameterEnd = fragmentString.find('&', offset);
115 if (parameterEnd == kNotFound)
116 parameterEnd = end;
117
118 size_t equalOffset = fragmentString.find('=', offset);
119 if (equalOffset == kNotFound || equalOffset > parameterEnd) {
120 offset = parameterEnd + 1;
121 continue;
122 }
123
124 // 2. For each name-value pair:
125 // a. Decode percent-encoded octets in name and value as defined by RFC 3986. If either
126 // name or value are not valid percent-encoded strings, then remove the name-value pair
127 // from the list.
128 String name = decodeURLEscapeSequences(fragmentString.substring(paramete rStart, equalOffset - parameterStart));
129 String value;
130 if (equalOffset != parameterEnd)
131 value = decodeURLEscapeSequences(fragmentString.substring(equalOffse t + 1, parameterEnd - equalOffset - 1));
132
133 // b. Convert name and value to Unicode strings by interpreting them as UTF-8. If either
134 // name or value are not valid UTF-8 strings, then remove the name-v alue pair from the list.
135 bool validUTF8 = true;
136 if (!name.isEmpty()) {
137 name = name.utf8(StrictUTF8Conversion).data();
138 validUTF8 = !name.isEmpty();
139 }
140 if (validUTF8 && !value.isEmpty()) {
141 value = value.utf8(StrictUTF8Conversion).data();
142 validUTF8 = !value.isEmpty();
143 }
144
145 if (validUTF8)
146 m_fragments.append(std::make_pair(name, value));
147
148 offset = parameterEnd + 1;
149 }
150 }
151
152 void MediaFragmentURIParser::parseTimeFragment()
153 {
154 ASSERT(m_timeFormat == None);
155
156 if (m_fragments.isEmpty())
157 parseFragments();
158
159 m_timeFormat = Invalid;
160
161 for (unsigned i = 0; i < m_fragments.size(); ++i) {
162 pair<String, String>& fragment = m_fragments[i];
163
164 ASSERT(fragment.first.is8Bit());
165 ASSERT(fragment.second.is8Bit());
166
167 // http://www.w3.org/2008/WebVideo/Fragments/WD-media-fragments-spec/#na ming-time
168 // Temporal clipping is denoted by the name t, and specified as an inter val with a begin
169 // time and an end time
170 if (fragment.first != "t")
171 continue;
172
173 // http://www.w3.org/2008/WebVideo/Fragments/WD-media-fragments-spec/#np t-time
174 // Temporal clipping can be specified either as Normal Play Time (npt) R FC 2326, as SMPTE timecodes,
175 // SMPTE, or as real-world clock time (clock) RFC 2326. Begin and end ti mes are always specified
176 // in the same format. The format is specified by name, followed by a co lon (:), with npt: being
177 // the default.
178
179 double start = MediaPlayer::invalidTime();
180 double end = MediaPlayer::invalidTime();
181 if (parseNPTFragment(fragment.second.characters8(), fragment.second.leng th(), start, end)) {
182 m_startTime = start;
183 m_endTime = end;
184 m_timeFormat = NormalPlayTime;
185
186 // Although we have a valid fragment, don't return yet because when a fragment dimensions
187 // occurs multiple times, only the last occurrence of that dimension is used:
188 // http://www.w3.org/2008/WebVideo/Fragments/WD-media-fragments-spec /#error-uri-general
189 // Multiple occurrences of the same dimension: only the last valid o ccurrence of a dimension
190 // (e.g., t=10 in #t=2&t=10) is interpreted, all previous occurrence s (valid or invalid)
191 // SHOULD be ignored by the UA.
192 }
193 }
194 m_fragments.clear();
195 }
196
197 bool MediaFragmentURIParser::parseNPTFragment(const LChar* timeString, unsigned length, double& startTime, double& endTime)
198 {
199 unsigned offset = 0;
200 if (length >= nptIdentiferLength && timeString[0] == 'n' && timeString[1] == 'p' && timeString[2] == 't' && timeString[3] == ':')
201 offset += nptIdentiferLength;
202
203 if (offset == length)
204 return false;
205
206 // http://www.w3.org/2008/WebVideo/Fragments/WD-media-fragments-spec/#naming -time
207 // If a single number only is given, this corresponds to the begin time exce pt if it is preceded
208 // by a comma that would in this case indicate the end time.
209 if (timeString[offset] == ',')
210 startTime = 0;
211 else {
212 if (!parseNPTTime(timeString, length, offset, startTime))
213 return false;
214 }
215
216 if (offset == length)
217 return true;
218
219 if (timeString[offset] != ',')
220 return false;
221 if (++offset == length)
222 return false;
223
224 if (!parseNPTTime(timeString, length, offset, endTime))
225 return false;
226
227 if (offset != length)
228 return false;
229
230 if (startTime >= endTime)
231 return false;
232
233 return true;
234 }
235
236 bool MediaFragmentURIParser::parseNPTTime(const LChar* timeString, unsigned leng th, unsigned& offset, double& time)
237 {
238 enum Mode { minutes, hours };
239 Mode mode = minutes;
240
241 if (offset >= length || !isASCIIDigit(timeString[offset]))
242 return false;
243
244 // http://www.w3.org/2008/WebVideo/Fragments/WD-media-fragments-spec/#npttim edef
245 // Normal Play Time can either be specified as seconds, with an optional
246 // fractional part to indicate miliseconds, or as colon-separated hours,
247 // minutes and seconds (again with an optional fraction). Minutes and
248 // seconds must be specified as exactly two digits, hours and fractional
249 // seconds can be any number of digits. The hours, minutes and seconds
250 // specification for NPT is a convenience only, it does not signal frame
251 // accuracy. The specification of the "npt:" identifier is optional since
252 // NPT is the default time scheme. This specification builds on the RTSP
253 // specification of NPT RFC 2326.
254 //
255 // ; defined in RFC 2326
256 // npt-sec = 1*DIGIT [ "." *DIGIT ] ; definitions taken
257 // npt-hhmmss = npt-hh ":" npt-mm ":" npt-ss [ "." *DIGIT] ; from RFC 232 6
258 // npt-mmss = npt-mm ":" npt-ss [ "." *DIGIT]
259 // npt-hh = 1*DIGIT ; any positive number
260 // npt-mm = 2DIGIT ; 0-59
261 // npt-ss = 2DIGIT ; 0-59
262
263 String digits1 = collectDigits(timeString, length, offset);
264 int value1 = digits1.toInt();
265 if (offset >= length || timeString[offset] == ',') {
266 time = value1;
267 return true;
268 }
269
270 double fraction = 0;
271 if (timeString[offset] == '.') {
272 if (offset == length)
273 return true;
274 String digits = collectFraction(timeString, length, offset);
275 fraction = digits.toDouble();
276 time = value1 + fraction;
277 return true;
278 }
279
280 if (digits1.length() < 2)
281 return false;
282 if (digits1.length() > 2)
283 mode = hours;
284
285 // Collect the next sequence of 0-9 after ':'
286 if (offset >= length || timeString[offset++] != ':')
287 return false;
288 if (offset >= length || !isASCIIDigit(timeString[(offset)]))
289 return false;
290 String digits2 = collectDigits(timeString, length, offset);
291 int value2 = digits2.toInt();
292 if (digits2.length() != 2)
293 return false;
294
295 // Detect whether this timestamp includes hours.
296 int value3;
297 if (mode == hours || (offset < length && timeString[offset] == ':')) {
298 if (offset >= length || timeString[offset++] != ':')
299 return false;
300 if (offset >= length || !isASCIIDigit(timeString[offset]))
301 return false;
302 String digits3 = collectDigits(timeString, length, offset);
303 if (digits3.length() != 2)
304 return false;
305 value3 = digits3.toInt();
306 } else {
307 value3 = value2;
308 value2 = value1;
309 value1 = 0;
310 }
311
312 if (offset < length && timeString[offset] == '.')
313 fraction = collectFraction(timeString, length, offset).toDouble();
314
315 time = (value1 * secondsPerHour) + (value2 * secondsPerMinute) + value3 + fr action;
316 return true;
317 }
318
319 }
OLDNEW
« no previous file with comments | « sky/engine/core/html/MediaFragmentURIParser.h ('k') | sky/engine/core/html/MediaKeyError.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698