diff --git a/lib/media/media_source_engine.js b/lib/media/media_source_engine.js index 1c2121392c..aa895d38a9 100644 --- a/lib/media/media_source_engine.js +++ b/lib/media/media_source_engine.js @@ -2247,32 +2247,32 @@ shaka.media.MediaSourceEngine = class { } /** - * Codec switch if necessary, this will not resolve until the codec - * switch is over. * @param {shaka.util.ManifestParserUtils.ContentType} contentType * @param {string} mimeType * @param {string} codecs - * @param {!Map.} streamsByType - * @return {!Promise.} true if there was a codec switch, - * false otherwise. + * @return {{transmuxer: ?shaka.extern.Transmuxer, + * transmuxerMuxed: boolean, basicType: string, codec: string, + * mimeType: string}} * @private */ - async codecSwitchIfNecessary_(contentType, mimeType, codecs, streamsByType) { + getRealInfo_(contentType, mimeType, codecs) { const ContentType = shaka.util.ManifestParserUtils.ContentType; - if (contentType == ContentType.TEXT) { - return false; - } const MimeUtils = shaka.util.MimeUtils; - const currentCodec = MimeUtils.getNormalizedCodec( - MimeUtils.getCodecs(this.sourceBufferTypes_[contentType])); - const currentBasicType = MimeUtils.getBasicType( - this.sourceBufferTypes_[contentType]); - /** @type {?shaka.extern.Transmuxer} */ let transmuxer; let transmuxerMuxed = false; - let newMimeType = shaka.util.MimeUtils.getFullType(mimeType, codecs); + const audioCodec = shaka.util.ManifestParserUtils.guessCodecsSafe( + ContentType.AUDIO, (codecs || '').split(',')); + const videoCodec = shaka.util.ManifestParserUtils.guessCodecsSafe( + ContentType.VIDEO, (codecs || '').split(',')); + let codec = videoCodec; + if (contentType == ContentType.AUDIO) { + codec = audioCodec; + } + if (!codec) { + codec = codecs; + } + let newMimeType = shaka.util.MimeUtils.getFullType(mimeType, codec); let needTransmux = this.config_.forceTransmux; if (!shaka.media.Capabilities.isTypeSupported(newMimeType) || (!this.sequenceMode_ && @@ -2282,36 +2282,79 @@ shaka.media.MediaSourceEngine = class { const TransmuxerEngine = shaka.transmuxer.TransmuxerEngine; if (needTransmux) { const newMimeTypeWithAllCodecs = - shaka.util.MimeUtils.getFullTypeWithAllCodecs(mimeType, codecs); + shaka.util.MimeUtils.getFullTypeWithAllCodecs(mimeType, codec); const transmuxerPlugin = TransmuxerEngine.findTransmuxer(newMimeTypeWithAllCodecs); if (transmuxerPlugin) { transmuxer = transmuxerPlugin(); - const audioCodec = shaka.util.ManifestParserUtils.guessCodecsSafe( - ContentType.AUDIO, (codecs || '').split(',')); - const videoCodec = shaka.util.ManifestParserUtils.guessCodecsSafe( - ContentType.VIDEO, (codecs || '').split(',')); if (audioCodec && videoCodec) { transmuxerMuxed = true; - let codec = videoCodec; - if (contentType == ContentType.AUDIO) { - codec = audioCodec; - } - newMimeType = transmuxer.convertCodecs(contentType, - shaka.util.MimeUtils.getFullTypeWithAllCodecs(mimeType, codec)); - } else { - newMimeType = - transmuxer.convertCodecs(contentType, newMimeTypeWithAllCodecs); } + newMimeType = + transmuxer.convertCodecs(contentType, newMimeTypeWithAllCodecs); } } const newCodec = MimeUtils.getNormalizedCodec( MimeUtils.getCodecs(newMimeType)); const newBasicType = MimeUtils.getBasicType(newMimeType); + return { + transmuxer, + transmuxerMuxed, + basicType: newBasicType, + codec: newCodec, + mimeType: newMimeType, + }; + } + + /** + * Codec switch if necessary, this will not resolve until the codec + * switch is over. + * @param {shaka.util.ManifestParserUtils.ContentType} contentType + * @param {string} mimeType + * @param {string} codecs + * @param {!Map.} streamsByType + * @return {!Promise.} true if there was a codec switch, + * false otherwise. + * @private + */ + async codecSwitchIfNecessary_(contentType, mimeType, codecs, streamsByType) { + const ContentType = shaka.util.ManifestParserUtils.ContentType; + if (contentType == ContentType.TEXT) { + return false; + } + const MimeUtils = shaka.util.MimeUtils; + const currentCodec = MimeUtils.getNormalizedCodec( + MimeUtils.getCodecs(this.sourceBufferTypes_[contentType])); + const currentBasicType = MimeUtils.getBasicType( + this.sourceBufferTypes_[contentType]); + + const realInfo = this.getRealInfo_(contentType, mimeType, codecs); + const transmuxer = realInfo.transmuxer; + const transmuxerMuxed = realInfo.transmuxerMuxed; + const newBasicType = realInfo.basicType; + const newCodec = realInfo.codec; + const newMimeType = realInfo.mimeType; + + let muxedContentCheck = true; + if (transmuxerMuxed) { + const muxedRealInfo = + this.getRealInfo_(ContentType.AUDIO, mimeType, codecs); + const muxedCurrentCodec = MimeUtils.getNormalizedCodec( + MimeUtils.getCodecs(this.sourceBufferTypes_[ContentType.AUDIO])); + const muxedCurrentBasicType = MimeUtils.getBasicType( + this.sourceBufferTypes_[ContentType.AUDIO]); + muxedContentCheck = muxedCurrentCodec == muxedRealInfo.codec && + muxedCurrentBasicType == muxedRealInfo.basicType; + if (muxedRealInfo.transmuxer) { + muxedRealInfo.transmuxer.destroy(); + } + } // Current/new codecs base and basic type match then no need to switch - if (currentCodec === newCodec && currentBasicType === newBasicType) { + if (currentCodec === newCodec && currentBasicType === newBasicType && + muxedContentCheck) { if (this.transmuxers_[contentType] && !transmuxer) { this.transmuxers_[contentType].destroy(); delete this.transmuxers_[contentType]; diff --git a/test/transmuxer/transmuxer_integration.js b/test/transmuxer/transmuxer_integration.js index 3b5806058d..8f73566d00 100644 --- a/test/transmuxer/transmuxer_integration.js +++ b/test/transmuxer/transmuxer_integration.js @@ -383,12 +383,7 @@ describe('Transmuxer Player', () => { // eslint-disable-next-line max-len await player.load('/base/test/test/assets/hls-ts-muxed-mp3-h264/index.m3u8'); - try { - await video.play(); - // eslint-disable-next-line no-restricted-syntax - } catch (e) { - // Ignore play errors - } + await video.play(); expect(player.isLive()).toBe(false); // Wait for the video to start playback. If it takes longer than 10