From b5461dc121da125e69f6328dcfaf3262b39e480d Mon Sep 17 00:00:00 2001 From: Paul Berberian Date: Tue, 19 Mar 2024 14:06:40 +0100 Subject: [PATCH] [v3] Await some delay before re-attempting to push a segment following an error This commit updates the way the RxPlayer handles a `QuotaExceededError` error thrown by a `SourceBuffer.prototype.appendBuffer` call, to align it better to how we do it in the v4 - which seems more appropriate. The idea is that a browser might throw this QuotaExceededError when too much data has been pushed to the buffer and thus the browser is not able to accept any more segments for now. In the v3 until now, what the RxPlayer did was trying to remove some data from the buffer - even skipping that part if the buffer was already empty enough - and then re-attempting to push the same segment. If the error repeats, there is a complex chain of events that lead to the buffering of that segment in our last v3 releases, so there's no real issue there. The idea of this commit is to prevent doing the re-attempt of pushing the same segment directly, mostly for cases where the data-removal step is skipped, by awaiting 200 milliseconds. I also added some code ensuring that we do not retry to push the segment if the corresponding "RepresentationStream" has been cancelled while it was awaiting those 200 milliseconds. --- src/core/stream/adaptation/adaptation_stream.ts | 3 +++ .../stream/representation/utils/append_segment_to_buffer.ts | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/src/core/stream/adaptation/adaptation_stream.ts b/src/core/stream/adaptation/adaptation_stream.ts index f2ce0cc59b..87601d39f1 100644 --- a/src/core/stream/adaptation/adaptation_stream.ts +++ b/src/core/stream/adaptation/adaptation_stream.ts @@ -257,6 +257,9 @@ export default function AdaptationStream( inbandEvent: callbacks.inbandEvent, warning: callbacks.warning, error(err : unknown) { + if (TaskCanceller.isCancellationError(err) && adapStreamCanceller.isUsed()) { + return; + } adapStreamCanceller.cancel(); callbacks.error(err); }, diff --git a/src/core/stream/representation/utils/append_segment_to_buffer.ts b/src/core/stream/representation/utils/append_segment_to_buffer.ts index da9a180f36..0b433032b9 100644 --- a/src/core/stream/representation/utils/append_segment_to_buffer.ts +++ b/src/core/stream/representation/utils/append_segment_to_buffer.ts @@ -19,6 +19,7 @@ */ import { MediaError } from "../../../../errors"; +import sleep from "../../../../utils/sleep"; import { CancellationError, CancellationSignal } from "../../../../utils/task_canceller"; import { IReadOnlyPlaybackObserver } from "../../../api"; import { @@ -64,6 +65,11 @@ export default async function appendSegmentToBuffer( const currentPos = position.pending ?? position.last; try { await forceGarbageCollection(currentPos, segmentBuffer, cancellationSignal); + await sleep(200); + if (cancellationSignal.cancellationError !== null) { + throw cancellationSignal.cancellationError; + } + await segmentBuffer.pushChunk(dataInfos, cancellationSignal); } catch (err2) { const reason = err2 instanceof Error ? err2.toString() :