Skip to content

Commit

Permalink
Merge pull request #3165 from mtoczko/bugfix/vtt-init-pts
Browse files Browse the repository at this point in the history
initPTS90Khz - (fmp4 + vtt)
  • Loading branch information
robwalch committed Nov 4, 2020
2 parents a24f6d4 + 268c6a4 commit c19056b
Show file tree
Hide file tree
Showing 6 changed files with 15 additions and 9 deletions.
2 changes: 1 addition & 1 deletion docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -1377,7 +1377,7 @@ Full list of Events is available below:
- `Hls.Events.SUBTITLE_FRAG_PROCESSED` - fired when a subtitle fragment has been processed
- data: { success : boolean, frag : the processed frag }
- `Hls.Events.INIT_PTS_FOUND` - fired when the first timestamp is found
- data: { d : demuxer id, initPTS: initPTS , frag : fragment object }
- data: { d : demuxer id, initPTS: initPTS, timescale: timescale, frag : fragment object }
- `Hls.Events.FRAG_LOADING` - fired when a fragment loading starts
- data: { frag : fragment object }
- `Hls.Events.FRAG_LOAD_PROGRESS` - fired when a fragment load is in progress
Expand Down
9 changes: 6 additions & 3 deletions src/controller/timeline-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class TimelineController extends EventHandler {
private textTracks: Array<TextTrack> = [];
private tracks: Array<MediaPlaylist> = [];
private initPTS: Array<number> = [];
private timescale: Array<number> = [];
private unparsedVttFrags: Array<{ frag: Fragment, payload: ArrayBuffer }> = [];
private captionsTracks: Record<string, TextTrack> = {};
private nonNativeCaptionsTracks: Record<string, NonNativeCaptionsTrack> = {};
Expand Down Expand Up @@ -150,11 +151,12 @@ 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 @@ -284,6 +286,7 @@ class TimelineController extends EventHandler {
this.textTracks = [];
this.unparsedVttFrags = this.unparsedVttFrags || [];
this.initPTS = [];
this.timescale = [];
if (this.cea608Parser1 && this.cea608Parser2) {
this.cea608Parser1.reset();
this.cea608Parser2.reset();
Expand Down Expand Up @@ -406,7 +409,7 @@ class TimelineController extends EventHandler {
this.prevCC = frag.cc;
}
// Parse the WebVTT file contents.
WebVTTParser.parse(payload, this.initPTS[frag.cc], vttCCs, frag.cc, (cues) => {
WebVTTParser.parse(payload, this.initPTS[frag.cc], this.timescale[frag.cc], vttCCs, frag.cc, (cues) => {
if (this.config.renderTextTracksNatively) {
const currentTrack = textTracks[frag.level];
// WebVTTParser.parse is an async method and if the currently selected text track mode is set to "disabled"
Expand Down
3 changes: 2 additions & 1 deletion src/demux/mp4demuxer.js
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,8 @@ class MP4Demuxer {
if (initPTS === undefined) {
let startDTS = MP4Demuxer.getStartDTS(initData, data);
this.initPTS = initPTS = startDTS - timeOffset;
this.observer.trigger(Event.INIT_PTS_FOUND, { initPTS: initPTS });
// getStartDTS - convert base time to seconds => timescale: 1
this.observer.trigger(Event.INIT_PTS_FOUND, { initPTS: initPTS, timescale: 1 });
}
MP4Demuxer.offsetStartDTS(initData, data, initPTS);
startDTS = MP4Demuxer.getStartDTS(initData, data);
Expand Down
2 changes: 1 addition & 1 deletion src/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ const HlsEvents = {
CUES_PARSED: 'hlsCuesParsed',
// fired when a text track to be managed externally is found - data: { tracks: [ { label: string, kind: string, default: boolean } ] }
NON_NATIVE_TEXT_TRACKS_FOUND: 'hlsNonNativeTextTracksFound',
// fired when the first timestamp is found - data: { id : demuxer id, initPTS: initPTS, frag : fragment object }
// fired when the first timestamp is found - data: { id : demuxer id, initPTS: initPTS, timescale: timescale, frag : fragment object }
INIT_PTS_FOUND: 'hlsInitPtsFound',
// fired when a fragment loading starts - data: { frag : fragment object }
FRAG_LOADING: 'hlsFragLoading',
Expand Down
4 changes: 2 additions & 2 deletions src/remux/mp4-remuxer.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,11 +192,11 @@ class MP4Remuxer {
const startOffset = Math.round(inputTimeScale * timeOffset);
initDTS = Math.min(initDTS, PTSNormalize(videoSamples[0].dts, startPTS) - startOffset);
initPTS = Math.min(initPTS, startPTS - startOffset);
this.observer.trigger(Event.INIT_PTS_FOUND, { initPTS });
this.observer.trigger(Event.INIT_PTS_FOUND, { initPTS: initPTS, timescale: inputTimeScale });
}
} else if (computePTSDTS && tracks.audio) {
// initPTS found for audio-only stream with main and alt audio
this.observer.trigger(Event.INIT_PTS_FOUND, { initPTS });
this.observer.trigger(Event.INIT_PTS_FOUND, { initPTS: initPTS, timescale: audioTrack.inputTimeScale });
}

if (Object.keys(tracks).length) {
Expand Down
4 changes: 3 additions & 1 deletion src/utils/webvtt-parser.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import VTTParser from './vttparser';
import { utf8ArrayToStr } from '../demux/id3';
import { toMpegTsClockFromTimescale } from './timescale-conversion';

// String.prototype.startsWith is not supported in IE11
const startsWith = function (inputString, searchString, position) {
Expand Down Expand Up @@ -59,12 +60,13 @@ const calculateOffset = function (vttCCs, cc, presentationTime) {
};

const WebVTTParser = {
parse: function (vttByteArray, syncPTS, vttCCs, cc, callBack, errorCallBack) {
parse: function (vttByteArray, initPTS, timescale, vttCCs, cc, callBack, errorCallBack) {
// Convert byteArray into string, replacing any somewhat exotic linefeeds with "\n", then split on that character.
let re = /\r\n|\n\r|\n|\r/g;
// Uint8Array.prototype.reduce is not implemented in IE11
let vttLines = utf8ArrayToStr(new Uint8Array(vttByteArray)).trim().replace(re, '\n').split('\n');

let syncPTS = toMpegTsClockFromTimescale(initPTS, timescale);
let cueTime = '00:00.000';
let mpegTs = 0;
let localTime = 0;
Expand Down

0 comments on commit c19056b

Please sign in to comment.