Skip to content

Commit

Permalink
Support for EME offline. Issue #23
Browse files Browse the repository at this point in the history
Change-Id: I27632f196b6ec65ace67d3ee9794683fd9f639ab
  • Loading branch information
natalieharris authored and Gerrit Code Review committed Mar 25, 2015
1 parent 069d8c3 commit c97ebf3
Show file tree
Hide file tree
Showing 8 changed files with 357 additions and 122 deletions.
105 changes: 82 additions & 23 deletions lib/media/eme_manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ goog.require('shaka.util.PublicPromise');
goog.require('shaka.util.Uint8ArrayUtils');


/**
* @event shaka.media.EmeManager.SessionReadyEvent
* @description Fired when a new MediaKeySession is ready.
* @property {string} type 'sessionReady'
* @property {MediaKeySession} detail
*/



/**
* Creates the EME manager.
Expand All @@ -38,6 +46,7 @@ goog.require('shaka.util.Uint8ArrayUtils');
* @param {!HTMLVideoElement} video The video element.
* @param {!shaka.player.IVideoSource} videoSource The video source.
*
* @fires shaka.media.EmeManager.SessionReadyEvent
* @fires shaka.player.Player.ErrorEvent
*
* @constructor
Expand Down Expand Up @@ -320,16 +329,20 @@ shaka.media.EmeManager.prototype.setupMediaKeys_ = function(mediaKeys) {
shaka.util.TypedBind(this, function() {
shaka.asserts.assert(this.video_.mediaKeys);
shaka.asserts.assert(this.video_.mediaKeys == this.mediaKeys_);
this.generateFakeEncryptedEvents_();

// Explicit init data for any one stream is sufficient to suppress
// 'encrypted' events for all streams.
if (this.drmScheme_.initDatas.length == 0) {
this.eventManager_.listen(
this.video_,
'encrypted',
/** @type {shaka.util.EventManager.ListenerType} */(
this.onEncrypted_.bind(this)));
if (this.videoSource_.getSessionIds().length > 0) {
this.loadSessions_();
} else {
this.generateFakeEncryptedEvents_();

// Explicit init data for any one stream is sufficient to suppress
// 'encrypted' events for all streams.
if (this.drmScheme_.initDatas.length == 0) {
this.eventManager_.listen(
this.video_,
'encrypted',
/** @type {shaka.util.EventManager.ListenerType} */(
this.onEncrypted_.bind(this)));
}
}
}));
};
Expand Down Expand Up @@ -383,17 +396,7 @@ shaka.media.EmeManager.prototype.onEncrypted_ = function(event) {
}

shaka.log.info('onEncrypted_', initData, event);

var session = this.mediaKeys_.createSession();
this.sessions_.push(session);

this.eventManager_.listen(session, 'message',
/** @type {shaka.util.EventManager.ListenerType} */(
this.onSessionMessage_.bind(this)));
this.eventManager_.listen(session, 'keystatuseschange',
/** @type {shaka.util.EventManager.ListenerType} */(
this.onKeyStatusChange_.bind(this)));

var session = this.createSession_();
var p = session.generateRequest(event.initDataType, event.initData);
this.requestGenerated_[initDataKey] = true;

Expand All @@ -405,6 +408,50 @@ shaka.media.EmeManager.prototype.onEncrypted_ = function(event) {
this.dispatchEvent(event);
})
);
this.sessions_.push(session);
};


/**
* Loads persistent sessions via sessionId saved within videoSource.
* @private
*/
shaka.media.EmeManager.prototype.loadSessions_ = function() {
var persistentSessionIds = this.videoSource_.getSessionIds();
shaka.asserts.assert(persistentSessionIds.length > 0);
for (var i = 0; i < persistentSessionIds.length; ++i) {
var session = this.createSession_();
var p = session.load(persistentSessionIds[i]);
this.sessions_.push(session);

p.catch(shaka.util.TypedBind(this,
/** @param {!Error} error */
function(error) {
var event = shaka.util.FakeEvent.createErrorEvent(error);
this.dispatchEvent(event);
})
);
}
};


/**
* Creates a new MediaKeySession.
* @return {MediaKeySession}
* @private
*/
shaka.media.EmeManager.prototype.createSession_ = function() {
var session = this.videoSource_.isOffline() ?
this.mediaKeys_.createSession('persistent-license') :
this.mediaKeys_.createSession();

this.eventManager_.listen(session, 'message',
/** @type {shaka.util.EventManager.ListenerType} */(
this.onSessionMessage_.bind(this)));
this.eventManager_.listen(session, 'keystatuseschange',
/** @type {shaka.util.EventManager.ListenerType} */(
this.onKeyStatusChange_.bind(this)));
return session;
};


Expand Down Expand Up @@ -476,10 +523,13 @@ shaka.media.EmeManager.prototype.requestLicense_ =
response = postProcessor(response);
return session.update(response);
})
).then(
).then(shaka.util.TypedBind(this,
function() {
shaka.log.info('onSessionReady_', session);
}
var event = shaka.util.FakeEvent.create(
{type: 'sessionReady', detail: session});
this.dispatchEvent(event);
})
).catch(shaka.util.TypedBind(this,
/** @param {!Error} error */
function(error) {
Expand All @@ -491,6 +541,15 @@ shaka.media.EmeManager.prototype.requestLicense_ =
};


/**
* Returns the DRM Scheme information.
* @return {shaka.player.DrmSchemeInfo}
*/
shaka.media.EmeManager.prototype.getDrmScheme = function() {
return this.drmScheme_;
};


/**
* A map of key statuses to errors. Not every key status appears in the map,
* in which case that key status is not treated as an error.
Expand Down
12 changes: 12 additions & 0 deletions lib/player/http_video_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,15 @@ shaka.player.HttpVideoSource.prototype.setRestrictions =
// nop
};


/** @override */
shaka.player.HttpVideoSource.prototype.getSessionIds = function() {
return [];
};


/** @override */
shaka.player.HttpVideoSource.prototype.isOffline = function() {
return false;
};

15 changes: 15 additions & 0 deletions lib/player/i_video_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,18 @@ shaka.player.IVideoSource.prototype.enableAdaptation = function(enabled) {};
*/
shaka.player.IVideoSource.prototype.setRestrictions = function(restrictions) {};


/**
* Gets the available session IDs.
*
* @return {!Array.<string>}
*/
shaka.player.IVideoSource.prototype.getSessionIds = function() {};


/**
* Determines if the stream is used for offline playback.
*
* @return {boolean} True if the stream is stored or being stored.
*/
shaka.player.IVideoSource.prototype.isOffline = function() {};
Loading

0 comments on commit c97ebf3

Please sign in to comment.