Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better handle multiple RepresentationStream errors in a row #1559

Merged
merged 1 commit into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion src/core/stream/adaptation/adaptation_stream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -376,15 +376,21 @@ export default function AdaptationStream(
representationStreamCallbacks: IRepresentationStreamCallbacks,
fnCancelSignal: CancellationSignal,
): void {
/** Set to `true` if we've encountered an error with this `RepresentationStream` */
let hasEncounteredError = false;

const bufferGoalCanceller = new TaskCanceller();
bufferGoalCanceller.linkToSignal(fnCancelSignal);

/** Actually built buffer size, in seconds. */
const bufferGoal = createMappedReference(
wantedBufferAhead,
(prev) => {
return getBufferGoal(representation, prev);
},
bufferGoalCanceller.signal,
);

const maxBufferSize =
adaptation.type === "video" ? maxVideoBufferSize : new SharedReference(Infinity);
log.info(
Expand All @@ -394,14 +400,30 @@ export default function AdaptationStream(
representation.bitrate,
);
const updatedCallbacks = objectAssign({}, representationStreamCallbacks, {
error(err: unknown) {
error(err: Error) {
if (hasEncounteredError) {
// A RepresentationStream might trigger multiple Errors (for example
// multiple segments it tried to push at once led to errors).
// In that case, we'll only consider the first Error.
//
// That could mean that we're hiding legitimate issues but handling
// multiple of those errors at once is too hard a task for now.
log.warn("Stream: Ignoring RepresentationStream error", err);
return;
}
hasEncounteredError = true;
const formattedError = formatError(err, {
defaultCode: "NONE",
defaultReason: "Unknown `RepresentationStream` error",
});
if (formattedError.code !== "BUFFER_FULL_ERROR") {
representationStreamCallbacks.error(err);
} else {
log.warn(
"Stream: received BUFFER_FULL_ERROR",
adaptation.type,
representation.bitrate,
);
const wba = wantedBufferAhead.getValue();
const lastBufferGoalRatio = bufferGoalRatioMap.get(representation.id) ?? 1;
// 70%, 49%, 34.3%, 24%, 16.81%, 11.76%, 8.24% and 5.76%
Expand Down
11 changes: 11 additions & 0 deletions src/core/stream/representation/representation_stream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ export default function RepresentationStream<TSegmentDataType>(
callbacks: IRepresentationStreamCallbacks,
parentCancelSignal: CancellationSignal,
): void {
log.debug(
"Stream: Creating RepresentationStream",
content.adaptation.type,
content.representation.bitrate,
);
const { period, adaptation, representation } = content;
const { bufferGoal, maxBufferSize, drmSystemId, fastSwitchThreshold } = options;
const bufferType = adaptation.type;
Expand Down Expand Up @@ -488,6 +493,12 @@ export default function RepresentationStream<TSegmentDataType>(
// We can thus ignore it, it is very unlikely to lead to true buffer issues.
return;
}
log.warn(
"Stream: Received fatal buffer error",
adaptation.type,
representation.bitrate,
err instanceof Error ? err : null,
);
globalCanceller.cancel();
callbacks.error(err);
}
Expand Down
Loading