Browse Source

fix: mp4 sources that use bigint numbers (#1217)

pull/1233/head
Brandon Casey 4 years ago
committed by GitHub
parent
commit
bfd0ad04fe
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 806
      package-lock.json
  2. 6
      package.json
  3. 51
      src/segment-loader.js
  4. 11
      src/xhr.js
  5. 72
      test/segment-loader.test.js
  6. 18
      test/videojs-http-streaming.test.js
  7. 23
      test/xhr.test.js

806
package-lock.json
File diff suppressed because it is too large
View File

6
package.json

@ -60,8 +60,8 @@
"aes-decrypter": "3.1.2",
"global": "^4.4.0",
"m3u8-parser": "4.7.0",
"mpd-parser": "0.19.2",
"mux.js": "5.14.1",
"mpd-parser": "0.20.0",
"mux.js": "6.0.0",
"video.js": "^6 || ^7"
},
"peerDependencies": {
@ -91,7 +91,7 @@
"videojs-generate-rollup-config": "^6.2.2",
"videojs-generator-verify": "~3.0.1",
"videojs-http-source-selector": "^1.1.6",
"videojs-standard": "^8.0.4"
"videojs-standard": "^9.0.0"
},
"generator-videojs-plugin": {
"version": "7.6.3"

51
src/segment-loader.js

@ -407,19 +407,36 @@ export const shouldWaitForTimelineChange = ({
return false;
};
export const mediaDuration = (audioTimingInfo, videoTimingInfo) => {
const audioDuration =
audioTimingInfo &&
typeof audioTimingInfo.start === 'number' &&
typeof audioTimingInfo.end === 'number' ?
audioTimingInfo.end - audioTimingInfo.start : 0;
const videoDuration =
videoTimingInfo &&
typeof videoTimingInfo.start === 'number' &&
typeof videoTimingInfo.end === 'number' ?
videoTimingInfo.end - videoTimingInfo.start : 0;
return Math.max(audioDuration, videoDuration);
export const mediaDuration = (timingInfos) => {
let maxDuration = 0;
['video', 'audio'].forEach(function(type) {
const typeTimingInfo = timingInfos[`${type}TimingInfo`];
if (!typeTimingInfo) {
return;
}
const {start, end} = typeTimingInfo;
let duration;
if (typeof start === 'bigint' || typeof end === 'bigint') {
duration = window.BigInt(end) - window.BigInt(start);
} else if (typeof start === 'number' && typeof end === 'number') {
duration = end - start;
}
if (typeof duration !== 'undefined' && duration > maxDuration) {
maxDuration = duration;
}
});
// convert back to a number if it is lower than MAX_SAFE_INTEGER
// as we only need BigInt when we are above that.
if (typeof maxDuration === 'bigint' && maxDuration < Number.MAX_SAFE_INTEGER) {
maxDuration = Number(maxDuration);
}
return maxDuration;
};
export const segmentTooLong = ({ segmentDuration, maxDuration }) => {
@ -450,10 +467,10 @@ export const getTroublesomeSegmentDurationMessage = (segmentInfo, sourceType) =>
return null;
}
const segmentDuration = mediaDuration(
segmentInfo.audioTimingInfo,
segmentInfo.videoTimingInfo
);
const segmentDuration = mediaDuration({
audioTimingInfo: segmentInfo.audioTimingInfo,
videoTimingInfo: segmentInfo.videoTimingInfo
});
// Don't report if we lack information.
//

11
src/xhr.js

@ -10,6 +10,7 @@
* @return {Request} the xhr request that is going to be made
*/
import videojs from 'video.js';
import window from 'global/window';
const {
xhr: videojsXHR,
@ -104,12 +105,18 @@ const xhrFactory = function() {
* @param {Object} byterange - an object with two values defining the start and end
* of a byte-range
*/
const byterangeStr = function(byterange) {
export const byterangeStr = function(byterange) {
// `byterangeEnd` is one less than `offset + length` because the HTTP range
// header uses inclusive ranges
const byterangeEnd = byterange.offset + byterange.length - 1;
let byterangeEnd;
const byterangeStart = byterange.offset;
if (typeof byterange.offset === 'bigint' || typeof byterange.length === 'bigint') {
byterangeEnd = window.BigInt(byterange.offset) + window.BigInt(byterange.length) - window.BigInt(1);
} else {
byterangeEnd = byterange.offset + byterange.length - 1;
}
return 'bytes=' + byterangeStart + '-' + byterangeEnd;
};

72
test/segment-loader.test.js

@ -550,32 +550,40 @@ QUnit.test('uses current time when seekable range is well before current time',
QUnit.module('mediaDuration');
QUnit.test('0 when no timing info', function(assert) {
assert.equal(mediaDuration({}, {}), 0, '0 when no timing info');
assert.equal(mediaDuration({ start: 1 }, { start: 1 }), 0, '0 when no end times');
assert.equal(mediaDuration({ end: 1 }, { end: 1 }), 0, '0 when no start times');
assert.equal(mediaDuration({}), 0, '0 when no timing info');
assert.equal(
mediaDuration({audioTimingInfo: {start: 1}, videoTimingInfo: {start: 1}}),
0,
'0 when no end times'
);
assert.equal(
mediaDuration({audioTimingInfo: {end: 1}, videoTimingInfo: {end: 1}}),
0,
'0 when no start times'
);
});
QUnit.test('reports audio duration', function(assert) {
assert.equal(
mediaDuration({ start: 1, end: 2 }, {}),
mediaDuration({audioTimingInfo: {start: 1, end: 2}}),
1,
'audio duration when no video info'
);
assert.equal(
mediaDuration({ start: 1, end: 2 }, { start: 1 }),
mediaDuration({audioTimingInfo: {start: 1, end: 2}, videoTimingInfo: {start: 1}}),
1,
'audio duration when not enough video info'
);
assert.equal(
mediaDuration({ start: 1, end: 2 }, { end: 3 }),
mediaDuration({audioTimingInfo: {start: 1, end: 2}, videoTimingInfo: {end: 3}}),
1,
'audio duration when not enough video info'
);
assert.equal(
mediaDuration({ start: 1, end: 3 }, { start: 1, end: 2 }),
mediaDuration({audioTimingInfo: {start: 1, end: 3}, videoTimingInfo: {start: 1, end: 2}}),
2,
'audio duration when audio duration > video duration'
);
@ -583,25 +591,67 @@ QUnit.test('reports audio duration', function(assert) {
QUnit.test('reports video duration', function(assert) {
assert.equal(
mediaDuration({}, { start: 1, end: 2 }),
mediaDuration({videoTimingInfo: {start: 1, end: 2}}),
1,
'video duration when no audio info'
);
assert.equal(
mediaDuration({audioTimingInfo: {start: 1}, videoTimingInfo: {start: 1, end: 2}}),
1,
'video duration when not enough audio info'
);
assert.equal(
mediaDuration({audioTimingInfo: {end: 3}, videoTimingInfo: {start: 1, end: 2}}),
1,
'video duration when not enough audio info'
);
assert.equal(
mediaDuration({audioTimingInfo: {start: 1, end: 2}, videoTimingInfo: {start: 1, end: 3}}),
2,
'video duration when video duration > audio duration'
);
});
if (window.BigInt) {
QUnit.test('handles bigint', function(assert) {
assert.equal(
mediaDuration({audioTimingInfo: {start: window.BigInt(1), end: window.BigInt(2)}}),
1,
'audio duration when no video info'
);
assert.equal(
mediaDuration({videoTimingInfo: {start: window.BigInt(1), end: window.BigInt(2)}}),
1,
'video duration when no audio info'
);
});
}
QUnit.test('reports video duration', function(assert) {
assert.equal(
mediaDuration({videoTimingInfo: {start: 1, end: 2}}),
1,
'video duration when no audio info'
);
assert.equal(
mediaDuration({ start: 1 }, { start: 1, end: 2 }),
mediaDuration({audioTimingInfo: {start: 1}, videoTimingInfo: {start: 1, end: 2}}),
1,
'video duration when not enough audio info'
);
assert.equal(
mediaDuration({ end: 3 }, { start: 1, end: 2 }),
mediaDuration({audioTimingInfo: {end: 3}, videoTimingInfo: {start: 1, end: 2}}),
1,
'video duration when not enough audio info'
);
assert.equal(
mediaDuration({ start: 1, end: 2 }, { start: 1, end: 3 }),
mediaDuration({audioTimingInfo: {start: 1, end: 2}, videoTimingInfo: {start: 1, end: 3}}),
2,
'video duration when video duration > audio duration'
);

18
test/videojs-http-streaming.test.js

@ -416,7 +416,7 @@ QUnit.test('logs deprecation notice when using hls for options', function(assert
assert.equal(this.env.log.warn.calls, 1, 'warning logged');
assert.equal(
this.env.log.warn.args[0][0],
'Using hls options is deprecated. Use vhs instead.',
'Using hls options is deprecated. Use vhs instead.'
);
});
@ -440,7 +440,7 @@ QUnit.test('logs deprecation notice when using hls for global options', function
assert.equal(this.env.log.warn.calls, 1, 'warning logged');
assert.equal(
this.env.log.warn.args[0][0],
'Using hls options is deprecated. Use vhs instead.',
'Using hls options is deprecated. Use vhs instead.'
);
videojs.options.hls = origHlsOptions;
@ -5994,7 +5994,7 @@ QUnit.test('emeKeySystems adds content types for all keySystems', function(asser
assert.deepEqual(
emeKeySystems(
{ keySystem1: {}, keySystem2: {} },
{ attributes: { CODECS: 'avc1.420015, mp4a.40.2c' } },
{ attributes: { CODECS: 'avc1.420015, mp4a.40.2c' } }
),
{
keySystem1: {
@ -6014,7 +6014,7 @@ QUnit.test('emeKeySystems adds content types for all keySystems', function(asser
emeKeySystems(
{ keySystem1: {}, keySystem2: {} },
{ attributes: { CODECS: 'avc1.420015' } },
{ attributes: { CODECS: 'mp4a.40.2c' } },
{ attributes: { CODECS: 'mp4a.40.2c' } }
),
{
keySystem1: {
@ -6034,7 +6034,7 @@ QUnit.test('emeKeySystems supports audio only', function(assert) {
assert.deepEqual(
emeKeySystems(
{ keySystem1: {}, keySystem2: {} },
{ attributes: { CODECS: 'mp4a.40.2c' } },
{ attributes: { CODECS: 'mp4a.40.2c' } }
),
{
keySystem1: {
@ -6053,7 +6053,7 @@ QUnit.test('emeKeySystems supports external audio only', function(assert) {
emeKeySystems(
{ keySystem1: {}, keySystem2: {} },
{ attributes: {} },
{ attributes: { CODECS: 'mp4a.40.2c' } },
{ attributes: { CODECS: 'mp4a.40.2c' } }
),
{
keySystem1: {
@ -6071,7 +6071,7 @@ QUnit.test('emeKeySystems supports video only', function(assert) {
assert.deepEqual(
emeKeySystems(
{ keySystem1: {}, keySystem2: {} },
{ attributes: { CODECS: 'avc1.420015' } },
{ attributes: { CODECS: 'avc1.420015' } }
),
{
keySystem1: {
@ -6089,7 +6089,7 @@ QUnit.test('emeKeySystems retains non content type properties', function(assert)
assert.deepEqual(
emeKeySystems(
{ keySystem1: { url: '1' }, keySystem2: { url: '2'} },
{ attributes: { CODECS: 'avc1.420015, mp4a.40.2c' } },
{ attributes: { CODECS: 'avc1.420015, mp4a.40.2c' } }
),
{
keySystem1: {
@ -6120,7 +6120,7 @@ QUnit.test('emeKeySystems overwrites content types', function(assert) {
videoContentType: 'd'
}
},
{ attributes: { CODECS: 'avc1.420015, mp4a.40.2c' } },
{ attributes: { CODECS: 'avc1.420015, mp4a.40.2c' } }
),
{
keySystem1: {

23
test/xhr.test.js

@ -1,5 +1,6 @@
import window from 'global/window';
import QUnit from 'qunit';
import xhrFactory from '../src/xhr';
import {default as xhrFactory, byterangeStr} from '../src/xhr';
import { useFakeEnvironment } from './test-helpers.js';
import videojs from 'video.js';
// needed for plugin registration
@ -46,3 +47,23 @@ QUnit.test('xhr respects beforeRequest', function(assert) {
this.xhr(defaultOptions);
assert.equal(this.requests.shift().url, 'global', 'url changed with global override');
});
QUnit.test('byterangeStr works as expected', function(assert) {
assert.equal(byterangeStr({offset: 20, length: 15}), 'bytes=20-34', 'as expected');
assert.equal(byterangeStr({offset: 0, length: 40}), 'bytes=0-39', 'as expected');
if (window.BigInt) {
assert.equal(
byterangeStr({offset: window.BigInt(20), length: window.BigInt(15)}),
'bytes=20-34',
'bigint result as expected'
);
assert.equal(
byterangeStr({offset: window.BigInt(0), length: window.BigInt(40)}),
'bytes=0-39',
'bigint result as expected'
);
}
});
Loading…
Cancel
Save