define('application/models/production/stream', [
'application/models/stream',
'rofl/lib/utils',
'rofl/media/source',
'rofl/devices/mediaplayer/mediaplayer',
'antie/runtimecontext',
'rofl/media/drm/item/playready',
'application/managers/feature'
], function (
Base,
Utils,
MediaSource,
MediaPlayer,
RuntimeContext,
PlayReadyDRMItem,
FeatureManager
) {
'use strict';
var device = RuntimeContext.getDevice(),
application = RuntimeContext.getCurrentApplication(),
capitalizeFirstLetter = function (text) {
return text.charAt(0).toUpperCase() + text.slice(1);
},
featureManager = FeatureManager.getInstance(),
baseUrl = '101/1.2.0/A/nld/smarttv/kpn/CONTENT/VIDEOURL',
commonUrlParams = 'deviceId={{deviceId}}&profile={{profile}}',
ENDPOINTS = {
LIVE: baseUrl + '/LIVE/{{contentId}}/{{assetId}}/?' + commonUrlParams,
REPLAY: baseUrl + '/LIVE/{{contentId}}/{{assetId}}/?time={{startTime}}-{{endTime}}&' + commonUrlParams,
VOD: baseUrl + '/PROGRAM/{{contentId}}/{{assetId}}?' + commonUrlParams,
VOD_MOVIE: baseUrl + '/VOD/{{contentId}}/{{assetId}}?' + commonUrlParams,
RESTART: baseUrl + '/LIVE/{{contentId}}/{{assetId}}/?time={{startTime}}&' + commonUrlParams,
RECORDING: baseUrl + '/RECORDING/{{contentId}}/{{assetId}}/?startDeltaTime={{startTime}}&' + commonUrlParams
},
PROFILES = {
DASH: 'M21',
SMOOTH: 'S22'
};
return Base.extend({
/**
* Resolves the endpoint.
*
* @param {Object} params - The parameters.
* @param {string} params.type - The stream type. LIVE, RESTART or VOD.
* @param {string} params.contentId - The content id.
* @param {string} params.assetId - The asset id.
* @param {boolean} [params.stop] - True if it should stop the stream. Optional.
* @returns {string} - The endpoint.
*/
resolveEndpoint: function (params) {
var now = application.getDate().getTime(),
timeGap = 24 * 60 * 60 * 1000,
replayBuffer = 15 * 60 * 1000,
type,
endpoint,
profile,
streamType;
if (!params || !params.type || !params.contentId) {
throw 'Missing type or content id.';
}
type = params.type;
streamType = featureManager.getStreamType(type);
profile = PROFILES[streamType.toUpperCase()];
endpoint = ENDPOINTS[type];
if (type === 'VOD') {
if ((params.replayAssetId && params.replayContentId) && (now - params.endTime < replayBuffer)) {
endpoint = ENDPOINTS.REPLAY;
params.contentId = params.replayContentId;
params.assetId = params.replayAssetId;
}
if (now - params.startTime < timeGap) {
params.startTime -= (5 * 60 * 1000);
}
}
params.profile = profile;
params.deviceId = device.getUdid();
this._type = type;
return Utils.formatTemplate(endpoint, params);
},
/**
* Determine the device MimeType.
*
* @param {string} type - The stream type.
* @returns {string} - The MimeType.
* @private
*/
_determineStreamMimeType: function (type) {
var streamType = featureManager.getStreamType(type),
streamMimeType;
switch (streamType.toUpperCase()) {
case 'DASH':
streamMimeType = MediaSource.MIME_TYPES.mpd;
break;
case 'SMOOTH':
streamMimeType = MediaSource.MIME_TYPES.ism;
break;
default:
throw Error('Streamtype ' + streamType.toUpperCase() + ' is not handled');
}
return streamMimeType;
},
/**
* Validates the response.
*
* @param {Object} response - The response.
* @returns {boolean} - True if valid.
*/
validateResponse: function (response) {
return response.resultCode === 'OK'
&& Utils.hasNested(response, 'resultObj', 'src', 'sources');
},
/**
* Return true in case failed request should be repeated.
*
* @param {Object} response - Response.
* @returns {boolean} True if retry.
*/
shouldRetry: function (response) {
return response.errorDescription !== '403-10146';
},
/**
* Transforms the response.
*
* @param {Object} response - The response.
* @returns {Object} - The media source.
*/
transformFrom: function (response) {
var data = Utils.getNested(response, 'resultObj', 'src', 'sources'),
streamUrl = data.src,
deviceBrand = device.getBrand(),
streamType = ((this._type === 'VOD' || this._type === 'VOD_MOVIE') || 'RECORDING') ? MediaPlayer.TYPE.VIDEO : MediaPlayer.TYPE.LIVE_VIDEO,
streamMimeType = this._determineStreamMimeType(this._type),
mediaSource = new MediaSource(streamUrl, streamType, streamMimeType),
drmItem = new PlayReadyDRMItem(),
licenseOverride;
mediaSource.setStartBitRate(2500000);
licenseOverride = this._getLicenseOverrideUrl(data);
if (licenseOverride) {
drmItem.setLicenseOverrideUri(licenseOverride);
}
if (deviceBrand === 'hbbtv' || deviceBrand === 'lg') {
drmItem.setEmbeddedLicense(false);
}
drmItem.setProtectionHeaderUTF16(true);
if (licenseOverride) {
mediaSource.setDrmItem(drmItem);
}
return mediaSource;
},
/**
* Returns the license override url.
*
* @param {Object} data - The data.
* @returns {string|null} - The license override url or null..
* @private
*/
_getLicenseOverrideUrl: function (data) {
var contentProtection = Utils.getNested(data, 'contentProtection'),
url = Utils.getNested(contentProtection, 'playready', 'licenseAcquisitionURL');
if (!url || !contentProtection) {
return null;
}
Utils.each(contentProtection, function (value, key) {
var object = {};
if (key !== 'playready') {
object[capitalizeFirstLetter(key)] = value;
url = Utils.addToQueryStringOfURL(url, object);
}
});
return url;
}
});
});