Skip to content

Commit

Permalink
buffer-controller: support async sourcebuffer creations
Browse files Browse the repository at this point in the history
sourcebuffers are now created once all codec infos are received from all stream controllers
related to https://github.com/dailymotion/hls.js/issues/30
  • Loading branch information
mangui committed Apr 29, 2016
1 parent f0e4fb7 commit 88d339b
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 16 deletions.
57 changes: 43 additions & 14 deletions src/controller/buffer-controller.js
Expand Up @@ -14,6 +14,7 @@ class BufferController extends EventHandler {
super(hls,
Event.MEDIA_ATTACHING,
Event.MEDIA_DETACHING,
Event.MANIFEST_PARSED,
Event.BUFFER_RESET,
Event.BUFFER_APPENDING,
Event.BUFFER_CODECS,
Expand All @@ -23,12 +24,24 @@ class BufferController extends EventHandler {
// Source Buffer listeners
this.onsbue = this.onSBUpdateEnd.bind(this);
this.onsbe = this.onSBUpdateError.bind(this);
this.pendingTracks = {};
}

destroy() {
EventHandler.prototype.destroy.call(this);
}

onManifestParsed(data) {
let audioExpected = data.audio,
videoExpected = data.video,
sourceBufferNb = 0;
if (audioExpected || videoExpected) {
sourceBufferNb = (audioExpected ? 1 : 0) + (videoExpected ? 1 : 0);
logger.log(`${sourceBufferNb} sourceBuffer(s) expected`);
}
this.sourceBufferNb = sourceBufferNb;
}

onMediaAttaching(data) {
var media = this.media = data.media;
// setup the media source
Expand Down Expand Up @@ -66,7 +79,7 @@ class BufferController extends EventHandler {
this.media.removeAttribute('src');
this.mediaSource = null;
this.media = null;
this.pendingTracks = null;
this.pendingTracks = {};
this.sourceBuffer = {};
}
this.onmso = this.onmse = this.onmsc = null;
Expand All @@ -78,11 +91,21 @@ class BufferController extends EventHandler {
this.hls.trigger(Event.MEDIA_ATTACHED, { media : this.media });
// once received, don't listen anymore to sourceopen event
this.mediaSource.removeEventListener('sourceopen', this.onmso);
// if any buffer codecs pending, treat it here.
var pendingTracks = this.pendingTracks;
if (pendingTracks) {
this.onBufferCodecs(pendingTracks);
this.pendingTracks = null;
this.checkPendingTracks();
}

checkPendingTracks() {
// if any buffer codecs pending, check if we have enough to create sourceBuffers
let pendingTracks = this.pendingTracks,
pendingTracksNb = Object.keys(pendingTracks).length;
// if any pending tracks and (if nb of pending tracks matching expected nb or if unknoown expected nb)
if (pendingTracksNb && (
this.sourceBufferNb === pendingTracksNb ||
this.sourceBufferNb === 0)) {
// ok, let's create them now !
this.createSourceBuffers(pendingTracks);
this.pendingTracks = {};
// append any pending segments now !
this.doAppending();
}
}
Expand Down Expand Up @@ -137,13 +160,19 @@ class BufferController extends EventHandler {
}

onBufferCodecs(tracks) {
var sb,trackName,track, codec, mimeType;

if (!this.media) {
this.pendingTracks = tracks;
return;
// if source buffer(s) not created yet, appended buffer tracks in this.pendingTracks
// if sourcebuffers already created, do nothing ...
if (Object.keys(this.sourceBuffer).length === 0) {
for (var trackName in tracks) { this.pendingTracks[trackName] = tracks[trackName]; }
if (this.media) {
// try to create sourcebuffers if media attached
this.checkPendingTracks();
}
}
}

createSourceBuffers(tracks) {
var sb,trackName,track, codec, mimeType;
var sourceBuffer = this.sourceBuffer,mediaSource = this.mediaSource;

for (trackName in tracks) {
Expand Down Expand Up @@ -236,7 +265,7 @@ class BufferController extends EventHandler {

doAppending() {
var hls = this.hls, sourceBuffer = this.sourceBuffer, segments = this.segments;
if (sourceBuffer) {
if (Object.keys(sourceBuffer).length) {
if (this.media.error) {
segments = [];
logger.error('trying to append although a media error occured, flush segment and abort');
Expand All @@ -248,10 +277,10 @@ class BufferController extends EventHandler {
return;
}
}
if (segments.length) {
if (segments && segments.length) {
var segment = segments.shift();
try {
//logger.log(`appending ${segment.type} SB, size:${segment.data.length});
//logger.log(`appending ${segment.type} SB, size:${segment.data.length}`);
if(sourceBuffer[segment.type]) {
sourceBuffer[segment.type].appendBuffer(segment.data);
this.appendError = 0;
Expand Down
4 changes: 2 additions & 2 deletions src/controller/level-controller.js
Expand Up @@ -97,7 +97,7 @@ class LevelController extends EventHandler {
break;
}
}
hls.trigger(Event.MANIFEST_PARSED, {levels: this._levels, firstLevel: this._firstLevel, stats: data.stats});
hls.trigger(Event.MANIFEST_PARSED, {levels: this._levels, firstLevel: this._firstLevel, stats: data.stats, audio : audioCodecFound, video : videoCodecFound});
} else {
hls.trigger(Event.ERROR, {type: ErrorTypes.MEDIA_ERROR, details: ErrorDetails.MANIFEST_INCOMPATIBLE_CODECS_ERROR, fatal: true, url: hls.url, reason: 'no level with compatible codecs found in manifest'});
}
Expand Down Expand Up @@ -242,7 +242,7 @@ class LevelController extends EventHandler {
if (!this.timer || timerInterval !== this.timerInterval) {
clearInterval(this.timer);
this.timer = setInterval(this.ontick, 1000 * timerInterval);
this.timerInterval = timerInterval;
this.timerInterval = timerInterval;
}
}
if (!data.details.live && this.timer) {
Expand Down

0 comments on commit 88d339b

Please sign in to comment.