Skip to content

Commit

Permalink
fix: Avoid useless MSE reset when transmuxing muxed content (#7818)
Browse files Browse the repository at this point in the history
  • Loading branch information
avelad authored and joeyparrish committed Jan 6, 2025
1 parent 306ab6e commit 5244029
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 37 deletions.
105 changes: 74 additions & 31 deletions lib/media/media_source_engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -2062,32 +2062,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.<shaka.util.ManifestParserUtils.ContentType,
* shaka.extern.Stream>} streamsByType
* @return {!Promise.<boolean>} 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_ &&
Expand All @@ -2097,36 +2097,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.<shaka.util.ManifestParserUtils.ContentType,
* shaka.extern.Stream>} streamsByType
* @return {!Promise.<boolean>} 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];
Expand Down
7 changes: 1 addition & 6 deletions test/transmuxer/transmuxer_integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -384,12 +384,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
Expand Down

0 comments on commit 5244029

Please sign in to comment.