-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
live stream can switch from clear content to encrypted content #1094 #1217
Changes from 3 commits
809444f
e69bca7
e6f6f72
bcc217f
66780a6
71df416
cac93de
40339d7
b4cc59c
6ecf267
9f95fbb
3d44c36
fefc493
db39469
e12cf4b
fc8f6e2
e729711
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -58,6 +58,7 @@ Rostislav Hejduk <[email protected]> | |
Sam Dutton <[email protected]> | ||
Sanborn Hilland <[email protected]> | ||
Sandra Lokshina <[email protected]> | ||
Semih Gokceoglu <[email protected]> | ||
Seth Madison <[email protected]> | ||
Theodore Abshire <[email protected]> | ||
Thomas Stephens <[email protected]> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -465,6 +465,7 @@ shaka.media.DrmEngine.prototype.getDrmInfo = function() { | |
shaka.media.DrmEngine.prototype.prepareMediaKeyConfigs_ = | ||
function(manifest, offline, configsByKeySystem, keySystemsInOrder) { | ||
var clearKeyDrmInfo = this.configureClearKey_(); | ||
var configDrmInfos = this.getDrmInfosByConfig_(manifest); | ||
|
||
manifest.periods.forEach(function(period) { | ||
period.variants.forEach(function(variant) { | ||
|
@@ -474,6 +475,14 @@ shaka.media.DrmEngine.prototype.prepareMediaKeyConfigs_ = | |
variant.drmInfos = [clearKeyDrmInfo]; | ||
} | ||
|
||
// If initial manifest contains unencrypted content, | ||
// drm configuration overrides DrmInfo so drmEngine can be activated. | ||
// Thus, player can play encrypted content if live stream switches from | ||
// unencrypted content to encrypted content during live stream. | ||
if (!!configDrmInfos) { | ||
variant.drmInfos = configDrmInfos; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This drmInfos is going to be generated with default drmInfos. When stream switches to encrypted content, encrypted content might have a different configured drmInfos. At this situation, I do not know if there is any risk that having different drm info settings may break the playback. As for my tests in our live streams, I could not reproduce any issue. |
||
} | ||
|
||
variant.drmInfos.forEach(function(drmInfo) { | ||
this.fillInDrmInfoDefaults_(drmInfo); | ||
|
||
|
@@ -774,6 +783,48 @@ shaka.media.DrmEngine.prototype.configureClearKey_ = function() { | |
}; | ||
|
||
|
||
/** | ||
* Returns the DrmInfo that is generated by drm configation. | ||
* It activates DrmEngine if drm configs have keySystems. | ||
* @param {!shakaExtern.Manifest} manifest | ||
* @return {(Array.<{object}>|null)} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be: I think |
||
* @private | ||
*/ | ||
shaka.media.DrmEngine.prototype.getDrmInfosByConfig_ = | ||
function(manifest) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style nit: It looks like this should fit on the previous line |
||
var config = this.config_; | ||
if (!config) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @joeyparrish suggested me a way that adding a propery to drm config may be a better way to understand this expectation. I did not add this property in this PR just in case you may be interested the "reinitialization drm" solution. If you do not, I will update this PR with a new config property that allows this method. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You shouldn't need to deal with a null |
||
return null; | ||
} | ||
|
||
var serverKeys = Object.keys(config.servers || {}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You don't need to worry about null config.servers, either, since |
||
|
||
if (!serverKeys.length) { | ||
return null; | ||
} | ||
|
||
var isEncryptedContent = manifest.periods.every(function(period) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think |
||
period.variants.every(function(variant) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here. I believe this should be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you for reviewing, @joeyparrish . Last min I reversed this behavior from unencrypted to encrypted. I should have noticed this mistake. Apologies. On the other hand, it seems @TheModMaker 's suggestion more simple than mine, but it throws an error. I was going to trace that error, but I was interrupted by something else and I could not spend enough time. Do you think it is not necessary to chase his solution? Thanks again. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is simpler, but I think we should keep ignoreDrmInfo separate. It serves a different purpose, and it isn't on by default. What you are changing here should, in my opinion, be default behavior to match developer expectations. |
||
return !!variant.drmInfos.length; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need to do !!, since length is a number which will implicitly convert to boolean. |
||
}); | ||
}); | ||
|
||
// Only creates for clear contents | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment seems a little bit vague. How about this one: // We only want to create phony DrmInfos when none are provided by the manifest. |
||
if (isEncryptedContent) { | ||
return null; | ||
} | ||
|
||
return serverKeys.map(function(keySystem) { | ||
return { | ||
// ignoring other properties | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With the recommended change to return |
||
// since fillInDrmInfoDefaults_ fills default values | ||
keySystem: keySystem, | ||
licenseServerUri: config.servers[keySystem] | ||
}; | ||
}); | ||
}; | ||
|
||
|
||
/** | ||
* Creates a DrmInfo object describing the settings used to initialize the | ||
* engine. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -374,18 +374,37 @@ describe('DrmEngine', function() { | |
}).then(done); | ||
}); | ||
|
||
it('makes no queries for clear content', function(done) { | ||
it('makes no queries for clear content if no key config', function(done) { | ||
requestMediaKeySystemAccessSpy.and.callFake( | ||
fakeRequestMediaKeySystemAccess.bind(null, [])); | ||
manifest.periods[0].variants[0].drmInfos = []; | ||
config.servers = {}; | ||
config.advanced = {}; | ||
|
||
drmEngine.configure(config); | ||
drmEngine.init(manifest, /* offline */ false).then(function() { | ||
expect(drmEngine.initialized()).toBe(true); | ||
expect(drmEngine.keySystem()).toBe(''); | ||
expect(requestMediaKeySystemAccessSpy.calls.count()).toBe(0); | ||
}).catch(fail).then(done); | ||
}); | ||
|
||
it('makes queries for clear content if key is configured', function(done) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Awesome! Thank you for writing tests! |
||
requestMediaKeySystemAccessSpy.and.callFake( | ||
fakeRequestMediaKeySystemAccess.bind(null, ['drm.abc'])); | ||
manifest.periods[0].variants[0].drmInfos = []; | ||
config.servers = { | ||
'drm.abc': 'http://abc.drm/license' | ||
}; | ||
|
||
drmEngine.configure(config); | ||
drmEngine.init(manifest, /* offline */ false).then(function() { | ||
expect(drmEngine.initialized()).toBe(true); | ||
expect(drmEngine.keySystem()).toBe('drm.abc'); | ||
expect(requestMediaKeySystemAccessSpy.calls.count()).toBe(1); | ||
}).then(done); | ||
}); | ||
|
||
it('uses advanced config to override DrmInfo fields', function(done) { | ||
// Leave only one drmInfo | ||
manifest = new shaka.test.ManifestGenerator() | ||
|
@@ -508,6 +527,8 @@ describe('DrmEngine', function() { | |
requestMediaKeySystemAccessSpy.and.callFake( | ||
fakeRequestMediaKeySystemAccess.bind(null, [])); | ||
manifest.periods[0].variants[0].drmInfos = []; | ||
config.servers = {}; | ||
config.advanced = {}; | ||
|
||
initAndAttach().then(function() { | ||
expect(mockVideo.setMediaKeys).not.toHaveBeenCalled(); | ||
|
@@ -775,6 +796,8 @@ describe('DrmEngine', function() { | |
|
||
it('dispatches an error if manifest says unencrypted', function(done) { | ||
manifest.periods[0].variants[0].drmInfos = []; | ||
config.servers = {}; | ||
config.advanced = {}; | ||
|
||
onErrorSpy.and.stub(); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only if manifest contains clear content,
configDrmInfos
won't be null. The drawback is that adds drmInfos to each variant although those do not break a playback. I considered to updateconfigsByKeySystem
directly instead of modifying manifest, but this way would cause a duplicated code issue. Also, keys are changed for chromecast in this code block. So, I preferred more simple way to add this fix.