Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: update m3u8-parser version and fix tests #1407

Merged
merged 3 commits into from
Jul 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 47 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
"@videojs/vhs-utils": "4.0.0",
"aes-decrypter": "4.0.1",
"global": "^4.4.0",
"m3u8-parser": "^6.2.0",
"m3u8-parser": "^7.0.0",
"mpd-parser": "^1.1.1",
"mux.js": "6.3.0",
"video.js": "^7 || ^8"
Expand Down
3 changes: 1 addition & 2 deletions src/segment-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -3180,8 +3180,7 @@ export default class SegmentLoader extends videojs.EventTarget {
const Cue = window.WebKitDataCue || window.VTTCue;
const value = {
custom: segment.custom,
dateTimeObject: segment.dateTimeObject,
dateTimeString: segment.dateTimeString,
programDateTime: segment.programDateTime,
bandwidth: segmentInfo.playlist.attributes.BANDWIDTH,
resolution: segmentInfo.playlist.attributes.RESOLUTION,
codecs: segmentInfo.playlist.attributes.CODECS,
Expand Down
12 changes: 6 additions & 6 deletions src/sync-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ export const syncPointStrategies = [
const datetimeMapping =
syncController.timelineToDatetimeMappings[segment.timeline];

if (!datetimeMapping || !segment.dateTimeObject) {
if (!datetimeMapping || !segment.programDateTime) {
continue;
}

const segmentTime = segment.dateTimeObject.getTime() / 1000;
const segmentTime = segment.programDateTime / 1000;
let start = segmentTime + datetimeMapping;

// take part duration into account.
Expand Down Expand Up @@ -408,9 +408,9 @@ export default class SyncController extends videojs.EventTarget {

if (playlist.segments &&
playlist.segments.length &&
playlist.segments[0].dateTimeObject) {
playlist.segments[0].programDateTime) {
const firstSegment = playlist.segments[0];
const playlistTimestamp = firstSegment.dateTimeObject.getTime() / 1000;
const playlistTimestamp = firstSegment.programDateTime / 1000;

this.timelineToDatetimeMappings[firstSegment.timeline] = -playlistTimestamp;
}
Expand Down Expand Up @@ -449,10 +449,10 @@ export default class SyncController extends videojs.EventTarget {
}
}

const dateTime = segment.dateTimeObject;
const dateTime = segment.programDateTime;

if (segment.discontinuity && shouldSaveTimelineMapping && dateTime) {
this.timelineToDatetimeMappings[segment.timeline] = -(dateTime.getTime() / 1000);
this.timelineToDatetimeMappings[segment.timeline] = -(dateTime / 1000);
}
}

Expand Down
16 changes: 8 additions & 8 deletions src/util/time.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const SEGMENT_END_FUDGE_PERCENT = 0.25;
* @return {Date} program time
*/
export const playerTimeToProgramTime = (playerTime, segment) => {
if (!segment.dateTimeObject) {
if (!segment.programDateTime) {
// Can't convert without an "anchor point" for the program time (i.e., a time that can
// be used to map the start of a segment with a real world time).
return null;
Expand All @@ -39,7 +39,7 @@ export const playerTimeToProgramTime = (playerTime, segment) => {
const startOfSegment = transmuxedStart + transmuxerPrependedSeconds;
const offsetFromSegmentStart = playerTime - startOfSegment;

return new Date(segment.dateTimeObject.getTime() + offsetFromSegmentStart * 1000);
return new Date(segment.programDateTime + offsetFromSegmentStart * 1000);
};

export const originalSegmentVideoDuration = (videoTimingInfo) => {
Expand Down Expand Up @@ -74,28 +74,28 @@ export const findSegmentForProgramTime = (programTime, playlist) => {

let segment = playlist.segments[0];

if (dateTimeObject < segment.dateTimeObject) {
if (dateTimeObject < segment.programDateTime) {
// Requested time is before stream start.
return null;
}

for (let i = 0; i < playlist.segments.length - 1; i++) {
segment = playlist.segments[i];

const nextSegmentStart = playlist.segments[i + 1].dateTimeObject;
const nextSegmentStart = playlist.segments[i + 1].programDateTime;

if (dateTimeObject < nextSegmentStart) {
break;
}
}

const lastSegment = playlist.segments[playlist.segments.length - 1];
const lastSegmentStart = lastSegment.dateTimeObject;
const lastSegmentStart = lastSegment.programDateTime;
const lastSegmentDuration = lastSegment.videoTimingInfo ?
originalSegmentVideoDuration(lastSegment.videoTimingInfo) :
lastSegment.duration + lastSegment.duration * SEGMENT_END_FUDGE_PERCENT;
const lastSegmentEnd =
new Date(lastSegmentStart.getTime() + lastSegmentDuration * 1000);
new Date(lastSegmentStart + lastSegmentDuration * 1000);

if (dateTimeObject > lastSegmentEnd) {
// Beyond the end of the stream, or our best guess of the end of the stream.
Expand Down Expand Up @@ -230,7 +230,7 @@ export const verifyProgramDateTimeTags = (playlist) => {
for (let i = 0; i < playlist.segments.length; i++) {
const segment = playlist.segments[i];

if (!segment.dateTimeObject) {
if (!segment.programDateTime) {
return false;
}
}
Expand Down Expand Up @@ -355,7 +355,7 @@ export const seekToProgramTime = ({

const segment = matchedSegment.segment;
const mediaOffset = getOffsetFromTimestamp(
segment.dateTimeObject,
segment.programDateTime,
programTime
);

Expand Down
2 changes: 1 addition & 1 deletion test/playlist-loader.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1052,7 +1052,7 @@ QUnit.module('Playlist Loader', function(hooks) {
const segment = loader.main.playlists[0].segments[0];

assert.strictEqual(segment.custom.test, '#PARSER:parsed', 'parsed custom tag');
assert.ok(segment.dateTimeObject, 'converted and parsed custom time');
assert.ok(segment.programDateTime, 'converted and parsed custom time');

delete this.fakeVhs.options_;
});
Expand Down
28 changes: 14 additions & 14 deletions test/segment-loader.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4560,26 +4560,26 @@ QUnit.module('SegmentLoader', function(hooks) {

const segmentDurationMs = targetDuration * 1000;

const playlist1Start = new Date('2021-01-01T00:00:00.000-05:00');
const playlist1Start = new Date('2021-01-01T00:00:00.000-05:00').getTime();

playlist1.segments[0].dateTimeObject = playlist1Start;
playlist1.segments[1].dateTimeObject = new Date(playlist1Start.getTime() + segmentDurationMs);
playlist1.segments[0].programDateTime = playlist1Start;
playlist1.segments[1].programDateTime = new Date(playlist1Start + segmentDurationMs).getTime();
// jump of 0.5 seconds after disco (0.5 seconds of missing real world time, e.g.,
// an encoder went down briefly), should have a PDT mapping difference of -3.5
// seconds from first mapping
playlist1.segments[2].dateTimeObject = new Date(playlist1.segments[1].dateTimeObject.getTime() + segmentDurationMs + 500);
playlist1.segments[3].dateTimeObject = new Date(playlist1.segments[2].dateTimeObject.getTime() + segmentDurationMs);
playlist1.segments[2].programDateTime = new Date(playlist1.segments[1].programDateTime + segmentDurationMs + 500).getTime();
playlist1.segments[3].programDateTime = new Date(playlist1.segments[2].programDateTime + segmentDurationMs).getTime();

// offset by 0.25 seconds from playlist1
const playlist2Start = new Date('2021-01-01T00:00:00.250-05:00');

playlist2.segments[0].dateTimeObject = playlist2Start;
playlist2.segments[1].dateTimeObject = new Date(playlist2Start.getTime() + segmentDurationMs);
playlist2.segments[0].programDateTime = playlist2Start.getTime();
playlist2.segments[1].programDateTime = new Date(playlist2Start + segmentDurationMs).getTime();
// jump of 0.5 seconds after disco (0.5 seconds of missing real world time, e.g.,
// an encoder went down briefly), should have a PDT mapping difference of -3.5
// seconds from first mapping
playlist2.segments[2].dateTimeObject = new Date(playlist2.segments[1].dateTimeObject.getTime() + segmentDurationMs + 500);
playlist2.segments[3].dateTimeObject = new Date(playlist2.segments[2].dateTimeObject.getTime() + segmentDurationMs);
playlist2.segments[2].programDateTime = new Date(playlist2.segments[1].programDateTime + segmentDurationMs + 500).getTime();
playlist2.segments[3].programDateTime = new Date(playlist2.segments[2].programDateTime + segmentDurationMs).getTime();

const {
mediaSource_: mediaSource,
Expand Down Expand Up @@ -4680,11 +4680,11 @@ QUnit.module('SegmentLoader', function(hooks) {
const segment3Start = new Date(segment2Start.getTime() + segmentDurationMs + 500);

[playlist1, playlist2].forEach((playlist) => {
playlist.dateTimeObject = segment0Start;
playlist.segments[0].dateTimeObject = segment0Start;
playlist.segments[1].dateTimeObject = segment1Start;
playlist.segments[2].dateTimeObject = segment2Start;
playlist.segments[3].dateTimeObject = segment3Start;
playlist.programDateTime = segment0Start;
playlist.segments[0].programDateTime = segment0Start;
playlist.segments[1].programDateTime = segment1Start;
playlist.segments[2].programDateTime = segment2Start;
playlist.segments[3].programDateTime = segment3Start;
});

const {
Expand Down
38 changes: 19 additions & 19 deletions test/sync-controller.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ QUnit.test('returns correct sync point for ProgramDateTime strategy', function(a

assert.equal(syncPoint, null, 'no syncpoint when no date time to display time mapping');

playlist.segments[0].dateTimeObject = datetime;
playlist.segments[0].programDateTime = datetime.getTime();

this.syncController.setDateTimeMappingForStart(playlist);

Expand All @@ -55,7 +55,7 @@ QUnit.test('returns correct sync point for ProgramDateTime strategy', function(a

assert.equal(syncPoint, null, 'no syncpoint when datetimeObject not set on playlist');

newPlaylist.segments[0].dateTimeObject = new Date(2012, 11, 12, 12, 12, 22);
newPlaylist.segments[0].programDateTime = new Date(2012, 11, 12, 12, 12, 22).getTime();

syncPoint = strategy.run(this.syncController, newPlaylist, duration, timeline);

Expand All @@ -78,7 +78,7 @@ QUnit.test('ProgramDateTime strategy finds nearest segment for sync', function(a
assert.equal(syncPoint, null, 'no syncpoint when no date time to display time mapping');

playlist.segments.forEach((segment, index) => {
segment.dateTimeObject = new Date(2012, 11, 12, 12, 12, 12 + (index * 10));
segment.programDateTime = new Date(2012, 11, 12, 12, 12, 12 + (index * 10)).getTime();
});

this.syncController.setDateTimeMappingForStart(playlist);
Expand All @@ -90,7 +90,7 @@ QUnit.test('ProgramDateTime strategy finds nearest segment for sync', function(a
assert.equal(syncPoint, null, 'no syncpoint when datetimeObject not set on playlist');

newPlaylist.segments.forEach((segment, index) => {
segment.dateTimeObject = new Date(2012, 11, 12, 12, 12, 22 + (index * 10));
segment.programDateTime = new Date(2012, 11, 12, 12, 12, 22 + (index * 10)).getTime();
});

syncPoint = strategy.run(this.syncController, newPlaylist, duration, timeline, 170);
Expand All @@ -115,7 +115,7 @@ QUnit.test(
function(assert) {
const playlist = playlistWithDuration(40);

playlist.segments[1].dateTimeObject = new Date(2012, 11, 12, 12, 12, 12);
playlist.segments[1].programDateTime = new Date(2012, 11, 12, 12, 12, 12).getTime();

this.syncController.setDateTimeMappingForStart(playlist);

Expand All @@ -125,7 +125,7 @@ QUnit.test(
'did not set datetime mapping'
);

playlist.segments[0].dateTimeObject = new Date(2012, 11, 12, 12, 12, 2);
playlist.segments[0].programDateTime = new Date(2012, 11, 12, 12, 12, 2).getTime();

this.syncController.setDateTimeMappingForStart(playlist);

Expand All @@ -140,12 +140,12 @@ QUnit.test(
QUnit.test('uses separate date time to display time mapping for each timeline', function(assert) {
const playlist = playlistWithDuration(40, { discontinuityStarts: [1, 3] });

playlist.segments[0].dateTimeObject = new Date(2020, 1, 1, 1, 1, 1);
playlist.segments[0].programDateTime = new Date(2020, 1, 1, 1, 1, 1).getTime();
// 20 seconds later (10 more than default)
playlist.segments[1].dateTimeObject = new Date(2020, 1, 1, 1, 1, 21);
playlist.segments[2].dateTimeObject = new Date(2020, 1, 1, 1, 1, 31);
playlist.segments[1].programDateTime = new Date(2020, 1, 1, 1, 1, 21).getTime();
playlist.segments[2].programDateTime = new Date(2020, 1, 1, 1, 1, 31).getTime();
// 30 seconds later (20 more than default)
playlist.segments[3].dateTimeObject = new Date(2020, 1, 1, 1, 2, 1);
playlist.segments[3].programDateTime = new Date(2020, 1, 1, 1, 2, 1).getTime();

// after this call, the initial playlist mapping will be provided
this.syncController.setDateTimeMappingForStart(playlist);
Expand All @@ -165,7 +165,7 @@ QUnit.test('uses separate date time to display time mapping for each timeline',
assert.deepEqual(
this.syncController.timelineToDatetimeMappings,
{
0: -(playlist.segments[0].dateTimeObject.getTime() / 1000)
0: -(playlist.segments[0].programDateTime / 1000)
},
'has correct mapping for timeline 0'
);
Expand All @@ -183,8 +183,8 @@ QUnit.test('uses separate date time to display time mapping for each timeline',
assert.deepEqual(
this.syncController.timelineToDatetimeMappings,
{
0: -(playlist.segments[0].dateTimeObject.getTime() / 1000),
1: -(playlist.segments[1].dateTimeObject.getTime() / 1000)
0: -(playlist.segments[0].programDateTime / 1000),
1: -(playlist.segments[1].programDateTime / 1000)
},
'has correct mapping for timelines 0 and 1'
);
Expand All @@ -202,8 +202,8 @@ QUnit.test('uses separate date time to display time mapping for each timeline',
assert.deepEqual(
this.syncController.timelineToDatetimeMappings,
{
0: -(playlist.segments[0].dateTimeObject.getTime() / 1000),
1: -(playlist.segments[1].dateTimeObject.getTime() / 1000)
0: -(playlist.segments[0].programDateTime / 1000),
1: -(playlist.segments[1].programDateTime / 1000)
},
'does not add a new timeline mapping when no disco'
);
Expand All @@ -221,9 +221,9 @@ QUnit.test('uses separate date time to display time mapping for each timeline',
assert.deepEqual(
this.syncController.timelineToDatetimeMappings,
{
0: -(playlist.segments[0].dateTimeObject.getTime() / 1000),
1: -(playlist.segments[1].dateTimeObject.getTime() / 1000),
2: -(playlist.segments[3].dateTimeObject.getTime() / 1000)
0: -(playlist.segments[0].programDateTime / 1000),
1: -(playlist.segments[1].programDateTime / 1000),
2: -(playlist.segments[3].programDateTime / 1000)
},
'has correct mappings for timelines 0, 1, and 2'
);
Expand All @@ -241,7 +241,7 @@ QUnit.test('ProgramDateTime strategy finds nearest llhls sync point', function(a
assert.equal(syncPoint, null, 'no syncpoint when no date time to display time mapping');

playlist.segments.forEach((segment, index) => {
segment.dateTimeObject = new Date(2012, 11, 12, 12, 12, 12 + (index * 10));
segment.programDateTime = new Date(2012, 11, 12, 12, 12, 12 + (index * 10)).getTime();
});

this.syncController.setDateTimeMappingForStart(playlist);
Expand Down
Loading