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

Update webvtt parse to v1.0.x #18

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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
27,810 changes: 13,951 additions & 13,859 deletions dist/hls.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/hls.js.map

Large diffs are not rendered by default.

37 changes: 33 additions & 4 deletions dist/hls.light.js
Original file line number Diff line number Diff line change
Expand Up @@ -4409,7 +4409,8 @@ function () {
},
computePTSDTS = this._initPTS === undefined,
initPTS,
initDTS;
initDTS,
timescale;

if (computePTSDTS) {
initPTS = initDTS = Infinity;
Expand Down Expand Up @@ -4444,8 +4445,9 @@ function () {
};

if (computePTSDTS) {
// remember first PTS of this demuxing context. for audio, PTS = DTS
initPTS = initDTS = audioSamples[0].pts - audioTrack.inputTimeScale * timeOffset;
timescale = audioTrack.inputTimeScale; // remember first PTS of this demuxing context. for audio, PTS = DTS

initPTS = initDTS = audioSamples[0].pts - Math.round(timescale * timeOffset);
}
}

Expand All @@ -4465,10 +4467,12 @@ function () {
};

if (computePTSDTS) {
timescale = videoTrack.inputTimeScale;
initPTS = Math.min(initPTS, videoSamples[0].pts - inputTimeScale * timeOffset);
initDTS = Math.min(initDTS, videoSamples[0].dts - inputTimeScale * timeOffset);
this.observer.trigger(events["default"].INIT_PTS_FOUND, {
initPTS: initPTS
initPTS: initPTS,
timescale: timescale
});
}
}
Expand Down Expand Up @@ -5150,6 +5154,31 @@ function () {
return MP4Remuxer;
}();

function normalizePts(value, reference) {
var offset;

if (reference === null) {
return value;
}

if (reference < value) {
// - 2^33
offset = -8589934592;
} else {
// + 2^33
offset = 8589934592;
}
/* PTS is 33bit (from 0 to 2^33 -1)
if diff between value and reference is bigger than half of the amplitude (2^32) then it means that
PTS looping occured. fill the gap */


while (Math.abs(value - reference) > 4294967296) {
value += offset;
}

return value;
}
/* harmony default export */ var mp4_remuxer = (mp4_remuxer_MP4Remuxer);
// CONCATENATED MODULE: ./src/remux/passthrough-remuxer.js
/**
Expand Down
2 changes: 1 addition & 1 deletion dist/hls.light.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/hls.light.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/hls.light.min.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/hls.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/hls.min.js.map

Large diffs are not rendered by default.

80 changes: 80 additions & 0 deletions package-lock.json

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

114 changes: 63 additions & 51 deletions src/controller/timeline-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Event from '../events';
import EventHandler from '../event-handler';
import Cea608Parser, { CaptionScreen } from '../utils/cea-608-parser';
import OutputFilter from '../utils/output-filter';
import WebVTTParser from '../utils/webvtt-parser';
import { parseWebVTT } from '../utils/webvtt-parser';
import { logger } from '../utils/logger';
import { sendAddTrackEvent, clearCurrentCues } from '../utils/texttrack-utils';
import Fragment from '../loader/fragment';
Expand All @@ -17,6 +17,7 @@ class TimelineController extends EventHandler {
private textTracks: Array<TextTrack> = [];
private tracks: Array<any> = [];
private initPTS: Array<number> = [];
private timescale: Array<number> = [];
private unparsedVttFrags: Array<{frag: Fragment, payload: any}> = [];
private cueRanges: Array<any> = [];
private captionsTracks: any = {};
Expand Down Expand Up @@ -82,11 +83,13 @@ class TimelineController extends EventHandler {
}

// Triggered when an initial PTS is found; used for synchronisation of WebVTT.
onInitPtsFound (data: { id: string, frag: Fragment, initPTS: number}) {
const { frag, id, initPTS } = data;
onInitPtsFound (data: { id: string, frag: Fragment, initPTS: number, timescale: number }) {
const { frag, id, initPTS, timescale } = data;
const { unparsedVttFrags } = this;

if (id === 'main') {
this.initPTS[frag.cc] = initPTS;
this.timescale[frag.cc] = timescale;
}

// Due to asynchronous processing, initial PTS may arrive later than the first VTT fragments are loaded.
Expand Down Expand Up @@ -168,6 +171,7 @@ class TimelineController extends EventHandler {
start: 0, prevCC: -1, new: false
}
};
this.timescale = [];
this._cleanTracks();
}

Expand Down Expand Up @@ -272,58 +276,66 @@ class TimelineController extends EventHandler {
this.prevCC = frag.cc;
}
// Parse the WebVTT file contents.
WebVTTParser.parse(payload, this.initPTS[frag.cc], vttCCs, frag.cc, function (cues) {
const currentTrack = textTracks[frag.level];
// WebVTTParser.parse is an async method and if the currently selected text track mode is set to "disabled"
// before parsing is done then don't try to access currentTrack.cues.getCueById as cues will be null
// and trying to access getCueById method of cues will throw an exception
if (currentTrack.mode === 'disabled') {
hls.trigger(Event.SUBTITLE_FRAG_PROCESSED, { success: false, frag: frag });
return;
}
let minStartTime = Number.MAX_SAFE_INTEGER;
// Add cues and trigger event with success true.

cues.forEach(cue => {
//find the first cue in the entire cue set since its not always sorted
minStartTime = Math.min(cue.startTime,minStartTime);
// Sometimes there are cue overlaps on segmented vtts so the same
// cue can appear more than once in different vtt files.
// This avoid showing duplicated cues with same timecode and text.
if (!currentTrack.cues.getCueById(cue.id)) {
try {
currentTrack.addCue(cue);
if (!currentTrack.cues.getCueById(cue.id)) {
throw new Error(`addCue is failed for: ${cue}`);
parseWebVTT(
payload,
this.initPTS[frag.cc],
this.timescale[frag.cc],
vttCCs,
frag.cc,
frag.start,
(cues) => {
const currentTrack = textTracks[frag.level];
// WebVTTParser.parse is an async method and if the currently selected text track mode is set to "disabled"
// before parsing is done then don't try to access currentTrack.cues.getCueById as cues will be null
// and trying to access getCueById method of cues will throw an exception
if (currentTrack.mode === 'disabled') {
hls.trigger(Event.SUBTITLE_FRAG_PROCESSED, { success: false, frag: frag });
return;
}
let minStartTime = Number.MAX_SAFE_INTEGER;
// Add cues and trigger event with success true.

cues.forEach(cue => {
//find the first cue in the entire cue set since its not always sorted
minStartTime = Math.min(cue.startTime,minStartTime);
// Sometimes there are cue overlaps on segmented vtts so the same
// cue can appear more than once in different vtt files.
// This avoid showing duplicated cues with same timecode and text.
if (!currentTrack.cues.getCueById(cue.id)) {
try {
currentTrack.addCue(cue);
if (!currentTrack.cues.getCueById(cue.id)) {
throw new Error(`addCue is failed for: ${cue}`);
}
} catch (err) {
logger.debug(`Failed occurred on adding cues: ${err}`);
const textTrackCue = new (window as any).TextTrackCue(cue.startTime, cue.endTime, cue.text);
textTrackCue.id = cue.id;
currentTrack.addCue(textTrackCue);
}
} catch (err) {
logger.debug(`Failed occurred on adding cues: ${err}`);
const textTrackCue = new (window as any).TextTrackCue(cue.startTime, cue.endTime, cue.text);
textTrackCue.id = cue.id;
currentTrack.addCue(textTrackCue);
}
}
);

let liveSyncPosition = hls.streamController.liveSyncPosition;
//need to remove cues only for live so if there is no sync position its a VOD
// if there is a better way to detect live vs vod we can use it.
while (cues.length > 0 && liveSyncPosition !== undefined ){
//We remove cues which are more than 5 minutes old than the current cue
if (currentTrack.cues[0].startTime < minStartTime - 300){
currentTrack.removeCue(currentTrack.cues[0]);
} else {
break;
}
}
}
);

let liveSyncPosition = hls.streamController.liveSyncPosition;
//need to remove cues only for live so if there is no sync position its a VOD
// if there is a better way to detect live vs vod we can use it.
while (cues.length > 0 && liveSyncPosition !== undefined ){
//We remove cues which are more than 5 minutes old than the current cue
if (currentTrack.cues[0].startTime < minStartTime - 300){
currentTrack.removeCue(currentTrack.cues[0]);
} else {
break;
}
hls.trigger(Event.SUBTITLE_FRAG_PROCESSED, { success: true, frag: frag });
},
(error) => {
// Something went wrong while parsing. Trigger event with success false.
logger.log(`Failed to parse VTT cue: ${error}`);
hls.trigger(Event.SUBTITLE_FRAG_PROCESSED, { success: false, frag: frag });
}
hls.trigger(Event.SUBTITLE_FRAG_PROCESSED, { success: true, frag: frag });
},
function (e) {
// Something went wrong while parsing. Trigger event with success false.
logger.log(`Failed to parse VTT cue: ${e}`);
hls.trigger(Event.SUBTITLE_FRAG_PROCESSED, { success: false, frag: frag });
});
);
}

onFragDecrypted (data: { frag: Fragment, payload: any}) {
Expand Down
31 changes: 28 additions & 3 deletions src/remux/mp4-remuxer.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ class MP4Remuxer {
tracks = {},
data = { tracks: tracks },
computePTSDTS = (this._initPTS === undefined),
initPTS, initDTS;
initPTS, initDTS, timescale;

if (computePTSDTS) {
initPTS = initDTS = Infinity;
Expand Down Expand Up @@ -143,8 +143,9 @@ class MP4Remuxer {
}
};
if (computePTSDTS) {
timescale = audioTrack.inputTimeScale;
// remember first PTS of this demuxing context. for audio, PTS = DTS
initPTS = initDTS = audioSamples[0].pts - audioTrack.inputTimeScale * timeOffset;
initPTS = initDTS = audioSamples[0].pts - Math.round(timescale * timeOffset);
}
}

Expand All @@ -163,9 +164,10 @@ class MP4Remuxer {
}
};
if (computePTSDTS) {
timescale = videoTrack.inputTimeScale;
initPTS = Math.min(initPTS, videoSamples[0].pts - inputTimeScale * timeOffset);
initDTS = Math.min(initDTS, videoSamples[0].dts - inputTimeScale * timeOffset);
this.observer.trigger(Event.INIT_PTS_FOUND, { initPTS: initPTS });
this.observer.trigger(Event.INIT_PTS_FOUND, { initPTS: initPTS, timescale });
}
}

Expand Down Expand Up @@ -799,4 +801,27 @@ class MP4Remuxer {
}
}

export function normalizePts (value, reference) {
let offset;
if (reference === null) {
return value;
}

if (reference < value) {
// - 2^33
offset = -8589934592;
} else {
// + 2^33
offset = 8589934592;
}
/* PTS is 33bit (from 0 to 2^33 -1)
if diff between value and reference is bigger than half of the amplitude (2^32) then it means that
PTS looping occured. fill the gap */
while (Math.abs(value - reference) > 4294967296) {
value += offset;
}

return value;
}

export default MP4Remuxer;
Loading