Skip to content

Commit

Permalink
Merge pull request #2943 from video-dev/bugfix/do-not-flush-main-to-m…
Browse files Browse the repository at this point in the history
…ain-audio-only-track-switch

Fix edge-case in main audio-only with track descriptions
  • Loading branch information
robwalch committed Aug 4, 2020
2 parents 07a051e + 8f1ef8e commit e530158
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 110 deletions.
2 changes: 1 addition & 1 deletion demo/chart/timeline-chart.ts
Expand Up @@ -274,7 +274,7 @@ export class TimelineChart {
return;
}
// eslint-disable-next-line no-restricted-properties
const fragData = arrayFind(levelDataSet.data, fragData => fragData.relurl === frag.relurl);
const fragData = arrayFind(levelDataSet.data, fragData => fragData.relurl === frag.relurl && fragData.sn === frag.sn);
if (fragData && fragData !== frag) {
Object.assign(fragData, frag);
}
Expand Down
1 change: 1 addition & 0 deletions demo/index.html
Expand Up @@ -169,6 +169,7 @@ <h3>
</p>
<p>
<span>
<button type="button" class="btn btn-xs btn-default" onclick="$('#streamSelect')[0].selectedIndex++;$('#streamSelect').change()">Next video</button>
<button type="button" class="btn btn-xs btn-default btn-dump" title="Save dumped audio mp4 appends" onclick="createfMP4('audio');">Create audio-fmp4</button>
<button type="button" class="btn btn-xs btn-default btn-dump" title="Save dumped video mp4 appends" onclick="createfMP4('video')">Create video-fmp4</button>
</span>
Expand Down
5 changes: 4 additions & 1 deletion demo/main.js
Expand Up @@ -58,10 +58,13 @@ $(document).ready(function () {

chart = setupTimelineChart();

Object.keys(testStreams).forEach((key) => {
Object.keys(testStreams).forEach((key, index) => {
const stream = testStreams[key];
const option = new Option(stream.description, key);
$('#streamSelect').append(option);
if (stream.url === sourceURL) {
$('#streamSelect')[0].selectedIndex = index + 1;
}
});

$('#streamSelect').change(function () {
Expand Down
11 changes: 7 additions & 4 deletions src/controller/audio-stream-controller.js
Expand Up @@ -58,7 +58,7 @@ class AudioStreamController extends BaseStreamController {
// Can change due level switch
this.initPTS[cc] = initPTS;
this.videoTrackCC = cc;
logger.log(`InitPTS for cc: ${cc} found from video track: ${initPTS}`);
logger.log(`InitPTS for cc: ${cc} found from main: ${initPTS}`);

// If we are waiting we need to demux/remux the waiting frag
// With the new initPTS
Expand Down Expand Up @@ -264,7 +264,9 @@ class AudioStreamController extends BaseStreamController {
// we force a frag loading in audio switch as fragment tracker might not have evicted previous frags in case of quick audio switch
this.fragCurrent = frag;
if (audioSwitch || this.fragmentTracker.getState(frag) === FragmentState.NOT_LOADED) {
logger.log(`Loading ${frag.sn}, cc: ${frag.cc} of [${trackDetails.startSN} ,${trackDetails.endSN}],track ${trackId}, currentTime:${pos},bufferEnd:${bufferEnd.toFixed(3)}`);
logger.log(`Loading ${frag.sn}, cc: ${frag.cc} of [${trackDetails.startSN} ,${trackDetails.endSN}],track ${trackId}, ${
this.loadedmetadata ? 'currentTime' : 'nextLoadPosition'
}: ${pos}, bufferEnd: ${bufferEnd.toFixed(3)}`);

if (frag.sn !== 'initSegment') {
this.startFragRequested = true;
Expand Down Expand Up @@ -593,9 +595,10 @@ class AudioStreamController extends BaseStreamController {
logger.log(`parsed ${data.type},PTS:[${data.startPTS.toFixed(3)},${data.endPTS.toFixed(3)}],DTS:[${data.startDTS.toFixed(3)}/${data.endDTS.toFixed(3)}],nb:${data.nb}`);
LevelHelper.updateFragPTSDTS(track.details, fragCurrent, data.startPTS, data.endPTS);

let audioSwitch = this.audioSwitch, media = this.media, appendOnBufferFlush = false;
const media = this.media;
let appendOnBufferFlush = false;
// Only flush audio from old audio tracks when PTS is known on new audio track
if (audioSwitch) {
if (this.audioSwitch) {
if (media && media.readyState) {
let currentTime = media.currentTime;
logger.log('switching audio track : currentTime:' + currentTime);
Expand Down
26 changes: 18 additions & 8 deletions src/controller/stream-controller.js
Expand Up @@ -426,7 +426,7 @@ class StreamController extends BaseStreamController {
}

_loadKey (frag, levelDetails) {
logger.log(`Loading key for ${frag.sn} of [${levelDetails.startSN} ,${levelDetails.endSN}],level ${this.level}`);
logger.log(`Loading key for ${frag.sn} of [${levelDetails.startSN}-${levelDetails.endSN}], level ${this.level}`);
this.state = State.KEY_LOADING;
this.hls.trigger(Event.KEY_LOADING, { frag });
}
Expand All @@ -449,7 +449,9 @@ class StreamController extends BaseStreamController {
frag.autoLevel = this.hls.autoLevelEnabled;
frag.bitrateTest = this.bitrateTest;

logger.log(`Loading ${frag.sn} of [${levelDetails.startSN} ,${levelDetails.endSN}],level ${this.level}, currentTime:${pos.toFixed(3)},bufferEnd:${bufferEnd.toFixed(3)}`);
logger.log(`Loading ${frag.sn} of [${levelDetails.startSN}-${levelDetails.endSN}], level ${this.level}, ${
this.loadedmetadata ? 'currentTime' : 'nextLoadPosition'
}: ${parseFloat(pos.toFixed(3))}, bufferEnd: ${parseFloat(bufferEnd.toFixed(3))}`);

this.hls.trigger(Event.FRAG_LOADING, { frag });
// lazy demuxer init, as this could take some time ... do it during frag loading
Expand Down Expand Up @@ -1085,8 +1087,9 @@ class StreamController extends BaseStreamController {

onAudioTrackSwitching (data) {
// if any URL found on new audio track, it is an alternate audio track
let altAudio = !!data.url,
trackId = data.id;
const fromAltAudio = this.altAudio;
const altAudio = !!data.url;
const trackId = data.id;
// if we switch on main audio, ensure that main fragment scheduling is synced with media.buffered
// don't do anything if we switch to alt audio: audio stream controller is handling it.
// we will just have to change buffer scheduling on audioTrackSwitched
Expand All @@ -1111,10 +1114,17 @@ class StreamController extends BaseStreamController {
this.state = State.IDLE;
}
let hls = this.hls;
// switching to main audio, flush all audio and trigger track switched
hls.trigger(Event.BUFFER_FLUSHING, { startOffset: 0, endOffset: Number.POSITIVE_INFINITY, type: 'audio' });
hls.trigger(Event.AUDIO_TRACK_SWITCHED, { id: trackId });
this.altAudio = false;
// If switching from alt to main audio, flush all audio and trigger track switched
if (fromAltAudio) {
hls.trigger(Event.BUFFER_FLUSHING, {
startOffset: 0,
endOffset: Number.POSITIVE_INFINITY,
type: 'audio'
});
}
hls.trigger(Event.AUDIO_TRACK_SWITCHED, {
id: trackId
});
}
}

Expand Down
4 changes: 2 additions & 2 deletions tests/functional/auto/setup.js
Expand Up @@ -123,10 +123,10 @@ async function testSmoothSwitch (url, config) {
const callback = arguments[arguments.length - 1];
window.startStream(url, config, callback);
const video = window.video;
window.hls.once(window.Hls.Events.FRAG_CHANGED, (event, data) => {
window.hls.once(window.Hls.Events.FRAG_CHANGED, function (event, data) {
window.switchToHighestLevel('next');
});
window.hls.on(window.Hls.Events.LEVEL_SWITCHED, (event, data) => {
window.hls.on(window.Hls.Events.LEVEL_SWITCHED, function (event, data) {
console.log('[test] > level switched: ' + data.level);
let currentTime = video.currentTime;
if (data.level === window.hls.levels.length - 1) {
Expand Down
169 changes: 75 additions & 94 deletions tests/test-streams.js
Expand Up @@ -35,116 +35,89 @@ function createTestStreamWithConfig (target, config) {
}

module.exports = {
bbb: createTestStreamWithConfig({
bbb: {
url: 'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8',
description: 'Big Buck Bunny - adaptive qualities'
description: 'Big Buck Bunny - adaptive qualities',
abr: true
},
{
// try to workaround test failing because of slow seek on Chrome/Win10
nudgeMaxRetry: 5
}
),
fdr: {
url: 'https://cdn.jwplayer.com/manifests/pZxWPRg4.m3u8',
description: 'FDR - CDN packaged, 4s segments, 180p - 1080p',
live: false,
abr: true
},
bigBuckBunny480p: {
'url': 'https://test-streams.mux.dev/x36xhzz/url_6/193039199_mp4_h264_aac_hq_7.m3u8',
'description': 'Big Buck Bunny - 480p only',
'live': false,
'abr': false,
'blacklist_ua': ['internet explorer']
url: 'https://test-streams.mux.dev/x36xhzz/url_6/193039199_mp4_h264_aac_hq_7.m3u8',
description: 'Big Buck Bunny - 480p only',
abr: false,
blacklist_ua: ['internet explorer']
},
arte: {
'url': 'https://test-streams.mux.dev/test_001/stream.m3u8',
'description': 'ARTE China,ABR',
'live': false,
'abr': true
url: 'https://test-streams.mux.dev/test_001/stream.m3u8',
description: 'ARTE China,ABR',
abr: true
},
deltatreDAI: {
'url': 'https://test-streams.mux.dev/dai-discontinuity-deltatre/manifest.m3u8',
'description': 'Ad-insertion in event stream',
'live': false,
'abr': false,
'blacklist_ua': ['internet explorer']
url: 'https://test-streams.mux.dev/dai-discontinuity-deltatre/manifest.m3u8',
description: 'Ad-insertion in event stream',
abr: false,
blacklist_ua: ['internet explorer']
},
issue666: {
'url': 'https://playertest.longtailvideo.com/adaptive/issue666/playlists/cisq0gim60007xzvi505emlxx.m3u8',
'description': 'Surveillance footage - https://github.com/video-dev/hls.js/issues/666',
'live': false,
'abr': false,
'blacklist_ua': ['internet explorer']
},
/* // went offline for us :( would be good to replace this for regression test with something mimicking the issue
issue649: {
'url': 'https://cdn3.screen9.com/media/c/W/cW87csHkxsgu5TV1qs78aA_auto_hls.m3u8?auth=qlUjeCtbVdtkDfZYrtveTIVUXX1yuSqgF8wfWabzKpX72r-d5upW88-FHuyRRdnZA_1PKRTGAtTt_6Z-aj22kw',
'description': 'hls.js/issues/649',
'live': false,
'abr': false
url: 'https://playertest.longtailvideo.com/adaptive/issue666/playlists/cisq0gim60007xzvi505emlxx.m3u8',
description: 'Surveillance footage - https://github.com/video-dev/hls.js/issues/666',
abr: false,
blacklist_ua: ['internet explorer']
},
*/
closedCaptions: {
'url': 'https://playertest.longtailvideo.com/adaptive/captions/playlist.m3u8',
'description': 'CNN special report, with CC',
'live': false,
'abr': false
url: 'https://playertest.longtailvideo.com/adaptive/captions/playlist.m3u8',
description: 'CNN special report, with CC',
abr: false
},
customIvBadDts: {
'url': 'https://playertest.longtailvideo.com/adaptive/customIV/prog_index.m3u8',
'description': 'Custom IV with bad PTS DTS',
'live': false,
'abr': false,
'blacklist_ua': ['safari']
url: 'https://playertest.longtailvideo.com/adaptive/customIV/prog_index.m3u8',
description: 'Custom IV with bad PTS DTS',
abr: false
},
oceansAES: {
'url': 'https://playertest.longtailvideo.com/adaptive/oceans_aes/oceans_aes.m3u8',
'description': 'AES encrypted,ABR',
'live': false,
'abr': true
url: 'https://playertest.longtailvideo.com/adaptive/oceans_aes/oceans_aes.m3u8',
description: 'AES encrypted,ABR',
abr: true
},
/*
bbbAES: {
'url': 'https://test-streams.mux.dev/bbbAES/playlists/sample_aes/index.m3u8',
'description': 'SAMPLE-AES encrypted',
'live': false,
'abr': false
url: 'https://test-streams.mux.dev/bbbAES/playlists/sample_aes/index.m3u8',
description: 'SAMPLE-AES encrypted',
live: false,
abr: false
},
*/
mp3Audio: {
'url': 'https://playertest.longtailvideo.com/adaptive/vod-with-mp3/manifest.m3u8',
'description': 'MP3 VOD demo',
'live': false,
'abr': false,
'blacklist_ua': ['safari']
url: 'https://playertest.longtailvideo.com/adaptive/vod-with-mp3/manifest.m3u8',
description: 'MP3 VOD demo',
abr: false
},
mpegAudioOnly: {
'url': 'https://pl.streamingvideoprovider.com/mp3-playlist/playlist.m3u8',
'description': 'MPEG Audio Only demo',
'live': false,
'abr': false,
'blacklist_ua': ['internet explorer', 'MicrosoftEdge', 'safari', 'firefox']
url: 'https://pl.streamingvideoprovider.com/mp3-playlist/playlist.m3u8',
description: 'MPEG Audio Only demo',
abr: false,
blacklist_ua: ['internet explorer', 'MicrosoftEdge', 'firefox']
},
fmp4: {
'url': 'https://storage.googleapis.com/shaka-demo-assets/angel-one-hls/hls.m3u8',
'description': 'HLS fMP4 Angel-One multiple audio-tracks',
'live': false,
'abr': false,
'blacklist_ua': ['safari', 'internet explorer']
url: 'https://storage.googleapis.com/shaka-demo-assets/angel-one-hls/hls.m3u8',
description: 'HLS fMP4 Angel-One multiple audio-tracks',
abr: true,
blacklist_ua: ['internet explorer']
},
fmp4Bitmovin: {
'url': 'https://bitdash-a.akamaihd.net/content/MI201109210084_1/m3u8s-fmp4/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8',
'description': 'HLS fMP4 by Bitmovin',
'live': false,
'abr': true,
'blacklist_ua': ['safari', 'internet explorer']
url: 'https://bitdash-a.akamaihd.net/content/MI201109210084_1/m3u8s-fmp4/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8',
description: 'HLS fMP4 by Bitmovin',
abr: true,
blacklist_ua: ['internet explorer']
},
offset_pts: {
'url': 'https://test-streams.mux.dev/pts_shift/master.m3u8',
'description': 'DK Turntable, PTS shifted by 2.3s',
'live': false,
'abr': false
url: 'https://test-streams.mux.dev/pts_shift/master.m3u8',
description: 'DK Turntable, PTS shifted by 2.3s',
abr: true
},
/*
uspHLSAteam: createTestStream(
Expand All @@ -155,59 +128,67 @@ module.exports = {
angelOneShakaWidevine: createTestStreamWithConfig({
url: 'https://storage.googleapis.com/shaka-demo-assets/angel-one-widevine-hls/hls.m3u8',
description: 'Shaka-packager Widevine DRM (EME) HLS-fMP4 - Angel One Demo',
abr: true,
blacklist_ua: ['firefox', 'safari', 'internet explorer']
},
{
}, {
widevineLicenseUrl: 'http://cwip-shaka-proxy.appspot.com/no_auth',
emeEnabled: true
}
),
}),
audioOnlyMultipleLevels: {
'url': 'https://s3.amazonaws.com/qa.jwplayer.com/~alex/121628/new_master.m3u8',
'description': 'Multiple non-alternate audio levels',
'live': false,
'abr': false
url: 'https://s3.amazonaws.com/qa.jwplayer.com/~alex/121628/new_master.m3u8',
description: 'Multiple non-alternate audio levels',
abr: true
},
pdtDuplicate: {
url: 'https://playertest.longtailvideo.com/adaptive/artbeats/manifest.m3u8',
description: 'Stream with duplicate sequential PDT values'
description: 'Stream with duplicate sequential PDT values',
abr: false
},
pdtLargeGap: {
url: 'https://playertest.longtailvideo.com/adaptive/boxee/playlist.m3u8',
description: 'PDTs with large gaps following discontinuities'
description: 'PDTs with large gaps following discontinuities',
abr: false
},
pdtBadValues: {
url: 'https://playertest.longtailvideo.com/adaptive/progdatime/playlist2.m3u8',
description: 'PDTs with bad values'
description: 'PDTs with bad values',
abr: false
},
pdtOneValue: {
url: 'https://playertest.longtailvideo.com/adaptive/aviion/manifest.m3u8',
description: 'One PDT, no discontinuities'
description: 'One PDT, no discontinuities',
abr: false
},
noTrackIntersection: {
noTrackIntersection: createTestStreamWithConfig({
url: 'https://s3.amazonaws.com/qa.jwplayer.com/~alex/123633/new_master.m3u8',
description: 'Audio/video track PTS values do not intersect; 10 second start gap',
abr: false
}, {
avBufferOffset: 10.5
},
}),
// altAudioNoVideoCodecSignaled: {
// url: 'https://d35u71x3nb8v2y.cloudfront.net/4b711b97-513c-4d36-ad29-298ab23a2e5e/3cbf1114-b2f4-4320-afb3-f0f7eeeb8630/playlist.m3u8',
// description: 'Alternate audio track, but no video codec is signaled in the master manifest'
// },
altAudioAndTracks: {
url: 'https://wowzaec2demo.streamlock.net/vod-multitrack/_definst_/smil:ElephantsDream/elephantsdream2.smil/playlist.m3u',
description: 'Alternate audio tracks, and multiple VTT tracks'
description: 'Alternate audio tracks, and multiple VTT tracks',
abr: true
},
altAudioAudioOnly: {
url: 'https://playertest.longtailvideo.com/adaptive/alt-audio-no-video/sintel/playlist.m3u8',
description: 'Audio only with alternate audio track (Sintel)'
description: 'Audio only with alternate audio track (Sintel)',
abr: false
},
altAudioMultiAudioOnly: {
url: 'https://playertest.longtailvideo.com/adaptive/alt-audio-no-video/angel-one.m3u8',
description: 'Audio only with multiple alternate audio tracks (Angel One)'
description: 'Audio only with multiple alternate audio tracks (Angel One)',
abr: false
},
muxedFmp4: {
url: 'https://s3.amazonaws.com/qa.jwplayer.com/hlsjs/muxed-fmp4/hls.m3u8',
description: 'Muxed av fmp4 - appended to "audiovideo" SourceBuffer'
description: 'Muxed av fmp4 - appended to "audiovideo" SourceBuffer',
abr: false
},
altAudioWithPdtAndStartGap: {
url: 'https://playertest.longtailvideo.com/adaptive/hls-test-streams/test-audio-pdt/playlist.m3u8',
Expand Down

0 comments on commit e530158

Please sign in to comment.