Skip to content

Commit

Permalink
fix(HLS): Allow disable initial variant if necessary (#6940)
Browse files Browse the repository at this point in the history
This change allows us to detect when the initial variant fails (for
example due to a 404, 503 in the m3u8 request) and we can change to
another variant.
  • Loading branch information
avelad authored Jun 29, 2024
1 parent 28d68e3 commit 3416054
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 29 deletions.
15 changes: 13 additions & 2 deletions lib/hls/hls_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -2377,8 +2377,19 @@ shaka.hls.HlsParser = class {

const uris = streamInfo.getUris();
// Download the actual manifest.
const response = await this.requestManifest_(
streamInfo.getUris(), /* isPlaylist= */ true);
let response;
try {
response = await this.requestManifest_(
streamInfo.getUris(), /* isPlaylist= */ true);
} catch (e) {
stream.closeSegmentIndex();
const handled = this.playerInterface_.disableStream(stream);
if (handled) {
return;
} else {
throw e;
}
}
if (abortSignal.aborted) {
return;
}
Expand Down
56 changes: 29 additions & 27 deletions lib/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -2106,9 +2106,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
});
}
},
disableStream: (stream) => {
this.disableStream(stream, this.config_.streaming.maxDisabledTime);
},
disableStream: (stream) => this.disableStream(
stream, this.config_.streaming.maxDisabledTime),
};
const regionTimeline =
new shaka.media.RegionTimeline(() => this.seekRange());
Expand Down Expand Up @@ -2453,23 +2452,28 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
// Unless the user has already picked a variant, anyway, by calling
// selectVariantTrack before this loading stage.
let initialVariant = prefetchedVariant;
const activeVariant = this.streamingEngine_.getCurrentVariant();
if (!activeVariant && !initialVariant) {
initialVariant = this.chooseVariant_(/* initialSelection= */ true);
goog.asserts.assert(initialVariant, 'Must choose an initial variant!');
}

// Lazy-load the stream, so we will have enough info to make the playhead.
const createSegmentIndexPromises = [];
const toLazyLoad = activeVariant || initialVariant;
for (const stream of [toLazyLoad.video, toLazyLoad.audio]) {
if (stream && !stream.segmentIndex) {
createSegmentIndexPromises.push(stream.createSegmentIndex());
let toLazyLoad;
let activeVariant;
do {
activeVariant = this.streamingEngine_.getCurrentVariant();
if (!activeVariant && !initialVariant) {
initialVariant = this.chooseVariant_(/* initialSelection= */ true);
goog.asserts.assert(initialVariant, 'Must choose an initial variant!');
}

// Lazy-load the stream, so we will have enough info to make the playhead.
const createSegmentIndexPromises = [];
toLazyLoad = activeVariant || initialVariant;
for (const stream of [toLazyLoad.video, toLazyLoad.audio]) {
if (stream && !stream.segmentIndex) {
createSegmentIndexPromises.push(stream.createSegmentIndex());
}
}
}
if (createSegmentIndexPromises.length > 0) {
await Promise.all(createSegmentIndexPromises);
}
if (createSegmentIndexPromises.length > 0) {
// eslint-disable-next-line no-await-in-loop
await Promise.all(createSegmentIndexPromises);
}
} while (!toLazyLoad || toLazyLoad.disabledUntilTime != 0);

if (this.parser_ && this.parser_.onInitialVariantChosen) {
this.parser_.onInitialVariantChosen(toLazyLoad);
Expand Down Expand Up @@ -6771,22 +6775,19 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
return str;
};

let shouldStopTimer = true;
for (const variant of this.manifest_.variants) {
if (variant.disabledUntilTime > 0 && variant.disabledUntilTime <= now) {
variant.disabledUntilTime = 0;
hasVariantUpdate = true;

shaka.log.v2('Re-enabled variant with ' + streamsAsString(variant));
}
if (variant.disabledUntilTime > 0) {
shouldStopTimer = false;
}
}

const shouldStopTimer = this.manifest_.variants.every((variant) => {
goog.asserts.assert(
variant.disabledUntilTime >= 0,
'|variant.disableTimeUntilTime| must always be >= 0');
return variant.disabledUntilTime === 0;
});

if (shouldStopTimer) {
this.checkVariantsTimer_.stop();
}
Expand Down Expand Up @@ -7219,7 +7220,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
const hasAltStream = this.manifest_.variants.some((variant) => {
const altStream = variant[stream.type];

if (altStream && altStream.id !== stream.id) {
if (altStream && altStream.id !== stream.id &&
!variant.disabledUntilTime) {
if (shaka.util.StreamUtils.isAudio(stream)) {
return stream.language === altStream.language;
}
Expand Down

0 comments on commit 3416054

Please sign in to comment.