Skip to content

Commit ab86fa0

Browse files
author
Greg Rutz
committed
Last fixes for 21Jan2015 EME - Working now
Instead of caching sessionID in the sessionToken, we have a method to retrieve it directly from the EME session. It seems that the sessionID is not automatically created when the session is created. This makes sense since sessions can be created as empty shells to be "loaded" with the state of a persisted session. Updated ProtectionController with all new methods. Updated Stream to make most calls to ProtectionController instead of ProtectionModel Moved key system selection process back to ProtectionExtensions where it belongs
1 parent dd80f9e commit ab86fa0

File tree

7 files changed

+123
-81
lines changed

7 files changed

+123
-81
lines changed

src/streaming/Stream.js

Lines changed: 20 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -59,60 +59,25 @@ MediaPlayer.dependencies.Stream = function () {
5959
},
6060

6161
// Encrypted Media Extensions
62+
pendingNeedKeyData = [],
63+
keySystem = undefined,
6264

6365
handleEMEError = function(message) {
6466
this.errHandler.mediaKeySessionError(message);
6567
this.debug.log(message);
6668
this.reset();
6769
},
6870

69-
keySystemAccess = null,
70-
pendingNeedKeyData = [],
71-
selectKeySystem = function(initData) {
72-
73-
// Does the initData contain a key system supported by the player?
74-
var supportedKS = this.protectionExt.getSupportedKeySystems(initData);
75-
if (supportedKS.length === 0) {
76-
handleEMEError.call(this,"DRM system for this content not supported by the player!");
77-
return;
78-
}
79-
80-
var ksConfig = new MediaPlayer.vo.protection.KeySystemConfiguration(
81-
[new MediaPlayer.vo.protection.MediaCapability(mediaInfos.audio.codec)],
82-
[new MediaPlayer.vo.protection.MediaCapability(mediaInfos.video.codec)]);
83-
var requestedKeySystems = [];
84-
for (var i = 0; i < supportedKS.length; i++) {
85-
requestedKeySystems.push({ ks: supportedKS[i].ks, configs: [ksConfig] });
86-
}
87-
88-
// Callback for KEY_SYSTEM_ACCESS_COMPLETE event
89-
var onKeySystemAccessComplete = function(event) {
90-
this.protectionModel.unsubscribe(MediaPlayer.models.ProtectionModel.eventList.ENAME_KEY_SYSTEM_ACCESS_COMPLETE, this);
91-
if (!event.error) {
92-
keySystemAccess = event.data;
93-
this.debug.log("KeySystem Access Granted (" + keySystemAccess.keySystem.systemString + ")!");
94-
this.protectionModel.selectKeySystem(keySystemAccess);
95-
} else {
96-
handleEMEError.call(this,event.error);
97-
}
98-
};
99-
100-
// Subscribe for event and then perform request
101-
this[MediaPlayer.models.ProtectionModel.eventList.ENAME_KEY_SYSTEM_ACCESS_COMPLETE] = onKeySystemAccessComplete.bind(this);
102-
this.protectionModel.subscribe(MediaPlayer.models.ProtectionModel.eventList.ENAME_KEY_SYSTEM_ACCESS_COMPLETE, this);
103-
this.protectionModel.requestKeySystemAccess(requestedKeySystems);
104-
},
105-
10671
createSession = function(needKeyInitData) {
107-
var initData = MediaPlayer.dependencies.protection.CommonEncryption.getPSSHForKeySystem(this.protectionModel.keySystem, needKeyInitData);
72+
var initData = MediaPlayer.dependencies.protection.CommonEncryption.getPSSHForKeySystem(keySystem, needKeyInitData);
10873
if (initData) {
10974
try {
110-
this.protectionModel.createKeySession(initData, "temporary");
75+
this.protectionController.createKeySession(initData, "temporary");
11176
} catch (error) {
11277
handleEMEError.call(this, "Error creating key session! " + error.message);
11378
}
11479
} else {
115-
handleEMEError.call(this,"Selected key system is " + this.protectionModel.keySystem.systemString + ". needkey/encrypted event contains no initData corresponding to that key system!");
80+
handleEMEError.call(this,"Selected key system is " + keySystem.systemString + ". needkey/encrypted event contains no initData corresponding to that key system!");
11681
}
11782
},
11883

@@ -123,14 +88,15 @@ MediaPlayer.dependencies.Stream = function () {
12388
return;
12489
}
12590

126-
if (this.keySystem) {
91+
if (keySystem) {
12792
// We have a key system
12893
createSession.call(this, event.data.initData);
12994
}
130-
else if (this.keySystem === undefined) {
95+
else if (keySystem === undefined) {
13196
// First time through, so we need to select a key system
132-
this.keySystem = null;
133-
selectKeySystem.call(this, event.data.initData);
97+
keySystem = null;
98+
this.protectionExt.autoSelectKeySystem(this.protectionModel, this.protectionController,
99+
mediaInfos, event.data.initData);
134100
pendingNeedKeyData.push(event.data.initData);
135101
} else {
136102
// We are in the process of selecting a key system, so just save the data
@@ -143,12 +109,12 @@ MediaPlayer.dependencies.Stream = function () {
143109
// events and process any pending initData generated by needkey/encrypted
144110
// events
145111

146-
if (!!this.keySystem && this.keySystem !== this.protectionModel.keySystem) {
112+
if (!!keySystem && keySystem !== this.protectionModel.keySystem) {
147113
handleEMEError.call(this, "DRM: Changing key systems within a single Period is not allowed!");
148114
}
149-
if (!this.keySystem) {
150-
this.keySystem = this.protectionModel.keySystem;
151-
this.protectionModel.keySystem.subscribe(MediaPlayer.dependencies.protection.KeySystem.eventList.ENAME_LICENSE_REQUEST_COMPLETE, this);
115+
if (!keySystem) {
116+
keySystem = this.protectionModel.keySystem;
117+
keySystem.subscribe(MediaPlayer.dependencies.protection.KeySystem.eventList.ENAME_LICENSE_REQUEST_COMPLETE, this);
152118
}
153119
for (var i = 0; i < pendingNeedKeyData.length; i++) {
154120
createSession.call(this, pendingNeedKeyData[i]);
@@ -165,7 +131,7 @@ MediaPlayer.dependencies.Stream = function () {
165131

166132
onKeySessionCreated = function(event) {
167133
if (!event.error) {
168-
this.debug.log("DRM: Session created. SessionID = " + event.data.sessionID);
134+
this.debug.log("DRM: Session created. SessionID = " + event.data.getSessionID());
169135
} else {
170136
handleEMEError.call(this, event.error);
171137
}
@@ -177,7 +143,7 @@ MediaPlayer.dependencies.Stream = function () {
177143

178144
onLicenseRequestComplete = function(e) {
179145
if (!e.error) {
180-
this.debug.log("DRM: License request successful. Session ID = " + e.data.requestData.sessionID);
146+
this.debug.log("DRM: License request successful. Session ID = " + e.data.requestData.getSessionID());
181147
this.protectionController.updateKeySession(e.data.requestData, e.data.message);
182148
} else {
183149
handleEMEError.call(this, e.error);
@@ -186,9 +152,8 @@ MediaPlayer.dependencies.Stream = function () {
186152

187153
onKeyError = function (event) {
188154
var session = event.data.sessionToken,
189-
sessionID = (session.sessionID) ? session.sessionID : "NONE",
190155
msg;
191-
msg = 'DRM: MediaKeyError - sessionId: ' + sessionID + '. ' + event.data.error;
156+
msg = 'DRM: MediaKeyError - sessionId: ' + session.getSessionID() + '. ' + event.data.error;
192157
handleEMEError.call(this, msg);
193158
},
194159

@@ -639,9 +604,9 @@ MediaPlayer.dependencies.Stream = function () {
639604
this.protectionModel.unsubscribe(MediaPlayer.models.ProtectionModel.eventList.ENAME_KEY_SESSION_CREATED, this);
640605
this.protectionModel.unsubscribe(MediaPlayer.models.ProtectionModel.eventList.ENAME_KEY_SESSION_CLOSED, this);
641606
this.protectionModel.unsubscribe(MediaPlayer.models.ProtectionModel.eventList.ENAME_KEY_SESSION_REMOVED, this);
642-
if (!!this.keySystem) {
643-
this.keySystem.unsubscribe(MediaPlayer.dependencies.protection.KeySystem.eventList.ENAME_LICENSE_REQUEST_COMPLETE, this);
644-
this.keySystem = undefined;
607+
if (!!keySystem) {
608+
keySystem.unsubscribe(MediaPlayer.dependencies.protection.KeySystem.eventList.ENAME_LICENSE_REQUEST_COMPLETE, this);
609+
keySystem = undefined;
645610
}
646611

647612
this.protectionController.teardown();

src/streaming/controllers/ProtectionController.js

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,23 +44,36 @@ MediaPlayer.dependencies.ProtectionController = function () {
4444
this.protectionModel.unsubscribe(MediaPlayer.models.ProtectionModel.eventList.ENAME_KEY_MESSAGE, this);
4545
},
4646

47-
/**
48-
* Called in response to a needkey event to auto select a key
49-
* system based on the media and initialization data
50-
*
51-
* @param mediaInfo media information
52-
* @param initData initialization data
53-
*/
54-
selectKeySystem : function(mediaInfo, initData) {
55-
this.protectionExt.autoSelectKeySystem(mediaInfo, initData);
47+
requestKeySystemAccess: function(ksConfiguration) {
48+
this.protectionModel.requestKeySystemAccess(ksConfiguration);
5649
},
5750

58-
createKeySession: function(initData, contentType) {
59-
this.protectionModel.createKeySession(initData, contentType, "cenc");
51+
selectKeySystem: function(keySystemAccess) {
52+
this.protectionModel.selectKeySystem(keySystemAccess);
53+
},
54+
55+
createKeySession: function(initData, sessionType) {
56+
this.protectionModel.createKeySession(initData, sessionType);
6057
},
6158

6259
updateKeySession: function(sessionToken, message) {
6360
this.protectionModel.updateKeySession(sessionToken, message);
61+
},
62+
63+
loadKeySession: function(sessionID) {
64+
this.protectionModel.loadKeySession(sessionID);
65+
},
66+
67+
removeKeySession: function(sessionToken) {
68+
this.protectionModel.removeKeySession(sessionToken);
69+
},
70+
71+
closeKeySession: function(sessionToken) {
72+
this.protectionModel.closeKeySession(sessionToken);
73+
},
74+
75+
setServerCertificate: function(serverCertificate) {
76+
this.protectionModel.setServerCertificate(serverCertificate);
6477
}
6578
};
6679

src/streaming/extensions/ProtectionExtensions.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,60 @@ MediaPlayer.dependencies.ProtectionExtensions = function () {
166166
}
167167
}
168168
return supportedKS;
169+
},
170+
171+
/**
172+
* Select a key system by using the priority-ordered key systems supported
173+
* by the player and the key systems supported by the content
174+
*
175+
* @param {MediaPlayer.models.ProtectionModel} protectionModel
176+
* @param {MediaPlayer.dependencies.ProtectionController} protectionController
177+
* @param {Object} mediaInfos media information set
178+
* @param {MediaPlayer.vo.MediaInfo} mediaInfos.video video media information
179+
* @param {MediaPlayer.vo.MediaInfo} mediaInfos.audio audio media information
180+
* @param {ArrayBuffer} initData the concatenated set of PSSH data found in
181+
* the content indicating DRM support for this content
182+
*/
183+
autoSelectKeySystem: function(protectionModel, protectionController, mediaInfos, initData) {
184+
185+
// Does the initData contain a key system supported by the player?
186+
var supportedKS = this.getSupportedKeySystems(initData);
187+
if (supportedKS.length === 0) {
188+
throw new Error("DRM system for this content not supported by the player!");
189+
}
190+
191+
var ksConfig = new MediaPlayer.vo.protection.KeySystemConfiguration(
192+
[new MediaPlayer.vo.protection.MediaCapability(mediaInfos.audio.codec)],
193+
[new MediaPlayer.vo.protection.MediaCapability(mediaInfos.video.codec)]);
194+
var requestedKeySystems = [];
195+
for (var i = 0; i < supportedKS.length; i++) {
196+
requestedKeySystems.push({ ks: supportedKS[i].ks, configs: [ksConfig] });
197+
}
198+
199+
// Since ProtectionExtensions is a singleton, we need to create an IIFE to wrap the
200+
// event callback and save the values of protectionModel and protectionController.
201+
var self = this;
202+
(function(protMod, protCont) {
203+
204+
// Callback object for KEY_SYSTEM_ACCESS_COMPLETE event
205+
var cbObj = {};
206+
207+
// Subscribe for event and then perform request
208+
cbObj[MediaPlayer.models.ProtectionModel.eventList.ENAME_KEY_SYSTEM_ACCESS_COMPLETE] = function(event) {
209+
protMod.unsubscribe(MediaPlayer.models.ProtectionModel.eventList.ENAME_KEY_SYSTEM_ACCESS_COMPLETE, this);
210+
if (!event.error) {
211+
var keySystemAccess = event.data;
212+
self.debug.log("KeySystem Access Granted (" + keySystemAccess.keySystem.systemString + ")!");
213+
protCont.selectKeySystem(keySystemAccess);
214+
} else {
215+
self.debug.log(event.error);
216+
}
217+
};
218+
219+
protMod.subscribe(MediaPlayer.models.ProtectionModel.eventList.ENAME_KEY_SYSTEM_ACCESS_COMPLETE, cbObj);
220+
protCont.requestKeySystemAccess(requestedKeySystems);
221+
222+
})(protectionModel, protectionController);
169223
}
170224
}
171225
};

src/streaming/models/ProtectionModel_01b.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,11 @@ MediaPlayer.models.ProtectionModel_01b = function () {
328328
var newSession = {
329329
prototype: (new MediaPlayer.models.SessionToken()).prototype,
330330
sessionID: null,
331-
initData: initData
331+
initData: initData,
332+
333+
getSessionID: function() {
334+
return this.sessionID;
335+
}
332336
};
333337
pendingSessions.push(newSession);
334338

src/streaming/models/ProtectionModel_21Jan2015.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@ MediaPlayer.models.ProtectionModel_21Jan2015 = function () {
103103
var token = {
104104
prototype: (new MediaPlayer.models.SessionToken()).prototype,
105105
session: session,
106-
sessionID: session.sessionId,
107106
initData: initData,
108107

109108
// This is our main event handler for all desired MediaKeySession events
@@ -124,6 +123,10 @@ MediaPlayer.models.ProtectionModel_21Jan2015 = function () {
124123
}
125124
},
126125

126+
getSessionID: function() {
127+
return this.session.sessionId;
128+
},
129+
127130
getExpirationTime: function() {
128131
return this.session.expiration;
129132
},
@@ -141,7 +144,7 @@ MediaPlayer.models.ProtectionModel_21Jan2015 = function () {
141144
session.closed.then(function () {
142145
removeSession(token);
143146
self.notify(MediaPlayer.models.ProtectionModel.eventList.ENAME_KEY_SESSION_CLOSED,
144-
token.sessionID);
147+
token.getSessionID());
145148
});
146149

147150
// Add to our session list
@@ -289,10 +292,10 @@ MediaPlayer.models.ProtectionModel_21Jan2015 = function () {
289292
var self = this;
290293
session.remove().then(function () {
291294
self.notify(MediaPlayer.models.ProtectionModel.eventList.ENAME_KEY_SESSION_REMOVED,
292-
sessionToken.sessionID);
295+
sessionToken.getSessionID());
293296
}).catch(function (error) {
294297
self.notify(MediaPlayer.models.ProtectionModel.eventList.ENAME_KEY_SESSION_REMOVED,
295-
null, "Error removing session (" + sessionToken.sessionID + "). " + error.name);
298+
null, "Error removing session (" + sessionToken.getSessionID() + "). " + error.name);
296299
});
297300
},
298301

@@ -307,7 +310,7 @@ MediaPlayer.models.ProtectionModel_21Jan2015 = function () {
307310
// Send our request to the key session
308311
session.close().catch(function(error) {
309312
self.notify(MediaPlayer.models.ProtectionModel.eventList.ENAME_KEY_SESSION_CLOSED,
310-
null, "Error closing session (" + sessionToken.sessionID + ") " + error.name);
313+
null, "Error closing session (" + sessionToken.getSessionID() + ") " + error.name);
311314
});
312315
}
313316
};

src/streaming/models/ProtectionModel_3Feb2014.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ MediaPlayer.models.ProtectionModel_3Feb2014 = function () {
6767
return {
6868
prototype: (new MediaPlayer.models.SessionToken()).prototype,
6969
session: keySession,
70-
sessionID: keySession.sessionId,
7170
initData: initData,
7271

7372
// This is our main event handler for all desired MediaKeySession events
@@ -94,9 +93,13 @@ MediaPlayer.models.ProtectionModel_3Feb2014 = function () {
9493

9594
case api.close:
9695
self.notify(MediaPlayer.models.ProtectionModel.eventList.ENAME_KEY_SESSION_CLOSED,
97-
this.sessionID);
96+
this.getSessionID());
9897
break;
9998
}
99+
},
100+
101+
getSessionID: function() {
102+
return this.session.sessionId;
100103
}
101104
};
102105
};

src/streaming/vo/protection/SessionToken.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,19 +43,19 @@ MediaPlayer.models.SessionToken = function () {
4343
MediaPlayer.models.SessionToken.prototype = {
4444

4545
/**
46-
* The unique session ID designated to this session
46+
* The initialization data used to create this session
4747
*
48-
* {Number} the session ID or null if the implementation does
49-
* not support session IDs
48+
* {Uint8Array} initialization data
5049
*/
51-
sessionID: null,
50+
initData: null,
5251

5352
/**
54-
* The initialization data used to create this session
53+
* The unique session ID designated to this session
5554
*
56-
* {Uint8Array} initialization data
55+
* @return {string} the session ID or the empty string if the implementation
56+
* does not support session IDs or the sessionID has not yet been established
5757
*/
58-
initData: null,
58+
getSessionID: function() { return ""; },
5959

6060
/**
6161
* The time, in milliseconds since 01 January, 1970 UTC, after which

0 commit comments

Comments
 (0)