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 Jun 30, 2016
1 parent 8ca82e7 commit a49ba2b
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
Expand Up @@ -282,16 +282,16 @@ class StreamController extends EventHandler {
}
if(frag) {
start = frag.start;
//logger.log('find SN matching with pos:' + bufferEnd + ':' + frag.sn);
logger.log('find SN matching with pos:' + bufferEnd + ':' + frag.sn);
if (fragPrevious && frag.level === fragPrevious.level && frag.sn === fragPrevious.sn) {
if (frag.sn < levelDetails.endSN) {
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 @@ -796,7 +796,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 @@ -892,12 +892,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
Expand Up @@ -38,7 +38,7 @@ var DemuxerWorker = function (self) {
});

observer.on(Event.FRAG_PARSING_DATA, function(ev, data) {
var objData = {event: ev, 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, 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
Expand Up @@ -88,7 +88,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
Expand Up @@ -37,7 +37,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 @@ -355,6 +355,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
Expand Up @@ -247,8 +247,10 @@ class MP4Remuxer {
}
// next AVC sample DTS should be equal to last sample DTS + last sample duration
this.nextAvcDts = dtsnorm + lastSampleDuration * pes2mp4ScaleFactor;
let dropped = track.dropped;
track.len = 0;
track.nbNalu = 0;
track.dropped = 0;
if(samples.length && navigator.userAgent.toLowerCase().indexOf('chrome') > -1) {
flags = samples[0].flags;
// chrome workaround, mark first sample as being a Random Access Point to avoid sourcebuffer append issue
Expand All @@ -267,7 +269,8 @@ class MP4Remuxer {
startDTS: firstDTS / pesTimeScale,
endDTS: this.nextAvcDts / pesTimeScale,
type: 'video',
nb: samples.length
nb: samples.length,
dropped : dropped
});
}

Expand Down
3 changes: 2 additions & 1 deletion src/remux/passthrough-remuxer.js
Expand Up @@ -62,7 +62,8 @@ class PassThroughRemuxer {
startPTS: timeOffset,
startDTS: timeOffset,
type: 'audiovideo',
nb: 1
nb: 1,
dropped : 0
});
}
}
Expand Down

0 comments on commit a49ba2b

Please sign in to comment.