Skip to content
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

Create window.shakaMediaCapabilities to allow override MediaCapabilities in Apple browsers #3668

Merged
merged 1 commit into from
Oct 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions externs/media_capabilities.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*! @license
* Shaka Player
* Copyright 2016 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

/**
* @fileoverview Externs for Shaka MediaCapabilities which were missing in the
* Closure compiler.
*
* @externs
*/


/** @type {MediaCapabilities} */
window.shakaMediaCapabilities;
16 changes: 9 additions & 7 deletions lib/polyfill/media_capabilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,16 @@ shaka.polyfill.MediaCapabilities = class {
navigator.mediaCapabilities) {
shaka.log.debug(
'MediaCapabilities: Native mediaCapabilities support found.');
return;
}

if (!navigator.mediaCapabilities) {
navigator.mediaCapabilities = /** @type {!MediaCapabilities} */ ({});
} else {
if (!navigator.mediaCapabilities) {
navigator.mediaCapabilities = /** @type {!MediaCapabilities} */ ({});
}
navigator.mediaCapabilities.decodingInfo =
shaka.polyfill.MediaCapabilities.decodingInfo_;
}
navigator.mediaCapabilities.decodingInfo =
shaka.polyfill.MediaCapabilities.decodingInfo_;
// Workaround because in Apple browsers there is no way to overwrite
// MediaCapabilities.
window.shakaMediaCapabilities = navigator.mediaCapabilities;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this works, doesn't that imply that setting the value above on line 44 was successful? That would seem to contradict the need for this PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I recall, when I last looked into this issue it looked like what was happening was that navigator.mediaCapabilities was being set successfully, but then being reset to the default value in some later stage of loading... I wasn't able to quite figure out what was resetting it, though.
Storing it into a custom variable would let us work around it being reset, basically.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since all polyfills are now exported, it seems appropriate to keep this. Also this works if called at a later stage.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to experiment a little to see if I can understand the root cause before merging.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not able to reproduce this yet with DASH content. Does the MCap polyfill only get replaced if I play FairPlay content?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the content you sent us via email, I am still unable to reproduce the issue. (Safari 14.1.1) I see MediaCapabilities negotiating successfully and instantiating a FairPlay CDM. (The license request fails with an HTTP 500 error, but at least MCap is successful.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move conversation to #3530 (comment)

}

/**
Expand Down
4 changes: 2 additions & 2 deletions lib/util/stream_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ shaka.util.StreamUtils = class {
*/
static async filterManifestByMediaCapabilities(
manifest, usePersistentLicenses) {
goog.asserts.assert(navigator.mediaCapabilities,
goog.asserts.assert(window.shakaMediaCapabilities,
'MediaCapabilities should be valid.');

await shaka.util.StreamUtils.getDecodingInfosForVariants(
Expand Down Expand Up @@ -468,7 +468,7 @@ shaka.util.StreamUtils = class {
return;
}

const mediaCapabilities = navigator.mediaCapabilities;
const mediaCapabilities = window.shakaMediaCapabilities;

const operations = [];
const getVariantDecodingInfos = (async (variant, decodingConfig) => {
Expand Down
6 changes: 3 additions & 3 deletions test/media/drm_engine_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ describe('DrmEngine', () => {
navigator.requestMediaKeySystemAccess;
const originalLogError = shaka.log.error;
const originalBatchTime = shaka.media.DrmEngine.KEY_STATUS_BATCH_TIME;
const originalDecodingInfo = navigator.mediaCapabilities.decodingInfo;
const originalDecodingInfo = window.shakaMediaCapabilities.decodingInfo;

/** @type {!jasmine.Spy} */
let decodingInfoSpy;
Expand Down Expand Up @@ -76,7 +76,7 @@ describe('DrmEngine', () => {

beforeEach(() => {
decodingInfoSpy = jasmine.createSpy('decodingInfo');
navigator.mediaCapabilities.decodingInfo =
window.shakaMediaCapabilities.decodingInfo =
shaka.test.Util.spyFunc(decodingInfoSpy);

logErrorSpy = jasmine.createSpy('shaka.log.error');
Expand Down Expand Up @@ -153,7 +153,7 @@ describe('DrmEngine', () => {

navigator.requestMediaKeySystemAccess =
originalRequestMediaKeySystemAccess;
navigator.mediaCapabilities.decodingInfo = originalDecodingInfo;
window.shakaMediaCapabilities.decodingInfo = originalDecodingInfo;
shaka.log.error = originalLogError;
});

Expand Down
10 changes: 5 additions & 5 deletions test/player_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ describe('Player', () => {
const originalLogWarn = shaka.log.warning;
const originalLogAlwaysWarn = shaka.log.alwaysWarn;
const originalIsTypeSupported = window.MediaSource.isTypeSupported;
const originalDecodingInfo = navigator.mediaCapabilities.decodingInfo;
const originalDecodingInfo = window.shakaMediaCapabilities.decodingInfo;

const fakeManifestUri = 'fake-manifest-uri';
const fakeMimeType = 'application/test';
Expand Down Expand Up @@ -93,7 +93,7 @@ describe('Player', () => {
// Since this is not an integration test, we don't want MediaCapabilities to
// fail assertions based on browser support for types. Pretend that all
// video and audio types are supported.
navigator.mediaCapabilities.decodingInfo = async (config) => {
window.shakaMediaCapabilities.decodingInfo = async (config) => {
await Promise.resolve();
const videoType = config['video'] ?
config['video'].contentType.split('/')[0] : null;
Expand Down Expand Up @@ -177,7 +177,7 @@ describe('Player', () => {
shaka.log.alwaysWarn = originalLogAlwaysWarn;
window.MediaSource.isTypeSupported = originalIsTypeSupported;
shaka.media.ManifestParser.unregisterParserByMime(fakeMimeType);
navigator.mediaCapabilities.decodingInfo = originalDecodingInfo;
window.shakaMediaCapabilities.decodingInfo = originalDecodingInfo;
}
});

Expand Down Expand Up @@ -2463,7 +2463,7 @@ describe('Player', () => {
it('throws CONTENT_UNSUPPORTED_BY_BROWSER', async () => {
window.MediaSource.isTypeSupported = (mimeType) => false;

navigator.mediaCapabilities.decodingInfo = async (config) => {
window.shakaMediaCapabilities.decodingInfo = async (config) => {
await Promise.resolve();
return {supported: false};
};
Expand Down Expand Up @@ -2827,7 +2827,7 @@ describe('Player', () => {
});
});

navigator.mediaCapabilities.decodingInfo = async (config) => {
window.shakaMediaCapabilities.decodingInfo = async (config) => {
await Promise.resolve();
const videoType = config['video'] ? config['video'].contentType : '';
if (videoType.includes('video') &&
Expand Down
8 changes: 4 additions & 4 deletions test/util/stream_utils_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ describe('StreamUtils', () => {
/** @type {!jasmine.Spy} */
let decodingInfoSpy;

const originalDecodingInfo = navigator.mediaCapabilities.decodingInfo;
const originalDecodingInfo = window.shakaMediaCapabilities.decodingInfo;

beforeEach(() => {
decodingInfoSpy = jasmine.createSpy('decodingInfo');
});

afterEach(() => {
navigator.mediaCapabilities.decodingInfo = originalDecodingInfo;
window.shakaMediaCapabilities.decodingInfo = originalDecodingInfo;
});

describe('filterStreamsByLanguageAndRole', () => {
Expand Down Expand Up @@ -511,7 +511,7 @@ describe('StreamUtils', () => {
});

it('handles decodingInfo exception', async () => {
navigator.mediaCapabilities.decodingInfo =
window.shakaMediaCapabilities.decodingInfo =
shaka.test.Util.spyFunc(decodingInfoSpy);
// If decodingInfo() fails, setDecodingInfo should finish without throwing
// an exception, and the variant should have no decodingInfo result.
Expand Down Expand Up @@ -826,7 +826,7 @@ describe('StreamUtils', () => {
});
});
});
navigator.mediaCapabilities.decodingInfo =
window.shakaMediaCapabilities.decodingInfo =
shaka.test.Util.spyFunc(decodingInfoSpy);
decodingInfoSpy.and.callFake((config) => {
const res = config.video.contentType.includes('notsmooth') ?
Expand Down