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

fix: Codec switch reload - apply boundaries correctly #7700

Merged
merged 8 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
1 change: 0 additions & 1 deletion AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ Cristian Atehortua <[email protected]>
Damien Deis <[email protected]>
Dany L'Hébreux <[email protected]>
Dave Nicholas <[email protected]>
David Pfister <[email protected]>
tykus160 marked this conversation as resolved.
Show resolved Hide resolved
Davide Zordan <[email protected]>
Dl Dador <[email protected]>
Edgeware AB <*@edgeware.tv>
Expand Down
1 change: 0 additions & 1 deletion CONTRIBUTORS
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ Cristian Atehortua <[email protected]>
Damien Deis <[email protected]>
Dany L'Hébreux <[email protected]>
Dave Nicholas <[email protected]>
David Pfister <[email protected]>
tykus160 marked this conversation as resolved.
Show resolved Hide resolved
Davide Zordan <[email protected]>
Dl Dador <[email protected]>
Donato Borrello <[email protected]>
Expand Down
89 changes: 3 additions & 86 deletions lib/media/media_source_engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,8 @@ shaka.media.MediaSourceEngine = class {
* @return {boolean}
*/
isStreamingAllowed() {
return this.streamingAllowed_ && !this.usingRemotePlayback_;
return this.streamingAllowed_ && !this.usingRemotePlayback_ &&
!this.reloadingMediaSource_;
}

/**
Expand Down Expand Up @@ -2099,48 +2100,6 @@ shaka.media.MediaSourceEngine = class {
null);
}

/**
* Returns the source buffer parameters
* @param {shaka.util.ManifestParserUtils.ContentType} contentType
* @return {?shaka.media.MediaSourceEngine.SourceBufferParams}
* @private
*/
getSourceBufferParams_(contentType) {
if (!this.sourceBuffers_[contentType]) {
return null;
}
return {
timestampOffset: this.sourceBuffers_[contentType].timestampOffset,
appendWindowStart: this.sourceBuffers_[contentType].appendWindowStart,
appendWindowEnd: this.sourceBuffers_[contentType].appendWindowEnd,
};
}

/**
* Restore source buffer parameters
* @param {shaka.util.ManifestParserUtils.ContentType} contentType
* @param {?shaka.media.MediaSourceEngine.SourceBufferParams} params
* @private
*/
restoreSourceBufferParams_(contentType, params) {
if (!params) {
return;
}

if (!this.sourceBuffers_[contentType]) {
shaka.log.warning('Attempted to restore a non-existent source buffer');
return;
}

this.sourceBuffers_[contentType].timestampOffset =
params.timestampOffset;
// `end` needs to be set before `start`
this.sourceBuffers_[contentType].appendWindowEnd =
params.appendWindowEnd;
this.sourceBuffers_[contentType].appendWindowStart =
params.appendWindowStart;
}

/**
* Resets the MediaSource and re-adds source buffers due to codec mismatch
*
Expand All @@ -2149,7 +2108,6 @@ shaka.media.MediaSourceEngine = class {
* @private
*/
async reset_(streamsByType) {
const Functional = shaka.util.Functional;
const ContentType = shaka.util.ManifestParserUtils.ContentType;
this.reloadingMediaSource_ = true;
this.needSplitMuxedContent_ = false;
Expand All @@ -2175,32 +2133,9 @@ shaka.media.MediaSourceEngine = class {
for (const contentType in this.transmuxers_) {
cleanup.push(this.transmuxers_[contentType].destroy());
}
for (const contentType in this.queues_) {
// Make a local copy of the queue and the first item.
const q = this.queues_[contentType];
const inProgress = q[0];

// Drop everything else out of the original queue.
this.queues_[contentType] = q.slice(0, 1);

// We will wait for this item to complete/fail.
if (inProgress) {
cleanup.push(inProgress.p.catch(Functional.noop));
}

// The rest will be rejected silently if possible.
for (const item of q.slice(1)) {
item.p.reject(shaka.util.Destroyer.destroyedError());
}
}
for (const contentType in this.sourceBuffers_) {
const sourceBuffer = this.sourceBuffers_[contentType];
try {
this.mediaSource_.removeSourceBuffer(sourceBuffer);
} catch (e) {}
}
await Promise.all(cleanup);
this.transmuxers_ = {};
this.sourceBuffers_ = {};

const previousDuration = this.mediaSource_.duration;
this.mediaSourceOpen_ = new shaka.util.PublicPromise();
Expand Down Expand Up @@ -2231,18 +2166,9 @@ shaka.media.MediaSourceEngine = class {
onSourceBufferAdded);

for (const contentType of streamsByType.keys()) {
const previousParams = this.getSourceBufferParams_(contentType);
const stream = streamsByType.get(contentType);
// eslint-disable-next-line no-await-in-loop
await this.initSourceBuffer_(contentType, stream, stream.codecs);
if (this.needSplitMuxedContent_) {
this.queues_[ContentType.AUDIO] = [];
this.queues_[ContentType.VIDEO] = [];
} else {
this.queues_[contentType] = [];
}

this.restoreSourceBufferParams_(contentType, previousParams);
}
const audio = streamsByType.get(ContentType.AUDIO);
if (audio && audio.isAudioMuxedInVideo) {
Expand Down Expand Up @@ -2540,12 +2466,3 @@ shaka.media.MediaSourceEngine.SourceBufferMode_ = {
* Called when an embedded 'emsg' box should trigger a manifest update.
*/
shaka.media.MediaSourceEngine.PlayerInterface;

/**
* @typedef {{
* timestampOffset: number,
* appendWindowStart: number,
* appendWindowEnd: number
* }}
*/
shaka.media.MediaSourceEngine.SourceBufferParams;
4 changes: 4 additions & 0 deletions lib/media/streaming_engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -2021,6 +2021,10 @@ shaka.media.StreamingEngine = class {
// Then clear our cache of the last init segment, since MSE will be
// reloaded and no init segment will be there post-reload.
otherState.lastInitSegmentReference = null;
// Clear cache of append window start and end, since they will need
// to be reapplied post-reload by streaming engine.
otherState.lastAppendWindowStart = null;
otherState.lastAppendWindowEnd = null;
tykus160 marked this conversation as resolved.
Show resolved Hide resolved
// Now force the existing buffer to be cleared. It is not necessary
// to perform the MSE clear operation, but this has the side-effect
// that our state for that stream will then match MSE's post-reload
Expand Down
Loading