2020-11-19 21:30:16 -07:00
|
|
|
|
import appSettings from './settings/appSettings';
|
|
|
|
|
import * as userSettings from './settings/userSettings';
|
2020-08-16 11:24:45 -07:00
|
|
|
|
import browser from './browser';
|
|
|
|
|
/* eslint-disable indent */
|
2020-08-02 05:25:20 -07:00
|
|
|
|
|
2020-03-30 02:02:16 -07:00
|
|
|
|
function canPlayH264(videoTestElement) {
|
|
|
|
|
return !!(videoTestElement.canPlayType && videoTestElement.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"').replace(/no/, ''));
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-12 05:03:38 -07:00
|
|
|
|
function canPlayHevc(videoTestElement, options) {
|
2020-06-06 10:16:48 -07:00
|
|
|
|
if (browser.tizen || browser.xboxOne || browser.web0s || options.supportsHevc) {
|
2020-03-30 02:02:16 -07:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (browser.ps4) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-12 05:03:38 -07:00
|
|
|
|
// hevc main level 4.0
|
2020-03-30 02:02:16 -07:00
|
|
|
|
return !!videoTestElement.canPlayType &&
|
|
|
|
|
(videoTestElement.canPlayType('video/mp4; codecs="hvc1.1.L120"').replace(/no/, '') ||
|
|
|
|
|
videoTestElement.canPlayType('video/mp4; codecs="hev1.1.L120"').replace(/no/, '') ||
|
|
|
|
|
videoTestElement.canPlayType('video/mp4; codecs="hvc1.1.0.L120"').replace(/no/, '') ||
|
|
|
|
|
videoTestElement.canPlayType('video/mp4; codecs="hev1.1.0.L120"').replace(/no/, ''));
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-07 05:12:14 -07:00
|
|
|
|
let _supportsTextTracks;
|
2020-03-30 02:02:16 -07:00
|
|
|
|
function supportsTextTracks() {
|
2020-06-06 10:16:48 -07:00
|
|
|
|
if (browser.tizen) {
|
2020-03-30 02:02:16 -07:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_supportsTextTracks == null) {
|
|
|
|
|
_supportsTextTracks = document.createElement('video').textTracks != null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// For now, until ready
|
|
|
|
|
return _supportsTextTracks;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-07 05:12:14 -07:00
|
|
|
|
let _canPlayHls;
|
2020-03-30 02:02:16 -07:00
|
|
|
|
function canPlayHls() {
|
|
|
|
|
if (_canPlayHls == null) {
|
|
|
|
|
_canPlayHls = canPlayNativeHls() || canPlayHlsWithMSE();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return _canPlayHls;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function canPlayNativeHls() {
|
2020-06-06 10:16:48 -07:00
|
|
|
|
if (browser.tizen) {
|
2020-03-30 02:02:16 -07:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-07 05:12:14 -07:00
|
|
|
|
const media = document.createElement('video');
|
2020-03-30 02:02:16 -07:00
|
|
|
|
if (media.canPlayType('application/x-mpegURL').replace(/no/, '') ||
|
|
|
|
|
media.canPlayType('application/vnd.apple.mpegURL').replace(/no/, '')) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function canPlayHlsWithMSE() {
|
|
|
|
|
// text tracks don’t work with this in firefox
|
2020-07-05 03:54:25 -07:00
|
|
|
|
return window.MediaSource != null; /* eslint-disable-line compat/compat */
|
2020-03-30 02:02:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function supportsAc3(videoTestElement) {
|
2020-06-06 10:16:48 -07:00
|
|
|
|
if (browser.edgeUwp || browser.tizen || browser.web0s) {
|
2020-03-30 02:02:16 -07:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-01 10:20:26 -07:00
|
|
|
|
// iPhones 5c and older and old model iPads do not support AC-3/E-AC-3
|
|
|
|
|
// These models can only run iOS 10.x or lower
|
|
|
|
|
if (browser.iOS && browser.iOSVersion < 11) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-30 02:02:16 -07:00
|
|
|
|
return videoTestElement.canPlayType('audio/mp4; codecs="ac-3"').replace(/no/, '');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function supportsEac3(videoTestElement) {
|
2020-06-06 10:16:48 -07:00
|
|
|
|
if (browser.tizen || browser.web0s) {
|
2020-03-30 02:02:16 -07:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-01 10:20:26 -07:00
|
|
|
|
// iPhones 5c and older and old model iPads do not support AC-3/E-AC-3
|
|
|
|
|
// These models can only run iOS 10.x or lower
|
|
|
|
|
if (browser.iOS && browser.iOSVersion < 11) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-30 02:02:16 -07:00
|
|
|
|
return videoTestElement.canPlayType('audio/mp4; codecs="ec-3"').replace(/no/, '');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function supportsAc3InHls(videoTestElement) {
|
2020-06-06 10:16:48 -07:00
|
|
|
|
if (browser.tizen || browser.web0s) {
|
2020-03-30 02:02:16 -07:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (videoTestElement.canPlayType) {
|
|
|
|
|
return videoTestElement.canPlayType('application/x-mpegurl; codecs="avc1.42E01E, ac-3"').replace(/no/, '') ||
|
|
|
|
|
videoTestElement.canPlayType('application/vnd.apple.mpegURL; codecs="avc1.42E01E, ac-3"').replace(/no/, '');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function canPlayAudioFormat(format) {
|
2020-10-07 05:12:14 -07:00
|
|
|
|
let typeString;
|
2020-03-30 02:02:16 -07:00
|
|
|
|
|
|
|
|
|
if (format === 'flac') {
|
2020-06-06 10:16:48 -07:00
|
|
|
|
if (browser.tizen || browser.web0s || browser.edgeUwp) {
|
2020-03-30 02:02:16 -07:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
} else if (format === 'wma') {
|
2020-06-06 10:16:48 -07:00
|
|
|
|
if (browser.tizen || browser.edgeUwp) {
|
2020-03-30 02:02:16 -07:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
} else if (format === 'asf') {
|
|
|
|
|
if (browser.tizen || browser.web0s || browser.edgeUwp) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
} else if (format === 'opus') {
|
|
|
|
|
if (!browser.web0s) {
|
|
|
|
|
typeString = 'audio/ogg; codecs="opus"';
|
|
|
|
|
return !!document.createElement('audio').canPlayType(typeString).replace(/no/, '');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
} else if (format === 'alac') {
|
|
|
|
|
if (browser.iOS || browser.osx) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
} else if (format === 'mp2') {
|
|
|
|
|
// For now
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (format === 'webma') {
|
|
|
|
|
typeString = 'audio/webm';
|
|
|
|
|
} else if (format === 'mp2') {
|
|
|
|
|
typeString = 'audio/mpeg';
|
|
|
|
|
} else {
|
|
|
|
|
typeString = 'audio/' + format;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return !!document.createElement('audio').canPlayType(typeString).replace(/no/, '');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function testCanPlayMkv(videoTestElement) {
|
2020-06-06 10:16:48 -07:00
|
|
|
|
if (browser.tizen || browser.web0s) {
|
2020-03-30 02:02:16 -07:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (videoTestElement.canPlayType('video/x-matroska').replace(/no/, '') ||
|
|
|
|
|
videoTestElement.canPlayType('video/mkv').replace(/no/, '')) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-27 06:11:12 -07:00
|
|
|
|
if (browser.edgeChromium && browser.windows) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-30 02:02:16 -07:00
|
|
|
|
if (browser.edgeUwp) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-03 09:26:25 -07:00
|
|
|
|
function testCanPlayAv1(videoTestElement) {
|
|
|
|
|
if (browser.tizenVersion >= 5.5) {
|
|
|
|
|
return true;
|
2022-02-03 10:54:11 -07:00
|
|
|
|
} else if (browser.web0sVersion >= 5) {
|
2020-06-03 09:26:25 -07:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return videoTestElement.canPlayType('video/webm; codecs="av01.0.15M.10"').replace(/no/, '');
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-30 02:02:16 -07:00
|
|
|
|
function testCanPlayTs() {
|
2020-06-06 10:16:48 -07:00
|
|
|
|
return browser.tizen || browser.web0s || browser.edgeUwp;
|
2020-03-30 02:02:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function supportsMpeg2Video() {
|
2020-06-06 10:16:48 -07:00
|
|
|
|
return browser.tizen || browser.web0s || browser.edgeUwp;
|
2020-03-30 02:02:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
2020-06-09 12:50:12 -07:00
|
|
|
|
function supportsVc1(videoTestElement) {
|
|
|
|
|
return browser.tizen || browser.web0s || browser.edgeUwp || videoTestElement.canPlayType('video/mp4; codecs="vc-1"').replace(/no/, '');
|
2020-03-30 02:02:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getDirectPlayProfileForVideoContainer(container, videoAudioCodecs, videoTestElement, options) {
|
2020-10-07 05:12:14 -07:00
|
|
|
|
let supported = false;
|
|
|
|
|
let profileContainer = container;
|
|
|
|
|
const videoCodecs = [];
|
2020-03-30 02:02:16 -07:00
|
|
|
|
|
|
|
|
|
switch (container) {
|
|
|
|
|
case 'asf':
|
2020-06-06 10:16:48 -07:00
|
|
|
|
supported = browser.tizen || browser.web0s || browser.edgeUwp;
|
2020-03-30 02:02:16 -07:00
|
|
|
|
videoAudioCodecs = [];
|
|
|
|
|
break;
|
|
|
|
|
case 'avi':
|
2020-06-06 10:16:48 -07:00
|
|
|
|
supported = browser.tizen || browser.web0s || browser.edgeUwp;
|
2020-03-30 02:02:16 -07:00
|
|
|
|
// New Samsung TV don't support XviD/DivX
|
|
|
|
|
// Explicitly add supported codecs to make other codecs be transcoded
|
|
|
|
|
if (browser.tizenVersion >= 4) {
|
|
|
|
|
videoCodecs.push('h264');
|
2020-11-12 05:03:38 -07:00
|
|
|
|
if (canPlayHevc(videoTestElement, options)) {
|
2020-03-30 02:02:16 -07:00
|
|
|
|
videoCodecs.push('hevc');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'mpg':
|
|
|
|
|
case 'mpeg':
|
2020-06-06 10:16:48 -07:00
|
|
|
|
supported = browser.tizen || browser.web0s || browser.edgeUwp;
|
2020-03-30 02:02:16 -07:00
|
|
|
|
break;
|
|
|
|
|
case 'flv':
|
2020-06-06 10:16:48 -07:00
|
|
|
|
supported = browser.tizen;
|
2020-03-30 02:02:16 -07:00
|
|
|
|
break;
|
|
|
|
|
case '3gp':
|
|
|
|
|
case 'mts':
|
|
|
|
|
case 'trp':
|
|
|
|
|
case 'vob':
|
|
|
|
|
case 'vro':
|
2020-06-06 10:16:48 -07:00
|
|
|
|
supported = browser.tizen;
|
2020-03-30 02:02:16 -07:00
|
|
|
|
break;
|
|
|
|
|
case 'mov':
|
2021-05-03 07:34:21 -07:00
|
|
|
|
supported = browser.safari || browser.tizen || browser.web0s || browser.chrome || browser.edgeChromium || browser.edgeUwp;
|
2020-03-30 02:02:16 -07:00
|
|
|
|
videoCodecs.push('h264');
|
|
|
|
|
break;
|
|
|
|
|
case 'm2ts':
|
2020-06-06 10:16:48 -07:00
|
|
|
|
supported = browser.tizen || browser.web0s || browser.edgeUwp;
|
2020-03-30 02:02:16 -07:00
|
|
|
|
videoCodecs.push('h264');
|
2020-06-09 12:50:12 -07:00
|
|
|
|
if (supportsVc1(videoTestElement)) {
|
2020-03-30 02:02:16 -07:00
|
|
|
|
videoCodecs.push('vc1');
|
|
|
|
|
}
|
|
|
|
|
if (supportsMpeg2Video()) {
|
|
|
|
|
videoCodecs.push('mpeg2video');
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'wmv':
|
2020-06-06 10:16:48 -07:00
|
|
|
|
supported = browser.tizen || browser.web0s || browser.edgeUwp;
|
2020-03-30 02:02:16 -07:00
|
|
|
|
videoAudioCodecs = [];
|
|
|
|
|
break;
|
|
|
|
|
case 'ts':
|
|
|
|
|
supported = testCanPlayTs();
|
|
|
|
|
videoCodecs.push('h264');
|
2020-11-12 05:03:38 -07:00
|
|
|
|
// safari doesn't support hevc in TS-HLS
|
|
|
|
|
if ((browser.tizen || browser.web0s) && canPlayHevc(videoTestElement, options)) {
|
2020-03-30 02:02:16 -07:00
|
|
|
|
videoCodecs.push('hevc');
|
|
|
|
|
}
|
2020-06-09 12:50:12 -07:00
|
|
|
|
if (supportsVc1(videoTestElement)) {
|
2020-03-30 02:02:16 -07:00
|
|
|
|
videoCodecs.push('vc1');
|
|
|
|
|
}
|
|
|
|
|
if (supportsMpeg2Video()) {
|
|
|
|
|
videoCodecs.push('mpeg2video');
|
|
|
|
|
}
|
|
|
|
|
profileContainer = 'ts,mpegts';
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return supported ? {
|
|
|
|
|
Container: profileContainer,
|
|
|
|
|
Type: 'Video',
|
|
|
|
|
VideoCodec: videoCodecs.join(','),
|
|
|
|
|
AudioCodec: videoAudioCodecs.join(',')
|
|
|
|
|
} : null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getMaxBitrate() {
|
|
|
|
|
return 120000000;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getGlobalMaxVideoBitrate() {
|
2020-10-07 05:12:14 -07:00
|
|
|
|
let isTizenFhd = false;
|
2020-03-30 02:02:16 -07:00
|
|
|
|
if (browser.tizen) {
|
|
|
|
|
try {
|
2020-10-07 05:12:14 -07:00
|
|
|
|
const isTizenUhd = webapis.productinfo.isUdPanelSupported();
|
2020-03-30 02:02:16 -07:00
|
|
|
|
isTizenFhd = !isTizenUhd;
|
2020-05-04 03:44:12 -07:00
|
|
|
|
console.debug('isTizenFhd = ' + isTizenFhd);
|
2020-03-30 02:02:16 -07:00
|
|
|
|
} catch (error) {
|
2020-05-04 03:44:12 -07:00
|
|
|
|
console.error('isUdPanelSupported() error code = ' + error.code);
|
2020-03-30 02:02:16 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return browser.ps4 ? 8000000 :
|
|
|
|
|
(browser.xboxOne ? 12000000 :
|
|
|
|
|
(browser.edgeUwp ? null :
|
|
|
|
|
(browser.tizen && isTizenFhd ? 20000000 : null)));
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-16 16:08:33 -07:00
|
|
|
|
function getSpeakerCount() {
|
|
|
|
|
const AudioContext = window.AudioContext || window.webkitAudioContext || false; /* eslint-disable-line compat/compat */
|
|
|
|
|
|
|
|
|
|
if (AudioContext) {
|
|
|
|
|
const audioCtx = new AudioContext();
|
|
|
|
|
|
|
|
|
|
return audioCtx.destination.maxChannelCount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getPhysicalAudioChannels(options) {
|
|
|
|
|
const allowedAudioChannels = parseInt(userSettings.allowedAudioChannels(), 10);
|
|
|
|
|
|
|
|
|
|
if (allowedAudioChannels > 0) {
|
|
|
|
|
return allowedAudioChannels;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (options.audioChannels) {
|
|
|
|
|
return options.audioChannels;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const isSurroundSoundSupportedBrowser = browser.safari || browser.chrome || browser.edgeChromium || browser.firefox || browser.tv || browser.ps4 || browser.xboxOne;
|
|
|
|
|
const speakerCount = getSpeakerCount();
|
|
|
|
|
|
|
|
|
|
if (speakerCount > 2) {
|
|
|
|
|
if (isSurroundSoundSupportedBrowser) {
|
|
|
|
|
return speakerCount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (speakerCount > 0) {
|
|
|
|
|
return speakerCount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isSurroundSoundSupportedBrowser) {
|
|
|
|
|
return 6;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 2;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-16 11:24:45 -07:00
|
|
|
|
export default function (options) {
|
2020-03-30 02:02:16 -07:00
|
|
|
|
options = options || {};
|
|
|
|
|
|
2022-01-16 16:08:33 -07:00
|
|
|
|
const physicalAudioChannels = getPhysicalAudioChannels(options);
|
2020-03-30 02:02:16 -07:00
|
|
|
|
|
2020-10-07 05:12:14 -07:00
|
|
|
|
const bitrateSetting = getMaxBitrate();
|
2020-03-30 02:02:16 -07:00
|
|
|
|
|
2020-10-07 05:12:14 -07:00
|
|
|
|
const videoTestElement = document.createElement('video');
|
2020-03-30 02:02:16 -07:00
|
|
|
|
|
2020-10-07 05:12:14 -07:00
|
|
|
|
const canPlayVp8 = videoTestElement.canPlayType('video/webm; codecs="vp8"').replace(/no/, '');
|
|
|
|
|
const canPlayVp9 = videoTestElement.canPlayType('video/webm; codecs="vp9"').replace(/no/, '');
|
|
|
|
|
const webmAudioCodecs = ['vorbis'];
|
2020-03-30 02:02:16 -07:00
|
|
|
|
|
2020-10-07 05:12:14 -07:00
|
|
|
|
const canPlayMkv = testCanPlayMkv(videoTestElement);
|
2020-03-30 02:02:16 -07:00
|
|
|
|
|
2020-10-07 05:12:14 -07:00
|
|
|
|
const profile = {};
|
2020-03-30 02:02:16 -07:00
|
|
|
|
|
|
|
|
|
profile.MaxStreamingBitrate = bitrateSetting;
|
|
|
|
|
profile.MaxStaticBitrate = 100000000;
|
2020-11-12 05:03:38 -07:00
|
|
|
|
profile.MusicStreamingTranscodingBitrate = Math.min(bitrateSetting, 384000);
|
2020-03-30 02:02:16 -07:00
|
|
|
|
|
|
|
|
|
profile.DirectPlayProfiles = [];
|
|
|
|
|
|
2020-10-07 05:12:14 -07:00
|
|
|
|
let videoAudioCodecs = [];
|
2020-11-12 05:03:38 -07:00
|
|
|
|
let hlsInTsVideoAudioCodecs = [];
|
|
|
|
|
let hlsInFmp4VideoAudioCodecs = [];
|
2020-03-30 02:02:16 -07:00
|
|
|
|
|
2020-10-07 05:12:14 -07:00
|
|
|
|
const supportsMp3VideoAudio = videoTestElement.canPlayType('video/mp4; codecs="avc1.640029, mp4a.69"').replace(/no/, '')
|
2020-06-06 09:53:05 -07:00
|
|
|
|
|| videoTestElement.canPlayType('video/mp4; codecs="avc1.640029, mp4a.6B"').replace(/no/, '')
|
|
|
|
|
|| videoTestElement.canPlayType('video/mp4; codecs="avc1.640029, mp3"').replace(/no/, '');
|
2020-03-30 02:02:16 -07:00
|
|
|
|
|
|
|
|
|
// Not sure how to test for this
|
2020-10-07 05:12:14 -07:00
|
|
|
|
const supportsMp2VideoAudio = browser.edgeUwp || browser.tizen || browser.web0s;
|
2020-03-30 02:02:16 -07:00
|
|
|
|
|
2020-08-24 18:12:35 -07:00
|
|
|
|
/* eslint-disable compat/compat */
|
2020-10-07 05:12:14 -07:00
|
|
|
|
let maxVideoWidth = browser.xboxOne ?
|
2020-08-24 18:12:35 -07:00
|
|
|
|
(window.screen ? window.screen.width : null) :
|
2020-03-30 02:02:16 -07:00
|
|
|
|
null;
|
|
|
|
|
|
2020-08-24 18:12:35 -07:00
|
|
|
|
/* eslint-enable compat/compat */
|
2020-03-30 02:02:16 -07:00
|
|
|
|
if (options.maxVideoWidth) {
|
|
|
|
|
maxVideoWidth = options.maxVideoWidth;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-07 05:12:14 -07:00
|
|
|
|
const canPlayAacVideoAudio = videoTestElement.canPlayType('video/mp4; codecs="avc1.640029, mp4a.40.2"').replace(/no/, '');
|
2020-10-31 06:20:20 -07:00
|
|
|
|
const canPlayAc3VideoAudio = supportsAc3(videoTestElement);
|
|
|
|
|
const canPlayEac3VideoAudio = supportsEac3(videoTestElement);
|
|
|
|
|
const canPlayAc3VideoAudioInHls = supportsAc3InHls(videoTestElement);
|
2020-03-30 02:02:16 -07:00
|
|
|
|
|
2020-11-29 00:31:14 -07:00
|
|
|
|
// Transcoding codec is the first in hlsVideoAudioCodecs.
|
|
|
|
|
// Prefer AAC, MP3 to other codecs when audio transcoding.
|
2020-10-31 06:20:20 -07:00
|
|
|
|
if (canPlayAacVideoAudio) {
|
|
|
|
|
videoAudioCodecs.push('aac');
|
2020-11-12 05:03:38 -07:00
|
|
|
|
hlsInTsVideoAudioCodecs.push('aac');
|
|
|
|
|
hlsInFmp4VideoAudioCodecs.push('aac');
|
2020-10-31 06:20:20 -07:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-30 02:02:16 -07:00
|
|
|
|
if (supportsMp3VideoAudio) {
|
|
|
|
|
videoAudioCodecs.push('mp3');
|
|
|
|
|
|
|
|
|
|
// PS4 fails to load HLS with mp3 audio
|
|
|
|
|
if (!browser.ps4) {
|
2020-11-12 05:03:38 -07:00
|
|
|
|
hlsInTsVideoAudioCodecs.push('mp3');
|
2020-03-30 02:02:16 -07:00
|
|
|
|
}
|
2020-11-12 05:03:38 -07:00
|
|
|
|
|
|
|
|
|
hlsInFmp4VideoAudioCodecs.push('mp3');
|
2020-03-30 02:02:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
2020-11-29 00:31:14 -07:00
|
|
|
|
// For AC3/EAC3 remuxing.
|
|
|
|
|
// Do not use AC3 for audio transcoding unless AAC and MP3 are not supported.
|
2020-10-31 06:20:20 -07:00
|
|
|
|
if (canPlayAc3VideoAudio) {
|
2020-11-29 00:31:14 -07:00
|
|
|
|
videoAudioCodecs.push('ac3');
|
|
|
|
|
if (canPlayEac3VideoAudio) {
|
|
|
|
|
videoAudioCodecs.push('eac3');
|
|
|
|
|
}
|
2020-11-12 05:03:38 -07:00
|
|
|
|
|
2020-11-29 00:31:14 -07:00
|
|
|
|
if (canPlayAc3VideoAudioInHls) {
|
|
|
|
|
hlsInTsVideoAudioCodecs.push('ac3');
|
|
|
|
|
hlsInFmp4VideoAudioCodecs.push('ac3');
|
2020-11-12 05:03:38 -07:00
|
|
|
|
|
|
|
|
|
if (canPlayEac3VideoAudio) {
|
2020-11-29 00:31:14 -07:00
|
|
|
|
hlsInTsVideoAudioCodecs.push('eac3');
|
|
|
|
|
hlsInFmp4VideoAudioCodecs.push('eac3');
|
2020-03-30 02:02:16 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (supportsMp2VideoAudio) {
|
|
|
|
|
videoAudioCodecs.push('mp2');
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-25 03:50:47 -07:00
|
|
|
|
let supportsDts = options.supportsDts;
|
|
|
|
|
if (supportsDts == null) {
|
|
|
|
|
supportsDts = browser.tizen || browser.web0sVersion || videoTestElement.canPlayType('video/mp4; codecs="dts-"').replace(/no/, '') || videoTestElement.canPlayType('video/mp4; codecs="dts+"').replace(/no/, '');
|
2020-03-30 02:02:16 -07:00
|
|
|
|
|
2021-09-25 03:50:47 -07:00
|
|
|
|
// DTS audio is not supported by Samsung TV 2018+ (Tizen 4.0+) and LG TV 2020+ (webOS 5.0+) models
|
|
|
|
|
if (browser.tizenVersion >= 4 || browser.web0sVersion >= 5) {
|
|
|
|
|
supportsDts = false;
|
|
|
|
|
}
|
2020-03-30 02:02:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (supportsDts) {
|
|
|
|
|
videoAudioCodecs.push('dca');
|
|
|
|
|
videoAudioCodecs.push('dts');
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-06 10:16:48 -07:00
|
|
|
|
if (browser.tizen || browser.web0s) {
|
2020-03-30 02:02:16 -07:00
|
|
|
|
videoAudioCodecs.push('pcm_s16le');
|
|
|
|
|
videoAudioCodecs.push('pcm_s24le');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (options.supportsTrueHd) {
|
|
|
|
|
videoAudioCodecs.push('truehd');
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-06 10:16:48 -07:00
|
|
|
|
if (browser.tizen) {
|
2020-03-30 02:02:16 -07:00
|
|
|
|
videoAudioCodecs.push('aac_latm');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (canPlayAudioFormat('opus')) {
|
|
|
|
|
videoAudioCodecs.push('opus');
|
|
|
|
|
webmAudioCodecs.push('opus');
|
2021-05-19 06:07:36 -07:00
|
|
|
|
if (browser.tizen) {
|
|
|
|
|
hlsInTsVideoAudioCodecs.push('opus');
|
|
|
|
|
}
|
2020-03-30 02:02:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (canPlayAudioFormat('flac')) {
|
|
|
|
|
videoAudioCodecs.push('flac');
|
2020-11-12 05:03:38 -07:00
|
|
|
|
hlsInFmp4VideoAudioCodecs.push('flac');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (canPlayAudioFormat('alac')) {
|
|
|
|
|
videoAudioCodecs.push('alac');
|
|
|
|
|
hlsInFmp4VideoAudioCodecs.push('alac');
|
2020-03-30 02:02:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
videoAudioCodecs = videoAudioCodecs.filter(function (c) {
|
|
|
|
|
return (options.disableVideoAudioCodecs || []).indexOf(c) === -1;
|
|
|
|
|
});
|
|
|
|
|
|
2020-11-12 05:03:38 -07:00
|
|
|
|
hlsInTsVideoAudioCodecs = hlsInTsVideoAudioCodecs.filter(function (c) {
|
|
|
|
|
return (options.disableHlsVideoAudioCodecs || []).indexOf(c) === -1;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
hlsInFmp4VideoAudioCodecs = hlsInFmp4VideoAudioCodecs.filter(function (c) {
|
2020-03-30 02:02:16 -07:00
|
|
|
|
return (options.disableHlsVideoAudioCodecs || []).indexOf(c) === -1;
|
|
|
|
|
});
|
|
|
|
|
|
2020-10-07 05:12:14 -07:00
|
|
|
|
const mp4VideoCodecs = [];
|
|
|
|
|
const webmVideoCodecs = [];
|
2020-11-12 05:03:38 -07:00
|
|
|
|
const hlsInTsVideoCodecs = [];
|
|
|
|
|
const hlsInFmp4VideoCodecs = [];
|
|
|
|
|
|
2020-11-20 02:33:35 -07:00
|
|
|
|
if ((browser.safari || browser.tizen || browser.web0s) && canPlayHevc(videoTestElement, options)) {
|
2020-11-12 05:03:38 -07:00
|
|
|
|
hlsInFmp4VideoCodecs.push('hevc');
|
|
|
|
|
}
|
2020-03-30 02:02:16 -07:00
|
|
|
|
|
|
|
|
|
if (canPlayH264(videoTestElement)) {
|
|
|
|
|
mp4VideoCodecs.push('h264');
|
2020-11-12 05:03:38 -07:00
|
|
|
|
hlsInTsVideoCodecs.push('h264');
|
2020-03-30 02:02:16 -07:00
|
|
|
|
|
2020-11-12 05:03:38 -07:00
|
|
|
|
if (browser.safari || browser.tizen || browser.web0s) {
|
|
|
|
|
hlsInFmp4VideoCodecs.push('h264');
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-03-30 02:02:16 -07:00
|
|
|
|
|
2020-11-12 05:03:38 -07:00
|
|
|
|
if (canPlayHevc(videoTestElement, options)) {
|
|
|
|
|
// safari is lying on HDR and 60fps videos, use fMP4 instead
|
|
|
|
|
if (!browser.safari) {
|
|
|
|
|
mp4VideoCodecs.push('hevc');
|
2020-03-30 02:02:16 -07:00
|
|
|
|
}
|
2021-03-20 01:56:51 -07:00
|
|
|
|
|
|
|
|
|
if (browser.tizen || browser.web0s) {
|
|
|
|
|
hlsInTsVideoCodecs.push('hevc');
|
|
|
|
|
}
|
2020-03-30 02:02:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (supportsMpeg2Video()) {
|
|
|
|
|
mp4VideoCodecs.push('mpeg2video');
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-09 12:50:12 -07:00
|
|
|
|
if (supportsVc1(videoTestElement)) {
|
2020-03-30 02:02:16 -07:00
|
|
|
|
mp4VideoCodecs.push('vc1');
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-06 10:16:48 -07:00
|
|
|
|
if (browser.tizen) {
|
2020-03-30 02:02:16 -07:00
|
|
|
|
mp4VideoCodecs.push('msmpeg4v2');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (canPlayVp8) {
|
|
|
|
|
mp4VideoCodecs.push('vp8');
|
2020-06-03 09:26:25 -07:00
|
|
|
|
webmVideoCodecs.push('vp8');
|
2020-03-30 02:02:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (canPlayVp9) {
|
|
|
|
|
mp4VideoCodecs.push('vp9');
|
2020-06-03 09:26:25 -07:00
|
|
|
|
webmVideoCodecs.push('vp9');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (testCanPlayAv1(videoTestElement)) {
|
|
|
|
|
mp4VideoCodecs.push('av1');
|
|
|
|
|
webmVideoCodecs.push('av1');
|
2020-03-30 02:02:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
2020-06-06 10:16:48 -07:00
|
|
|
|
if (canPlayVp8 || browser.tizen) {
|
2020-03-30 02:02:16 -07:00
|
|
|
|
videoAudioCodecs.push('vorbis');
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-03 09:26:25 -07:00
|
|
|
|
if (webmVideoCodecs.length) {
|
|
|
|
|
profile.DirectPlayProfiles.push({
|
|
|
|
|
Container: 'webm',
|
|
|
|
|
Type: 'Video',
|
|
|
|
|
VideoCodec: webmVideoCodecs.join(','),
|
|
|
|
|
AudioCodec: webmAudioCodecs.join(',')
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-30 02:02:16 -07:00
|
|
|
|
if (mp4VideoCodecs.length) {
|
|
|
|
|
profile.DirectPlayProfiles.push({
|
|
|
|
|
Container: 'mp4,m4v',
|
|
|
|
|
Type: 'Video',
|
|
|
|
|
VideoCodec: mp4VideoCodecs.join(','),
|
|
|
|
|
AudioCodec: videoAudioCodecs.join(',')
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (canPlayMkv && mp4VideoCodecs.length) {
|
|
|
|
|
profile.DirectPlayProfiles.push({
|
|
|
|
|
Container: 'mkv',
|
|
|
|
|
Type: 'Video',
|
|
|
|
|
VideoCodec: mp4VideoCodecs.join(','),
|
|
|
|
|
AudioCodec: videoAudioCodecs.join(',')
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// These are formats we can't test for but some devices will support
|
|
|
|
|
['m2ts', 'wmv', 'ts', 'asf', 'avi', 'mpg', 'mpeg', 'flv', '3gp', 'mts', 'trp', 'vob', 'vro', 'mov'].map(function (container) {
|
|
|
|
|
return getDirectPlayProfileForVideoContainer(container, videoAudioCodecs, videoTestElement, options);
|
|
|
|
|
}).filter(function (i) {
|
|
|
|
|
return i != null;
|
|
|
|
|
}).forEach(function (i) {
|
|
|
|
|
profile.DirectPlayProfiles.push(i);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
['opus', 'mp3', 'mp2', 'aac', 'flac', 'alac', 'webma', 'wma', 'wav', 'ogg', 'oga'].filter(canPlayAudioFormat).forEach(function (audioFormat) {
|
2020-10-31 13:15:46 -07:00
|
|
|
|
profile.DirectPlayProfiles.push({
|
|
|
|
|
Container: audioFormat,
|
|
|
|
|
Type: 'Audio'
|
|
|
|
|
});
|
|
|
|
|
|
2020-11-30 00:20:32 -07:00
|
|
|
|
// https://www.webmproject.org/about/faq/
|
|
|
|
|
if (audioFormat === 'opus' || audioFormat === 'webma') {
|
2020-03-30 02:02:16 -07:00
|
|
|
|
profile.DirectPlayProfiles.push({
|
2020-10-31 13:15:46 -07:00
|
|
|
|
Container: 'webm',
|
2020-11-30 00:20:32 -07:00
|
|
|
|
AudioCodec: audioFormat,
|
2020-03-30 02:02:16 -07:00
|
|
|
|
Type: 'Audio'
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// aac also appears in the m4a and m4b container
|
2020-11-30 00:20:32 -07:00
|
|
|
|
// m4a/alac only works when using safari
|
2020-03-30 02:02:16 -07:00
|
|
|
|
if (audioFormat === 'aac' || audioFormat === 'alac') {
|
|
|
|
|
profile.DirectPlayProfiles.push({
|
2020-11-30 00:20:32 -07:00
|
|
|
|
Container: 'm4a',
|
|
|
|
|
AudioCodec: audioFormat,
|
|
|
|
|
Type: 'Audio'
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
profile.DirectPlayProfiles.push({
|
|
|
|
|
Container: 'm4b',
|
|
|
|
|
AudioCodec: audioFormat,
|
2020-03-30 02:02:16 -07:00
|
|
|
|
Type: 'Audio'
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
profile.TranscodingProfiles = [];
|
|
|
|
|
|
2020-10-07 05:12:14 -07:00
|
|
|
|
const hlsBreakOnNonKeyFrames = browser.iOS || browser.osx || browser.edge || !canPlayNativeHls() ? true : false;
|
2020-03-30 02:02:16 -07:00
|
|
|
|
|
|
|
|
|
if (canPlayHls() && browser.enableHlsAudio !== false) {
|
|
|
|
|
profile.TranscodingProfiles.push({
|
|
|
|
|
// hlsjs, edge, and android all seem to require ts container
|
|
|
|
|
Container: !canPlayNativeHls() || browser.edge || browser.android ? 'ts' : 'aac',
|
|
|
|
|
Type: 'Audio',
|
|
|
|
|
AudioCodec: 'aac',
|
|
|
|
|
Context: 'Streaming',
|
|
|
|
|
Protocol: 'hls',
|
|
|
|
|
MaxAudioChannels: physicalAudioChannels.toString(),
|
|
|
|
|
MinSegments: browser.iOS || browser.osx ? '2' : '1',
|
|
|
|
|
BreakOnNonKeyFrames: hlsBreakOnNonKeyFrames
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// For streaming, prioritize opus transcoding after mp3/aac. It is too problematic with random failures
|
|
|
|
|
// But for static (offline sync), it will be just fine.
|
|
|
|
|
// Prioritize aac higher because the encoder can accept more channels than mp3
|
|
|
|
|
['aac', 'mp3', 'opus', 'wav'].filter(canPlayAudioFormat).forEach(function (audioFormat) {
|
|
|
|
|
profile.TranscodingProfiles.push({
|
|
|
|
|
Container: audioFormat,
|
|
|
|
|
Type: 'Audio',
|
|
|
|
|
AudioCodec: audioFormat,
|
|
|
|
|
Context: 'Streaming',
|
|
|
|
|
Protocol: 'http',
|
|
|
|
|
MaxAudioChannels: physicalAudioChannels.toString()
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
['opus', 'mp3', 'aac', 'wav'].filter(canPlayAudioFormat).forEach(function (audioFormat) {
|
|
|
|
|
profile.TranscodingProfiles.push({
|
|
|
|
|
Container: audioFormat,
|
|
|
|
|
Type: 'Audio',
|
|
|
|
|
AudioCodec: audioFormat,
|
|
|
|
|
Context: 'Static',
|
|
|
|
|
Protocol: 'http',
|
|
|
|
|
MaxAudioChannels: physicalAudioChannels.toString()
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2020-06-06 10:16:48 -07:00
|
|
|
|
if (canPlayMkv && !browser.tizen && options.enableMkvProgressive !== false) {
|
2020-03-30 02:02:16 -07:00
|
|
|
|
profile.TranscodingProfiles.push({
|
|
|
|
|
Container: 'mkv',
|
|
|
|
|
Type: 'Video',
|
|
|
|
|
AudioCodec: videoAudioCodecs.join(','),
|
|
|
|
|
VideoCodec: mp4VideoCodecs.join(','),
|
|
|
|
|
Context: 'Streaming',
|
|
|
|
|
MaxAudioChannels: physicalAudioChannels.toString(),
|
|
|
|
|
CopyTimestamps: true
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (canPlayMkv) {
|
|
|
|
|
profile.TranscodingProfiles.push({
|
|
|
|
|
Container: 'mkv',
|
|
|
|
|
Type: 'Video',
|
|
|
|
|
AudioCodec: videoAudioCodecs.join(','),
|
|
|
|
|
VideoCodec: mp4VideoCodecs.join(','),
|
|
|
|
|
Context: 'Static',
|
|
|
|
|
MaxAudioChannels: physicalAudioChannels.toString(),
|
|
|
|
|
CopyTimestamps: true
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-12 05:03:38 -07:00
|
|
|
|
if (canPlayHls() && options.enableHls !== false) {
|
|
|
|
|
if (hlsInFmp4VideoCodecs.length && hlsInFmp4VideoAudioCodecs.length && userSettings.preferFmp4HlsContainer() && (browser.safari || browser.tizen || browser.web0s)) {
|
|
|
|
|
profile.TranscodingProfiles.push({
|
|
|
|
|
Container: 'mp4',
|
|
|
|
|
Type: 'Video',
|
|
|
|
|
AudioCodec: hlsInFmp4VideoAudioCodecs.join(','),
|
|
|
|
|
VideoCodec: hlsInFmp4VideoCodecs.join(','),
|
|
|
|
|
Context: 'Streaming',
|
|
|
|
|
Protocol: 'hls',
|
|
|
|
|
MaxAudioChannels: physicalAudioChannels.toString(),
|
|
|
|
|
MinSegments: browser.iOS || browser.osx ? '2' : '1',
|
|
|
|
|
BreakOnNonKeyFrames: hlsBreakOnNonKeyFrames
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (hlsInTsVideoCodecs.length && hlsInTsVideoAudioCodecs.length) {
|
|
|
|
|
profile.TranscodingProfiles.push({
|
|
|
|
|
Container: 'ts',
|
|
|
|
|
Type: 'Video',
|
|
|
|
|
AudioCodec: hlsInTsVideoAudioCodecs.join(','),
|
|
|
|
|
VideoCodec: hlsInTsVideoCodecs.join(','),
|
|
|
|
|
Context: 'Streaming',
|
|
|
|
|
Protocol: 'hls',
|
|
|
|
|
MaxAudioChannels: physicalAudioChannels.toString(),
|
|
|
|
|
MinSegments: browser.iOS || browser.osx ? '2' : '1',
|
|
|
|
|
BreakOnNonKeyFrames: hlsBreakOnNonKeyFrames
|
|
|
|
|
});
|
|
|
|
|
}
|
2020-03-30 02:02:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
2021-08-24 15:36:31 -07:00
|
|
|
|
if (webmAudioCodecs.length && webmVideoCodecs.length) {
|
2021-08-20 14:48:14 -07:00
|
|
|
|
profile.TranscodingProfiles.push({
|
|
|
|
|
Container: 'webm',
|
|
|
|
|
Type: 'Video',
|
2021-08-24 15:36:31 -07:00
|
|
|
|
AudioCodec: webmAudioCodecs.join(','),
|
|
|
|
|
// TODO: Remove workaround when servers migrate away from 'vpx' for transcoding profiles.
|
|
|
|
|
VideoCodec: (canPlayVp8 ? webmVideoCodecs.concat('vpx') : webmVideoCodecs).join(','),
|
2021-08-20 14:48:14 -07:00
|
|
|
|
Context: 'Streaming',
|
|
|
|
|
Protocol: 'http',
|
|
|
|
|
// If audio transcoding is needed, limit channels to number of physical audio channels
|
|
|
|
|
// Trying to transcode to 5 channels when there are only 2 speakers generally does not sound good
|
|
|
|
|
MaxAudioChannels: physicalAudioChannels.toString()
|
|
|
|
|
});
|
2020-03-30 02:02:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
profile.TranscodingProfiles.push({
|
|
|
|
|
Container: 'mp4',
|
|
|
|
|
Type: 'Video',
|
|
|
|
|
AudioCodec: videoAudioCodecs.join(','),
|
|
|
|
|
VideoCodec: 'h264',
|
|
|
|
|
Context: 'Static',
|
|
|
|
|
Protocol: 'http'
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
profile.ContainerProfiles = [];
|
|
|
|
|
|
|
|
|
|
profile.CodecProfiles = [];
|
|
|
|
|
|
2020-10-07 05:12:14 -07:00
|
|
|
|
const supportsSecondaryAudio = browser.tizen || videoTestElement.audioTracks;
|
2020-03-30 02:02:16 -07:00
|
|
|
|
|
2020-10-07 05:12:14 -07:00
|
|
|
|
const aacCodecProfileConditions = [];
|
2020-03-30 02:02:16 -07:00
|
|
|
|
|
|
|
|
|
// Handle he-aac not supported
|
|
|
|
|
if (!videoTestElement.canPlayType('video/mp4; codecs="avc1.640029, mp4a.40.5"').replace(/no/, '')) {
|
|
|
|
|
// TODO: This needs to become part of the stream url in order to prevent stream copy
|
|
|
|
|
aacCodecProfileConditions.push({
|
|
|
|
|
Condition: 'NotEquals',
|
|
|
|
|
Property: 'AudioProfile',
|
|
|
|
|
Value: 'HE-AAC'
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!supportsSecondaryAudio) {
|
|
|
|
|
aacCodecProfileConditions.push({
|
|
|
|
|
Condition: 'Equals',
|
|
|
|
|
Property: 'IsSecondaryAudio',
|
|
|
|
|
Value: 'false',
|
|
|
|
|
IsRequired: false
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (aacCodecProfileConditions.length) {
|
|
|
|
|
profile.CodecProfiles.push({
|
|
|
|
|
Type: 'VideoAudio',
|
|
|
|
|
Codec: 'aac',
|
|
|
|
|
Conditions: aacCodecProfileConditions
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!supportsSecondaryAudio) {
|
|
|
|
|
profile.CodecProfiles.push({
|
|
|
|
|
Type: 'VideoAudio',
|
|
|
|
|
Conditions: [
|
|
|
|
|
{
|
|
|
|
|
Condition: 'Equals',
|
|
|
|
|
Property: 'IsSecondaryAudio',
|
|
|
|
|
Value: 'false',
|
|
|
|
|
IsRequired: false
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-07 05:12:14 -07:00
|
|
|
|
let maxH264Level = 42;
|
|
|
|
|
let h264Profiles = 'high|main|baseline|constrained baseline';
|
2020-03-30 02:02:16 -07:00
|
|
|
|
|
2020-06-06 10:16:48 -07:00
|
|
|
|
if (browser.tizen || browser.web0s ||
|
2020-03-30 02:02:16 -07:00
|
|
|
|
videoTestElement.canPlayType('video/mp4; codecs="avc1.640833"').replace(/no/, '')) {
|
|
|
|
|
maxH264Level = 51;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Support H264 Level 52 (Tizen 5.0) - app only
|
2021-10-26 11:40:51 -07:00
|
|
|
|
if ((browser.tizenVersion >= 5 && window.NativeShell) ||
|
|
|
|
|
videoTestElement.canPlayType('video/mp4; codecs="avc1.640834"').replace(/no/, '')) {
|
2020-03-30 02:02:16 -07:00
|
|
|
|
maxH264Level = 52;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-06 10:16:48 -07:00
|
|
|
|
if (browser.tizen ||
|
2020-03-30 02:02:16 -07:00
|
|
|
|
videoTestElement.canPlayType('video/mp4; codecs="avc1.6e0033"').replace(/no/, '')) {
|
|
|
|
|
// These tests are passing in safari, but playback is failing
|
|
|
|
|
if (!browser.safari && !browser.iOS && !browser.web0s && !browser.edge && !browser.mobile) {
|
|
|
|
|
h264Profiles += '|high 10';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-12 05:03:38 -07:00
|
|
|
|
let maxHevcLevel = 120;
|
|
|
|
|
let hevcProfiles = 'main';
|
|
|
|
|
|
|
|
|
|
// hevc main level 4.1
|
|
|
|
|
if (videoTestElement.canPlayType('video/mp4; codecs="hvc1.1.4.L123"').replace(/no/, '') ||
|
|
|
|
|
videoTestElement.canPlayType('video/mp4; codecs="hev1.1.4.L123"').replace(/no/, '')) {
|
|
|
|
|
maxHevcLevel = 123;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// hevc main10 level 4.1
|
|
|
|
|
if (videoTestElement.canPlayType('video/mp4; codecs="hvc1.2.4.L123"').replace(/no/, '') ||
|
|
|
|
|
videoTestElement.canPlayType('video/mp4; codecs="hev1.2.4.L123"').replace(/no/, '')) {
|
|
|
|
|
maxHevcLevel = 123;
|
|
|
|
|
hevcProfiles = 'main|main 10';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// hevc main10 level 5.1
|
|
|
|
|
if (videoTestElement.canPlayType('video/mp4; codecs="hvc1.2.4.L153"').replace(/no/, '') ||
|
|
|
|
|
videoTestElement.canPlayType('video/mp4; codecs="hev1.2.4.L153"').replace(/no/, '')) {
|
|
|
|
|
maxHevcLevel = 153;
|
|
|
|
|
hevcProfiles = 'main|main 10';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// hevc main10 level 6.1
|
|
|
|
|
if (videoTestElement.canPlayType('video/mp4; codecs="hvc1.2.4.L183"').replace(/no/, '') ||
|
2020-11-12 05:35:56 -07:00
|
|
|
|
videoTestElement.canPlayType('video/mp4; codecs="hev1.2.4.L183"').replace(/no/, '')) {
|
2020-11-12 05:03:38 -07:00
|
|
|
|
maxHevcLevel = 183;
|
|
|
|
|
hevcProfiles = 'main|main 10';
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-27 10:06:08 -07:00
|
|
|
|
const h264CodecProfileConditions = [
|
|
|
|
|
{
|
|
|
|
|
Condition: 'NotEquals',
|
|
|
|
|
Property: 'IsAnamorphic',
|
|
|
|
|
Value: 'true',
|
|
|
|
|
IsRequired: false
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
Condition: 'EqualsAny',
|
|
|
|
|
Property: 'VideoProfile',
|
|
|
|
|
Value: h264Profiles,
|
|
|
|
|
IsRequired: false
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
Condition: 'LessThanEqual',
|
|
|
|
|
Property: 'VideoLevel',
|
|
|
|
|
Value: maxH264Level.toString(),
|
|
|
|
|
IsRequired: false
|
|
|
|
|
}
|
|
|
|
|
];
|
2020-03-30 02:02:16 -07:00
|
|
|
|
|
2020-11-12 05:03:38 -07:00
|
|
|
|
const hevcCodecProfileConditions = [
|
|
|
|
|
{
|
|
|
|
|
Condition: 'NotEquals',
|
|
|
|
|
Property: 'IsAnamorphic',
|
|
|
|
|
Value: 'true',
|
|
|
|
|
IsRequired: false
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
Condition: 'EqualsAny',
|
|
|
|
|
Property: 'VideoProfile',
|
|
|
|
|
Value: hevcProfiles,
|
|
|
|
|
IsRequired: false
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
Condition: 'LessThanEqual',
|
|
|
|
|
Property: 'VideoLevel',
|
|
|
|
|
Value: maxHevcLevel.toString(),
|
|
|
|
|
IsRequired: false
|
|
|
|
|
}
|
|
|
|
|
];
|
|
|
|
|
|
2020-06-06 10:16:48 -07:00
|
|
|
|
if (!browser.edgeUwp && !browser.tizen && !browser.web0s) {
|
2020-07-27 10:06:08 -07:00
|
|
|
|
h264CodecProfileConditions.push({
|
2020-06-06 10:16:48 -07:00
|
|
|
|
Condition: 'NotEquals',
|
|
|
|
|
Property: 'IsInterlaced',
|
|
|
|
|
Value: 'true',
|
|
|
|
|
IsRequired: false
|
|
|
|
|
});
|
2020-11-12 05:03:38 -07:00
|
|
|
|
|
|
|
|
|
hevcCodecProfileConditions.push({
|
|
|
|
|
Condition: 'NotEquals',
|
|
|
|
|
Property: 'IsInterlaced',
|
|
|
|
|
Value: 'true',
|
|
|
|
|
IsRequired: false
|
|
|
|
|
});
|
2020-03-30 02:02:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (maxVideoWidth) {
|
2020-07-27 10:06:08 -07:00
|
|
|
|
h264CodecProfileConditions.push({
|
2020-03-30 02:02:16 -07:00
|
|
|
|
Condition: 'LessThanEqual',
|
|
|
|
|
Property: 'Width',
|
|
|
|
|
Value: maxVideoWidth.toString(),
|
|
|
|
|
IsRequired: false
|
|
|
|
|
});
|
2020-11-12 05:03:38 -07:00
|
|
|
|
|
|
|
|
|
hevcCodecProfileConditions.push({
|
|
|
|
|
Condition: 'LessThanEqual',
|
|
|
|
|
Property: 'Width',
|
|
|
|
|
Value: maxVideoWidth.toString(),
|
|
|
|
|
IsRequired: false
|
|
|
|
|
});
|
2020-03-30 02:02:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
2020-10-07 05:12:14 -07:00
|
|
|
|
const globalMaxVideoBitrate = (getGlobalMaxVideoBitrate() || '').toString();
|
2020-03-30 02:02:16 -07:00
|
|
|
|
|
2020-10-07 05:12:14 -07:00
|
|
|
|
const h264MaxVideoBitrate = globalMaxVideoBitrate;
|
2020-03-30 02:02:16 -07:00
|
|
|
|
|
2020-11-12 05:03:38 -07:00
|
|
|
|
const hevcMaxVideoBitrate = globalMaxVideoBitrate;
|
|
|
|
|
|
2020-03-30 02:02:16 -07:00
|
|
|
|
if (h264MaxVideoBitrate) {
|
2020-07-27 10:06:08 -07:00
|
|
|
|
h264CodecProfileConditions.push({
|
2020-03-30 02:02:16 -07:00
|
|
|
|
Condition: 'LessThanEqual',
|
|
|
|
|
Property: 'VideoBitrate',
|
|
|
|
|
Value: h264MaxVideoBitrate,
|
|
|
|
|
IsRequired: true
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-12 05:03:38 -07:00
|
|
|
|
if (hevcMaxVideoBitrate) {
|
|
|
|
|
hevcCodecProfileConditions.push({
|
|
|
|
|
Condition: 'LessThanEqual',
|
|
|
|
|
Property: 'VideoBitrate',
|
|
|
|
|
Value: hevcMaxVideoBitrate,
|
|
|
|
|
IsRequired: true
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-27 10:06:08 -07:00
|
|
|
|
// On iOS 12.x, for TS container max h264 level is 4.2
|
|
|
|
|
if (browser.iOS && browser.iOSVersion < 13) {
|
|
|
|
|
const codecProfile = {
|
|
|
|
|
Type: 'Video',
|
|
|
|
|
Codec: 'h264',
|
|
|
|
|
Container: 'ts',
|
|
|
|
|
Conditions: h264CodecProfileConditions.filter((condition) => {
|
|
|
|
|
return condition.Property !== 'VideoLevel';
|
|
|
|
|
})
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
codecProfile.Conditions.push({
|
|
|
|
|
Condition: 'LessThanEqual',
|
|
|
|
|
Property: 'VideoLevel',
|
|
|
|
|
Value: '42',
|
|
|
|
|
IsRequired: false
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
profile.CodecProfiles.push(codecProfile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
profile.CodecProfiles.push({
|
|
|
|
|
Type: 'Video',
|
|
|
|
|
Codec: 'h264',
|
|
|
|
|
Conditions: h264CodecProfileConditions
|
|
|
|
|
});
|
|
|
|
|
|
2020-11-12 05:03:38 -07:00
|
|
|
|
profile.CodecProfiles.push({
|
|
|
|
|
Type: 'Video',
|
|
|
|
|
Codec: 'hevc',
|
|
|
|
|
Conditions: hevcCodecProfileConditions
|
|
|
|
|
});
|
|
|
|
|
|
2020-10-07 05:12:14 -07:00
|
|
|
|
const globalVideoConditions = [];
|
2020-03-30 02:02:16 -07:00
|
|
|
|
|
|
|
|
|
if (globalMaxVideoBitrate) {
|
|
|
|
|
globalVideoConditions.push({
|
|
|
|
|
Condition: 'LessThanEqual',
|
|
|
|
|
Property: 'VideoBitrate',
|
|
|
|
|
Value: globalMaxVideoBitrate
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (maxVideoWidth) {
|
|
|
|
|
globalVideoConditions.push({
|
|
|
|
|
Condition: 'LessThanEqual',
|
|
|
|
|
Property: 'Width',
|
|
|
|
|
Value: maxVideoWidth.toString(),
|
|
|
|
|
IsRequired: false
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (globalVideoConditions.length) {
|
|
|
|
|
profile.CodecProfiles.push({
|
|
|
|
|
Type: 'Video',
|
|
|
|
|
Conditions: globalVideoConditions
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Subtitle profiles
|
|
|
|
|
// External vtt or burn in
|
|
|
|
|
profile.SubtitleProfiles = [];
|
2021-04-26 17:35:17 -07:00
|
|
|
|
const subtitleBurninSetting = appSettings.get('subtitleburnin');
|
2021-05-01 13:56:37 -07:00
|
|
|
|
if (subtitleBurninSetting !== 'all') {
|
2021-04-25 17:31:19 -07:00
|
|
|
|
if (supportsTextTracks()) {
|
|
|
|
|
profile.SubtitleProfiles.push({
|
|
|
|
|
Format: 'vtt',
|
|
|
|
|
Method: 'External'
|
|
|
|
|
});
|
|
|
|
|
}
|
2021-05-01 13:56:37 -07:00
|
|
|
|
if (options.enableSsaRender !== false && !options.isRetry && subtitleBurninSetting !== 'allcomplexformats') {
|
2021-04-25 17:31:19 -07:00
|
|
|
|
profile.SubtitleProfiles.push({
|
|
|
|
|
Format: 'ass',
|
|
|
|
|
Method: 'External'
|
|
|
|
|
});
|
|
|
|
|
profile.SubtitleProfiles.push({
|
|
|
|
|
Format: 'ssa',
|
|
|
|
|
Method: 'External'
|
|
|
|
|
});
|
|
|
|
|
}
|
2020-04-27 13:09:59 -07:00
|
|
|
|
}
|
2020-03-30 02:02:16 -07:00
|
|
|
|
|
|
|
|
|
profile.ResponseProfiles = [];
|
|
|
|
|
profile.ResponseProfiles.push({
|
|
|
|
|
Type: 'Video',
|
|
|
|
|
Container: 'm4v',
|
|
|
|
|
MimeType: 'video/mp4'
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return profile;
|
2020-10-17 12:04:52 -07:00
|
|
|
|
}
|
2020-08-16 11:24:45 -07:00
|
|
|
|
/* eslint-enable indent */
|