rx-player
Version:
Canal+ HTML5 Video Player
128 lines (109 loc) • 3.86 kB
text/typescript
import getMonotonicTimeStamp from "../../../utils/monotonic_timestamp";
/**
* Maximum history of the buffer size that will be displayed, in milliseconds.
* For example, a value of `3000` indicates that we will just show at most the
* buffer size evolution during the last 3 seconds.
*/
const TIME_SAMPLES_MS = 30000;
/**
* At minimum, that value will be taken in the chart as a maximum buffer size,
* in seconds.
* If samples go higher than this size, the chart will adapt automatically to
* a higher scale.
* However if values go below that value, the chart won't scale down more than
* this.
*/
const MINIMUM_MAX_BUFFER_SIZE = 20;
export default class BufferSizeGraph {
private _history: IHistoryItem[];
/** Canvas that will contain the buffer size graph itself. */
private readonly _canvasElt: HTMLCanvasElement;
private readonly _canvasCtxt: CanvasRenderingContext2D | null;
constructor(canvasElt: HTMLCanvasElement) {
this._canvasElt = canvasElt;
this._canvasCtxt = this._canvasElt.getContext("2d");
this._history = [];
}
public pushBufferSize(bufferSize: number): void {
const now = getMonotonicTimeStamp();
this._history.push({ timestamp: now, bufferSize });
if (this._history.length > 0) {
const minimumTime = now - TIME_SAMPLES_MS;
let i;
for (i = this._history.length - 1; i >= 1; i--) {
if (this._history[i].timestamp <= minimumTime) {
break;
}
}
this._history = this._history.slice(i);
} else {
this._history = [];
}
}
public clear() {
if (this._canvasCtxt !== null) {
this._canvasCtxt.clearRect(0, 0, this._canvasElt.width, this._canvasElt.height);
}
}
public reRender(width: number, height: number): void {
this._canvasElt.style.width = `${width}px`;
this._canvasElt.style.height = `${height}px`;
this._canvasElt.width = width;
this._canvasElt.height = height;
this.clear();
const history = this._history;
const canvasCtx = this._canvasCtxt;
if (history.length === 0) {
return;
}
const currentMaxSize = getNewMaxBufferSize();
const minDate = history[0].timestamp;
const gridHeight = height / currentMaxSize;
const gridWidth = width / TIME_SAMPLES_MS;
drawData();
/**
* Get more appropriate maximum buffer size to put on top of the graph
* according to current history.
*/
function getNewMaxBufferSize() {
const maxPoint = Math.max(...history.map((d) => d.bufferSize));
return Math.max(maxPoint + 5, MINIMUM_MAX_BUFFER_SIZE);
}
/**
* Draw all data contained in `history` in the canvas given.
*/
function drawData() {
if (canvasCtx === null) {
return;
}
canvasCtx.beginPath();
canvasCtx.fillStyle = "rgb(200, 100, 200)";
for (let i = 1; i < history.length; i++) {
const diff = dateToX(history[i].timestamp) - dateToX(history[i - 1].timestamp);
const y = height - bufferValueToHeight(history[i].bufferSize);
canvasCtx.fillRect(dateToX(history[i - 1].timestamp), y, diff, height);
}
canvasCtx.stroke();
}
/**
* Convert a value of a given data point, to a u coordinate in the canvas.
* @param {number} bufferVal - Value to convert
* @returns {number} - y coordinate
*/
function bufferValueToHeight(bufferVal: number): number {
return height - (currentMaxSize - bufferVal) * gridHeight;
}
/**
* Convert a date of a given data point, to a x coordinate in the canvas.
* @param {number} date - Date to convert, in milliseconds
* @returns {number} - x coordinate
*/
function dateToX(date: number): number {
return (date - minDate) * gridWidth;
}
}
}
interface IHistoryItem {
timestamp: number;
bufferSize: number;
}