progress
http://www.w3.org/TR/progress-events/
http://www.w3.org/TR/XMLHttpRequest/
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest
function makeXHR(buf, url, start, end, init_ref, is_init, is_index) {
dlog(3, "leosu add ....... makeXHR");
var xhr = new XMLHttpRequest();
var range = mkrange(start, end);
var useArg = !!/youtube.com/.exec(url)
if (range && useArg) {
url = url.replace(/&range=[^&]*/, '');
url += '&range=' + range.substring(6);
}
xhr.open("GET", url);
xhr.responseType = 'arraybuffer';
xhr.startByte = start;
if (range != null && !useArg) xhr.setRequestHeader('Range', range);
xhr.addEventListener('load', onXHRLoad);
if (url == null) throw "Null URL";
buf.url = url;
xhr.buf = buf;
xhr.init = init_ref;
xhr.is_init = is_init;
xhr.is_index = is_index;
buf.xhr = xhr;
xhr.lastTime = null;
xhr.lastSize = null;
xhr.addEventListener('progress', onXHRProgress);
xhr.send();
dlog(2, 'Sent XHR: url=' + url + ', range=' + range + 'start=' + start + 'end= ' + end);
return xhr;
}
function onXHRLoad(evt) {
dlog(3, "leosu add ....... onXHRLoad");
var xhr = evt.target;
var buf = xhr.buf;
buf.xhr = null;
var vid = buf.video;
if (xhr.readyState != xhr.DONE) return;
if (xhr.status >= 300) {
log('XHR failure, status=' + xhr.status);
throw 'TODO: retry XHRs on failure';
}
if (xhr.is_init) {
xhr.init.value = new Uint8Array(xhr.response);
}
if (xhr.is_index) {
var index = new player.dash.SegmentIndex();
buf.reps[buf.currentRep].index = index;
if (buf.mime.indexOf('mp4') >= 0) {
index.parseSidx(xhr.response, xhr.startByte);
} else {
index.parseWebM(xhr.init.value.buffer, xhr.response);
}
// We need the index before we append the init.
if (buf.last_init == null) appendInit(buf, xhr.init);
}
if (xhr.is_init || xhr.is_index) {
return;
}
if (buf.last_init !== xhr.init) {
appendInit(buf, xhr.init);
}
queueAppend(buf, xhr.response);
buf.segIdx++;
if (buf.segIdx >= buf.reps[buf.currentRep].index.getCount()) {
buf.active = false;
}
if (xhr.expected_time != null && !buf.appendBuffer) {
// The expected time is the start time of the first buffer in this sequence.
// This check ensures that media data append time is (roughly) reflected in
// the buffered range.
range = findRangeForPlaybackTime(buf, xhr.expected_time);
if (range == null ||
!(range.start <= xhr.expected_time && range.end >= xhr.expected_time)) {
log('Media data expected time not reflected in updated buffer range. ' +
'MSE implementation bug?');
if (range == null) {
dlog(2, 'Reason: range is null');
} else {
dlog(2, 'Reason: expected time ' + xhr.expected_time + ' not in (' +
range.start + ', ' + range.end + ')');
}
}
}
}
function onXHRProgress(evt) {
dlog(3, "leosu add ....... onXHRProgress");
var xhr = evt.target;
if (xhr.lastTime != null && evt.timeStamp != xhr.lastTime) {
var bw = 8000 * (evt.loaded - xhr.lastSize) / (evt.timeStamp - xhr.lastTime);
globalSlowBandwidth = kSlowEWMACoeff * globalSlowBandwidth + (1 - kSlowEWMACoeff) * bw;
globalFastBandwidth = kFastEWMACoeff * globalFastBandwidth + (1 - kFastEWMACoeff) * bw;
}
xhr.lastTime = evt.timeStamp;
xhr.lastSize = evt.loaded;
}
4 Interface XMLHttpRequest
[NoInterfaceObject] interface XMLHttpRequestEventTarget : EventTarget { // event handlers attribute EventHandler onloadstart; attribute EventHandler onprogress; attribute EventHandler onabort; attribute EventHandler onerror; attribute EventHandler onload; attribute EventHandler ontimeout; attribute EventHandler onloadend; }; interface XMLHttpRequestUpload : XMLHttpRequestEventTarget { }; enum XMLHttpRequestResponseType { "", "arraybuffer", "blob", "document", "json", "text" }; [Constructor] interface XMLHttpRequest : XMLHttpRequestEventTarget { // event handler attribute EventHandler onreadystatechange; // states const unsigned short UNSENT = 0; const unsigned short OPENED = 1; const unsigned short HEADERS_RECEIVED = 2; const unsigned short LOADING = 3; const unsigned short DONE = 4; readonly attribute unsigned short readyState; // request void open(ByteString method, [EnsureUTF16] DOMString url); void open(ByteString method, [EnsureUTF16] DOMString url, boolean async, optional [EnsureUTF16] DOMString? username = null, optional [EnsureUTF16] DOMString? password = null); void setRequestHeader(ByteString header, ByteString value); attribute unsigned long timeout; attribute boolean withCredentials; readonly attribute XMLHttpRequestUpload upload; void send(optional (ArrayBufferView or Blob or Document or [EnsureUTF16] DOMString or FormData)? data = null); void abort(); // response readonly attribute unsigned short status; readonly attribute ByteString statusText; ByteString? getResponseHeader(ByteString header); ByteString getAllResponseHeaders(); void overrideMimeType(DOMString mime); attribute XMLHttpRequestResponseType responseType; readonly attribute any response; readonly attribute DOMString responseText; readonly attribute Document? responseXML; };
Each XMLHttpRequest
object has a unique, associated XMLHttpRequestUpload
object.
4.3 Suggested names for events using the ProgressEvent
interface
This section is non-normative.
The suggested type
attribute values for use with events using the ProgressEvent
interface are summarized in the table below. Specification editors are free to tune the details to their specific scenarios, though are strongly encouraged to discuss their usage with the W3C WebApps Working Group on public-webapps@w3.org to ensure input from people familiar with the subject.
type attribute value | Description | Times | When |
---|---|---|---|
loadstart | Progress has begun. | Once. | First. |
progress | In progress. | Zero or more. | After loadstart has been dispatched. |
error | Progression failed. | Zero or once. | After the last progress has been dispatched, or after loadstart has been dispatched if progress has not been dispatched. |
abort | Progression is terminated. | Zero or once. | |
load | Progression is successful. | Zero or once. | |
loadend | Progress has stopped. | Once. | After one of error , abort , or load has been dispatched. |
The error
, abort
, and load
event types are mutually exclusive.
Throughout the web platform the error
, abort
, and load
event types have their bubbles
and cancelable
attributes initialized to false, so it is suggested that for consistency all events using the ProgressEvent
interface do the same.