Skip to content

Commit

Permalink
Add videoCodec field to VideoSelectionOption and improve SDR/HDR init…
Browse files Browse the repository at this point in the history
…ial selection results
  • Loading branch information
robwalch committed Jun 7, 2024
1 parent 514cc10 commit 9b71874
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 18 deletions.
1 change: 1 addition & 0 deletions api-extractor/report/hls.js.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -3495,6 +3495,7 @@ export type VariableMap = Record<string, string>;
export type VideoSelectionOption = {
preferHDR?: boolean;
allowedVideoRanges?: Array<VideoRange>;
videoCodec?: string;
};

// (No @packageDocumentation comment for this package)
Expand Down
7 changes: 4 additions & 3 deletions src/controller/abr-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -814,9 +814,10 @@ class AbrController extends Logger implements AbrComponentAPI {

// Use average bitrate when starvation delay (buffer length) is gt or eq two segment durations and rebuffering is not expected (maxStarvationDelay > 0)
const bitrate: number =
currentFragDuration &&
bufferStarvationDelay >= currentFragDuration * 2 &&
maxStarvationDelay === 0
(currentFragDuration &&
bufferStarvationDelay >= currentFragDuration * 2 &&
maxStarvationDelay === 0) ||
firstSelection
? levels[i].averageBitrate
: levels[i].maxBitrate;
const fetchDuration: number = this.getTimeToLoadFrag(
Expand Down
7 changes: 4 additions & 3 deletions src/hls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -813,7 +813,7 @@ export default class Hls implements HlsEventEmitter {
public setAudioOption(
audioOption: MediaPlaylist | AudioSelectionOption | undefined,
): MediaPlaylist | null {
return this.audioTrackController?.setAudioOption(audioOption);
return this.audioTrackController?.setAudioOption(audioOption) || null;
}
/**
* Find and select the best matching subtitle track, making a level switch when a Group change is necessary.
Expand All @@ -822,8 +822,9 @@ export default class Hls implements HlsEventEmitter {
public setSubtitleOption(
subtitleOption: MediaPlaylist | SubtitleSelectionOption | undefined,
): MediaPlaylist | null {
this.subtitleTrackController?.setSubtitleOption(subtitleOption);
return null;
return (
this.subtitleTrackController?.setSubtitleOption(subtitleOption) || null
);
}

/**
Expand Down
10 changes: 9 additions & 1 deletion src/types/media-playlist.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { AttrList } from '../utils/attr-list';
import type { LevelDetails } from '../loader/level-details';
import type { VideoRange } from './level';
import type { Level, VideoRange } from './level';
import type { PlaylistLevelType } from './loader';

export type AudioPlaylistType = 'AUDIO';

Expand All @@ -10,9 +11,16 @@ export type SubtitlePlaylistType = 'SUBTITLES' | 'CLOSED-CAPTIONS';

export type MediaPlaylistType = MainPlaylistType | SubtitlePlaylistType;

export type MediaSelection = {
[PlaylistLevelType.MAIN]: Level;
[PlaylistLevelType.AUDIO]?: MediaPlaylist;
[PlaylistLevelType.SUBTITLE]?: MediaPlaylist;
};

export type VideoSelectionOption = {
preferHDR?: boolean;
allowedVideoRanges?: Array<VideoRange>;
videoCodec?: string;
};

export type AudioSelectionOption = {
Expand Down
11 changes: 4 additions & 7 deletions src/utils/hdr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,13 @@ export function getVideoSelectionOptions(
if (videoPreference) {
allowedVideoRanges =
videoPreference.allowedVideoRanges || VideoRangeValues.slice(0);
const allowAutoPreferHDR =
allowedVideoRanges.join('') !== 'SDR' && !videoPreference.videoCodec;
preferHDR =
videoPreference.preferHDR !== undefined
? videoPreference.preferHDR
: isHdrSupported();

if (preferHDR) {
allowedVideoRanges = allowedVideoRanges.filter(
(range: VideoRange) => range !== 'SDR',
);
} else {
: allowAutoPreferHDR && isHdrSupported();
if (!preferHDR) {
allowedVideoRanges = ['SDR'];
}
}
Expand Down
22 changes: 18 additions & 4 deletions src/utils/rendition-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,10 @@ export function getStartCodecTier(
const codecSets = Object.keys(codecTiers);
const channelsPreference = audioPreference?.channels;
const audioCodecPreference = audioPreference?.audioCodec;
const videoCodecPreference = videoPreference?.videoCodec;
const preferStereo = channelsPreference && parseInt(channelsPreference) === 2;
// Use first level set to determine stereo, and minimum resolution and framerate
let hasStereo = true;
let hasStereo = false;
let hasCurrentVideoRange = false;
let minHeight = Infinity;
let minFramerate = Infinity;
Expand All @@ -61,7 +62,7 @@ export function getStartCodecTier(

for (let i = codecSets.length; i--; ) {
const tier = codecTiers[codecSets[i]];
hasStereo = tier.channels[2] > 0;
hasStereo ||= tier.channels[2] > 0;
minHeight = Math.min(minHeight, tier.minHeight);
minFramerate = Math.min(minFramerate, tier.minFramerate);
minBitrate = Math.min(minBitrate, tier.minBitrate);
Expand All @@ -70,7 +71,6 @@ export function getStartCodecTier(
);
if (matchingVideoRanges.length > 0) {
hasCurrentVideoRange = true;
videoRanges = matchingVideoRanges;
}
}
minHeight = Number.isFinite(minHeight) ? minHeight : 0;
Expand All @@ -82,7 +82,6 @@ export function getStartCodecTier(
// If there are no variants with matching preference, set currentVideoRange to undefined
if (!hasCurrentVideoRange) {
currentVideoRange = undefined;
videoRanges = [];
}
const codecSet = codecSets.reduce(
(selected: string | undefined, candidate: string) => {
Expand All @@ -91,6 +90,11 @@ export function getStartCodecTier(
if (candidate === selected) {
return selected;
}
videoRanges = hasCurrentVideoRange
? allowedVideoRanges.filter(
(range) => candidateTier.videoRanges[range] > 0,
)
: [];
if (candidateTier.minBitrate > currentBw) {
logStartCodecCandidateIgnored(
candidate,
Expand Down Expand Up @@ -159,6 +163,16 @@ export function getStartCodecTier(
);
return selected;
}
if (
videoCodecPreference &&
candidate.indexOf(videoCodecPreference.substring(0, 4)) % 5 !== 0
) {
logStartCodecCandidateIgnored(
candidate,
`video codec preference "${videoCodecPreference}" not found`,
);
return selected;
}
if (candidateTier.maxScore < selectedScore) {
logStartCodecCandidateIgnored(
candidate,
Expand Down

0 comments on commit 9b71874

Please sign in to comment.