Skip to content

Commit

Permalink
stream-controller: only force reloading previous fragment if last rem…
Browse files Browse the repository at this point in the history
…uxed fragment does not start with a keyframe

related to https://github.com/dailymotion/hls.js/issues/517
  • Loading branch information
mangui committed Jul 4, 2016
1 parent 5ddffac commit 8e2a964
Show file tree
Hide file tree
Showing 6 changed files with 23 additions and 10 deletions.
15 changes: 10 additions & 5 deletions src/controller/stream-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class StreamController extends EventHandler {
this.tick();
} else {
logger.warn('cannot start loading as manifest not parsed yet');
this.state = State.STOPPED;
this.state = State.STOPPED;
}
}

Expand Down Expand Up @@ -377,10 +377,10 @@ class StreamController extends EventHandler {
let deltaPTS = fragPrevious.deltaPTS,
curSNIdx = frag.sn - levelDetails.startSN;
// if there is a significant delta between audio and video, larger than max allowed hole,
// it might be because video fragment does not start with a keyframe.
// and if previous remuxed fragment did not start with a keyframe. (fragPrevious.dropped)
// let's try to load previous fragment again to get last keyframe
// then we will reload again current fragment (that way we should be able to fill the buffer hole ...)
if (deltaPTS && deltaPTS > config.maxBufferHole) {
if (deltaPTS && deltaPTS > config.maxBufferHole && fragPrevious.dropped) {
frag = fragments[curSNIdx-1];
logger.warn(`SN just loaded, with large PTS gap between audio and video, maybe frag is not starting with a keyframe ? load previous one to try to overcome this`);
// decrement previous frag load counter to avoid frag loop loading error when next fragment will get reloaded
Expand Down Expand Up @@ -874,7 +874,7 @@ class StreamController extends EventHandler {
}
}
this.pendingAppending = 0;
logger.log(`Demuxing ${sn} of [${details.startSN} ,${details.endSN}],level ${level}`);
logger.log(`Demuxing ${sn} of [${details.startSN} ,${details.endSN}],level ${level}, cc ${fragCurrent.cc}`);
let demuxer = this.demuxer;
if (demuxer) {
demuxer.push(data.payload, audioCodec, currentLevel.videoCodec, start, fragCurrent.cc, level, sn, duration, fragCurrent.decryptdata);
Expand Down Expand Up @@ -981,12 +981,17 @@ class StreamController extends EventHandler {
var level = this.levels[this.level],
frag = this.fragCurrent;

logger.log(`parsed ${data.type},PTS:[${data.startPTS.toFixed(3)},${data.endPTS.toFixed(3)}],DTS:[${data.startDTS.toFixed(3)}/${data.endDTS.toFixed(3)}],nb:${data.nb}`);
logger.log(`parsed ${data.type},PTS:[${data.startPTS.toFixed(3)},${data.endPTS.toFixed(3)}],DTS:[${data.startDTS.toFixed(3)}/${data.endDTS.toFixed(3)}],nb:${data.nb},dropped:${data.dropped || 0}`);

var drift = LevelHelper.updateFragPTSDTS(level.details,frag.sn,data.startPTS,data.endPTS,data.startDTS,data.endDTS),
hls = this.hls;
hls.trigger(Event.LEVEL_PTS_UPDATED, {details: level.details, level: this.level, drift: drift});

// has remuxer dropped video frames located before first keyframe ?
if(data.type === 'video') {
frag.dropped = data.dropped;
}

[data.data1, data.data2].forEach(buffer => {
if (buffer) {
this.pendingAppending++;
Expand Down
2 changes: 1 addition & 1 deletion src/demux/demuxer-worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ var DemuxerWorker = function (self) {
});

observer.on(Event.FRAG_PARSING_DATA, function(ev, data) {
var objData = {event: ev, id : data.id, level : data.level, sn : data.sn, type: data.type, startPTS: data.startPTS, endPTS: data.endPTS, startDTS: data.startDTS, endDTS: data.endDTS, data1: data.data1.buffer, data2: data.data2.buffer, nb: data.nb};
var objData = {event: ev, id : data.id, level : data.level, sn : data.sn, type: data.type, startPTS: data.startPTS, endPTS: data.endPTS, startDTS: data.startDTS, endDTS: data.endDTS, data1: data.data1.buffer, data2: data.data2.buffer, nb: data.nb, , dropped : data.dropped};
// pass data1/data2 as transferable object (no copy)
self.postMessage(objData, [objData.data1, objData.data2]);
});
Expand Down
3 changes: 2 additions & 1 deletion src/demux/demuxer.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ class Demuxer {
startDTS: data.startDTS,
endDTS: data.endDTS,
type: data.type,
nb: data.nb
nb: data.nb,
dropped: data.dropped,
});
break;
case Event.FRAG_PARSING_METADATA:
Expand Down
5 changes: 4 additions & 1 deletion src/demux/tsdemuxer.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
switchLevel() {
this.pmtParsed = false;
this._pmtId = -1;
this._avcTrack = {container : 'video/mp2t', type: 'video', id :-1, sequenceNumber: 0, samples : [], len : 0, nbNalu : 0};
this._avcTrack = {container : 'video/mp2t', type: 'video', id :-1, sequenceNumber: 0, samples : [], len : 0, nbNalu : 0, dropped : 0};
this._aacTrack = {container : 'video/mp2t', type: 'audio', id :-1, sequenceNumber: 0, samples : [], len : 0};
this._id3Track = {type: 'id3', id :-1, sequenceNumber: 0, samples : [], len : 0};
this._txtTrack = {type: 'text', id: -1, sequenceNumber: 0, samples: [], len: 0};
Expand Down Expand Up @@ -361,6 +361,9 @@
samples.push(avcSample);
track.len += length;
track.nbNalu += units2.length;
} else {
// dropped samples, track it
track.dropped++;
}
units2 = [];
length = 0;
Expand Down
5 changes: 4 additions & 1 deletion src/remux/mp4-remuxer.js
Original file line number Diff line number Diff line change
Expand Up @@ -315,8 +315,10 @@ class MP4Remuxer {
}
// next AVC sample DTS should be equal to last sample DTS + last sample duration (in PES timescale)
this.nextAvcDts = lastDTS + mp4SampleDuration*pes2mp4ScaleFactor;
let dropped = track.dropped;
track.len = 0;
track.nbNalu = 0;
track.dropped = 0;
if(outputSamples.length && navigator.userAgent.toLowerCase().indexOf('chrome') > -1) {
let flags = outputSamples[0].flags;
// chrome workaround, mark first sample as being a Random Access Point to avoid sourcebuffer append issue
Expand All @@ -339,7 +341,8 @@ class MP4Remuxer {
startDTS: firstDTS / pesTimeScale,
endDTS: this.nextAvcDts / pesTimeScale,
type: 'video',
nb: outputSamples.length
nb: outputSamples.length,
dropped : dropped
};
this.observer.trigger(Event.FRAG_PARSING_DATA, data);
return data;
Expand Down
3 changes: 2 additions & 1 deletion src/remux/passthrough-remuxer.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ class PassThroughRemuxer {
startPTS: timeOffset,
startDTS: timeOffset,
type: 'audiovideo',
nb: 1
nb: 1,
dropped : 0
});
}
}
Expand Down

0 comments on commit 8e2a964

Please sign in to comment.