Skip to content

Commit

Permalink
Fix misdetection of HLS audio-only+group as video.
Browse files Browse the repository at this point in the history
Closes shaka-project#1875

Change-Id: I09c5f6cda31762992d9d76cadea8037f1245f5c3
  • Loading branch information
joeyparrish committed Jan 24, 2020
1 parent f57a7d9 commit 139aa4c
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 1 deletion.
3 changes: 2 additions & 1 deletion lib/hls/hls_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -666,10 +666,11 @@ shaka.hls.HlsParser = class {
const videoCodecs = this.guessCodecsSafe_(ContentType.VIDEO, allCodecs);
const hasVideoRelatedInfo = resolution || frameRate || videoCodecs;

if (!streamInfos.length && allCodecs.length == 1 && !hasVideoRelatedInfo) {
if (allCodecs.length == 1 && !hasVideoRelatedInfo) {
// There are no associated media tags, and there's only one codec, and no
// video related information, so it should be audio.
type = ContentType.AUDIO;
shaka.log.debug('Guessing audio-only.');
} else if (!streamInfos.length && allCodecs.length > 1) {
// There are multiple codecs, so assume multiplexed content.
// Note that the default used when CODECS is missing assumes multiple
Expand Down
53 changes: 53 additions & 0 deletions test/hls/hls_parser_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -2486,4 +2486,57 @@ describe('HlsParser', () => {
// We should log a warning when this happens.
expect(alwaysWarnSpy).toHaveBeenCalled();
});

// Issue #1875
it('ignores audio groups on audio-only content', async () => {
// NOTE: To reproduce the original issue accurately, the two audio playlist
// URIs must differ. When the issue occurred, the audio-only variant would
// be detected as a video stream and combined with the audio group, leading
// the player to buffer "video" that was really audio, resulting in
// audio-only playback to the exclusion of any other streams. Since the
// root cause of that was the mis-detection, this repro case does not need
// to include any audio+video variants.
const master = [
'#EXTM3U\n',
'#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aud",LANG="en",URI="audio1"\n',
'#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aud",LANG="eo",URI="audio2"\n',
'#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="mp4a",AUDIO="aud"\n',
'audio3\n',
].join('');

const media = [
'#EXTM3U\n',
'#EXT-X-PLAYLIST-TYPE:VOD\n',
'#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
'#EXTINF:5,\n',
'#EXT-X-BYTERANGE:121090@616\n',
'main.mp4',
].join('');

const manifest = shaka.test.ManifestGenerator.generate((manifest) => {
manifest.anyTimeline();
manifest.addPeriod(0, (period) => {
const anyVariantId = /** @type {?} */(jasmine.any(Number));
period.addVariant(anyVariantId, (variant) => {
variant.bandwidth = 200;
variant.language = 'und';
variant.addPartialStream(ContentType.AUDIO, (stream) => {
stream.mime('audio/mp4', 'mp4a');
});
});
});
});

fakeNetEngine
.setResponseText('test:/master', master)
.setResponseText('test:/audio1', media)
.setResponseText('test:/audio2', media)
.setResponseText('test:/audio3', media)
.setResponseValue('test:/init.mp4', initSegmentData)
.setResponseValue('test:/main.mp4', segmentData);

const actual = await parser.start('test:/master', playerInterface);
expect(actual.periods[0].variants.length).toBe(1);
expect(actual).toEqual(manifest);
});
});

0 comments on commit 139aa4c

Please sign in to comment.