Skip to content

Commit

Permalink
Merge pull request #5533 from video-dev/bugfix/filter-variants-with-a…
Browse files Browse the repository at this point in the history
…ny-unsupported-codecs

Filter variants with any unsupported codecs
  • Loading branch information
robwalch committed Jun 2, 2023
2 parents fc112bc + 090c28f commit f97f561
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 18 deletions.
16 changes: 14 additions & 2 deletions src/controller/audio-stream-controller.ts
Expand Up @@ -452,6 +452,7 @@ class AudioStreamController
this.switchingTrack = data;
// main audio track are handled by stream-controller, just do something if switching to alt audio track
this.state = State.IDLE;
this.flushAudioIfNeeded(data);
} else {
this.switchingTrack = null;
this.bufferedTrack = data;
Expand Down Expand Up @@ -746,6 +747,11 @@ class AudioStreamController
if (this.state === State.ENDED) {
this.state = State.IDLE;
}
const mediaBuffer = this.mediaBuffer || this.media;
if (mediaBuffer) {
this.afterBufferFlushed(mediaBuffer, type, PlaylistLevelType.AUDIO);
this.tick();
}
}
}

Expand Down Expand Up @@ -912,8 +918,8 @@ class AudioStreamController
}
}

private completeAudioSwitch(switchingTrack: MediaPlaylist) {
const { hls, media, bufferedTrack } = this;
private flushAudioIfNeeded(switchingTrack: MediaPlaylist) {
const { media, bufferedTrack } = this;
const bufferedAttributes = bufferedTrack?.attrs;
const switchAttributes = switchingTrack.attrs;
if (
Expand All @@ -925,7 +931,13 @@ class AudioStreamController
) {
this.log('Switching audio track : flushing all audio');
super.flushMainBuffer(0, Number.POSITIVE_INFINITY, 'audio');
this.bufferedTrack = null;
}
}

private completeAudioSwitch(switchingTrack: MediaPlaylist) {
const { hls } = this;
this.flushAudioIfNeeded(switchingTrack);
this.bufferedTrack = switchingTrack;
this.switchingTrack = null;
hls.trigger(Events.AUDIO_TRACK_SWITCHED, { ...switchingTrack });
Expand Down
17 changes: 13 additions & 4 deletions src/controller/level-controller.ts
Expand Up @@ -16,7 +16,10 @@ import {
import { Level } from '../types/level';
import { Events } from '../events';
import { ErrorTypes, ErrorDetails } from '../errors';
import { isCodecSupportedInMp4, getCodecCompatibleName } from '../utils/codecs';
import {
getCodecCompatibleName,
areCodecsMediaSourceSupported,
} from '../utils/codecs';
import BasePlaylistController from './base-playlist-controller';
import { PlaylistContextType, PlaylistLevelType } from '../types/loader';
import type Hls from '../hls';
Expand Down Expand Up @@ -175,8 +178,8 @@ export default class LevelController extends BasePlaylistController {
audioCodecFound ||= !!audioCodec;
return (
!unknownCodecs?.length &&
(!audioCodec || isCodecSupportedInMp4(audioCodec, 'audio')) &&
(!videoCodec || isCodecSupportedInMp4(videoCodec, 'video'))
(!audioCodec || areCodecsMediaSourceSupported(audioCodec, 'audio')) &&
(!videoCodec || areCodecsMediaSourceSupported(videoCodec, 'video'))
);
}
);
Expand All @@ -192,6 +195,11 @@ export default class LevelController extends BasePlaylistController {
// Dispatch error after MANIFEST_LOADED is done propagating
Promise.resolve().then(() => {
if (this.hls) {
if (unfilteredLevels.length) {
this.warn(
`One or more CODECS in variant not supported: "${unfilteredLevels[0].attrs.CODECS}"`
);
}
const error = new Error(
'no level with compatible codecs found in manifest'
);
Expand All @@ -211,7 +219,8 @@ export default class LevelController extends BasePlaylistController {
if (data.audioTracks) {
audioTracks = data.audioTracks.filter(
(track) =>
!track.audioCodec || isCodecSupportedInMp4(track.audioCodec, 'audio')
!track.audioCodec ||
areCodecsMediaSourceSupported(track.audioCodec, 'audio')
);
// Assign ids after filtering as array indices by group-id
assignTrackIdsByGroup(audioTracks);
Expand Down
1 change: 1 addition & 0 deletions src/controller/stream-controller.ts
Expand Up @@ -967,6 +967,7 @@ export default class StreamController
? this.videoBuffer
: this.mediaBuffer) || this.media;
this.afterBufferFlushed(mediaBuffer, type, PlaylistLevelType.MAIN);
this.tick();
}
}

Expand Down
14 changes: 4 additions & 10 deletions src/loader/m3u8-parser.ts
Expand Up @@ -809,19 +809,13 @@ function parseStartTimeOffset(startAttributes: string): number | null {
return null;
}

function setCodecs(codecs: Array<string>, level: LevelParsed) {
function setCodecs(codecs: string[], level: LevelParsed) {
['video', 'audio', 'text'].forEach((type: CodecType) => {
const filtered = codecs.filter((codec) => isCodecType(codec, type));
if (filtered.length) {
const preferred = filtered.filter((codec) => {
return (
codec.lastIndexOf('avc1', 0) === 0 ||
codec.lastIndexOf('mp4a', 0) === 0
);
});
level[`${type}Codec`] = preferred.length > 0 ? preferred[0] : filtered[0];

// remove from list
// Comma separated list of all codecs for type
level[`${type}Codec`] = filtered.join(',');
// Remove known codecs so that only unknownCodecs are left after iterating through each type
codecs = codecs.filter((codec) => filtered.indexOf(codec) === -1);
}
});
Expand Down
13 changes: 11 additions & 2 deletions src/utils/codecs.ts
Expand Up @@ -85,7 +85,16 @@ export function isCodecType(codec: string, type: CodecType): boolean {
return !!typeCodes && typeCodes[codec.slice(0, 4)] === true;
}

export function isCodecSupportedInMp4(codec: string, type: CodecType): boolean {
export function areCodecsMediaSourceSupported(
codecs: string,
type: CodecType
): boolean {
return !codecs
.split(',')
.some((codec) => !isCodecMediaSourceSupported(codec, type));
}

function isCodecMediaSourceSupported(codec: string, type: CodecType): boolean {
return (
MediaSource?.isTypeSupported(`${type || 'video'}/mp4;codecs="${codec}"`) ??
false
Expand Down Expand Up @@ -117,7 +126,7 @@ function getCodecCompatibleNameLower(
}[lowerCaseCodec];

for (let i = 0; i < codecsToCheck.length; i++) {
if (isCodecSupportedInMp4(codecsToCheck[i], 'audio')) {
if (isCodecMediaSourceSupported(codecsToCheck[i], 'audio')) {
CODEC_COMPATIBLE_NAMES[lowerCaseCodec] = codecsToCheck[i];
return codecsToCheck[i];
}
Expand Down

0 comments on commit f97f561

Please sign in to comment.