From e34e3809d2eb34ccc5e5c940fb5cd0137619fb5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Velad=20Galv=C3=A1n?= Date: Sat, 19 Nov 2022 01:33:06 +0100 Subject: [PATCH] fix(HLS): Fix support legacy AVC1 codec used in HLS (#4716) --- lib/util/stream_utils.js | 40 +++++++++++++++++++++++++--------- test/util/stream_utils_unit.js | 18 +++++++++++++++ 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/lib/util/stream_utils.js b/lib/util/stream_utils.js index 6b305d9757..10a5d677b0 100644 --- a/lib/util/stream_utils.js +++ b/lib/util/stream_utils.js @@ -438,15 +438,20 @@ shaka.util.StreamUtils = class { const video = variant.video; const ContentType = shaka.util.ManifestParserUtils.ContentType; if (video) { - let videoCodecs = shaka.util.StreamUtils.patchVp9(video.codecs); + let videoCodecs = + shaka.util.StreamUtils.getCorrectVideoCodecs_(video.codecs); // For multiplexed streams. Here we must check the audio of the // stream to see if it is compatible. if (video.codecs.includes(',')) { const allCodecs = video.codecs.split(','); videoCodecs = shaka.util.ManifestParserUtils.guessCodecs( ContentType.VIDEO, allCodecs); - const audioCodecs = shaka.util.ManifestParserUtils.guessCodecs( + videoCodecs = + shaka.util.StreamUtils.getCorrectVideoCodecs_(videoCodecs); + let audioCodecs = shaka.util.ManifestParserUtils.guessCodecs( ContentType.AUDIO, allCodecs); + audioCodecs = + shaka.util.StreamUtils.getCorrectAudioCodecs_(audioCodecs); const audioFullType = shaka.util.MimeUtils.getFullOrConvertedType( video.mimeType, audioCodecs, ContentType.AUDIO); if (!MediaSource.isTypeSupported(audioFullType)) { @@ -566,7 +571,8 @@ shaka.util.StreamUtils = class { const allCodecs = video.codecs.split(','); videoCodecs = shaka.util.ManifestParserUtils.guessCodecs( ContentType.VIDEO, allCodecs); - videoCodecs = shaka.util.StreamUtils.patchVp9(videoCodecs); + videoCodecs = + shaka.util.StreamUtils.getCorrectVideoCodecs_(videoCodecs); const audioCodecs = shaka.util.ManifestParserUtils.guessCodecs( ContentType.AUDIO, allCodecs); @@ -580,7 +586,7 @@ shaka.util.StreamUtils = class { spatialRendering: false, }; } - videoCodecs = shaka.util.StreamUtils.patchVp9(videoCodecs); + videoCodecs = shaka.util.StreamUtils.getCorrectVideoCodecs_(videoCodecs); const fullType = shaka.util.MimeUtils.getFullOrConvertedType( video.mimeType, videoCodecs, ContentType.VIDEO); // VideoConfiguration @@ -749,15 +755,29 @@ shaka.util.StreamUtils = class { /** - * MediaCapabilities supports 'vp09...' codecs, but not 'vp9'. Translate vp9 - * codec strings into 'vp09...', to allow such content to play with - * mediaCapabilities enabled. - * + * Generates the correct video codec for MediaDecodingConfiguration and + * for MediaSource.isTypeSupported. * @param {string} codec * @return {string} + * @private */ - static patchVp9(codec) { - if (codec == 'vp9') { + static getCorrectVideoCodecs_(codec) { + if (codec.includes('avc1')) { + // Convert avc1 codec string from RFC-4281 to RFC-6381 for + // MediaSource.isTypeSupported + // Example, convert avc1.66.30 to avc1.42001e (0x42 == 66 and 0x1e == 30) + const avcdata = codec.split('.'); + if (avcdata.length == 3) { + let result = avcdata.shift() + '.'; + result += parseInt(avcdata.shift(), 10).toString(16); + result += + ('000' + parseInt(avcdata.shift(), 10).toString(16)).slice(-4); + return result; + } + } else if (codec == 'vp9') { + // MediaCapabilities supports 'vp09...' codecs, but not 'vp9'. Translate + // vp9 codec strings into 'vp09...', to allow such content to play with + // mediaCapabilities enabled. // This means profile 0, level 4.1, 8-bit color. This supports 1080p @ // 60Hz. See https://en.wikipedia.org/wiki/VP9#Levels // diff --git a/test/util/stream_utils_unit.js b/test/util/stream_utils_unit.js index 1e662743f1..da02e5a5e0 100644 --- a/test/util/stream_utils_unit.js +++ b/test/util/stream_utils_unit.js @@ -717,6 +717,24 @@ describe('StreamUtils', () => { expect(manifest.variants.length).toBe(1); }); + + it('supports legacy AVC1 codec', async () => { + if (!MediaSource.isTypeSupported('video/mp4; codecs="avc1.42001e"')) { + pending('Codec avc1.42001e is not supported by the platform.'); + } + manifest = shaka.test.ManifestGenerator.generate((manifest) => { + manifest.addVariant(0, (variant) => { + variant.addVideo(1, (stream) => { + stream.mime('video/mp4', 'avc1.66.30'); + }); + }); + }); + + await shaka.util.StreamUtils.filterManifest( + fakeDrmEngine, /* currentVariant= */ null, manifest); + + expect(manifest.variants.length).toBe(1); + }); }); describe('chooseCodecsAndFilterManifest', () => {