Skip to content

Commit

Permalink
fix(drm): Fix TS DRM failures
Browse files Browse the repository at this point in the history
Before asking the CDM about its support for a MIME type, convert TS
types as the Transmuxer will.  That way, we're asking the CDM about
what it will eventually consume, not what we're streaming.

Fixes shaka-project#2981

Change-Id: I6539e9a7e4c8afca348367c788e6438fb6e07b08
  • Loading branch information
joeyparrish committed Nov 17, 2020
1 parent 65a6f26 commit cb38573
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 11 deletions.
35 changes: 24 additions & 11 deletions lib/media/drm_engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ goog.provide('shaka.media.DrmEngine');

goog.require('goog.asserts');
goog.require('shaka.log');
goog.require('shaka.media.Transmuxer');
goog.require('shaka.net.NetworkingEngine');
goog.require('shaka.util.BufferUtils');
goog.require('shaka.util.Destroyer');
Expand Down Expand Up @@ -726,17 +727,16 @@ shaka.media.DrmEngine = class {
continue;
}

const mimeType = shaka.util.MimeUtils.getFullType(
stream.mimeType, stream.codecs);
const mimeType = shaka.media.DrmEngine.computeMimeType_(stream);
let fallbackMimeType = null;

if (stream.codecs.toLowerCase() == 'ac-3' &&
shaka.util.Platform.isTizen()) {
// Some Tizen devices seem to misreport AC-3 support, but correctly
// report EC-3 support. So query EC-3 as a fallback for AC-3.
// See https://github.com/google/shaka-player/issues/2989 for details.
fallbackMimeType = shaka.util.MimeUtils.getFullType(
stream.mimeType, 'ec-3');
fallbackMimeType = shaka.media.DrmEngine.computeMimeType_(stream,
'ec-3');
}

for (const info of stream.drmInfos) {
Expand Down Expand Up @@ -793,6 +793,23 @@ shaka.media.DrmEngine = class {
return configs;
}

/**
* @param {shaka.extern.Stream} stream
* @param {string=} codecOverride
* @return {string}
* @private
*/
static computeMimeType_(stream, codecOverride) {
const realMimeType = shaka.util.MimeUtils.getFullType(stream.mimeType,
codecOverride || stream.codecs);
if (shaka.media.Transmuxer.isSupported(realMimeType)) {
// This will be handled by the Transmuxer, so use the MIME type that the
// Transmuxer will produce.
return shaka.media.Transmuxer.convertTsCodecs(stream.type, realMimeType);
}
return realMimeType;
}

/**
* @param {!Map.<string, MediaKeySystemConfiguration>} configsByKeySystem
* A dictionary of configs, indexed by key system, with an iteration order
Expand Down Expand Up @@ -1641,26 +1658,22 @@ shaka.media.DrmEngine = class {
*
* @param {!shaka.extern.Variant} variant
* @return {boolean}
**/
*/
supportsVariant(variant) {
/** @type {?shaka.extern.Stream} */
const audio = variant.audio;
/** @type {?shaka.extern.Stream} */
const video = variant.video;

if (audio && audio.encrypted) {
const audioContentType = shaka.util.MimeUtils.getFullType(
audio.mimeType, audio.codecs);

const audioContentType = shaka.media.DrmEngine.computeMimeType_(audio);
if (!this.willSupport(audioContentType)) {
return false;
}
}

if (video && video.encrypted) {
const videoContentType = shaka.util.MimeUtils.getFullType(
video.mimeType, video.codecs);

const videoContentType = shaka.media.DrmEngine.computeMimeType_(video);
if (!this.willSupport(videoContentType)) {
return false;
}
Expand Down
50 changes: 50 additions & 0 deletions test/media/drm_engine_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

goog.require('shaka.log');
goog.require('shaka.media.DrmEngine');
goog.require('shaka.media.Transmuxer');
goog.require('shaka.net.DataUriPlugin');
goog.require('shaka.net.NetworkingEngine');
goog.require('shaka.test.FakeNetworkingEngine');
Expand Down Expand Up @@ -629,6 +630,55 @@ describe('DrmEngine', () => {
drmEngine.initForPlayback(variants, manifest.offlineSessionIds))
.toBeRejectedWith(expected);
});

it('maps TS MIME types through the transmuxer', async () => {
const originalIsSupported = shaka.media.Transmuxer.isSupported;

try {
// Mock out isSupported on Transmuxer so that we don't have to care
// about what MediaSource supports under that. All we really care about
// is the translation of MIME types.
shaka.media.Transmuxer.isSupported = (mimeType, contentType) => {
return mimeType.startsWith('video/mp2t');
};

// The default mock for this is so unrealistic, some of our test
// conditions would always fail. Make it realistic enough for this
// test case by returning the same types we are supposed to be querying
// for. That way, supportsVariant() should work produce the correct
// result after translating the types of the variant's streams.
mockMediaKeySystemAccess.getConfiguration.and.callFake(() => {
return {
audioCapabilities: [{contentType: 'audio/mp4; codecs="abar"'}],
videoCapabilities: [{contentType: 'video/mp4; codecs="vbar"'}],
};
});

setRequestMediaKeySystemAccessSpy(['drm.abc']);

const variants = manifest.variants;
variants[0].video.mimeType = 'video/mp2t';
variants[0].audio.mimeType = 'video/mp2t';

await drmEngine.initForPlayback(variants, manifest.offlineSessionIds);
expect(drmEngine.initialized()).toBe(true);

expect(requestMediaKeySystemAccessSpy)
.toHaveBeenCalledWith('drm.abc', [jasmine.objectContaining({
audioCapabilities: [jasmine.objectContaining({
contentType: 'audio/mp4; codecs="abar"',
})],
videoCapabilities: [jasmine.objectContaining({
contentType: 'video/mp4; codecs="vbar"',
})],
})]);

expect(drmEngine.supportsVariant(variants[0])).toBeTruthy();
} finally {
// Restore the mock.
shaka.media.Transmuxer.isSupported = originalIsSupported;
}
});
}); // describe('init')

describe('attach', () => {
Expand Down

0 comments on commit cb38573

Please sign in to comment.