Skip to content

Commit

Permalink
endTime calculation with endOnNext
Browse files Browse the repository at this point in the history
  • Loading branch information
harisha-swaminathan committed Jun 23, 2023
1 parent fa0758c commit d5b1887
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 9 deletions.
45 changes: 37 additions & 8 deletions src/util/text-tracks.js
Original file line number Diff line number Diff line change
Expand Up @@ -249,28 +249,57 @@ export const addDaterangeMetadata = ({
mediaPlaylist,
timestampOffset
}) => {
if (!mediaPlaylist) {
return;
}

const Cue = window.WebKitDataCue || window.VTTCue;
const metadataTrack = inbandTextTracks.metadataTrack_;

if (!metadataTrack) {
if (!mediaPlaylist || !metadataTrack) {
return;
}

const dateRanges = mediaPlaylist.daterange;
const dateRangeClasses = {};
let classList;
let classListIndex;
let startTime;
let endTime;

dateRanges.forEach((dateRange)=>{
startTime = timestampOffset + (new Date(dateRange.startDate).getTime() - new Date(mediaPlaylist.dateTimeObject).getTime()) / 1000;
dateRange.startTime = startTime;

if (dateRange.class) {
if (dateRangeClasses[dateRange.class]) {
dateRangeClasses[dateRange.class].push(dateRange);
} else {
dateRangeClasses[dateRange.class] = [dateRange];
}
}
});

dateRanges.forEach((dateRange) => {
const startTime = timestampOffset + (new Date(dateRange.startDate).getTime() - new Date(mediaPlaylist.dateTimeObject).getTime()) / 1000;
const endTime = dateRange.endDate ? (new Date(dateRange.endDate).getTime() - new Date(mediaPlaylist.dateTimeObject).getTime()) / 1000 : 0;
if (dateRange.class) {
classList = dateRangeClasses[dateRange.class];
classListIndex = classList.indexOf(dateRange);
}

if (dateRange.endDate) {
endTime = (new Date(dateRange.endDate).getTime() - new Date(mediaPlaylist.dateTimeObject).getTime()) / 1000;
} else if (dateRange.endOnNext && classList[classListIndex + 1]) {
endTime = classList[classListIndex + 1].startTime;
} else if (dateRange.duration) {
endTime = startTime + dateRange.duration;
} else if (dateRange.plannedDuration) {
endTime = startTime + dateRange.plannedDuration;
} else {
endTime = 0;
}

const cue = new Cue(startTime, endTime, '');

cue.id = dateRange.id;
cue.type = 'com.apple.quicktime.HLS';
Object.keys(dateRange).forEach((key) => {
if (!['id', 'class', 'startDate', 'duration', 'endDate', 'endOnNext'].includes(key)) {
if (!['id', 'class', 'startDate', 'duration', 'endDate', 'endOnNext', 'startTime'].includes(key)) {
if (key === 'scte35Out') {
dateRange[key] = new Uint8Array(dateRange[key].match(/[\da-f]{2}/gi)).buffer;
}
Expand Down
101 changes: 100 additions & 1 deletion test/text-tracks.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import {
addCaptionData,
createMetadataTrackIfNotExists,
addMetadata,
removeDuplicateCuesFromTrack
removeDuplicateCuesFromTrack,
addDaterangeMetadata
} from '../src/util/text-tracks';

const { module, test } = Qunit;
Expand Down Expand Up @@ -273,6 +274,104 @@ test('does nothing if there is no metadataTrack or no metadata cues given', func
);
});

test('daterange text track cues - endDate is used for endTime calculation', function(assert) {
const inbandTextTracks = {
metadataTrack_: new MockTextTrack()
};

addDaterangeMetadata({
inbandTextTracks,
mediaPlaylist: {
daterange: [{
startDate: new Date(0),
endDate: new Date(2000),
scte35Out: '0xFC30200000FFF00F0500D4DF747FFFFE0034BC00C00000E4612424',
id: 'testId'
}],
dateTimeObject: 5
},
timestampOffset: 10
});

assert.ok(inbandTextTracks.metadataTrack_, 'metadataTrack exists');
assert.equal(inbandTextTracks.metadataTrack_.cues[0].endTime, 1.995, 'endDate is used when available');
});

test('daterange text track cues - duration is used for endTime calculation', function(assert) {
const inbandTextTracks = {
metadataTrack_: new MockTextTrack()
};

addDaterangeMetadata({
inbandTextTracks,
mediaPlaylist: {
daterange: [{
startDate: new Date(10),
scte35Out: '0xFC30200000FFF00F0500D4DF747FFFFE0034BC00C00000E4612424',
duration: 40,
id: 'testId'
}],
dateTimeObject: 5
},
timestampOffset: 10
});

assert.ok(inbandTextTracks.metadataTrack_, 'metadataTrack exists');
assert.equal(inbandTextTracks.metadataTrack_.cues[0].endTime, 40.005, 'duration is used when endDate and class not available');
});

test('daterange text track cues - plannedDuration is used for endTime calculation', function(assert) {
const inbandTextTracks = {
metadataTrack_: new MockTextTrack()
};

addDaterangeMetadata({
inbandTextTracks,
mediaPlaylist: {
daterange: [{
startDate: new Date(2000),
scte35Out: '0xFC30200000FFF00F0500D4DF747FFFFE0034BC00C00000E4612424',
plannedDuration: 15,
id: 'testId'
}],
dateTimeObject: 1000
},
timestampOffset: 9
});

assert.ok(inbandTextTracks.metadataTrack_, 'metadataTrack exists');
assert.equal(inbandTextTracks.metadataTrack_.cues[0].endTime, 25, 'plannedDuration is used when endDate, class and duration not available');
});

test('daterange text track cues - endOnNext and classList are used', function(assert) {
const inbandTextTracks = {
metadataTrack_: new MockTextTrack()
};

addDaterangeMetadata({
inbandTextTracks,
mediaPlaylist: {
daterange: [{
startDate: new Date(2000),
scte35Out: '0xFC30200000FFF00F0500D4DF747FFFFE0034BC00C00000E4612424',
id: 'testId1',
class: 'TestClass',
endOnNext: true
}, {
startDate: new Date(4000),
scte35Out: '0xFC30200000FFF00F0500D4DF747FFFFE0034BC00C00000E46',
id: 'testId2',
class: 'TestClass'
}],
dateTimeObject: 1000
},
timestampOffset: 9
});

assert.ok(inbandTextTracks.metadataTrack_, 'metadataTrack exists');
assert.equal(inbandTextTracks.metadataTrack_.cues[0].endTime, 12, 'startTime of the next dateRange with the same class is used as endTime');
});

test('adds cues for each metadata frame seen', function(assert) {
const tech = new MockTech();
const inbandTextTracks = {};
Expand Down

0 comments on commit d5b1887

Please sign in to comment.