1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // The PlayerUtils provides utility functions to binding common media events
6 // to specific player functions. It also provides functions to load media source
7 // base on test configurations.
8 var PlayerUtils
= new function() {
11 // Prepares a video element for playback by setting default event handlers
12 // and source attribute.
13 PlayerUtils
.registerDefaultEventListeners = function(player
) {
14 Utils
.timeLog('Registering video event handlers.');
15 // Map from event name to event listener function name. It is common for
16 // event listeners to be named onEventName.
17 var eventListenerMap
= {
18 'encrypted': 'onEncrypted',
19 'webkitneedkey': 'onWebkitNeedKey',
20 'webkitkeymessage': 'onWebkitKeyMessage',
21 'webkitkeyadded': 'onWebkitKeyAdded',
22 'webkitkeyerror': 'onWebkitKeyError'
24 for (eventName
in eventListenerMap
) {
25 var eventListenerFunction
= player
[eventListenerMap
[eventName
]];
26 if (eventListenerFunction
) {
27 player
.video
.addEventListener(eventName
, function(e
) {
28 player
[eventListenerMap
[e
.type
]](e
);
32 // List of events that fail tests.
33 var failingEvents
= ['error', 'abort'];
34 for (var i
= 0; i
< failingEvents
.length
; i
++) {
35 player
.video
.addEventListener(failingEvents
[i
], Utils
.failTest
);
39 // Register the necessary event handlers needed when playing encrypted content
40 // using the unprefixed API. Returns a promise that resolves to the player.
41 PlayerUtils
.registerEMEEventListeners = function(player
) {
42 player
.video
.addEventListener('encrypted', function(message
) {
44 function addMediaKeySessionListeners(mediaKeySession
) {
45 mediaKeySession
.addEventListener('message', function(message
) {
46 player
.video
.receivedKeyMessage
= true;
47 if (Utils
.isRenewalMessage(message
)) {
48 Utils
.timeLog('MediaKeySession onMessage - renewal', message
);
49 player
.video
.receivedRenewalMessage
= true;
51 if (message
.messageType
!= 'license-request') {
52 Utils
.failTest('Unexpected message type "' + message
.messageType
+
57 player
.onMessage(message
);
59 mediaKeySession
.addEventListener('error', function(error
) {
60 Utils
.failTest(error
, KEY_ERROR
);
65 if (player
.testConfig
.sessionToLoad
) {
66 Utils
.timeLog('Loading session: ' + player
.testConfig
.sessionToLoad
);
68 message
.target
.mediaKeys
.createSession('persistent-license');
69 addMediaKeySessionListeners(session
);
70 session
.load(player
.testConfig
.sessionToLoad
)
71 .catch(function(error
) { Utils
.failTest(error
, KEY_ERROR
); });
73 Utils
.timeLog('Creating new media key session for initDataType: ' +
74 message
.initDataType
+ ', initData: ' +
75 Utils
.getHexString(new Uint8Array(message
.initData
)));
76 var session
= message
.target
.mediaKeys
.createSession();
77 addMediaKeySessionListeners(session
);
78 session
.generateRequest(message
.initDataType
, message
.initData
)
79 .catch(function(error
) { Utils
.failTest(error
, KEY_ERROR
); });
86 this.registerDefaultEventListeners(player
);
87 Utils
.timeLog('Setting video media keys: ' + player
.testConfig
.keySystem
);
88 return navigator
.requestMediaKeySystemAccess(
89 player
.testConfig
.keySystem
, [{}])
90 .then(function(access
) { return access
.createMediaKeys(); })
91 .then(function(mediaKeys
) {
92 return player
.video
.setMediaKeys(mediaKeys
);
94 .then(function(result
) { return player
; })
95 .catch(function(error
) { Utils
.failTest(error
, NOTSUPPORTEDERROR
); });
98 // Register the necessary event handlers needed when playing encrypted content
99 // using the prefixed API. Even though the prefixed API is all synchronous,
100 // returns a promise that resolves to the player.
101 PlayerUtils
.registerPrefixedEMEEventListeners = function(player
) {
102 player
.video
.addEventListener('webkitneedkey', function(message
) {
103 var initData
= message
.initData
;
104 if (player
.testConfig
.sessionToLoad
) {
105 Utils
.timeLog('Loading session: ' + player
.testConfig
.sessionToLoad
);
106 initData
= Utils
.convertToUint8Array(
107 PREFIXED_API_LOAD_SESSION_HEADER
+ player
.testConfig
.sessionToLoad
);
109 Utils
.timeLog(player
.testConfig
.keySystem
+
110 ' Generate key request, initData: ' +
111 Utils
.getHexString(initData
));
113 message
.target
.webkitGenerateKeyRequest(player
.testConfig
.keySystem
,
120 player
.video
.addEventListener('webkitkeyadded', function(message
) {
121 Utils
.timeLog('onWebkitKeyAdded', message
);
122 message
.target
.receivedKeyAdded
= true;
125 player
.video
.addEventListener('webkitkeyerror', function(error
) {
126 Utils
.timeLog('onWebkitKeyError', error
);
127 Utils
.failTest(error
, KEY_ERROR
);
130 player
.video
.addEventListener('webkitkeymessage', function(message
) {
131 Utils
.timeLog('onWebkitKeyMessage', message
);
132 message
.target
.receivedKeyMessage
= true;
133 if (Utils
.isRenewalMessagePrefixed(message
.message
)) {
134 Utils
.timeLog('onWebkitKeyMessage - renewal', message
);
135 message
.target
.receivedRenewalMessage
= true;
139 // The prefixed API is all synchronous, so wrap the calls in a promise.
140 return new Promise(function(resolve
, reject
) {
141 PlayerUtils
.registerDefaultEventListeners(player
);
146 PlayerUtils
.setVideoSource = function(player
) {
147 if (player
.testConfig
.useMSE
) {
148 Utils
.timeLog('Loading media using MSE.');
150 MediaSourceUtils
.loadMediaSourceFromTestConfig(player
.testConfig
);
151 player
.video
.src
= window
.URL
.createObjectURL(mediaSource
);
153 Utils
.timeLog('Loading media using src.');
154 player
.video
.src
= player
.testConfig
.mediaFile
;
158 // Initialize the player to play encrypted content. Returns a promise that
159 // resolves to the player.
160 PlayerUtils
.initEMEPlayer = function(player
) {
161 return player
.registerEventListeners().then(function(result
) {
162 PlayerUtils
.setVideoSource(player
);
167 // Return the appropriate player based on test configuration.
168 PlayerUtils
.createPlayer = function(video
, testConfig
) {
169 // Update keySystem if using prefixed Clear Key since it is not available as a
170 // separate key system to choose from; however it can be set in URL query.
171 var usePrefixedEME
= testConfig
.usePrefixedEME
;
172 if (testConfig
.keySystem
== CLEARKEY
&& usePrefixedEME
)
173 testConfig
.keySystem
= PREFIXED_CLEARKEY
;
175 function getPlayerType(keySystem
) {
177 case WIDEVINE_KEYSYSTEM
:
179 return PrefixedWidevinePlayer
;
180 return WidevinePlayer
;
181 case PREFIXED_CLEARKEY
:
182 return PrefixedClearKeyPlayer
;
183 case EXTERNAL_CLEARKEY
:
186 return PrefixedClearKeyPlayer
;
187 return ClearKeyPlayer
;
188 case FILE_IO_TEST_KEYSYSTEM
:
189 return FileIOTestPlayer
;
191 Utils
.timeLog(keySystem
+ ' is not a known key system');
193 return PrefixedClearKeyPlayer
;
194 return ClearKeyPlayer
;
197 var Player
= getPlayerType(testConfig
.keySystem
);
198 return new Player(video
, testConfig
);