Skip to content

Commit

Permalink
Refactor MediaPlayerFactory to support a cleaner declarative setup.
Browse files Browse the repository at this point in the history
This marks significant progress towards Dash-Industry-Forum#1136.
  • Loading branch information
boushley committed Feb 6, 2016
1 parent 7658318 commit cee121f
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 35 deletions.
17 changes: 10 additions & 7 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,15 @@ import MediaPlayerFactory from './src/streaming/MediaPlayerFactory.js';
// Shove both of these into the global scope
var context = window || global;

context.dashjs = {
MediaPlayer: MediaPlayer,
Protection: Protection,
MetricsReporting: MetricsReporting,
MediaPlayerFactory: MediaPlayerFactory
};
var dashjs = context.dashjs;
if (!dashjs) {
dashjs = context.dashjs = {};
}

export default context.dashjs;
dashjs.MediaPlayer = MediaPlayer;
dashjs.Protection = Protection;
dashjs.MetricsReporting = MetricsReporting;
dashjs.MediaPlayerFactory = MediaPlayerFactory;

export default dashjs;
export { MediaPlayer, Protection, MetricsReporting, MediaPlayerFactory };
10 changes: 5 additions & 5 deletions samples/getting-started-basic-embed/auto-load-multi-video.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,27 @@
}
</style>

<body onload="dashjs.MediaPlayerFactory.createAll()">
<body>
<div>
<video class="dashjs-player" autoplay controls>
<video autoplay controls>
<source src="http://dash.edgesuite.net/envivio/EnvivioDash3/manifest.mpd" type="application/dash+xml"/>
</video>
<br/>This is a dash.js player that should autostart<p/>
</div>
<div>
<video class="any-other-class" autoplay controls="true">
<video autoplay controls="true">
<source src="http://mediapm.edgesuite.net/ovp/content/test/video/spacealonehd_sounas_640_300.mp4" type="video/mp4"/>
</video>
<br/>This is a standard mp4 (non-dash)<p/>
</div>
<div>
<video class="dashjs-player" poster="http://mediapm.edgesuite.net/will/dash/temp/poster.png" controls="true">
<video poster="http://mediapm.edgesuite.net/will/dash/temp/poster.png" controls="true">
<source src="http://dash.edgesuite.net/digitalprimates/fraunhofer/480p_video/heaac_2_0_with_video/Sintel/sintel_480p_heaac2_0.mpd" type="application/dash+xml"/>
</video>
<br/>This is a dash.js player that should not autostart<p/>
</div>
<div>
<video class="dashjs-player" autoplay src="http://dash.edgesuite.net/envivio/EnvivioDash3/manifest.mpd" controls="true">
<video data-dashjs-player autoplay src="http://dash.edgesuite.net/envivio/EnvivioDash3/manifest.mpd" controls="true">
</video>
<br/>This is a dash.js player that where the manifest is defined via the src attribute of the video element.
</div>
Expand Down
82 changes: 59 additions & 23 deletions src/streaming/MediaPlayerFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ function MediaPlayerFactory() {
*/
const SUPPORTED_MIME_TYPE = 'application/dash+xml';

let instance;

/**
* A new MediaPlayer is instantiated for the supplied videoElement and optional source and context. If no context is provided,
* a default DashContext is used. If no source is provided, the videoElement is interrogated to extract the first source whose
Expand All @@ -21,59 +19,97 @@ function MediaPlayerFactory() {
* @returns {MediaPlayer}
*/
function create(video, source, context) {
if (video === null || typeof video === 'undefined' || video.nodeName !== 'VIDEO') return null;
if (!video || video.nodeName !== 'VIDEO') return null;

if (video._dashjs_player) return video._dashjs_player;

var player;
var videoID = (video.id || video.name || 'video element');

source = source || [].slice.call(video.querySelectorAll('source')).filter(function (s) {
return s.type == SUPPORTED_MIME_TYPE;
})[0];
if (source === undefined && video.src) {
if (!source && video.src) {
source = document.createElement('source');
source.src = video.src;
} else if (source === undefined && !video.src) {
} else if (!source && !video.src) {
return null;
}
if (context === undefined) {
context = {};
}

context = context || {};
player = MediaPlayer(context).create();
player.initialize(video, source.src, video.autoplay);
player.getDebug().log('Converted ' + videoID + ' to dash.js player and added content: ' + source.src);

// Store a reference to the player on the video element so it can be gotten at for debugging and so we know its
// already been setup.
video._dashjs_player = player;

return player;
}

/**
* Searches the provided scope for all instances of the indicated className. If no scope is provided, document is used. If no className is
* specified, dashjs-player is used. It then looks for those video elements which have a source element defined with a type matching 'application/dash+xml'.
* Searches the provided scope for all instances of the indicated selector. If no scope is provided, document is used. If no selector is
* specified, [data-dashjs-player] is used. The declarative setup also looks for source elements with the type attribute set to 'application/dash+xml'.
* It then looks for those video elements which have a source element defined with a type matching 'application/dash+xml'.
* A new MediaPlayer is instantiated for each matching video element and the appropriate source is assigned.
* The autoplay property of the video element is preserved. Any preload attribute is ignored. This method should be called after the page onLoad event is dispatched.
* Returns an array holding all the MediaPlayer instances that were added by this method.
* @param className
* @param selector
* @param scope
* @param context
* @returns {Array} an array of MediaPlayer objects
*/
function createAll(className, scope) {
var aPlayers = [];
className = className || '.dashjs-player';
function createAll(selector, scope) {
let aPlayers = [];
selector = selector || '[data-dashjs-player]';
scope = scope || document;
var videos = scope.querySelectorAll(className);
for (var i = 0; i < videos.length; i++) {
var player = create(videos[i], null);
let videos = scope.querySelectorAll(selector);
for (let i = 0; i < videos.length; i++) {
let player = create(videos[i], null);
aPlayers.push(player);
}

let sources = scope.querySelectorAll('source[type="' + SUPPORTED_MIME_TYPE + '"]');
for (let i = 0; i < sources.length; i++) {
let video = findVideo(sources[i]);
let player = create(video, null);
aPlayers.push(player);
}

return aPlayers;
}

instance = {
function findVideo(el) {
if (el.nodeName.toLowerCase() === 'video') {
return el;
} else {
return findVideo(el.parentNode);
}
}

return {
create: create,
createAll: createAll
};

return instance;
}

MediaPlayerFactory.__dashjs_factory_name = 'MediaPlayerFactory';
var factoryFactory = FactoryMaker.getSingletonFactory(MediaPlayerFactory);
export default factoryFactory().getInstance();
let factoryFactory = FactoryMaker.getSingletonFactory(MediaPlayerFactory);
let instance = factoryFactory().getInstance();

function loadHandler() {
window.removeEventListener('load', loadHandler);
instance.createAll();
}

let avoidAutoCreate = window && window.dashjs && window.dashjs.skipAutoCreate;

if (window && window.addEventListener && !avoidAutoCreate) {
if (window.document.readyState === 'complete') {
instance.createAll();
} else {
window.addEventListener('load', loadHandler);
}
}

export default instance;

0 comments on commit cee121f

Please sign in to comment.