MediaPlayer_PlatformOptions.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  1. using UnityEngine;
  2. using System;
  3. using System.Collections.Generic;
  4. //-----------------------------------------------------------------------------
  5. // Copyright 2015-2022 RenderHeads Ltd. All rights reserved.
  6. //-----------------------------------------------------------------------------
  7. namespace RenderHeads.Media.AVProVideo
  8. {
  9. public partial class MediaPlayer : MonoBehaviour
  10. {
  11. #region PlatformOptions
  12. [System.Serializable]
  13. public class PlatformOptions
  14. {
  15. public virtual bool IsModified()
  16. {
  17. return (httpHeaders.IsModified()
  18. || keyAuth.IsModified()
  19. );
  20. }
  21. public HttpHeaderData httpHeaders = new HttpHeaderData();
  22. public KeyAuthData keyAuth = new KeyAuthData();
  23. // Decryption support
  24. public virtual string GetKeyServerAuthToken() { return keyAuth.keyServerToken; }
  25. //public virtual string GetKeyServerURL() { return null; }
  26. public virtual byte[] GetOverrideDecryptionKey() { return keyAuth.overrideDecryptionKey; }
  27. public virtual bool StartWithHighestBandwidth() { return false; }
  28. }
  29. [System.Serializable]
  30. public class OptionsWindows : PlatformOptions, ISerializationCallbackReceiver
  31. {
  32. public Windows.VideoApi videoApi = Windows.VideoApi.MediaFoundation;
  33. public bool useHardwareDecoding = true;
  34. public bool useTextureMips = false;
  35. public bool use10BitTextures = false;
  36. public bool hintAlphaChannel = false;
  37. public bool useLowLatency = false;
  38. public bool useCustomMovParser = false;
  39. public bool useHapNotchLC = false;
  40. public bool useStereoDetection = true;
  41. public bool useTextTrackSupport = true;
  42. public bool useFacebookAudio360Support = true;
  43. public bool useAudioDelay = false;
  44. public BufferedFrameSelectionMode bufferedFrameSelection = BufferedFrameSelectionMode.None;
  45. public bool pauseOnPrerollComplete = false;
  46. public string forceAudioOutputDeviceName = string.Empty;
  47. public List<string> preferredFilters = new List<string>();
  48. public Windows.AudioOutput audioOutput = Windows.AudioOutput.System;
  49. public Audio360ChannelMode audio360ChannelMode = Audio360ChannelMode.TBE_8_2;
  50. /// WinRT only
  51. public bool startWithHighestBitrate = false;
  52. /// WinRT only
  53. public bool useLowLiveLatency = false;
  54. /// Hap & NotchLC only
  55. [Range(1, 16)]
  56. public int parallelFrameCount = 3;
  57. /// Hap & NotchLC only
  58. [Range(1, 16)]
  59. public int prerollFrameCount = 4;
  60. public override bool IsModified()
  61. {
  62. return (base.IsModified()
  63. || !useHardwareDecoding
  64. || useTextureMips
  65. || use10BitTextures
  66. || hintAlphaChannel
  67. || useLowLatency
  68. || useCustomMovParser
  69. || useHapNotchLC
  70. || !useStereoDetection
  71. || !useTextTrackSupport
  72. || !useFacebookAudio360Support
  73. || useAudioDelay
  74. || pauseOnPrerollComplete
  75. || bufferedFrameSelection != BufferedFrameSelectionMode.None
  76. || videoApi != Windows.VideoApi.MediaFoundation
  77. || audioOutput != Windows.AudioOutput.System
  78. || audio360ChannelMode != Audio360ChannelMode.TBE_8_2
  79. || !string.IsNullOrEmpty(forceAudioOutputDeviceName)
  80. || preferredFilters.Count != 0
  81. || startWithHighestBitrate
  82. || useLowLiveLatency
  83. || parallelFrameCount != 3
  84. || prerollFrameCount != 4
  85. );
  86. }
  87. public override bool StartWithHighestBandwidth() { return startWithHighestBitrate; }
  88. #region Upgrade from Version 1.x
  89. [SerializeField, HideInInspector]
  90. private bool useUnityAudio = false;
  91. [SerializeField, HideInInspector]
  92. private bool enableAudio360 = false;
  93. void ISerializationCallbackReceiver.OnBeforeSerialize() { }
  94. void ISerializationCallbackReceiver.OnAfterDeserialize()
  95. {
  96. if (useUnityAudio && audioOutput == Windows.AudioOutput.System)
  97. {
  98. audioOutput = Windows.AudioOutput.Unity;
  99. useUnityAudio = false;
  100. }
  101. if (enableAudio360 && audioOutput == Windows.AudioOutput.System)
  102. {
  103. audioOutput = Windows.AudioOutput.FacebookAudio360;
  104. enableAudio360 = false;
  105. }
  106. }
  107. #endregion // Upgrade from Version 1.x
  108. }
  109. [System.Serializable]
  110. public class OptionsWindowsUWP : PlatformOptions
  111. {
  112. public bool useHardwareDecoding = true;
  113. public bool useTextureMips = false;
  114. public bool use10BitTextures = false;
  115. public bool hintOutput10Bit = false;
  116. public bool useLowLatency = false;
  117. public WindowsUWP.VideoApi videoApi = WindowsUWP.VideoApi.WinRT;
  118. public WindowsUWP.AudioOutput audioOutput = WindowsUWP.AudioOutput.System;
  119. public Audio360ChannelMode audio360ChannelMode = Audio360ChannelMode.TBE_8_2;
  120. /// WinRT only
  121. public bool startWithHighestBitrate = false;
  122. /// WinRT only
  123. public bool useLowLiveLatency = false;
  124. public override bool IsModified()
  125. {
  126. return (base.IsModified()
  127. || !useHardwareDecoding
  128. || useTextureMips
  129. || use10BitTextures
  130. || useLowLatency
  131. || audioOutput != WindowsUWP.AudioOutput.System
  132. || (audio360ChannelMode != Audio360ChannelMode.TBE_8_2)
  133. || videoApi != WindowsUWP.VideoApi.WinRT
  134. || startWithHighestBitrate
  135. || useLowLiveLatency
  136. );
  137. }
  138. public override bool StartWithHighestBandwidth() { return startWithHighestBitrate; }
  139. }
  140. [System.Serializable]
  141. public class OptionsApple: PlatformOptions
  142. {
  143. public enum TextureFormat: int
  144. {
  145. BGRA,
  146. YCbCr420,
  147. }
  148. public enum AudioMode
  149. {
  150. SystemDirect,
  151. Unity,
  152. SystemDirectWithCapture,
  153. };
  154. [Flags]
  155. public enum Flags: int
  156. {
  157. // Common
  158. None = 0,
  159. GenerateMipMaps = 1 << 0,
  160. // iOS & macOS
  161. AllowExternalPlayback = 1 << 8,
  162. PlayWithoutBuffering = 1 << 9,
  163. UseSinglePlayerItem = 1 << 10,
  164. // iOS
  165. ResumeMediaPlaybackAfterAudioSessionRouteChange = 1 << 16,
  166. }
  167. public enum Resolution
  168. {
  169. NoPreference,
  170. _480p,
  171. _720p,
  172. _1080p,
  173. _1440p,
  174. _2160p,
  175. Custom
  176. }
  177. public enum BitRateUnits
  178. {
  179. bps,
  180. Kbps,
  181. Mbps,
  182. }
  183. private readonly TextureFormat DefaultTextureFormat;
  184. private readonly Flags DefaultFlags;
  185. public TextureFormat textureFormat;
  186. private AudioMode _previousAudioMode = AudioMode.SystemDirect;
  187. public AudioMode previousAudioMode
  188. {
  189. get { return _previousAudioMode; }
  190. }
  191. [SerializeField]
  192. private AudioMode _audioMode;
  193. public AudioMode audioMode
  194. {
  195. get { return _audioMode; }
  196. set
  197. {
  198. if (_audioMode != value)
  199. {
  200. _previousAudioMode = _audioMode;
  201. _audioMode = value;
  202. _changed |= ChangeFlags.AudioMode;
  203. }
  204. }
  205. }
  206. [SerializeField]
  207. private Flags _flags;
  208. public Flags flags
  209. {
  210. get { return _flags; }
  211. set
  212. {
  213. Flags changed = _flags ^ value;
  214. if (changed != 0)
  215. {
  216. if ((changed & Flags.PlayWithoutBuffering) == Flags.PlayWithoutBuffering)
  217. {
  218. _changed |= ChangeFlags.PlayWithoutBuffering;
  219. }
  220. _flags = value;
  221. }
  222. }
  223. }
  224. public float maximumPlaybackRate = 2.0f;
  225. [Flags]
  226. public enum ChangeFlags: int
  227. {
  228. None = 0,
  229. PreferredPeakBitRate = 1 << 1,
  230. PreferredForwardBufferDuration = 1 << 2,
  231. PlayWithoutBuffering = 1 << 3,
  232. PreferredMaximumResolution = 1 << 4,
  233. AudioMode = 1 << 5,
  234. All = -1
  235. }
  236. private ChangeFlags _changed = ChangeFlags.None;
  237. [SerializeField]
  238. private float _preferredPeakBitRate = 0.0f;
  239. public float preferredPeakBitRate
  240. {
  241. get { return _preferredPeakBitRate; }
  242. set
  243. {
  244. if (_preferredPeakBitRate != value)
  245. {
  246. _changed |= ChangeFlags.PreferredPeakBitRate;
  247. _preferredPeakBitRate = value;
  248. }
  249. }
  250. }
  251. [SerializeField]
  252. private BitRateUnits _preferredPeakBitRateUnits = BitRateUnits.Kbps;
  253. public BitRateUnits preferredPeakBitRateUnits
  254. {
  255. get { return _preferredPeakBitRateUnits; }
  256. set
  257. {
  258. if (_preferredPeakBitRateUnits != value)
  259. {
  260. _changed |= ChangeFlags.PreferredPeakBitRate;
  261. _preferredPeakBitRateUnits = value;
  262. }
  263. }
  264. }
  265. [SerializeField]
  266. private double _preferredForwardBufferDuration = 0.0;
  267. public double preferredForwardBufferDuration
  268. {
  269. get
  270. {
  271. return _preferredForwardBufferDuration;
  272. }
  273. set
  274. {
  275. if (_preferredForwardBufferDuration != value)
  276. {
  277. _changed |= ChangeFlags.PreferredForwardBufferDuration;
  278. _preferredForwardBufferDuration = value;
  279. }
  280. }
  281. }
  282. [SerializeField]
  283. private Resolution _preferredMaximumResolution = Resolution.NoPreference;
  284. public Resolution preferredMaximumResolution
  285. {
  286. get
  287. {
  288. return _preferredMaximumResolution;
  289. }
  290. set
  291. {
  292. if (_preferredMaximumResolution != value)
  293. {
  294. _changed |= ChangeFlags.PreferredMaximumResolution;
  295. _preferredMaximumResolution = value;
  296. }
  297. }
  298. }
  299. #if UNITY_2017_2_OR_NEWER
  300. [SerializeField]
  301. private Vector2Int _customPreferredMaximumResolution = Vector2Int.zero;
  302. public Vector2Int customPreferredMaximumResolution
  303. {
  304. get
  305. {
  306. return _customPreferredMaximumResolution;
  307. }
  308. set
  309. {
  310. if (_customPreferredMaximumResolution != value)
  311. {
  312. _changed |= ChangeFlags.PreferredMaximumResolution;
  313. _customPreferredMaximumResolution = value;
  314. }
  315. }
  316. }
  317. #endif
  318. private static double BitRateInBitsPerSecond(float value, BitRateUnits units)
  319. {
  320. switch (units)
  321. {
  322. case BitRateUnits.bps:
  323. return (double)value;
  324. case BitRateUnits.Kbps:
  325. return (double)value * 1000.0;
  326. case BitRateUnits.Mbps:
  327. return (double)value * 1000000.0;
  328. default:
  329. return 0.0;
  330. }
  331. }
  332. public double GetPreferredPeakBitRateInBitsPerSecond()
  333. {
  334. return BitRateInBitsPerSecond(preferredPeakBitRate, preferredPeakBitRateUnits);
  335. }
  336. public OptionsApple(TextureFormat defaultTextureFormat, Flags defaultFlags)
  337. {
  338. DefaultTextureFormat = defaultTextureFormat;
  339. DefaultFlags = defaultFlags;
  340. textureFormat = defaultTextureFormat;
  341. audioMode = AudioMode.SystemDirect;
  342. flags = defaultFlags;
  343. }
  344. public override bool IsModified()
  345. {
  346. return base.IsModified()
  347. || textureFormat != DefaultTextureFormat
  348. || audioMode != AudioMode.SystemDirect
  349. || flags != DefaultFlags
  350. || preferredMaximumResolution != Resolution.NoPreference
  351. || preferredPeakBitRate != 0.0f
  352. || preferredForwardBufferDuration != 0.0;
  353. }
  354. public bool HasChanged(ChangeFlags flags = ChangeFlags.All)
  355. {
  356. return (_changed & flags) != ChangeFlags.None;
  357. }
  358. public void ClearChanges()
  359. {
  360. _changed = ChangeFlags.None;
  361. }
  362. }
  363. [System.Serializable]
  364. public class OptionsAndroid : PlatformOptions, ISerializationCallbackReceiver
  365. {
  366. public enum Resolution
  367. {
  368. NoPreference,
  369. _480p,
  370. _720p,
  371. _1080p,
  372. _2160p,
  373. Custom
  374. }
  375. public enum BitRateUnits
  376. {
  377. bps,
  378. Kbps,
  379. Mbps,
  380. }
  381. [Flags]
  382. public enum ChangeFlags : int
  383. {
  384. None = 0,
  385. PreferredPeakBitRate = 1 << 1,
  386. PreferredMaximumResolution = 1 << 2,
  387. PreferredCustomResolution = 1 << 3,
  388. All = -1
  389. }
  390. private ChangeFlags _changed = ChangeFlags.None;
  391. [SerializeField]
  392. private Resolution _preferredMaximumResolution = Resolution.NoPreference;
  393. public Resolution preferredMaximumResolution
  394. {
  395. get { return _preferredMaximumResolution; }
  396. set
  397. {
  398. if (_preferredMaximumResolution != value)
  399. {
  400. _changed |= ChangeFlags.PreferredMaximumResolution;
  401. _preferredMaximumResolution = value;
  402. }
  403. }
  404. }
  405. #if UNITY_2017_2_OR_NEWER
  406. [SerializeField]
  407. private Vector2Int _customPreferredMaximumResolution = Vector2Int.zero;
  408. public Vector2Int customPreferredMaximumResolution
  409. {
  410. get { return _customPreferredMaximumResolution; }
  411. set
  412. {
  413. if (_customPreferredMaximumResolution != value)
  414. {
  415. _changed |= ChangeFlags.PreferredCustomResolution;
  416. _customPreferredMaximumResolution = value;
  417. }
  418. }
  419. }
  420. #endif
  421. [SerializeField]
  422. private float _preferredPeakBitRate = 0.0f;
  423. public float preferredPeakBitRate
  424. {
  425. get { return _preferredPeakBitRate; }
  426. set
  427. {
  428. if (_preferredPeakBitRate != value)
  429. {
  430. _changed |= ChangeFlags.PreferredPeakBitRate;
  431. _preferredPeakBitRate = value;
  432. }
  433. }
  434. }
  435. [SerializeField]
  436. private BitRateUnits _preferredPeakBitRateUnits = BitRateUnits.Kbps;
  437. public BitRateUnits preferredPeakBitRateUnits
  438. {
  439. get { return _preferredPeakBitRateUnits; }
  440. set
  441. {
  442. if (_preferredPeakBitRateUnits != value)
  443. {
  444. _changed |= ChangeFlags.PreferredPeakBitRate;
  445. _preferredPeakBitRateUnits = value;
  446. }
  447. }
  448. }
  449. public Android.VideoApi videoApi = Android.VideoApi.ExoPlayer;
  450. public bool useFastOesPath = false;
  451. public bool showPosterFrame = false;
  452. public Android.AudioOutput audioOutput = Android.AudioOutput.System;
  453. public Audio360ChannelMode audio360ChannelMode = Audio360ChannelMode.TBE_8_2;
  454. public bool preferSoftwareDecoder = false;
  455. public Android.TextureFiltering blitTextureFiltering = Android.TextureFiltering.Point;
  456. [SerializeField, Tooltip("Byte offset into the file where the media file is located. This is useful when hiding or packing media files within another file.")]
  457. public int fileOffset = 0;
  458. public bool startWithHighestBitrate = false;
  459. public int minBufferMs = Android.Default_MinBufferTimeMs;
  460. public int maxBufferMs = Android.Default_MaxBufferTimeMs;
  461. public int bufferForPlaybackMs = Android.Default_BufferForPlaybackMs;
  462. public int bufferForPlaybackAfterRebufferMs = Android.Default_BufferForPlaybackAfterRebufferMs;
  463. public override bool IsModified()
  464. {
  465. return (base.IsModified()
  466. || (fileOffset != 0)
  467. || useFastOesPath
  468. || showPosterFrame
  469. || (videoApi != Android.VideoApi.ExoPlayer)
  470. || audioOutput != Android.AudioOutput.System
  471. || (audio360ChannelMode != Audio360ChannelMode.TBE_8_2)
  472. || preferSoftwareDecoder
  473. || startWithHighestBitrate
  474. || (minBufferMs != Android.Default_MinBufferTimeMs)
  475. || (maxBufferMs != Android.Default_MaxBufferTimeMs)
  476. || (bufferForPlaybackMs != Android.Default_BufferForPlaybackMs)
  477. || (bufferForPlaybackAfterRebufferMs != Android.Default_BufferForPlaybackAfterRebufferMs)
  478. || (preferredMaximumResolution != Resolution.NoPreference)
  479. || (preferredPeakBitRate != 0.0f)
  480. || (blitTextureFiltering != Android.TextureFiltering.Point)
  481. );
  482. }
  483. private static double BitRateInBitsPerSecond(float value, BitRateUnits units)
  484. {
  485. switch (units)
  486. {
  487. case BitRateUnits.bps:
  488. return (double)value;
  489. case BitRateUnits.Kbps:
  490. return (double)value * 1000.0;
  491. case BitRateUnits.Mbps:
  492. return (double)value * 1000000.0;
  493. default:
  494. return 0.0;
  495. }
  496. }
  497. public double GetPreferredPeakBitRateInBitsPerSecond()
  498. {
  499. _changed &= ~ChangeFlags.PreferredPeakBitRate;
  500. return BitRateInBitsPerSecond(preferredPeakBitRate, preferredPeakBitRateUnits);
  501. }
  502. public override bool StartWithHighestBandwidth()
  503. {
  504. return startWithHighestBitrate;
  505. }
  506. public bool HasChanged(ChangeFlags flags = ChangeFlags.All, bool bClearFlags = false)
  507. {
  508. bool bReturn = ((_changed & flags) != ChangeFlags.None);
  509. if (bClearFlags)
  510. {
  511. _changed = ChangeFlags.None;
  512. }
  513. return bReturn;
  514. }
  515. #region Upgrade from Version 1.x
  516. [SerializeField, HideInInspector]
  517. private bool enableAudio360 = false;
  518. void ISerializationCallbackReceiver.OnBeforeSerialize() { }
  519. void ISerializationCallbackReceiver.OnAfterDeserialize()
  520. {
  521. if (enableAudio360 && audioOutput == Android.AudioOutput.System)
  522. {
  523. audioOutput = Android.AudioOutput.FacebookAudio360;
  524. enableAudio360 = false;
  525. }
  526. }
  527. #endregion // Upgrade from Version 1.x
  528. }
  529. [System.Serializable]
  530. public class OptionsWebGL : PlatformOptions
  531. {
  532. public WebGL.ExternalLibrary externalLibrary = WebGL.ExternalLibrary.None;
  533. public bool useTextureMips = false;
  534. public override bool IsModified()
  535. {
  536. return (base.IsModified() || externalLibrary != WebGL.ExternalLibrary.None || useTextureMips);
  537. }
  538. // Decryption support
  539. public override string GetKeyServerAuthToken() { return null; }
  540. public override byte[] GetOverrideDecryptionKey() { return null; }
  541. }
  542. // TODO: move these to a Setup object
  543. [SerializeField] OptionsWindows _optionsWindows = new OptionsWindows();
  544. [SerializeField] OptionsApple _optionsMacOSX = new OptionsApple(OptionsApple.TextureFormat.BGRA, OptionsApple.Flags.None);
  545. [SerializeField] OptionsApple _optionsIOS = new OptionsApple(OptionsApple.TextureFormat.BGRA, OptionsApple.Flags.None);
  546. [SerializeField] OptionsApple _optionsTVOS = new OptionsApple(OptionsApple.TextureFormat.BGRA, OptionsApple.Flags.None);
  547. [SerializeField] OptionsAndroid _optionsAndroid = new OptionsAndroid();
  548. [SerializeField] OptionsWindowsUWP _optionsWindowsUWP = new OptionsWindowsUWP();
  549. [SerializeField] OptionsWebGL _optionsWebGL = new OptionsWebGL();
  550. public OptionsWindows PlatformOptionsWindows { get { return _optionsWindows; } }
  551. public OptionsApple PlatformOptionsMacOSX { get { return _optionsMacOSX; } }
  552. public OptionsApple PlatformOptionsIOS { get { return _optionsIOS; } }
  553. public OptionsApple PlatformOptionsTVOS { get { return _optionsTVOS; } }
  554. public OptionsAndroid PlatformOptionsAndroid { get { return _optionsAndroid; } }
  555. public OptionsWindowsUWP PlatformOptionsWindowsUWP { get { return _optionsWindowsUWP; } }
  556. public OptionsWebGL PlatformOptionsWebGL { get { return _optionsWebGL; } }
  557. #endregion // PlatformOptions
  558. }
  559. #region PlatformOptionsExtensions
  560. public static class OptionsAppleExtensions
  561. {
  562. public static bool GenerateMipmaps(this MediaPlayer.OptionsApple.Flags flags)
  563. {
  564. return (flags & MediaPlayer.OptionsApple.Flags.GenerateMipMaps) == MediaPlayer.OptionsApple.Flags.GenerateMipMaps;
  565. }
  566. public static MediaPlayer.OptionsApple.Flags SetGenerateMipMaps(this MediaPlayer.OptionsApple.Flags flags, bool b)
  567. {
  568. if (flags.GenerateMipmaps() ^ b)
  569. {
  570. flags = b ? flags | MediaPlayer.OptionsApple.Flags.GenerateMipMaps
  571. : flags & ~MediaPlayer.OptionsApple.Flags.GenerateMipMaps;
  572. }
  573. return flags;
  574. }
  575. public static bool AllowExternalPlayback(this MediaPlayer.OptionsApple.Flags flags)
  576. {
  577. return (flags & MediaPlayer.OptionsApple.Flags.AllowExternalPlayback) == MediaPlayer.OptionsApple.Flags.AllowExternalPlayback;
  578. }
  579. public static MediaPlayer.OptionsApple.Flags SetAllowExternalPlayback(this MediaPlayer.OptionsApple.Flags flags, bool b)
  580. {
  581. if (flags.AllowExternalPlayback() ^ b)
  582. {
  583. flags = b ? flags | MediaPlayer.OptionsApple.Flags.AllowExternalPlayback
  584. : flags & ~MediaPlayer.OptionsApple.Flags.AllowExternalPlayback;
  585. }
  586. return flags;
  587. }
  588. public static bool PlayWithoutBuffering(this MediaPlayer.OptionsApple.Flags flags)
  589. {
  590. return (flags & MediaPlayer.OptionsApple.Flags.PlayWithoutBuffering) == MediaPlayer.OptionsApple.Flags.PlayWithoutBuffering;
  591. }
  592. public static MediaPlayer.OptionsApple.Flags SetPlayWithoutBuffering(this MediaPlayer.OptionsApple.Flags flags, bool b)
  593. {
  594. if (flags.PlayWithoutBuffering() ^ b)
  595. {
  596. flags = b ? flags | MediaPlayer.OptionsApple.Flags.PlayWithoutBuffering
  597. : flags & ~MediaPlayer.OptionsApple.Flags.PlayWithoutBuffering;
  598. }
  599. return flags;
  600. }
  601. public static bool UseSinglePlayerItem(this MediaPlayer.OptionsApple.Flags flags)
  602. {
  603. return (flags & MediaPlayer.OptionsApple.Flags.UseSinglePlayerItem) == MediaPlayer.OptionsApple.Flags.UseSinglePlayerItem;
  604. }
  605. public static MediaPlayer.OptionsApple.Flags SetUseSinglePlayerItem(this MediaPlayer.OptionsApple.Flags flags, bool b)
  606. {
  607. if (flags.UseSinglePlayerItem() ^ b)
  608. {
  609. flags = b ? flags | MediaPlayer.OptionsApple.Flags.UseSinglePlayerItem
  610. : flags & ~MediaPlayer.OptionsApple.Flags.UseSinglePlayerItem;
  611. }
  612. return flags;
  613. }
  614. public static bool ResumePlaybackAfterAudioSessionRouteChange(this MediaPlayer.OptionsApple.Flags flags)
  615. {
  616. return (flags & MediaPlayer.OptionsApple.Flags.ResumeMediaPlaybackAfterAudioSessionRouteChange) == MediaPlayer.OptionsApple.Flags.ResumeMediaPlaybackAfterAudioSessionRouteChange;
  617. }
  618. public static MediaPlayer.OptionsApple.Flags SetResumePlaybackAfterAudioSessionRouteChange(this MediaPlayer.OptionsApple.Flags flags, bool b)
  619. {
  620. if (flags.ResumePlaybackAfterAudioSessionRouteChange() ^ b)
  621. {
  622. flags = b ? flags | MediaPlayer.OptionsApple.Flags.ResumeMediaPlaybackAfterAudioSessionRouteChange
  623. : flags & ~MediaPlayer.OptionsApple.Flags.ResumeMediaPlaybackAfterAudioSessionRouteChange;
  624. }
  625. return flags;
  626. }
  627. }
  628. #endregion // PlatformOptionsExtensions
  629. }