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

Do not add failed push operations in the BufferedHistory #1323

Merged
merged 1 commit into from
Dec 11, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,15 @@ export default class AudioVideoSegmentBuffer extends SegmentBuffer {
err :
new Error("An unknown error occured when doing operations " +
"on the SourceBuffer");
this._pendingTask.reject(error);
const task = this._pendingTask;
if (task.type === SegmentBufferOperation.Push &&
task.data.length === 0 &&
task.inventoryData !== null)
{
this._segmentInventory.insertChunk(task.inventoryData, false);
}
this._pendingTask = null;
task.reject(error);
}
}

Expand Down Expand Up @@ -429,7 +437,7 @@ export default class AudioVideoSegmentBuffer extends SegmentBuffer {
switch (task.type) {
case SegmentBufferOperation.Push:
if (task.inventoryData !== null) {
this._segmentInventory.insertChunk(task.inventoryData);
this._segmentInventory.insertChunk(task.inventoryData, true);
}
break;
case SegmentBufferOperation.EndOfSegment:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export default class ImageSegmentBuffer extends SegmentBuffer {
try {
this._buffered.insert(startTime, endTime);
if (infos.inventoryInfos !== null) {
this._segmentInventory.insertChunk(infos.inventoryInfos);
this._segmentInventory.insertChunk(infos.inventoryInfos, true);
}
} catch (err) {
return Promise.reject(err);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ export default class HTMLTextSegmentBuffer extends SegmentBuffer {
}

if (infos.inventoryInfos !== null) {
this._segmentInventory.insertChunk(infos.inventoryInfos);
this._segmentInventory.insertChunk(infos.inventoryInfos, true);
}
this._buffer.insert(cues, start, end);
this._buffered.insert(start, end);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ export default class NativeTextSegmentBuffer extends SegmentBuffer {
}
this._buffered.insert(start, end);
if (infos.inventoryInfos !== null) {
this._segmentInventory.insertChunk(infos.inventoryInfos);
this._segmentInventory.insertChunk(infos.inventoryInfos, true);
}
} catch (err) {
return Promise.reject(err);
Expand Down
2 changes: 2 additions & 0 deletions src/core/segment_buffers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
SegmentBufferOperation,
} from "./implementations";
import {
ChunkStatus,
IBufferedChunk,
IChunkContext,
IInsertedChunkInfos,
Expand All @@ -40,6 +41,7 @@ import SegmentBuffersStore, {
export default SegmentBuffersStore;
export {
BufferGarbageCollector,
ChunkStatus,

ISegmentBufferOptions,
ITextTrackSegmentBufferOptions,
Expand Down
2 changes: 2 additions & 0 deletions src/core/segment_buffers/inventory/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@
*/

import SegmentInventory, {
ChunkStatus,
IBufferedChunk,
IInsertedChunkInfos,
} from "./segment_inventory";

export default SegmentInventory;
export {
ChunkStatus,
IBufferedChunk,
IInsertedChunkInfos,
};
Expand Down
66 changes: 49 additions & 17 deletions src/core/segment_buffers/inventory/segment_inventory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,27 @@ import BufferedHistory, {
} from "./buffered_history";
import { IChunkContext } from "./types";

/** Categorization of a given chunk in the `SegmentInventory`. */
export const enum ChunkStatus {
/**
* This chunk is only a part of a partially-pushed segment for now, meaning
* that it is only a sub-part of a requested segment that was not yet
* fully-loaded and pushed.
*
* Once and if the corresponding segment is fully-pushed, its `ChunkStatus`
* switches to `Complete`.
*/
PartiallyPushed = 0,
/** This chunk corresponds to a fully-loaded segment. */
Complete = 1,
/**
* This chunk's push operation failed, in this scenario there is no certitude
* about the presence of that chunk in the buffer: it may not be present,
* partially-present, or fully-present depending on why that push operation
* failed, which is generally only known by the lower-level code.
*/
Failed = 2,
}

/** Information stored on a single chunk by the SegmentInventory. */
export interface IBufferedChunk {
Expand Down Expand Up @@ -82,14 +103,10 @@ export interface IBufferedChunk {
/** Information on what that chunk actually contains. */
infos : IChunkContext;
/**
* If `true`, this chunk is only a partial chunk of a whole segment.
*
* Inversely, if `false`, this chunk is a whole segment whose inner chunks
* have all been fully pushed.
* In that condition, the `start` and `end` properties refer to that fully
* pushed segment.
* Status of this chunk.
* @see ChunkStatus
*/
partiallyPushed : boolean;
status : ChunkStatus;
/**
* If `true`, the segment as a whole is divided into multiple parts in the
* buffer, with other segment(s) between them.
Expand Down Expand Up @@ -244,7 +261,11 @@ export default class SegmentInventory {
log.debug(`SI: ${numberOfSegmentToDelete} segments GCed.`, bufferType);
const removed = inventory.splice(indexBefore, numberOfSegmentToDelete);
for (const seg of removed) {
if (seg.bufferedStart === undefined && seg.bufferedEnd === undefined) {
if (
seg.bufferedStart === undefined &&
seg.bufferedEnd === undefined &&
seg.status !== ChunkStatus.Failed
) {
this._bufferedHistory.addBufferedSegment(seg.infos, null);
}
}
Expand Down Expand Up @@ -318,7 +339,11 @@ export default class SegmentInventory {
bufferType, inventoryIndex, inventory.length);
const removed = inventory.splice(inventoryIndex, inventory.length - inventoryIndex);
for (const seg of removed) {
if (seg.bufferedStart === undefined && seg.bufferedEnd === undefined) {
if (
seg.bufferedStart === undefined &&
seg.bufferedEnd === undefined &&
seg.status !== ChunkStatus.Failed
) {
this._bufferedHistory.addBufferedSegment(seg.infos, null);
}
}
Expand All @@ -343,7 +368,8 @@ export default class SegmentInventory {
segment,
chunkSize,
start,
end } : IInsertedChunkInfos
end } : IInsertedChunkInfos,
succeed: boolean
) : void {
if (segment.isInit) {
return;
Expand All @@ -357,7 +383,8 @@ export default class SegmentInventory {
}

const inventory = this._inventory;
const newSegment = { partiallyPushed: true,
const newSegment = { status: succeed ? ChunkStatus.PartiallyPushed :
ChunkStatus.Failed,
chunkSize,
splitted: false,
start,
Expand Down Expand Up @@ -565,7 +592,7 @@ export default class SegmentInventory {
// ===> : |--|====|-|
log.warn("SI: Segment pushed is contained in a previous one",
bufferType, start, end, segmentI.start, segmentI.end);
const nextSegment = { partiallyPushed: segmentI.partiallyPushed,
const nextSegment = { status: segmentI.status,
/**
* Note: this sadly means we're doing as if
* that chunk is present two times.
Expand Down Expand Up @@ -743,7 +770,9 @@ export default class SegmentInventory {
this._inventory.splice(firstI + 1, length);
i -= length;
}
this._inventory[firstI].partiallyPushed = false;
if (this._inventory[firstI].status === ChunkStatus.PartiallyPushed) {
this._inventory[firstI].status = ChunkStatus.Complete;
}
this._inventory[firstI].chunkSize = segmentSize;
this._inventory[firstI].end = lastEnd;
this._inventory[firstI].bufferedEnd = lastBufferedEnd;
Expand All @@ -760,8 +789,11 @@ export default class SegmentInventory {
this.synchronizeBuffered(newBuffered);
for (const seg of resSegments) {
if (seg.bufferedStart !== undefined && seg.bufferedEnd !== undefined) {
this._bufferedHistory.addBufferedSegment(seg.infos, { start: seg.bufferedStart,
end: seg.bufferedEnd });
if (seg.status !== ChunkStatus.Failed) {
this._bufferedHistory.addBufferedSegment(seg.infos,
{ start: seg.bufferedStart,
end: seg.bufferedEnd });
}
} else {
log.debug("SI: buffered range not known after sync. Skipping history.",
seg.start,
Expand Down Expand Up @@ -810,7 +842,7 @@ function bufferedStartLooksCoherent(
thisSegment : IBufferedChunk
) : boolean {
if (thisSegment.bufferedStart === undefined ||
thisSegment.partiallyPushed)
thisSegment.status !== ChunkStatus.Complete)
{
return false;
}
Expand All @@ -837,7 +869,7 @@ function bufferedEndLooksCoherent(
thisSegment : IBufferedChunk
) : boolean {
if (thisSegment.bufferedEnd === undefined ||
thisSegment.partiallyPushed)
thisSegment.status !== ChunkStatus.Complete)
{
return false;
}
Expand Down
3 changes: 2 additions & 1 deletion src/core/stream/representation/utils/get_buffer_status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import Manifest, {
import isNullOrUndefined from "../../../../utils/is_null_or_undefined";
import { IReadOnlyPlaybackObserver } from "../../../api";
import SegmentBuffersStore, {
ChunkStatus,
IBufferedChunk,
IEndOfSegmentOperation,
SegmentBuffer,
Expand Down Expand Up @@ -299,7 +300,7 @@ function getPlayableBufferedSegments(
const eltInventory = segmentInventory[i];

const { representation } = eltInventory.infos;
if (!eltInventory.partiallyPushed &&
if (eltInventory.status === ChunkStatus.Complete &&
representation.decipherable !== false &&
representation.isSupported)
{
Expand Down
Loading