Skip to content
This repository has been archived by the owner on Oct 20, 2022. It is now read-only.

Commit

Permalink
Merge branch 'release/1.9.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
bbert committed Mar 8, 2017
2 parents 09c548e + eb8785c commit ee84f4e
Show file tree
Hide file tree
Showing 34 changed files with 707 additions and 541 deletions.
21 changes: 21 additions & 0 deletions RELEASES NOTES.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
### Release Notes v1.9.0 (2017/03/08)
* Consolidate EME/Protection layer management:
* - Start playback only once ProtectionController is initialized (avoids conflicts on Chrome when setting MediaKeys on <video>)
* - Reset Streams and the <video> source before resetting ProtectionController and MediaKeys (avoid playback issue on Firefox)
* - Correct application-level's license persistence management
* - Listen for 'waitingforkey' event only once the license is usable
* - Add new error code MEDIA_KEYERR_EXPIRED for expired licences (instead of MEDIA_ERR_ENCRYPTED)
* Enrich MEDIA_ERR_CODEC_UNSUPPORTED error's data
* Stop/reset current playback when an error is raised
* [MSS] Consider empty FourCC field only for audio streams
* [HLS] Add error code HLS_INVALID_PACKET_ERROR in case of invalid MPEG2-TS chunks (for example if unsuccessfully decrypted)
* [HLS] Add error code HLS_INVALID_KEY_ERROR in case of invalid AES keys
* Bugs fixing:
* - [HLS] Fix H.264 IDR access units detection
* - [HLS] Fix segment lists processing when switching among alternative tracks
* - [HLS] Fix reset process when AES key file is being downloaded
* - [HLS] Fix DVR window refresh when playback is paused
* - [MSS] Fix MP4 media fragments processing in case of trick play (when sample_duration is set as default in tfhd)
* - Fix VTT parser if X-TIMESTAMP-MAP filed is missing
* - Fix ABR DownloadRatioRule's bandwidth calculation in case of aborted requests

### Release Notes v1.8.0 (2017/01/23)
* Implements license persistence at application layer (protection model 21Jan2015) according to player configuration (by default no license persistence)
* [MSS] Add support for MSS static streams starting at t > 0 (live delinearization use case)
Expand Down
4 changes: 2 additions & 2 deletions app/js/dash/FragmentExtensions.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ Dash.dependencies.FragmentExtensions = function () {
deferred.reject(errorStr);
};

request.responseType = "arraybuffer";
request.open("GET", url);
request.responseType = "arraybuffer";
request.send(null);

return deferred.promise;
Expand All @@ -158,4 +158,4 @@ Dash.dependencies.FragmentExtensions = function () {

Dash.dependencies.FragmentExtensions.prototype = {
constructor: Dash.dependencies.FragmentExtensions
};
};
15 changes: 14 additions & 1 deletion app/js/hls/HlsDemux.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ Hls.dependencies.HlsDemux = function() {
return null;
},

checkTsPacket = function(data) {
var tsPacket = new mpegts.ts.TsPacket();
return tsPacket.checkSyncWord(data.subarray(0, mpegts.ts.TsPacket.prototype.TS_PACKET_SIZE));
},

getPAT = function(data) {
var tsPacket = getTsPacket.call(this, data, 0, mpegts.ts.TsPacket.prototype.PAT_PID);

Expand Down Expand Up @@ -434,6 +439,14 @@ Hls.dependencies.HlsDemux = function() {
track,
streamTypeDesc;

// First, check that packet is really a TS packet
if( !checkTsPacket.call(this,data) ) {
throw {
name: MediaPlayer.dependencies.ErrorHandler.prototype.HLS_INVALID_PACKET_ERROR,
message: "Failed to demux, packet is invalid, missing SYNC byte"
};
}

// Get PSI (PAT, PMT)
pat = getPAT.call(this, data);
if (pat === null) {
Expand Down Expand Up @@ -596,4 +609,4 @@ Hls.dependencies.HlsDemux = function() {

Hls.dependencies.HlsDemux.prototype = {
constructor: Hls.dependencies.HlsDemux
};
};
43 changes: 28 additions & 15 deletions app/js/hls/HlsFragmentController.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
Hls.dependencies.HlsFragmentController = function() {
Hls.dependencies.HlsFragmentController = function () {
"use strict";

var decryptionInfos = {},

generateMediaSegment = function(data, request) {
generateMediaSegment = function (data, request) {
var i = 0,
// Demultiplex HLS chunk to get samples
tracks = rslt.hlsDemux.demux(new Uint8Array(data), request);
Expand All @@ -42,7 +42,7 @@ Hls.dependencies.HlsFragmentController = function() {
return rslt.mp4Processor.generateInitMediaSegment(tracks);
},

createInitializationVector = function(segmentNumber) {
createInitializationVector = function (segmentNumber) {
var uint8View = new Uint8Array(16),
i = 0;

Expand All @@ -53,7 +53,7 @@ Hls.dependencies.HlsFragmentController = function() {
return uint8View;
},

decrypt = function(data, decryptionInfo) {
decrypt = function (data, decryptionInfo) {

var t = new Date();

Expand All @@ -79,7 +79,7 @@ Hls.dependencies.HlsFragmentController = function() {
return decrypter.decrypt(data);
},

loadDecryptionKey = function(decryptionInfo) {
loadDecryptionKey = function (decryptionInfo) {
var deferred = Q.defer();

this.debug.log("[HlsFragmentController]", "Load decryption key: " + decryptionInfo.uri);
Expand All @@ -91,7 +91,7 @@ Hls.dependencies.HlsFragmentController = function() {
decryptionInfo.key = new Uint8Array(request.response);
deferred.resolve();
},
function(request) {
function (request) {
if (!request || request.aborted) {
deferred.reject();
} else {
Expand All @@ -110,7 +110,7 @@ Hls.dependencies.HlsFragmentController = function() {
return deferred.promise;
},

decryptSegment = function(bytes, request) {
decryptSegment = function (bytes, request) {
var deferred = Q.defer(),
decryptionInfo,
self = this;
Expand All @@ -130,7 +130,15 @@ Hls.dependencies.HlsFragmentController = function() {
} else {
decryptionInfo = request.decryptionInfo;
loadDecryptionKey.call(this, decryptionInfo).then(
function() {
function () {

// check key
if (decryptionInfo.key && decryptionInfo.key.byteLength !== 16) {
return deferred.reject({
name: MediaPlayer.dependencies.ErrorHandler.prototype.HLS_INVALID_KEY_ERROR,
message: "Invalid HLS key - Key length (" + decryptionInfo.key.byteLength + ") does not respect specification"
});
}
decryptionInfos[decryptionInfo.uri] = decryptionInfo;
deferred.resolve(decrypt.call(self, bytes, decryptionInfo));
},
Expand All @@ -149,7 +157,7 @@ Hls.dependencies.HlsFragmentController = function() {
rslt.hlsDemux = undefined;
rslt.mp4Processor = undefined;

rslt.process = function(bytes, request/*, representation*/) {
rslt.process = function (bytes, request /*, representation*/ ) {
var deferred = Q.defer(),
result = null;

Expand All @@ -170,13 +178,18 @@ Hls.dependencies.HlsFragmentController = function() {
}

// Decrypt the segment if encrypted
decryptSegment.call(rslt, bytes, request).then(function(data) {
decryptSegment.call(rslt, bytes, request).then(function (data) {
//console.saveBinArray(data, request.url.substring(request.url.lastIndexOf('/') + 1));
try {
// Generate media segment (moof) from demultiplexed MPEG2-TS chunk
result = generateMediaSegment(data, request);
rslt.sequenceNumber++;
deferred.resolve(result);
// First check stream has not been reset while decrypting the chunk
if (!rslt.manifestModel.getValue()) {
deferred.resolve(null);
} else {
// Generate media segment (moof) from demultiplexed MPEG2-TS chunk
result = generateMediaSegment(data, request);
rslt.sequenceNumber++;
deferred.resolve(result);
}
} catch (e) {
deferred.reject(e);
}
Expand All @@ -193,4 +206,4 @@ Hls.dependencies.HlsFragmentController = function() {

Hls.dependencies.HlsFragmentController.prototype = {
constructor: Hls.dependencies.HlsFragmentController
};
};
53 changes: 36 additions & 17 deletions app/js/hls/HlsParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ Hls.dependencies.HlsParser = function() {
return false;
}

this.debug.log(manifest);
// this.debug.log(manifest);

if (manifest.indexOf('#EXTM3U') !== 0) {
return false;
Expand Down Expand Up @@ -290,13 +290,15 @@ Hls.dependencies.HlsParser = function() {
postProcess = function(manifest, quality) {
var deferred = Q.defer(),
period = manifest.Period_asArray[0],
// Consider video AdaptationSet (always the 1st one)
adaptationSet = period.AdaptationSet_asArray[0],
// Consider representation of current and downloaded quality
representation = adaptationSet.Representation_asArray[quality],
request = new MediaPlayer.vo.SegmentRequest(),
self = this,
manifestDuration,
mpdLoadedTime;

mpdLoadedTime,
maxSequenceNumber,
i, j, k;

period.start = 0; //segmentTimes[adaptationSet.Representation_asArray[0].SegmentList.startNumber];

Expand All @@ -315,20 +317,38 @@ Hls.dependencies.HlsParser = function() {

// Dynamic use case
if (manifest.type === "dynamic") {
// => set manifest refresh period as the duration of 1 fragment/chunk
//manifest.minimumUpdatePeriod = representation.SegmentList.duration;

// => set availabilityStartTime property
// Set availabilityStartTime property
mpdLoadedTime = new Date();
manifest.availabilityStartTime = new Date(mpdLoadedTime.getTime() - (manifestDuration * 1000));

// => set timeshift buffer depth
// Set timeshift buffer depth
manifest.timeShiftBufferDepth = manifestDuration;
}

// Set minBufferTime
manifest.minBufferTime = representation.SegmentList.duration * 3; //MediaPlayer.dependencies.BufferExtensions.DEFAULT_MIN_BUFFER_TIME

// Align segment lists of all adaptations
maxSequenceNumber = Math.max.apply(null, period.AdaptationSet_asArray.map(function(adaptation) {
var repIndex = quality > adaptation.Representation_asArray.length ? 0 : quality;
return adaptation.Representation_asArray[repIndex].SegmentList.startNumber;
}));
for (i = 0; i < period.AdaptationSet_asArray.length; i++) {
var adaptation = period.AdaptationSet_asArray[i];
for (j = 0; j < adaptation.Representation_asArray.length; j++) {
if (adaptation.Representation_asArray[j].SegmentList) {
var segments = adaptation.Representation_asArray[j].SegmentList.SegmentURL_asArray;
if (segments[0].sequenceNumber < maxSequenceNumber) {
removeSegments(segments, maxSequenceNumber);
segments[0].time = 0;
for (k = 1; k < segments.length; k++) {
segments[k].time = segments[k - 1].time + segments[k - 1].duration;
}
}
}
}
}

// Download initialization data (PSI, IDR...) of 1st representation to obtain codec information
representation = adaptationSet.Representation_asArray[quality];
request.type = "Initialization Segment";
Expand All @@ -352,13 +372,12 @@ Hls.dependencies.HlsParser = function() {
};

var onError = function() {
// ERROR
deferred.resolve();
};

if (representation.codecs === "") {
self.debug.log("[HlsParser]", "Load initialization segment: " + request.url);
self.fragmentLoader.load(request).then(onLoaded.bind(self, representation), onError.bind(self));
this.debug.log("[HlsParser]", "Load initialization segment: " + request.url);
this.fragmentLoader.load(request).then(onLoaded.bind(this, representation), onError.bind(this));
} else {
deferred.resolve();
}
Expand All @@ -380,8 +399,8 @@ Hls.dependencies.HlsParser = function() {
},

updatePlaylist = function(representation, adaptation) {
var deferred = Q.defer(),
self = this;
var self = this,
deferred = Q.defer();

this.debug.log("[HlsParser]", "Load playlist manifest: " + representation.url);
xhrLoader = new MediaPlayer.dependencies.XHRLoader();
Expand Down Expand Up @@ -420,7 +439,8 @@ Hls.dependencies.HlsParser = function() {
},

processManifest = function(manifest, baseUrl) {
var deferred = Q.defer(),
var self = this,
deferred = Q.defer(),
mpd,
period,
adaptationsSets = [],
Expand All @@ -434,7 +454,6 @@ Hls.dependencies.HlsParser = function() {
media,
quality,
playlistDefers = [],
self = this,
i = 0;

if (manifest.indexOf('#EXTM3U') !== 0) {
Expand Down Expand Up @@ -534,7 +553,7 @@ Hls.dependencies.HlsParser = function() {
representation = adaptationsSets[0].Representation_asArray[quality];
playlistDefers.push(updatePlaylist.call(this, representation, adaptationSet));

// alternative renditions of the same content (alternative audio tracks or subtitles) #EXT-X-MEDIA
// Alternative renditions of the same content (alternative audio tracks or subtitles) #EXT-X-MEDIA
medias = getMedias(manifest);
for (i =0; i < medias.length; i++) {
media = medias[i];
Expand Down
Loading

0 comments on commit ee84f4e

Please sign in to comment.