diff --git a/karma.conf.js b/karma.conf.js index 8a9bbe4838..853293d7be 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -260,6 +260,7 @@ module.exports = (config) => { {pattern: 'test/test/assets/7401/*', included: false}, {pattern: 'test/test/assets/6339/*', included: false}, {pattern: 'test/test/assets/dash-aes-128/*', included: false}, + {pattern: 'test/test/assets/dash-audio-ac3/*', included: false}, {pattern: 'test/test/assets/dash-clearkey/*', included: false}, {pattern: 'test/test/assets/dash-mpd-alternate/*', included: false}, {pattern: 'test/test/assets/dash-vr/*', included: false}, diff --git a/lib/transmuxer/ac3_transmuxer.js b/lib/transmuxer/ac3_transmuxer.js index bd546c8fbc..94a4915c8e 100644 --- a/lib/transmuxer/ac3_transmuxer.js +++ b/lib/transmuxer/ac3_transmuxer.js @@ -14,6 +14,7 @@ goog.require('shaka.util.Error'); goog.require('shaka.util.Id3Utils'); goog.require('shaka.util.ManifestParserUtils'); goog.require('shaka.util.Mp4Generator'); +goog.require('shaka.util.Platform'); goog.require('shaka.util.Uint8ArrayUtils'); @@ -86,7 +87,11 @@ shaka.transmuxer.Ac3Transmuxer = class { */ convertCodecs(contentType, mimeType) { if (this.isAc3Container_(mimeType)) { - return 'audio/mp4; codecs="ac-3"'; + if (shaka.util.Platform.requiresEC3InitSegments()) { + return 'audio/mp4; codecs="ec-3"'; + } else { + return 'audio/mp4; codecs="ac-3"'; + } } return mimeType; } diff --git a/lib/util/mp4_generator.js b/lib/util/mp4_generator.js index ae24fcd84c..e8d12c7d07 100644 --- a/lib/util/mp4_generator.js +++ b/lib/util/mp4_generator.js @@ -8,6 +8,7 @@ goog.provide('shaka.util.Mp4Generator'); goog.require('goog.asserts'); goog.require('shaka.util.ManifestParserUtils'); +goog.require('shaka.util.Platform'); goog.require('shaka.util.Uint8ArrayUtils'); @@ -298,6 +299,20 @@ shaka.util.Mp4Generator = class { stsd_(streamInfo) { const Mp4Generator = shaka.util.Mp4Generator; const ContentType = shaka.util.ManifestParserUtils.ContentType; + let audioCodec = 'aac'; + if (streamInfo.codecs.includes('mp3')) { + audioCodec = 'mp3'; + } else if (streamInfo.codecs.includes('ac-3')) { + if (shaka.util.Platform.requiresEC3InitSegments()) { + audioCodec = 'ec-3'; + } else { + audioCodec = 'ac-3'; + } + } else if (streamInfo.codecs.includes('ec-3')) { + audioCodec = 'ec-3'; + } else if (streamInfo.codecs.includes('opus')) { + audioCodec = 'opus'; + } let bytes = new Uint8Array([]); switch (streamInfo.type) { case ContentType.VIDEO: @@ -308,13 +323,13 @@ shaka.util.Mp4Generator = class { } break; case ContentType.AUDIO: - if (streamInfo.codecs.includes('mp3')) { + if (audioCodec == 'mp3') { bytes = this.mp3_(streamInfo); - } else if (streamInfo.codecs.includes('ac-3')) { + } else if (audioCodec == 'ac-3') { bytes = this.ac3_(streamInfo); - } else if (streamInfo.codecs.includes('ec-3')) { + } else if (audioCodec == 'ec-3') { bytes = this.ec3_(streamInfo); - } else if (streamInfo.codecs.includes('opus')) { + } else if (audioCodec == 'opus') { bytes = this.opus_(streamInfo); } else { bytes = this.mp4a_(streamInfo); diff --git a/test/media/content_workarounds_integration.js b/test/media/content_workarounds_integration.js new file mode 100644 index 0000000000..fc3ed87eaa --- /dev/null +++ b/test/media/content_workarounds_integration.js @@ -0,0 +1,79 @@ +/*! @license + * Shaka Player + * Copyright 2016 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +describe('ContentWorkarounds', () => { + const Util = shaka.test.Util; + + /** @type {!jasmine.Spy} */ + let onErrorSpy; + + /** @type {!HTMLVideoElement} */ + let video; + /** @type {shaka.Player} */ + let player; + /** @type {!shaka.util.EventManager} */ + let eventManager; + + let compiledShaka; + + /** @type {!shaka.test.Waiter} */ + let waiter; + + beforeAll(async () => { + video = shaka.test.UiUtils.createVideoElement(); + document.body.appendChild(video); + compiledShaka = + await shaka.test.Loader.loadShaka(getClientArg('uncompiled')); + }); + + beforeEach(async () => { + await shaka.test.TestScheme.createManifests(compiledShaka, '_compiled'); + player = new compiledShaka.Player(); + await player.attach(video); + + // Disable stall detection, which can interfere with playback tests. + player.configure('streaming.stallEnabled', false); + + // Grab event manager from the uncompiled library: + eventManager = new shaka.util.EventManager(); + waiter = new shaka.test.Waiter(eventManager); + waiter.setPlayer(player); + + onErrorSpy = jasmine.createSpy('onError'); + onErrorSpy.and.callFake((event) => fail(event.detail)); + eventManager.listen(player, 'error', Util.spyFunc(onErrorSpy)); + }); + + afterEach(async () => { + eventManager.release(); + await player.destroy(); + }); + + afterAll(() => { + document.body.removeChild(video); + }); + + // Check that fakeEC3 workaround is applied on the platforms where it is + // needed. + it('supports AC-3 if platform supports it', async () => { + if (!await Util.isTypeSupported('audio/mp4; codecs="ac-3"')) { + pending('Codec AC-3 is not supported by the platform.'); + } + await player.load('/base/test/test/assets/dash-audio-ac3/dash.mpd'); + await video.play(); + expect(player.isLive()).toBe(false); + + // Wait for the video to start playback. If it takes longer than 10 + // seconds, fail the test. + await waiter.waitForMovementOrFailOnTimeout(video, 10); + + // Play for 5 seconds, but stop early if the video ends. If it takes + // longer than 30 seconds, fail the test. + await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 5, 30); + + await player.unload(); + }); +}); diff --git a/test/test/assets/dash-audio-ac3/audio_und_2c_192k_ac3_1.mp4 b/test/test/assets/dash-audio-ac3/audio_und_2c_192k_ac3_1.mp4 new file mode 100644 index 0000000000..939d94811c Binary files /dev/null and b/test/test/assets/dash-audio-ac3/audio_und_2c_192k_ac3_1.mp4 differ diff --git a/test/test/assets/dash-audio-ac3/audio_und_2c_192k_ac3_2.mp4 b/test/test/assets/dash-audio-ac3/audio_und_2c_192k_ac3_2.mp4 new file mode 100644 index 0000000000..4ad86eb89b Binary files /dev/null and b/test/test/assets/dash-audio-ac3/audio_und_2c_192k_ac3_2.mp4 differ diff --git a/test/test/assets/dash-audio-ac3/audio_und_2c_192k_ac3_init.mp4 b/test/test/assets/dash-audio-ac3/audio_und_2c_192k_ac3_init.mp4 new file mode 100644 index 0000000000..5b6f9610c3 Binary files /dev/null and b/test/test/assets/dash-audio-ac3/audio_und_2c_192k_ac3_init.mp4 differ diff --git a/test/test/assets/dash-audio-ac3/dash.mpd b/test/test/assets/dash-audio-ac3/dash.mpd new file mode 100644 index 0000000000..5e2823bb9b --- /dev/null +++ b/test/test/assets/dash-audio-ac3/dash.mpd @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/test/test/util/util.js b/test/test/util/util.js index 59e97c13e2..c2e8c09a21 100644 --- a/test/test/util/util.js +++ b/test/test/util/util.js @@ -360,10 +360,6 @@ shaka.test.Util = class { const baseMimeType = MimeUtils.getBasicType(mimetype); const codecs = StreamUtils.getCorrectAudioCodecs( MimeUtils.getCodecs(mimetype), baseMimeType); - if (codecs == 'ac-3' && shaka.util.Platform.isTizen()) { - // AC3 is flaky in some Tizen devices, so we need omit it for now. - return false; - } // AudioConfiguration mediaDecodingConfig.audio = { contentType: MimeUtils.getFullOrConvertedType( diff --git a/test/transmuxer/transmuxer_integration.js b/test/transmuxer/transmuxer_integration.js index 7d5428386e..da88d7c6f7 100644 --- a/test/transmuxer/transmuxer_integration.js +++ b/test/transmuxer/transmuxer_integration.js @@ -400,6 +400,10 @@ describe('Transmuxer Player', () => { if (!await Util.isTypeSupported('audio/mp4; codecs="ac-3"')) { pending('Codec AC-3 is not supported by the platform.'); } + // This tests is flaky in some Tizen devices, so we need omit it for now. + if (shaka.util.Platform.isTizen()) { + pending('Disabled on Tizen.'); + } // eslint-disable-next-line max-len await player.load('/base/test/test/assets/hls-ts-muxed-ac3-h264/media.m3u8');