Source: lib/device/tizen.js

  1. /*! @license
  2. * Shaka Player
  3. * Copyright 2025 Google LLC
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. goog.provide('shaka.device.Tizen');
  7. goog.require('shaka.config.CrossBoundaryStrategy');
  8. goog.require('shaka.device.AbstractDevice');
  9. goog.require('shaka.device.DeviceFactory');
  10. goog.require('shaka.device.IDevice');
  11. goog.require('shaka.log');
  12. /**
  13. * @final
  14. */
  15. shaka.device.Tizen = class extends shaka.device.AbstractDevice {
  16. constructor() {
  17. super();
  18. const match = navigator.userAgent.match(/Tizen (\d+).(\d+)/);
  19. /** @private {?number} */
  20. this.osMajorVersion_ = match ? parseInt(match[1], 10) : null;
  21. /** @private {?number} */
  22. this.osMinorVersion_ = match ? parseInt(match[2], 10) : null;
  23. }
  24. /**
  25. * @override
  26. */
  27. getVersion() {
  28. return this.osMajorVersion_;
  29. }
  30. /**
  31. * @override
  32. */
  33. getDeviceName() {
  34. return 'Tizen';
  35. }
  36. /**
  37. * @override
  38. */
  39. getBrowserEngine() {
  40. return shaka.device.IDevice.BrowserEngine.CHROMIUM;
  41. }
  42. /**
  43. * @override
  44. */
  45. getDeviceType() {
  46. return shaka.device.IDevice.DeviceType.TV;
  47. }
  48. /**
  49. * @override
  50. */
  51. requiresEncryptionInfoInAllInitSegments(keySystem) {
  52. return true;
  53. }
  54. /**
  55. * @override
  56. */
  57. requiresEC3InitSegments() {
  58. return this.getVersion() === 3;
  59. }
  60. /**
  61. * @override
  62. */
  63. supportsMediaCapabilities() {
  64. return false;
  65. }
  66. /**
  67. * @override
  68. */
  69. supportsSequenceMode() {
  70. const version = this.getVersion();
  71. return version !== null ? version >= 4 : super.supportsSequenceMode();
  72. }
  73. /**
  74. * @override
  75. */
  76. supportsSmoothCodecSwitching() {
  77. return false;
  78. }
  79. /**
  80. * @override
  81. */
  82. supportsServerCertificate() {
  83. // Tizen 5.0 and earlier do not support server certificates.
  84. if (!this.osMajorVersion_ || !this.osMinorVersion_) {
  85. return super.supportsServerCertificate();
  86. }
  87. if (this.osMajorVersion_ === 5) {
  88. return this.osMinorVersion_ >= 5;
  89. }
  90. return this.osMajorVersion_ > 5;
  91. }
  92. /**
  93. * @override
  94. */
  95. detectMaxHardwareResolution() {
  96. const devicePixelRatio = window.devicePixelRatio;
  97. const maxResolution = {
  98. width: window.screen.width * devicePixelRatio > 1920 ? 3840 : 1920,
  99. height: window.screen.height * devicePixelRatio > 1080 ? 2160 : 1080,
  100. };
  101. try {
  102. if (webapis.systeminfo && webapis.systeminfo.getMaxVideoResolution) {
  103. const maxVideoResolution =
  104. webapis.systeminfo.getMaxVideoResolution();
  105. maxResolution.width = maxVideoResolution.width;
  106. maxResolution.height = maxVideoResolution.height;
  107. } else {
  108. if (webapis.productinfo.is8KPanelSupported &&
  109. webapis.productinfo.is8KPanelSupported()) {
  110. maxResolution.width = 7680;
  111. maxResolution.height = 4320;
  112. } else if (webapis.productinfo.isUdPanelSupported &&
  113. webapis.productinfo.isUdPanelSupported()) {
  114. maxResolution.width = 3840;
  115. maxResolution.height = 2160;
  116. }
  117. }
  118. } catch (e) {
  119. shaka.log.alwaysWarn('Tizen: Error detecting screen size, default ' +
  120. 'screen size 1920x1080.');
  121. }
  122. return Promise.resolve(maxResolution);
  123. }
  124. /**
  125. * @override
  126. */
  127. adjustConfig(config) {
  128. super.adjustConfig(config);
  129. config.drm.ignoreDuplicateInitData = this.getVersion() !== 2;
  130. if (this.getVersion() === 3) {
  131. config.streaming.crossBoundaryStrategy =
  132. shaka.config.CrossBoundaryStrategy.RESET;
  133. }
  134. config.streaming.shouldFixTimestampOffset = true;
  135. // Tizen has long hardware pipeline that respond slowly to seeking.
  136. // Therefore we should not seek when we detect a stall on this platform.
  137. // Instead, default stallSkip to 0 to force the stall detector to pause
  138. // and play instead.
  139. config.streaming.stallSkip = 0;
  140. config.streaming.gapPadding = 2;
  141. return config;
  142. }
  143. /**
  144. * @override
  145. */
  146. rejectCodecs() {
  147. // Tizen's implementation of MSE does not work well with opus. To prevent
  148. // the player from trying to play opus on Tizen, we will override media
  149. // source to always reject opus content.
  150. const codecs = [];
  151. if (this.osMajorVersion_ !== null && this.osMajorVersion_ < 5) {
  152. codecs.push('opus');
  153. }
  154. return codecs;
  155. }
  156. /**
  157. * @override
  158. */
  159. misreportAC3UsingDrm() {
  160. return true;
  161. }
  162. /**
  163. * @override
  164. */
  165. misreportsSupportForPersistentLicenses() {
  166. return this.getVersion() === 3;
  167. }
  168. /**
  169. * @return {boolean}
  170. * @private
  171. */
  172. static isTizen_() {
  173. return navigator.userAgent.includes('Tizen');
  174. }
  175. };
  176. if (shaka.device.Tizen.isTizen_()) {
  177. shaka.device.DeviceFactory.registerDeviceFactory(
  178. () => new shaka.device.Tizen());
  179. }