Skip to content

Commit

Permalink
chore: update m3u8-parser version and fix tests (#1407)
Browse files Browse the repository at this point in the history
  • Loading branch information
harisha-swaminathan authored Jul 11, 2023
1 parent a21182d commit fe25a04
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 104 deletions.
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

0 comments on commit fe25a04

Please sign in to comment.