/
time_ranges_utils.js
163 lines (145 loc) · 4.33 KB
/
time_ranges_utils.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/*! @license
* Shaka Player
* Copyright 2016 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
goog.provide('shaka.media.TimeRangesUtils');
/**
* @summary A set of utility functions for dealing with TimeRanges objects.
*/
shaka.media.TimeRangesUtils = class {
/**
* Gets the first timestamp in the buffer.
*
* @param {TimeRanges} b
* @return {?number} The first buffered timestamp, in seconds, if |buffered|
* is non-empty; otherwise, return null.
*/
static bufferStart(b) {
if (!b) {
return null;
}
// Workaround Safari bug: https://bit.ly/2trx6O8
if (b.length == 1 && b.end(0) - b.start(0) < 1e-6) {
return null;
}
// Workaround Edge bug: https://bit.ly/2JYLPeB
if (b.length == 1 && b.start(0) < 0) {
return 0;
}
return b.length ? b.start(0) : null;
}
/**
* Gets the last timestamp in the buffer.
*
* @param {TimeRanges} b
* @return {?number} The last buffered timestamp, in seconds, if |buffered|
* is non-empty; otherwise, return null.
*/
static bufferEnd(b) {
if (!b) {
return null;
}
// Workaround Safari bug: https://bit.ly/2trx6O8
if (b.length == 1 && b.end(0) - b.start(0) < 1e-6) {
return null;
}
return b.length ? b.end(b.length - 1) : null;
}
/**
* Determines if the given time is inside a buffered range. This includes
* gaps, meaning that if the playhead is in a gap, it is considered buffered.
* If there is a small gap between the playhead and buffer start, consider it
* as buffered.
*
* @param {TimeRanges} b
* @param {number} time Playhead time
* @param {number=} smallGapLimit Set in configuration
* @return {boolean}
*/
static isBuffered(b, time, smallGapLimit = 0) {
if (!b || !b.length) {
return false;
}
// Workaround Safari bug: https://bit.ly/2trx6O8
if (b.length == 1 && b.end(0) - b.start(0) < 1e-6) {
return false;
}
if (time > b.end(b.length - 1)) {
return false;
}
// Push the time forward by the gap limit so that it is more likely to be in
// the range.
return (time + smallGapLimit >= b.start(0));
}
/**
* Computes how far ahead of the given timestamp is buffered. To provide
* smooth playback while jumping gaps, we don't include the gaps when
* calculating this.
* This only includes the amount of content that is buffered.
*
* @param {TimeRanges} b
* @param {number} time
* @return {number} The number of seconds buffered, in seconds, ahead of the
* given time.
*/
static bufferedAheadOf(b, time) {
if (!b || !b.length) {
return 0;
}
// Workaround Safari bug: https://bit.ly/2trx6O8
if (b.length == 1 && b.end(0) - b.start(0) < 1e-6) {
return 0;
}
// We calculate the buffered amount by ONLY accounting for the content
// buffered (i.e. we ignore the times of the gaps). We also buffer through
// all gaps.
// Therefore, we start at the end and add up all buffers until |time|.
let result = 0;
for (const {start, end} of shaka.media.TimeRangesUtils.getBufferedInfo(b)) {
if (end > time) {
result += end - Math.max(start, time);
}
}
return result;
}
/**
* Determines if the given time is inside a gap between buffered ranges. If
* it is, this returns the index of the buffer that is *ahead* of the gap.
*
* @param {TimeRanges} b
* @param {number} time
* @param {number} threshold
* @return {?number} The index of the buffer after the gap, or null if not in
* a gap.
*/
static getGapIndex(b, time, threshold) {
const TimeRangesUtils = shaka.media.TimeRangesUtils;
if (!b || !b.length) {
return null;
}
// Workaround Safari bug: https://bit.ly/2trx6O8
if (b.length == 1 && b.end(0) - b.start(0) < 1e-6) {
return null;
}
const idx = TimeRangesUtils.getBufferedInfo(b).findIndex((item, i, arr) => {
return item.start > time &&
(i == 0 || arr[i - 1].end - time <= threshold);
});
return idx >= 0 ? idx : null;
}
/**
* @param {TimeRanges} b
* @return {!Array.<shaka.extern.BufferedRange>}
*/
static getBufferedInfo(b) {
if (!b) {
return [];
}
const ret = [];
for (let i = 0; i < b.length; i++) {
ret.push({start: b.start(i), end: b.end(i)});
}
return ret;
}
};