Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: extend stats object #10

Merged
merged 3 commits into from
Dec 15, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 2 additions & 12 deletions src/playback-watcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

import window from 'global/window';
import Ranges from './ranges';
import videojs from 'video.js';
import logger from './util/logger';

// Set of events that reset the playback-watcher time check logic and clear the timeout
const timerCancelEvents = [
Expand Down Expand Up @@ -38,10 +38,8 @@ export default class PlaybackWatcher {
this.lastRecordedTime = null;
this.timer_ = null;
this.checkCurrentTimeTimeout_ = null;
this.logger_ = logger('PlaybackWatcher');

if (options.debug) {
this.logger_ = videojs.log.bind(videojs, 'playback-watcher ->');
}
this.logger_('initialize');

let canPlayHandler = () => this.monitorCurrentTime_();
Expand Down Expand Up @@ -403,12 +401,4 @@ export default class PlaybackWatcher {

return null;
}

/**
* A debugging logger noop that is set to console.log only if debugging
* is enabled globally
*
* @private
*/
logger_() {}
}
21 changes: 20 additions & 1 deletion src/ranges.js
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,24 @@ const timeUntilRebuffer = function(buffered, currentTime, playbackRate = 1) {
return (bufferedEnd - currentTime) / playbackRate;
};

/**
* Converts a TimeRanges object into an array representation
* @param {TimeRanges} timeRanges
* @returns {Array}
*/
const timeRangesToArray = (timeRanges) => {
const timeRangesList = [];

for (let i = 0; i < timeRanges.length; i++) {
timeRangesList.push({
start: timeRanges.start(i),
end: timeRanges.end(i)
});
}

return timeRangesList;
};

export default {
findRange,
findNextRange,
Expand All @@ -373,5 +391,6 @@ export default {
TIME_FUDGE_FACTOR,
SAFE_TIME_DELTA,
printableRange,
timeUntilRebuffer
timeUntilRebuffer,
timeRangesToArray
};
26 changes: 2 additions & 24 deletions src/segment-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { initSegmentId } from './bin-utils';
import {mediaSegmentRequest, REQUEST_ERRORS} from './media-segment-request';
import { TIME_FUDGE_FACTOR, timeUntilRebuffer as timeUntilRebuffer_ } from './ranges';
import { minRebufferMaxBandwidthSelector } from './playlist-selectors';
import logger from './util/logger';

// in ms
const CHECK_BUFFER_DELAY = 500;
Expand Down Expand Up @@ -177,9 +178,7 @@ export default class SegmentLoader extends videojs.EventTarget {
// ...for determining the fetch location
this.fetchAtBuffer_ = false;

if (options.debug) {
this.logger_ = videojs.log.bind(videojs, 'segment-loader', this.loaderType_, '->');
}
this.logger_ = logger(`SegmentLoader[${this.loaderType_}]`);
}

/**
Expand Down Expand Up @@ -672,27 +671,17 @@ export default class SegmentLoader extends videojs.EventTarget {
return null;
}

this.logger_('checkBuffer_',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any specific reason for removing this and other logs that currently exist?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mjneil was removing some excessive logging

'mediaIndex:', mediaIndex,
'hasPlayed:', hasPlayed,
'currentTime:', currentTime,
'syncPoint:', syncPoint,
'fetchAtBuffer:', this.fetchAtBuffer_,
'bufferedTime:', bufferedTime);

// When the syncPoint is null, there is no way of determining a good
// conservative segment index to fetch from
// The best thing to do here is to get the kind of sync-point data by
// making a request
if (syncPoint === null) {
mediaIndex = this.getSyncSegmentCandidate_(playlist);
this.logger_('getSync', 'mediaIndex:', mediaIndex);
return this.generateSegmentInfo_(playlist, mediaIndex, null, true);
}

// Under normal playback conditions fetching is a simple walk forward
if (mediaIndex !== null) {
this.logger_('walkForward', 'mediaIndex:', mediaIndex + 1);
let segment = playlist.segments[mediaIndex];

if (segment && segment.end) {
Expand Down Expand Up @@ -725,9 +714,6 @@ export default class SegmentLoader extends videojs.EventTarget {
mediaIndex = mediaSourceInfo.mediaIndex;
startOfSegment = mediaSourceInfo.startTime;
}
this.logger_('getMediaIndexForTime',
'mediaIndex:', mediaIndex,
'startOfSegment:', startOfSegment);

return this.generateSegmentInfo_(playlist, mediaIndex, startOfSegment, false);
}
Expand Down Expand Up @@ -1274,14 +1260,6 @@ export default class SegmentLoader extends videojs.EventTarget {
(segmentProcessingThroughput - rate) / (++this.throughput.count);
}

/**
* A debugging logger noop that is set to console.log only if debugging
* is enabled globally
*
* @private
*/
logger_() {}

/**
* Adds a cue to the segment-metadata track with some metadata information about the
* segment
Expand Down
14 changes: 2 additions & 12 deletions src/sync-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import mp4probe from 'mux.js/lib/mp4/probe';
import {inspect as tsprobe} from 'mux.js/lib/tools/ts-inspector.js';
import {sumDurations} from './playlist';
import videojs from 'video.js';
import logger from './util/logger';

export const syncPointStrategies = [
// Stategy "VOD": Handle the VOD-case where the sync-point is *always*
Expand Down Expand Up @@ -147,9 +148,7 @@ export default class SyncController extends videojs.EventTarget {
this.discontinuities = [];
this.datetimeToDisplayTime = null;

if (options.debug) {
this.logger_ = videojs.log.bind(videojs, 'sync-controller ->');
}
this.logger_ = logger('SyncController');
}

/**
Expand Down Expand Up @@ -258,7 +257,6 @@ export default class SyncController extends videojs.EventTarget {
strategy: strategy.name,
syncPoint
});
this.logger_(`syncPoint found via <${strategy.name}>:`, syncPoint);
}
}

Expand Down Expand Up @@ -547,12 +545,4 @@ export default class SyncController extends videojs.EventTarget {
}
}
}

/**
* A debugging logger noop that is set to console.log only if debugging
* is enabled globally
*
* @private
*/
logger_() {}
}
11 changes: 11 additions & 0 deletions src/util/logger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import videojs from 'video.js';

const logger = (source) => {
Copy link
Contributor

@mjneil mjneil Dec 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will not allow us the ability to turn debug logging on mid session via videojs.log.level('debug') . If we want to support that, we will need something like this

const logger = (source) => (...args) => {
  if (videojs.log.level() === 'debug') {
    videojs.log.debug('VHS:', `${source} >`, ...args);
  }
};

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you don't even need the .call(videojs, in your way @mjneil.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh right, good call!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops this is checking if debug api is available, not if the mode is debug

if (videojs.log.debug) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know we discussed how the history object might get crowded by the debug logging once it's available. Do we know about how many logs per minute of video we'll be generating?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like around ~35 items per minute with what's being logged at the moment

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If that's pretty standard (and we can't get into a case where the log messages explode), that seems pretty good (to not have to hide behind another config flag). We should be careful to look at some of the cases in case any could spew messages though, and test some scenarios to make sure we don't kill a browser tab from memory consumptions.

return videojs.log.debug.bind(videojs, 'VHS:', `${source} >`);
}

return function() {};
};

export default logger;
41 changes: 41 additions & 0 deletions src/videojs-http-streaming.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Playlist from './playlist';
import xhrFactory from './xhr';
import {Decrypter, AsyncStream, decrypt} from 'aes-decrypter';
import utils from './bin-utils';
import {timeRangesToArray} from './ranges';
import {MediaSource, URL} from 'videojs-contrib-media-sources';
import m3u8 from 'm3u8-parser';
import videojs from 'video.js';
Expand Down Expand Up @@ -409,6 +410,46 @@ class HlsHandler extends Component {
mediaSecondsLoaded: {
get: () => this.masterPlaylistController_.mediaSecondsLoaded_() || 0,
enumerable: true
},
buffered: {
get: () => timeRangesToArray(this.tech_.buffered()),
enumerable: true
},
currentTime: {
get: () => this.tech_.currentTime(),
enumerable: true
},
currentSource: {
get: () => this.tech_.currentSource_,
enumerable: true
},
currentTech: {
get: () => this.tech_.name_,
enumerable: true
},
duration: {
get: () => this.tech_.duration(),
enumerable: true
},
master: {
get: () => this.playlists.master,
enumerable: true
},
playerDimensions: {
get: () => this.tech_.currentDimensions(),
enumerable: true
},
seekable: {
get: () => timeRangesToArray(this.tech_.seekable()),
enumerable: true
},
timestamp: {
get: () => Date.now(),
enumerable: true
},
videoPlaybackQuality: {
get: () => this.tech_.getVideoPlaybackQuality(),
enumerable: true
}
});

Expand Down
10 changes: 10 additions & 0 deletions test/ranges.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -331,3 +331,13 @@ QUnit.test('creates printable ranges', function(assert) {
'10 => 25, 20 => 40, -1 => -2',
'formats ranges correctly');
});

QUnit.test('converts time ranges to an array', function(assert) {
assert.deepEqual(Ranges.timeRangesToArray(createTimeRanges()), [], 'empty range empty array');
assert.deepEqual(Ranges.timeRangesToArray(createTimeRanges([[0, 1]])),
[{start: 0, end: 1}],
'formats range correctly');
assert.deepEqual(Ranges.timeRangesToArray(createTimeRanges([[10, 20], [30, 40]])),
[{start: 10, end: 20}, {start: 30, end: 40}],
'formats ranges correctly');
});