// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // The PlayerUtils provides utility functions to binding common media events // to specific player functions. It also provides functions to load media source // base on test configurations. var PlayerUtils = new function() { } // Prepares a video element for playback by setting default event handlers // and source attribute. PlayerUtils.registerDefaultEventListeners = function(player) { Utils.timeLog('Registering video event handlers.'); // Map from event name to event listener function name. It is common for // event listeners to be named onEventName. var eventListenerMap = { 'encrypted': 'onEncrypted', 'webkitneedkey': 'onWebkitNeedKey', 'webkitkeymessage': 'onWebkitKeyMessage', 'webkitkeyadded': 'onWebkitKeyAdded', 'webkitkeyerror': 'onWebkitKeyError' }; for (eventName in eventListenerMap) { var eventListenerFunction = player[eventListenerMap[eventName]]; if (eventListenerFunction) { player.video.addEventListener(eventName, function(e) { player[eventListenerMap[e.type]](e); }); } } // List of events that fail tests. var failingEvents = ['error', 'abort']; for (var i = 0; i < failingEvents.length; i++) { player.video.addEventListener(failingEvents[i], Utils.failTest); } }; PlayerUtils.registerEMEEventListeners = function(player) { player.video.addEventListener('encrypted', function(message) { function addMediaKeySessionListeners(mediaKeySession) { mediaKeySession.addEventListener('message', function(message) { player.video.receivedKeyMessage = true; if (Utils.isHeartBeatMessage(message.message)) { Utils.timeLog('MediaKeySession onMessage - heart beat', message); player.video.receivedHeartbeat = true; } player.onMessage(message); }); mediaKeySession.addEventListener('error', function(error) { Utils.failTest(error, KEY_ERROR); }); } try { if (player.testConfig.sessionToLoad) { Utils.timeLog('Loading session: ' + player.testConfig.sessionToLoad); var session = message.target.mediaKeys.createSession('persistent'); addMediaKeySessionListeners(session); session.load(player.testConfig.sessionToLoad) .catch(function(error) { Utils.failTest(error, KEY_ERROR); }); } else { Utils.timeLog('Creating new media key session for initDataType: ' + message.initDataType + ', initData: ' + Utils.getHexString(new Uint8Array(message.initData))); var session = message.target.mediaKeys.createSession(); addMediaKeySessionListeners(session); session.generateRequest(message.initDataType, message.initData) .catch(function(error) { Utils.failTest(error, KEY_ERROR); }); } } catch (e) { Utils.failTest(e); } }); this.registerDefaultEventListeners(player); try { Utils.timeLog('Setting video media keys: ' + player.testConfig.keySystem); if (typeof navigator.requestMediaKeySystemAccess == 'function') { navigator.requestMediaKeySystemAccess(player.testConfig.keySystem) .then(function(access) { return access.createMediaKeys(); }) .then(function(mediaKeys) { player.video.setMediaKeys(mediaKeys); }) .catch(function(error) { Utils.failTest(error, NOTSUPPORTEDERROR); }); } else { // TODO(jrummell): Remove this once the blink change for // requestMediaKeySystemAccess lands. MediaKeys.create(player.testConfig.keySystem) .then(function(mediaKeys) { player.video.setMediaKeys(mediaKeys); }) .catch(function(error) { Utils.failTest(error, NOTSUPPORTEDERROR); }); } } catch (e) { Utils.failTest(e); } }; PlayerUtils.registerPrefixedEMEEventListeners = function(player) { player.video.addEventListener('webkitneedkey', function(message) { var initData = message.initData; if (player.testConfig.sessionToLoad) { Utils.timeLog('Loading session: ' + player.testConfig.sessionToLoad); initData = Utils.convertToUint8Array( PREFIXED_API_LOAD_SESSION_HEADER + player.testConfig.sessionToLoad); } Utils.timeLog(player.testConfig.keySystem + ' Generate key request, initData: ' + Utils.getHexString(initData)); try { message.target.webkitGenerateKeyRequest(player.testConfig.keySystem, initData); } catch (e) { Utils.failTest(e); } }); player.video.addEventListener('webkitkeyadded', function(message) { Utils.timeLog('onWebkitKeyAdded', message); message.target.receivedKeyAdded = true; }); player.video.addEventListener('webkitkeyerror', function(error) { Utils.timeLog('onWebkitKeyError', error); Utils.failTest(error, KEY_ERROR); }); player.video.addEventListener('webkitkeymessage', function(message) { Utils.timeLog('onWebkitKeyMessage', message); message.target.receivedKeyMessage = true; if (Utils.isHeartBeatMessage(message.message)) { Utils.timeLog('onWebkitKeyMessage - heart beat', message); message.target.receivedHeartbeat = true; } }); this.registerDefaultEventListeners(player); }; PlayerUtils.setVideoSource = function(player) { if (player.testConfig.useMSE) { Utils.timeLog('Loading media using MSE.'); var mediaSource = MediaSourceUtils.loadMediaSourceFromTestConfig(player.testConfig); player.video.src = window.URL.createObjectURL(mediaSource); } else { Utils.timeLog('Loading media using src.'); player.video.src = player.testConfig.mediaFile; } }; PlayerUtils.initEMEPlayer = function(player) { this.registerEMEEventListeners(player); this.setVideoSource(player); }; PlayerUtils.initPrefixedEMEPlayer = function(player) { this.registerPrefixedEMEEventListeners(player); this.setVideoSource(player); }; // Return the appropriate player based on test configuration. PlayerUtils.createPlayer = function(video, testConfig) { // Update keySystem if using prefixed Clear Key since it is not available as a // separate key system to choose from; however it can be set in URL query. var usePrefixedEME = testConfig.usePrefixedEME; if (testConfig.keySystem == CLEARKEY && usePrefixedEME) testConfig.keySystem = PREFIXED_CLEARKEY; function getPlayerType(keySystem) { switch (keySystem) { case WIDEVINE_KEYSYSTEM: if (usePrefixedEME) return PrefixedWidevinePlayer; return WidevinePlayer; case PREFIXED_CLEARKEY: return PrefixedClearKeyPlayer; case EXTERNAL_CLEARKEY: case CLEARKEY: if (usePrefixedEME) return PrefixedClearKeyPlayer; return ClearKeyPlayer; case FILE_IO_TEST_KEYSYSTEM: if (usePrefixedEME) return FileIOTestPlayer; default: Utils.timeLog(keySystem + ' is not a known key system'); if (usePrefixedEME) return PrefixedClearKeyPlayer; return ClearKeyPlayer; } } var Player = getPlayerType(testConfig.keySystem); return new Player(video, testConfig); };