Skip to content

Commit

Permalink
Fix interstitial transfer of media while primary is re-attaching
Browse files Browse the repository at this point in the history
  • Loading branch information
robwalch committed Dec 10, 2024
1 parent ca2101f commit d7090f0
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 21 deletions.
2 changes: 1 addition & 1 deletion src/controller/buffer-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ import {
isCompatibleTrackChange,
isManagedMediaSource,
} from '../utils/mediasource-helper';
import type Hls from '../hls';
import type { FragmentTracker } from './fragment-tracker';
import type { HlsConfig } from '../config';
import type Hls from '../hls';
import type { MediaFragment, Part } from '../loader/fragment';
import type { LevelDetails } from '../loader/level-details';
import type {
Expand Down
17 changes: 12 additions & 5 deletions src/controller/interstitials-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ export type PlayheadTimes = {
seekTo: (time: number) => void;
};

function playWithCatch(media: HTMLMediaElement | null) {
media?.play().catch(/* no-op */);
}

export default class InterstitialsController
extends Logger
implements NetworkComponentAPI
Expand Down Expand Up @@ -120,7 +124,10 @@ export default class InterstitialsController
this.hls = hls;
this.HlsPlayerClass = HlsPlayerClass;
this.assetListLoader = new AssetListLoader(hls);
this.schedule = new InterstitialsSchedule(this.onScheduleUpdate);
this.schedule = new InterstitialsSchedule(
this.onScheduleUpdate,
hls.logger,
);
this.registerListeners();
}

Expand Down Expand Up @@ -721,8 +728,8 @@ MediaSource ${JSON.stringify(attachMediaSourceData)} from ${logFromSource}`,
this.log(
`using detachedData: MediaSource ${JSON.stringify(attachMediaSourceData)}`,
);
} else if (!this.detachedData) {
this.warn(`missing MediaSource (detachedData)!`);
} else if (!this.detachedData || this.hls.media === media) {
// Media is attaching when `detachedData` and `hls.media` are populated. Detach to clear the MediaSource.
this.hls.detachMedia();
this.detachedData = { media };
}
Expand Down Expand Up @@ -1117,12 +1124,12 @@ MediaSource ${JSON.stringify(attachMediaSourceData)} from ${logFromSource}`,
media,
);
if (this.shouldPlay) {
player.media?.play();
playWithCatch(player.media);
}
} else if (scheduledItem !== null) {
this.resumePrimary(scheduledItem, index, currentItem);
if (this.shouldPlay) {
this.hls.media?.play();
playWithCatch(this.hls.media);
}
} else if (playingLastItem && this.isInterstitial(currentItem)) {
// Maintain playingItem state at end of schedule (setSchedulePosition(-1) called to end program)
Expand Down
31 changes: 17 additions & 14 deletions src/controller/interstitials-schedule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import {
type InterstitialId,
TimelineOccupancy,
} from '../loader/interstitial-event';
import { logger } from '../utils/logger';
import { Logger } from '../utils/logger';
import type { DateRange } from '../loader/date-range';
import type { MediaSelection } from '../types/media-playlist';
import type { ILogger } from '../utils/logger';

const ABUTTING_THRESHOLD_SECONDS = 0.033;

Expand Down Expand Up @@ -59,7 +60,7 @@ type ScheduleUpdateCallback = (
previousItems: InterstitialScheduleItem[] | null,
) => void;

export class InterstitialsSchedule {
export class InterstitialsSchedule extends Logger {
private onScheduleUpdate: ScheduleUpdateCallback;
private eventMap: Record<string, InterstitialEvent> = {};
public events: InterstitialEvent[] | null = null;
Expand All @@ -70,7 +71,8 @@ export class InterstitialsSchedule {
integrated: 0,
};

constructor(onScheduleUpdate: ScheduleUpdateCallback) {
constructor(onScheduleUpdate: ScheduleUpdateCallback, logger: ILogger) {
super('interstitials-sched', logger);
this.onScheduleUpdate = onScheduleUpdate;
}

Expand Down Expand Up @@ -579,23 +581,23 @@ export class InterstitialsSchedule {
if (
Math.abs(resumeTime - resumesInPlaceAt) > ALIGNED_END_THRESHOLD_SECONDS
) {
logger.log(
`Interstitial resumption ${resumeTime} not aligned with estimated timeline end ${resumesInPlaceAt}`,
this.log(
`"${interstitial.identifier}" resumption ${resumeTime} not aligned with estimated timeline end ${resumesInPlaceAt}`,
);
return false;
}
if (!mediaSelection) {
logger.log(
`Interstitial resumption ${resumeTime} can not be aligned with media (none selected)`,
this.log(
`"${interstitial.identifier}" resumption ${resumeTime} can not be aligned with media (none selected)`,
);
return false;
}
return !Object.keys(mediaSelection).some((playlistType) => {
const details = mediaSelection[playlistType].details;
const playlistEnd = details.edge;
if (resumeTime > playlistEnd) {
logger.log(
`Interstitial resumption ${resumeTime} past ${playlistType} playlist end ${playlistEnd}`,
this.log(
`"${interstitial.identifier}" resumption ${resumeTime} past ${playlistType} playlist end ${playlistEnd}`,
);
return true;
}
Expand All @@ -605,19 +607,20 @@ export class InterstitialsSchedule {
resumeTime,
);
if (!startFragment) {
logger.log(
`Interstitial resumption ${resumeTime} does not overlap with any fragments in ${playlistType} playlist`,
this.log(
`"${interstitial.identifier}" resumption ${resumeTime} does not align with any fragments in ${playlistType} playlist`,
);
return true;
}
const endAllowance = playlistType === 'audio' ? 0.175 : 0;
const alignedWithSegment =
Math.abs(startFragment.start - resumeTime) <
ALIGNED_END_THRESHOLD_SECONDS ||
Math.abs(startFragment.end - resumeTime) <
ALIGNED_END_THRESHOLD_SECONDS;
ALIGNED_END_THRESHOLD_SECONDS + endAllowance;
if (!alignedWithSegment) {
logger.log(
`Interstitial resumption ${resumeTime} does not overlap with fragment in ${playlistType} playlist (${startFragment.start}-${startFragment.end})`,
this.log(
`"${interstitial.identifier}" resumption ${resumeTime} not aligned with ${playlistType} fragment bounds (${startFragment.start}-${startFragment.end} sn: ${startFragment.sn} cc: ${startFragment.cc})`,
);
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion src/loader/interstitial-event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { DateRange, DateRangeCue } from './date-range';
import type { MediaFragmentRef } from './fragment';
import type { Loader, LoaderContext } from '../types/loader';

export const ALIGNED_END_THRESHOLD_SECONDS = 0.02; // 0.1 // 0.2
export const ALIGNED_END_THRESHOLD_SECONDS = 0.02;

export type PlaybackRestrictions = {
skip: boolean;
Expand Down

0 comments on commit d7090f0

Please sign in to comment.