Skip to content

Commit

Permalink
fix: Default to using segmentInfo.trackInfo over this.currentMediaInf…
Browse files Browse the repository at this point in the history
…o_ to get segment track info. (#1162)
  • Loading branch information
brandonocasey authored Jul 13, 2021
1 parent df07176 commit 1d6bb55
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 18 deletions.
15 changes: 10 additions & 5 deletions src/master-playlist-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -1045,9 +1045,10 @@ export class MasterPlaylistController extends videojs.EventTarget {
let isEndOfStream = this.mainSegmentLoader_.ended_;

if (this.mediaTypes_.AUDIO.activePlaylistLoader) {
const mainMediaInfo = this.mainSegmentLoader_.getCurrentMediaInfo_();

// if the audio playlist loader exists, then alternate audio is active
if (!this.mainSegmentLoader_.currentMediaInfo_ ||
this.mainSegmentLoader_.currentMediaInfo_.hasVideo) {
if (!mainMediaInfo || mainMediaInfo.hasVideo) {
// if we do not know if the main segment loader contains video yet or if we
// definitively know the main segment loader contains video, then we need to wait
// for both main and audio segment loaders to call endOfStream
Expand Down Expand Up @@ -1619,9 +1620,13 @@ export class MasterPlaylistController extends videojs.EventTarget {

areMediaTypesKnown_() {
const usingAudioLoader = !!this.mediaTypes_.AUDIO.activePlaylistLoader;
const hasMainMediaInfo = !!this.mainSegmentLoader_.getCurrentMediaInfo_();
// if we are not using an audio loader, then we have audio media info
// otherwise check on the segment loader.
const hasAudioMediaInfo = !usingAudioLoader ? true : !!this.audioSegmentLoader_.getCurrentMediaInfo_();

// one or both loaders has not loaded sufficently to get codecs
if (!this.mainSegmentLoader_.currentMediaInfo_ || (usingAudioLoader && !this.audioSegmentLoader_.currentMediaInfo_)) {
if (!hasMainMediaInfo || !hasAudioMediaInfo) {
return false;
}

Expand All @@ -1630,8 +1635,8 @@ export class MasterPlaylistController extends videojs.EventTarget {

getCodecsOrExclude_() {
const media = {
main: this.mainSegmentLoader_.currentMediaInfo_ || {},
audio: this.audioSegmentLoader_.currentMediaInfo_ || {}
main: this.mainSegmentLoader_.getCurrentMediaInfo_() || {},
audio: this.audioSegmentLoader_.getCurrentMediaInfo_() || {}
};

// set "main" media equal to video
Expand Down
37 changes: 26 additions & 11 deletions src/segment-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -811,12 +811,14 @@ export default class SegmentLoader extends videojs.EventTarget {
* TimeRange object representing the current buffered ranges
*/
buffered_() {
if (!this.sourceUpdater_ || !this.startingMediaInfo_) {
const trackInfo = this.getMediaInfo_();

if (!this.sourceUpdater_ || !trackInfo) {
return videojs.createTimeRanges();
}

if (this.loaderType_ === 'main') {
const { hasAudio, hasVideo, isMuxed } = this.startingMediaInfo_;
const { hasAudio, hasVideo, isMuxed } = trackInfo;

if (hasVideo && hasAudio && !this.audioDisabled_ && !isMuxed) {
return this.sourceUpdater_.buffered();
Expand Down Expand Up @@ -1206,7 +1208,7 @@ export default class SegmentLoader extends videojs.EventTarget {
return;
}

if (!this.sourceUpdater_ || !this.startingMediaInfo_) {
if (!this.sourceUpdater_ || !this.getMediaInfo_()) {
this.logger_('skipping remove because no source updater or starting media info');
// nothing to remove if we haven't processed any media
return;
Expand Down Expand Up @@ -1871,7 +1873,7 @@ export default class SegmentLoader extends videojs.EventTarget {
// created together (before appending). Source buffer creation uses the presence of
// audio and video data to determine whether to create audio/video source buffers, and
// uses processed (transmuxed or parsed) media to determine the types required.
if (!this.currentMediaInfo_) {
if (!this.getCurrentMediaInfo_()) {
return true;
}

Expand Down Expand Up @@ -1905,6 +1907,14 @@ export default class SegmentLoader extends videojs.EventTarget {
return true;
}

getCurrentMediaInfo_(segmentInfo = this.pendingSegment_) {
return segmentInfo && segmentInfo.trackInfo || this.currentMediaInfo_;
}

getMediaInfo_(segmentInfo = this.pendingSegment_) {
return this.getCurrentMediaInfo_(segmentInfo) || this.startingMediaInfo_;
}

hasEnoughInfoToAppend_() {
if (!this.sourceUpdater_.ready()) {
return false;
Expand All @@ -1917,15 +1927,16 @@ export default class SegmentLoader extends videojs.EventTarget {
}

const segmentInfo = this.pendingSegment_;
const trackInfo = this.getCurrentMediaInfo_();

// no segment to append any data for or
// we do not have information on this specific
// segment yet
if (!segmentInfo || !segmentInfo.trackInfo) {
if (!segmentInfo || !trackInfo) {
return false;
}

const {hasAudio, hasVideo, isMuxed} = this.currentMediaInfo_;
const {hasAudio, hasVideo, isMuxed} = trackInfo;

if (hasVideo && !segmentInfo.videoTimingInfo) {
return false;
Expand Down Expand Up @@ -2005,8 +2016,9 @@ export default class SegmentLoader extends videojs.EventTarget {
segmentInfo.timingInfo.start =
segmentInfo[timingInfoPropertyForMedia(result.type)].start;
} else {
const trackInfo = this.getCurrentMediaInfo_();
const useVideoTimingInfo =
this.loaderType_ === 'main' && this.currentMediaInfo_.hasVideo;
this.loaderType_ === 'main' && trackInfo && trackInfo.hasVideo;
let firstVideoFrameTimeForData;

if (useVideoTimingInfo) {
Expand Down Expand Up @@ -2714,7 +2726,9 @@ export default class SegmentLoader extends videojs.EventTarget {
}

waitForAppendsToComplete_(segmentInfo) {
if (!this.currentMediaInfo_) {
const trackInfo = this.getCurrentMediaInfo_(segmentInfo);

if (!trackInfo) {
this.error({
message: 'No starting media returned, likely due to an unsupported media format.',
blacklistDuration: Infinity
Expand All @@ -2725,7 +2739,7 @@ export default class SegmentLoader extends videojs.EventTarget {
// Although transmuxing is done, appends may not yet be finished. Throw a marker
// on each queue this loader is responsible for to ensure that the appends are
// complete.
const {hasAudio, hasVideo, isMuxed} = this.currentMediaInfo_;
const {hasAudio, hasVideo, isMuxed} = trackInfo;
const waitForVideo = this.loaderType_ === 'main' && hasVideo;
const waitForAudio = !this.audioDisabled_ && hasAudio && !isMuxed;

Expand Down Expand Up @@ -2793,7 +2807,7 @@ export default class SegmentLoader extends videojs.EventTarget {

checkForIllegalMediaSwitch(trackInfo) {
const illegalMediaSwitchError =
illegalMediaSwitch(this.loaderType_, this.currentMediaInfo_, trackInfo);
illegalMediaSwitch(this.loaderType_, this.getCurrentMediaInfo_(), trackInfo);

if (illegalMediaSwitchError) {
this.error({
Expand Down Expand Up @@ -2848,8 +2862,9 @@ export default class SegmentLoader extends videojs.EventTarget {

updateTimingInfoEnd_(segmentInfo) {
segmentInfo.timingInfo = segmentInfo.timingInfo || {};
const trackInfo = this.getMediaInfo_();
const useVideoTimingInfo =
this.loaderType_ === 'main' && this.currentMediaInfo_.hasVideo;
this.loaderType_ === 'main' && trackInfo && trackInfo.hasVideo;
const prioritizedTimingInfo = useVideoTimingInfo && segmentInfo.videoTimingInfo ?
segmentInfo.videoTimingInfo : segmentInfo.audioTimingInfo;

Expand Down
35 changes: 33 additions & 2 deletions test/loader-common.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ import { Vhs } from '../src/videojs-http-streaming';
import {
muxed as muxedSegment,
mp4Video as mp4VideoSegment,
mp4VideoInit as mp4VideoInitSegment
mp4VideoInit as mp4VideoInitSegment,
videoOneSecond as tsVideoSegment
} from 'create-test-data!segments';

/**
Expand Down Expand Up @@ -821,8 +822,38 @@ export const LoaderCommonFactory = ({
});
});

// only main/fmp4 segment loaders use parts/partIndex
// only main/fmp4 segment loaders use async appends and parts/partIndex
if (usesAsyncAppends) {
QUnit.test('playlist change before any appends does not error', function(assert) {
return setupMediaSource(loader.mediaSource_, loader.sourceUpdater_).then(() => {
loader.playlist(playlistWithDuration(50, {
uri: 'bar-720.m3u8',
mediaSequence: 0,
endList: true
}));

loader.load();
this.clock.tick(1);
return Promise.resolve();
}).then(() => new Promise((resolve, reject) => {
loader.on('playlistupdate', () => {
this.clock.tick(1);
resolve();
});
loader.on('trackinfo', () => {
loader.playlist(playlistWithDuration(50, {
uri: 'bar-1080.m3u8',
mediaSequence: 0,
endList: true
}));
});
standardXHRResponse(this.requests.shift(), tsVideoSegment());

})).then(() => {
assert.equal(loader.pendingSegment_.playlist.uri, 'bar-720.m3u8', 'previous playlist segment');
});
});

QUnit.test('mediaIndex and partIndex are used', function(assert) {
return setupMediaSource(loader.mediaSource_, loader.sourceUpdater_).then(() => {
loader.playlist(playlistWithDuration(50, {
Expand Down

0 comments on commit 1d6bb55

Please sign in to comment.