diff --git a/karma.conf.js b/karma.conf.js index 08ed388b06..9fe085edab 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -234,6 +234,7 @@ module.exports = (config) => { {pattern: 'test/**/*.js', included: false}, {pattern: 'test/test/assets/*', included: false}, {pattern: 'test/test/assets/dash-multi-codec/*', included: false}, + {pattern: 'test/test/assets/dash-multi-codec-ec3/*', included: false}, {pattern: 'test/test/assets/3675/*', included: false}, {pattern: 'test/test/assets/6339/*', included: false}, {pattern: 'test/test/assets/dash-aes-128/*', included: false}, diff --git a/lib/util/platform.js b/lib/util/platform.js index bfe50706a8..d9bc9de3e2 100644 --- a/lib/util/platform.js +++ b/lib/util/platform.js @@ -186,6 +186,17 @@ shaka.util.Platform = class { return shaka.util.Platform.userAgentContains_('CrKey'); } + /** + * Check if the current platform is a Google Chromecast with Android + * (i.e. Chromecast with GoogleTV). + * + * @return {boolean} + */ + static isAndroidCastDevice() { + const Platform = shaka.util.Platform; + return Platform.isChromecast() && Platform.isAndroid(); + } + /** * Returns a major version number for Chrome, or Chromium-based browsers. * @@ -562,6 +573,10 @@ shaka.util.Platform = class { Platform.isWebOS4() || Platform.isWebOS5()) { return false; } + // Older chromecasts without GoogleTV seem to not support SMOOTH properly. + if (Platform.isChromecast() && !Platform.isAndroidCastDevice()) { + return false; + } // See: https://chromium-review.googlesource.com/c/chromium/src/+/4577759 if (Platform.isWindows() && Platform.isEdge()) { return false; diff --git a/test/codec_switching/codec_switching_integration.js b/test/codec_switching/codec_switching_integration.js index 586c225551..5d8984b51f 100644 --- a/test/codec_switching/codec_switching_integration.js +++ b/test/codec_switching/codec_switching_integration.js @@ -5,6 +5,8 @@ */ describe('Codec Switching', () => { + const Util = shaka.test.Util; + /** @type {!HTMLVideoElement} */ let video; /** @type {shaka.Player} */ @@ -17,6 +19,21 @@ describe('Codec Switching', () => { /** @type {!shaka.test.Waiter} */ let waiter; + function isEc3Supported() { + if (!MediaSource.isTypeSupported('audio/mp4; codecs="ec-3"')) { + return false; + } + // It seems that EC3 on Edge Windows from github actions is not working + // (in the lab EC3 is working). The EC3 detection is currently hard-coded + // to true, which leads to a failure in GitHub's environment. + // We must enable this, once it is resolved: + // https://bugs.chromium.org/p/chromium/issues/detail?id=1450313 + if (shaka.util.Platform.isWindows() && shaka.util.Platform.isEdge()) { + return false; + } + return true; + } + beforeAll(async () => { video = shaka.test.UiUtils.createVideoElement(); document.body.appendChild(video); @@ -29,15 +46,24 @@ describe('Codec Switching', () => { player = new compiledShaka.Player(); await player.attach(video); + // Disable allow MediaSource recoveries, which can interfere with playback + // tests. + player.configure('streaming.allowMediaSourceRecoveries', false); + // Disable stall detection, which can interfere with playback tests. player.configure('streaming.stallEnabled', false); eventManager = new shaka.util.EventManager(); waiter = new shaka.test.Waiter(eventManager); waiter.setPlayer(player); + + const onErrorSpy = jasmine.createSpy('onError'); + onErrorSpy.and.callFake((event) => fail(event.detail)); + eventManager.listen(player, 'error', Util.spyFunc(onErrorSpy)); }); afterEach(async () => { + await player.unload(); eventManager.release(); await player.destroy(); }); @@ -46,7 +72,7 @@ describe('Codec Switching', () => { document.body.removeChild(video); }); - describe('for audio and only-audio content', () => { + describe('for audio and only-audio content aac -> opus', () => { it('can switch codecs RELOAD', async () => { if (!MediaSource.isTypeSupported('audio/webm; codecs="opus"')) { pending('Codec OPUS in WEBM is not supported by the platform.'); @@ -77,8 +103,6 @@ describe('Codec Switching', () => { variants = player.getVariantTracks(); expect(variants.find((v) => !!v.active).language).toBe('es'); - - await player.unload(); }); it('can switch codecs SMOOTH', async () => { @@ -115,12 +139,10 @@ describe('Codec Switching', () => { variants = player.getVariantTracks(); expect(variants.find((v) => !!v.active).language).toBe('es'); - - await player.unload(); }); }); - describe('for audio', () => { + describe('for audio opus -> aac', () => { it('can switch codecs RELOAD', async () => { if (!MediaSource.isTypeSupported('audio/webm; codecs="opus"')) { pending('Codec OPUS in WEBM is not supported by the platform.'); @@ -150,8 +172,6 @@ describe('Codec Switching', () => { variants = player.getVariantTracks(); expect(variants.find((v) => !!v.active).language).toBe('es'); - - await player.unload(); }); it('can switch codecs SMOOTH', async () => { @@ -187,8 +207,146 @@ describe('Codec Switching', () => { variants = player.getVariantTracks(); expect(variants.find((v) => !!v.active).language).toBe('es'); + }); + }); + + describe('for audio aac -> ec3', () => { + it('can switch codecs RELOAD', async () => { + if (!isEc3Supported()) { + pending('Codec EC3 in MP4 is not supported by the platform.'); + } + + // English is AAC MP4. + const preferredAudioLanguage = 'en'; + player.configure({preferredAudioLanguage: preferredAudioLanguage}); + player.configure('mediaSource.codecSwitchingStrategy', + shaka.config.CodecSwitchingStrategy.RELOAD); + + await player.load( + '/base/test/test/assets/dash-multi-codec-ec3/dash.mpd', 1); + await video.play(); + await waiter.waitForMovementOrFailOnTimeout(video, 10); + + expect(player.isLive()).toBe(false); + + let variants = player.getVariantTracks(); + + expect(variants.length).toBe(2); + expect(variants.find((v) => !!v.active).language).toBe('en'); + + // Spanish is EC3. + player.selectAudioLanguage('es'); + await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 2, 45); + + variants = player.getVariantTracks(); + + expect(variants.find((v) => !!v.active).language).toBe('es'); + }); + + it('can switch codecs SMOOTH', async () => { + if (!shaka.util.Platform.supportsSmoothCodecSwitching()) { + pending('Mediasource.ChangeType is not considered ' + + 'reliable on this device'); + } + if (!isEc3Supported()) { + pending('Codec EC3 in MP4 is not supported by the platform.'); + } + + // English is AAC MP4. + const preferredAudioLanguage = 'en'; + player.configure({preferredAudioLanguage: preferredAudioLanguage}); + player.configure('mediaSource.codecSwitchingStrategy', + shaka.config.CodecSwitchingStrategy.SMOOTH); + + await player.load( + '/base/test/test/assets/dash-multi-codec-ec3/dash.mpd', 1); + await video.play(); + await waiter.waitForMovementOrFailOnTimeout(video, 10); + + expect(player.isLive()).toBe(false); + + let variants = player.getVariantTracks(); + + expect(variants.length).toBe(2); + expect(variants.find((v) => !!v.active).language).toBe('en'); + + // Spanish is EC3. + player.selectAudioLanguage('es'); + await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 2, 45); + + variants = player.getVariantTracks(); + + expect(variants.find((v) => !!v.active).language).toBe('es'); + }); + }); + + describe('for audio ec3 -> aac', () => { + it('can switch codecs RELOAD', async () => { + if (!isEc3Supported()) { + pending('Codec EC3 in MP4 is not supported by the platform.'); + } + + // Spanish is EC3. + const preferredAudioLanguage = 'es'; + player.configure({preferredAudioLanguage: preferredAudioLanguage}); + player.configure('mediaSource.codecSwitchingStrategy', + shaka.config.CodecSwitchingStrategy.RELOAD); + + await player.load( + '/base/test/test/assets/dash-multi-codec-ec3/dash.mpd', 1); + await video.play(); + await waiter.waitForMovementOrFailOnTimeout(video, 10); + + expect(player.isLive()).toBe(false); + + let variants = player.getVariantTracks(); + + expect(variants.length).toBe(2); + expect(variants.find((v) => !!v.active).language).toBe('es'); + + // English is AAC MP4. + player.selectAudioLanguage('en'); + await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 2, 45); + + variants = player.getVariantTracks(); + + expect(variants.find((v) => !!v.active).language).toBe('en'); + }); + + it('can switch codecs SMOOTH', async () => { + if (!shaka.util.Platform.supportsSmoothCodecSwitching()) { + pending('Mediasource.ChangeType is not considered ' + + 'reliable on this device'); + } + if (!isEc3Supported()) { + pending('Codec EC3 in MP4 is not supported by the platform.'); + } + + // Spanish is EC3. + const preferredAudioLanguage = 'es'; + player.configure({preferredAudioLanguage: preferredAudioLanguage}); + player.configure('mediaSource.codecSwitchingStrategy', + shaka.config.CodecSwitchingStrategy.SMOOTH); + + await player.load( + '/base/test/test/assets/dash-multi-codec-ec3/dash.mpd', 1); + await video.play(); + await waiter.waitForMovementOrFailOnTimeout(video, 10); + + expect(player.isLive()).toBe(false); + + let variants = player.getVariantTracks(); + + expect(variants.length).toBe(2); + expect(variants.find((v) => !!v.active).language).toBe('es'); + + // English is AAC MP4. + player.selectAudioLanguage('en'); + await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 2, 45); - await player.unload(); + variants = player.getVariantTracks(); + + expect(variants.find((v) => !!v.active).language).toBe('en'); }); }); }); diff --git a/test/test/assets/dash-multi-codec-ec3/ChID_voices_6ch_256kbps_ddp.mp4 b/test/test/assets/dash-multi-codec-ec3/ChID_voices_6ch_256kbps_ddp.mp4 new file mode 100644 index 0000000000..a417fbf348 Binary files /dev/null and b/test/test/assets/dash-multi-codec-ec3/ChID_voices_6ch_256kbps_ddp.mp4 differ diff --git a/test/test/assets/dash-multi-codec-ec3/ChID_voices_6ch_640kbps_aac.mp4 b/test/test/assets/dash-multi-codec-ec3/ChID_voices_6ch_640kbps_aac.mp4 new file mode 100644 index 0000000000..236465581b Binary files /dev/null and b/test/test/assets/dash-multi-codec-ec3/ChID_voices_6ch_640kbps_aac.mp4 differ diff --git a/test/test/assets/dash-multi-codec-ec3/dash.mpd b/test/test/assets/dash-multi-codec-ec3/dash.mpd new file mode 100644 index 0000000000..9d088cf1fb --- /dev/null +++ b/test/test/assets/dash-multi-codec-ec3/dash.mpd @@ -0,0 +1,32 @@ + + + + + + + + + + + ChID_voices_6ch_256kbps_ddp.mp4 + + + + + + + + + + + + ChID_voices_6ch_640kbps_aac.mp4 + + + + + + +