Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/origin/development'
Browse files Browse the repository at this point in the history
  • Loading branch information
dsilhavy committed Jul 24, 2020
2 parents db496cb + 32b50c6 commit ea1362f
Show file tree
Hide file tree
Showing 93 changed files with 4,151 additions and 4,378 deletions.
14 changes: 7 additions & 7 deletions README.md
Expand Up @@ -3,7 +3,7 @@

Build status (CircleCI): [![CircleCI](https://circleci.com/gh/Dash-Industry-Forum/dash.js/tree/development.svg?style=svg)](https://circleci.com/gh/Dash-Industry-Forum/dash.js/tree/development)

Join the discussion: [![Slack Status](https://dashif-slack.azurewebsites.net/badge.svg)](https://dashif-slack.azurewebsites.net)
[Join #dashjs on Slack!](https://join.slack.com/t/dashif/shared_invite/zt-egme869x-JH~UPUuLoKJB26fw7wj3Gg)

## Overview
A reference client implementation for the playback of MPEG DASH via JavaScript and [compliant browsers](http://caniuse.com/#feat=mediasource). Learn more about DASH IF Reference Client on our [wiki](https://github.com/Dash-Industry-Forum/dash.js/wiki).
Expand All @@ -27,15 +27,15 @@ The [nightly build of the /dev branch reference player](http://reference.dashif.


### CDN hosted files
The latest minified files have been hosted on a global CDN and are free to use in production:
The latest minified files have been hosted on a global CDN and are free to use in production:

- [dash.all.min.js](http://cdn.dashjs.org/latest/dash.all.min.js)
- [dash.all.debug.js](http://cdn.dashjs.org/latest/dash.all.debug.js)
- [dash.all.min.js](http://cdn.dashjs.org/latest/dash.all.min.js)
- [dash.all.debug.js](http://cdn.dashjs.org/latest/dash.all.debug.js)

In addition, all the releases are available under the following urls. Replace "vx.x.x" with the release version, for instance "v3.1.0".
In addition, all the releases are available under the following urls. Replace "vx.x.x" with the release version, for instance "v3.1.0".

- [http://cdn.dashjs.org/vx.x.x/dash.all.min.js](http://cdn.dashjs.org/v3.1.0/dash.all.min.js)
- [http://cdn.dashjs.org/vx.x.x/dash.all.debug.js](http://cdn.dashjs.org/v3.1.0/dash.all.debug.js)
- [http://cdn.dashjs.org/vx.x.x/dash.all.min.js](http://cdn.dashjs.org/v3.1.0/dash.all.min.js)
- [http://cdn.dashjs.org/vx.x.x/dash.all.debug.js](http://cdn.dashjs.org/v3.1.0/dash.all.debug.js)



Expand Down
27 changes: 21 additions & 6 deletions contrib/akamai/controlbar/ControlBar.js
Expand Up @@ -278,7 +278,7 @@ var ControlBar = function (dashjsMediaPlayer, displayUTCTimeCodes) {
}

// Get thumbnail information
player.getThumbnail(mouseTime, function (thumbnail) {
player.provideThumbnail(mouseTime, function (thumbnail) {
if (!thumbnail) return;

// Adjust left variable for positioning thumbnail with regards to its viewport
Expand Down Expand Up @@ -433,8 +433,10 @@ var ControlBar = function (dashjsMediaPlayer, displayUTCTimeCodes) {
window.removeEventListener('mousemove', onFullScreenMouseMove);
clearFullscreenState();

if (document.exitFullscreen) {
if (document.fullscreenElement) {
document.exitFullscreen();
} else if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.msExitFullscreen) {
Expand Down Expand Up @@ -489,6 +491,8 @@ var ControlBar = function (dashjsMediaPlayer, displayUTCTimeCodes) {
menuHandlersList.push(func);
captionBtn.addEventListener('click', func);
captionBtn.classList.remove('hide');
} else {
setMenuItemsState(e.index + 1, 'caption-list');
}
};

Expand All @@ -505,7 +509,8 @@ var ControlBar = function (dashjsMediaPlayer, displayUTCTimeCodes) {
var availableBitrates = { menuType: 'bitrate' };
availableBitrates.audio = player.getBitrateInfoListFor('audio') || [];
availableBitrates.video = player.getBitrateInfoListFor('video') || [];
if (availableBitrates.audio.length > 1 || availableBitrates.video.length > 1) {
availableBitrates.images = player.getBitrateInfoListFor('image') || [];
if (availableBitrates.audio.length > 1 || availableBitrates.video.length > 1 || availableBitrates.images.length > 1) {
contentFunc = function (element, index) {
var result = isNaN(index) ? ' Auto Switch' : Math.floor(element.bitrate / 1000) + ' kbps';
result += element && element.width && element.height ? ' (' + element.width + 'x' + element.height + ')' : '';
Expand Down Expand Up @@ -578,6 +583,11 @@ var ControlBar = function (dashjsMediaPlayer, displayUTCTimeCodes) {
el = createMenuContent(el, getMenuContent(menuType, info.audio, contentFunc), 'audio', 'audio-' + menuType + '-list');
setMenuItemsState(getMenuInitialIndex(info.audio, menuType, 'audio'), 'audio-' + menuType + '-list');
}
if (info.images && info.images.length > 1) {
el.appendChild(createMediaTypeMenu('image'));
el = createMenuContent(el, getMenuContent(menuType, info.images, contentFunc, false), 'image', 'image-' + menuType + '-list');
setMenuItemsState(getMenuInitialIndex(info.images, menuType, 'image'), 'image-' + menuType + '-list');
}
break;
}

Expand Down Expand Up @@ -619,12 +629,14 @@ var ControlBar = function (dashjsMediaPlayer, displayUTCTimeCodes) {
return (sameId && sameViewpoint && sameLang && sameRoles && sameAccessibility && sameAudioChannelConfiguration);
};

var getMenuContent = function (type, arr, contentFunc) {
var getMenuContent = function (type, arr, contentFunc, autoswitch) {
autoswitch = (autoswitch !== undefined) ? autoswitch : true;

var content = [];
arr.forEach(function (element, index) {
content.push(contentFunc(element, index));
});
if (type !== 'track') {
if (type !== 'track' && autoswitch) {
content.unshift(contentFunc(null, NaN));
}
return content;
Expand Down Expand Up @@ -655,7 +667,7 @@ var ControlBar = function (dashjsMediaPlayer, displayUTCTimeCodes) {

div.id = type;

title.textContent = type === 'video' ? 'Video' : 'Audio';
title.textContent = type.charAt(0).toUpperCase() + type.slice(1);
title.classList.add('menu-sub-menu-title');

content.id = type + 'Content';
Expand Down Expand Up @@ -749,6 +761,9 @@ var ControlBar = function (dashjsMediaPlayer, displayUTCTimeCodes) {
player.updateSettings(cfg);
}
break;
case 'image-bitrate-list':
player.setQualityFor(self.mediaType, self.index);
break;
case 'caption-list':
player.setTextTrack(self.index - 1);
break;
Expand Down
88 changes: 81 additions & 7 deletions index.d.ts
Expand Up @@ -44,7 +44,29 @@ declare namespace dashjs {
reset(): void;
}

export interface OfflineRecord {
id: string;
progress: number;
url: string;
originalUrl: string;
status: string;
}

interface OfflineController {
loadRecordsFromStorage(): Promise<void>;
getAllRecords(): OfflineRecord[];
createRecord(manifestURL: string): Promise<string>;
startRecord(id: string, mediaInfos: MediaInfo[]): void;
stopRecord(id: string): void;
resumeRecord(id: string): void;
deleteRecord(id: string): void;
getRecordProgression(id: string): number;
resetRecords(): void;
reset(): void;
}

export interface Bitrate {
id?: string;
width?: number;
height?: number;
bandwidth?: number;
Expand Down Expand Up @@ -195,7 +217,8 @@ declare namespace dashjs {
on(type: ManifestLoadedEvent['type'], listener: (e: ManifestLoadedEvent) => void, scope?: object): void;
on(type: MetricEvent['type'], listener: (e: MetricEvent) => void, scope?: object): void;
on(type: MetricChangedEvent['type'], listener: (e: MetricChangedEvent) => void, scope?: object): void;
on(type: OfflineStreamEvent['type'], listener: (e: OfflineStreamEvent) => void, scope?: object): void;
on(type: OfflineRecordEvent['type'], listener: (e: OfflineRecordEvent) => void, scope?: object): void;
on(type: OfflineRecordLoademetadataEvent['type'], listener: (e: OfflineRecordLoademetadataEvent) => void, scope?: object): void;
on(type: PeriodSwitchEvent['type'], listener: (e: PeriodSwitchEvent) => void, scope?: object): void;
on(type: PlaybackErrorEvent['type'], listener: (e: PlaybackErrorEvent) => void, scope?: object): void;
on(type: PlaybackPausedEvent['type'], listener: (e: PlaybackPausedEvent) => void, scope?: object): void;
Expand Down Expand Up @@ -260,7 +283,7 @@ declare namespace dashjs {
setTextDefaultLanguage(lang: string): void;
getTextDefaultEnabled(): boolean | undefined;
setTextDefaultEnabled(enable: boolean): void;
getThumbnail(time: number): Thumbnail;
provideThumbnail(time: number, callback: (thumbnail: Thumbnail | null) => void): void;
getBitrateInfoListFor(type: MediaType): BitrateInfo[];
getStreamsFromManifest(manifest: object): StreamInfo[];
getTracksFor(type: MediaType): MediaInfo[];
Expand All @@ -283,6 +306,7 @@ declare namespace dashjs {
getProtectionController(): ProtectionController;
attachProtectionController(value: ProtectionController): void;
setProtectionData(value: ProtectionData): void;
getOfflineController(): OfflineController;
enableManifestDateHeaderTimeSource(value: boolean): void;
displayCaptionsOnTop(value: boolean): void;
attachTTMLRenderingDiv(div: HTMLDivElement): void;
Expand Down Expand Up @@ -352,7 +376,24 @@ declare namespace dashjs {
KEY_SYSTEM_ACCESS_DENIED_ERROR_CODE: 112;
KEY_SESSION_CREATED_ERROR_CODE: 113;
MEDIA_KEY_MESSAGE_LICENSER_ERROR_CODE: 114;
// MSS errors
MSS_NO_TFRF_CODE: 200;
MSS_UNSUPPORTED_CODEC_CODE: 201;
// Offline errors
OFFLINE_ERROR: 11000;
INDEXEDDB_QUOTA_EXCEED_ERROR: 11001;
INDEXEDDB_INVALID_STATE_ERROR: 11002;
INDEXEDDB_NOT_READABLE_ERROR: 11003;
INDEXEDDB_NOT_FOUND_ERROR: 11004;
INDEXEDDB_NETWORK_ERROR: 11005;
INDEXEDDB_DATA_ERROR: 11006;
INDEXEDDB_TRANSACTION_INACTIVE_ERROR: 11007;
INDEXEDDB_NOT_ALLOWED_ERROR: 11008;
INDEXEDDB_NOT_SUPPORTED_ERROR: 11009;
INDEXEDDB_VERSION_ERROR: 11010;
INDEXEDDB_TIMEOUT_ERROR: 11011;
INDEXEDDB_ABORT_ERROR: 11012;
INDEXEDDB_UNKNOWN_ERROR: 11013;
}

interface MediaPlayerEvents {
Expand Down Expand Up @@ -382,6 +423,10 @@ declare namespace dashjs {
METRIC_ADDED: 'metricAdded';
METRIC_CHANGED: 'metricChanged';
METRIC_UPDATED: 'metricUpdated';
OFFLINE_RECORD_FINISHED: 'public_offlineRecordFinished';
OFFLINE_RECORD_LOADEDMETADATA: 'public_offlineRecordLoadedmetadata';
OFFLINE_RECORD_STARTED: 'public_offlineRecordStarted';
OFFLINE_RECORD_STOPPED: 'public_offlineRecordStopped';
PERIOD_SWITCH_COMPLETED: 'periodSwitchCompleted';
PERIOD_SWITCH_STARTED: 'periodSwitchStarted';
PLAYBACK_ENDED: 'playbackEnded';
Expand Down Expand Up @@ -496,6 +541,7 @@ declare namespace dashjs {
MediaPlayerErrors['TIMED_TEXT_ERROR_ID_PARSE_CODE'] |
MediaPlayerErrors['MANIFEST_ERROR_ID_MULTIPLEXED_CODE'] |
MediaPlayerErrors['MEDIASOURCE_TYPE_UNSUPPORTED_CODE'] |
// Protection errors
MediaPlayerErrors['MEDIA_KEYERR_CODE'] |
MediaPlayerErrors['MEDIA_KEYERR_UNKNOWN_CODE'] |
MediaPlayerErrors['MEDIA_KEYERR_CLIENT_CODE'] |
Expand All @@ -511,9 +557,26 @@ declare namespace dashjs {
MediaPlayerErrors['KEY_SYSTEM_ACCESS_DENIED_ERROR_CODE'] |
MediaPlayerErrors['KEY_SESSION_CREATED_ERROR_CODE'] |
MediaPlayerErrors['MEDIA_KEY_MESSAGE_LICENSER_ERROR_CODE'] |
MediaPlayerErrors['MSS_NO_TFRF_CODE'],
message:string,
data:object,
// Offline errors
MediaPlayerErrors['OFFLINE_ERROR'] |
MediaPlayerErrors['INDEXEDDB_QUOTA_EXCEED_ERROR'] |
MediaPlayerErrors['INDEXEDDB_INVALID_STATE_ERROR'] |
MediaPlayerErrors['INDEXEDDB_NOT_READABLE_ERROR'] |
MediaPlayerErrors['INDEXEDDB_NOT_FOUND_ERROR'] |
MediaPlayerErrors['INDEXEDDB_NETWORK_ERROR'] |
MediaPlayerErrors['INDEXEDDB_DATA_ERROR'] |
MediaPlayerErrors['INDEXEDDB_TRANSACTION_INACTIVE_ERROR'] |
MediaPlayerErrors['INDEXEDDB_NOT_ALLOWED_ERROR'] |
MediaPlayerErrors['INDEXEDDB_NOT_SUPPORTED_ERROR'] |
MediaPlayerErrors['INDEXEDDB_VERSION_ERROR'] |
MediaPlayerErrors['INDEXEDDB_TIMEOUT_ERROR'] |
MediaPlayerErrors['INDEXEDDB_ABORT_ERROR'] |
MediaPlayerErrors['INDEXEDDB_UNKNOWN_ERROR'] |
// MSS errors
MediaPlayerErrors['MSS_NO_TFRF_CODE'] |
MediaPlayerErrors['MSS_UNSUPPORTED_CODEC_CODE'],
message: string,
data: object,
}
}

Expand Down Expand Up @@ -621,6 +684,16 @@ declare namespace dashjs {
mediaType: MediaType;
}

export interface OfflineRecordEvent extends Event {
type: MediaPlayerEvents['OFFLINE_RECORD_FINISHED' | 'OFFLINE_RECORD_STARTED' | 'OFFLINE_RECORD_STOPPED' | 'OFFLINE_RECORD_STOPPED'];
id: string;
}

export interface OfflineRecordLoademetadataEvent extends Event {
type: MediaPlayerEvents['OFFLINE_RECORD_LOADEDMETADATA'];
madiaInfos: MediaInfo[];
}

export interface PeriodSwitchEvent extends Event {
type: MediaPlayerEvents['PERIOD_SWITCH_COMPLETED' | 'PERIOD_SWITCH_STARTED'];
toStreamInfo: StreamInfo | null;
Expand Down Expand Up @@ -730,7 +803,7 @@ declare namespace dashjs {
}

export class BitrateInfo {
mediaType: 'video' | 'audio';
mediaType: 'video' | 'audio' | 'image';
bitrate: number;
width: number;
height: number;
Expand Down Expand Up @@ -800,14 +873,15 @@ declare namespace dashjs {
loadedTime: Date;
maxFragmentDuration: number;
minBufferTime: number;
protocol?: string;
}

export class StreamInfo {
id: string;
index: number;
start: number;
duration: number;
manifestInfo: object;
manifestInfo: IManifestInfo;
isLast: boolean;
}

Expand Down
2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "dashjs",
"version": "3.1.1",
"version": "3.1.2",
"description": "A reference client implementation for the playback of MPEG DASH via Javascript and compliant browsers.",
"main": "build/es5/index.js",
"types": "build/typings/index.d.ts",
Expand Down
33 changes: 20 additions & 13 deletions samples/advanced/monitoring.html
Expand Up @@ -18,12 +18,12 @@
video = document.querySelector("video");
player = dashjs.MediaPlayer().create();
player.initialize(video, url, true);
player.on(dashjs.MediaPlayer.events["PLAYBACK_ENDED"], function() {
player.on(dashjs.MediaPlayer.events["PLAYBACK_ENDED"], function () {
clearInterval(eventPoller);
clearInterval(bitrateCalculator);
});

var eventPoller = setInterval(function() {
var eventPoller = setInterval(function () {
var streamInfo = player.getActiveStream().getStreamInfo();
var dashMetrics = player.getDashMetrics();
var dashAdapter = player.getDashAdapter();
Expand All @@ -33,15 +33,20 @@
var repSwitch = dashMetrics.getCurrentRepresentationSwitch('video', true);
var bufferLevel = dashMetrics.getCurrentBufferLevel('video', true);
var bitrate = repSwitch ? Math.round(dashAdapter.getBandwidthForRepresentation(repSwitch.to, periodIdx) / 1000) : NaN;
var adaptation = dashAdapter.getAdaptationForType(periodIdx, 'video', streamInfo)
var frameRate = adaptation.Representation_asArray.find(function (rep) {
return rep.id === repSwitch.to
}).frameRate;
document.getElementById('bufferLevel').innerText = bufferLevel + " secs";
document.getElementById('framerate').innerText = frameRate + " fps";
document.getElementById('reportedBitrate').innerText = bitrate + " Kbps";
}
}, 1000);

if (video.webkitVideoDecodedByteCount !== undefined) {
var lastDecodedByteCount = 0;
const bitrateInterval = 5;
var bitrateCalculator = setInterval(function() {
var bitrateCalculator = setInterval(function () {
var calculatedBitrate = (((video.webkitVideoDecodedByteCount - lastDecodedByteCount) / 1000) * 8) / bitrateInterval;
document.getElementById('calculatedBitrate').innerText = Math.round(calculatedBitrate) + " Kbps";
lastDecodedByteCount = video.webkitVideoDecodedByteCount;
Expand Down Expand Up @@ -75,19 +80,21 @@
<body>
<div id="container">
<div class="video-container">
<video data-dashjs-player autoplay controls="true">
<video data-dashjs-player autoplay controls="true">
</video>
</div>
<div>
<strong>Reported bitrate:</strong>
<span id="reportedBitrate"></span>
<br />
<strong>Buffer level:</strong>
<span id="bufferLevel"></span>
<div id="chrome-only">
<strong>Calculated bitrate:</strong>
<span id="calculatedBitrate"></span>
</div>
<strong>Reported bitrate:</strong>
<span id="reportedBitrate"></span>
<br/>
<strong>Buffer level:</strong>
<span id="bufferLevel"></span>
<div id="chrome-only">
<strong>Calculated bitrate:</strong>
<span id="calculatedBitrate"></span>
</div>
<strong>Framerate:</strong>
<span id="framerate"></span>
</div>
</div>
<script>
Expand Down
1 change: 1 addition & 0 deletions samples/captioning/caption_vtt.html
Expand Up @@ -19,6 +19,7 @@

player = dashjs.MediaPlayer({}).create();
player.initialize(video, url, true);
player.setTextDefaultEnabled(true);
}
</script>

Expand Down

0 comments on commit ea1362f

Please sign in to comment.