PlaylistMediaPlayer.cs 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. //-----------------------------------------------------------------------------
  5. // Copyright 2015-2022 RenderHeads Ltd. All rights reserved.
  6. //-----------------------------------------------------------------------------
  7. namespace RenderHeads.Media.AVProVideo
  8. {
  9. [System.Serializable]
  10. public class MediaPlaylist
  11. {
  12. [System.Serializable]
  13. public class MediaItem
  14. {
  15. public enum SourceType
  16. {
  17. AVProVideoPlayer,
  18. //Texture2D,
  19. }
  20. [SerializeField] public string name = string.Empty;
  21. [SerializeField] public SourceType sourceType = SourceType.AVProVideoPlayer;
  22. [SerializeField] public MediaPath mediaPath = new MediaPath();
  23. [SerializeField] public Texture2D texture = null;
  24. [SerializeField] public float textureDuration;
  25. [SerializeField] public bool loop = false;
  26. [SerializeField] public PlaylistMediaPlayer.StartMode startMode = PlaylistMediaPlayer.StartMode.Immediate;
  27. [SerializeField] public PlaylistMediaPlayer.ProgressMode progressMode = PlaylistMediaPlayer.ProgressMode.OnFinish;
  28. [SerializeField] public float progressTimeSeconds = 0.5f;
  29. [SerializeField] public bool isOverrideTransition = false;
  30. [SerializeField] public PlaylistMediaPlayer.Transition overrideTransition = PlaylistMediaPlayer.Transition.None;
  31. [SerializeField] public float overrideTransitionDuration = 1f;
  32. [SerializeField] public PlaylistMediaPlayer.Easing.Preset overrideTransitionEasing = PlaylistMediaPlayer.Easing.Preset.Linear;
  33. }
  34. [SerializeField] List<MediaItem> _items = new List<MediaItem>(8);
  35. public List<MediaItem> Items { get { return _items; } }
  36. public bool HasItemAt(int index)
  37. {
  38. return (index >= 0 && index < _items.Count);
  39. }
  40. }
  41. /// <summary>
  42. /// This is a BETA component
  43. /// </summary>
  44. [AddComponentMenu("AVPro Video/Playlist Media Player (BETA)", -80)]
  45. [HelpURL("https://www.renderheads.com/products/avpro-video/")]
  46. public class PlaylistMediaPlayer : MediaPlayer, ITextureProducer
  47. {
  48. public enum Transition
  49. {
  50. None,
  51. Fade,
  52. Black,
  53. White,
  54. Transparent,
  55. Horiz,
  56. Vert,
  57. Diag,
  58. MirrorH,
  59. MirrorV,
  60. MirrorD,
  61. ScrollV,
  62. ScrollH,
  63. Circle,
  64. Diamond,
  65. Blinds,
  66. Arrows,
  67. SlideH,
  68. SlideV,
  69. Zoom,
  70. RectV,
  71. Random,
  72. }
  73. public enum PlaylistLoopMode
  74. {
  75. None,
  76. Loop,
  77. }
  78. public enum StartMode
  79. {
  80. Immediate,
  81. //AfterSeconds,
  82. Manual,
  83. }
  84. public enum ProgressMode
  85. {
  86. OnFinish,
  87. BeforeFinish,
  88. //AfterTime,
  89. Manual,
  90. }
  91. [SerializeField] Shader _transitionShader = null;
  92. [SerializeField] MediaPlayer _playerA = null;
  93. [SerializeField] MediaPlayer _playerB = null;
  94. [SerializeField] bool _playlistAutoProgress = true;
  95. [Tooltip("Close the video on the other MediaPlayer when it is not visible any more. This is useful for freeing up memory and GPU decoding resources.")]
  96. [SerializeField] bool _autoCloseVideo = true;
  97. [SerializeField] PlaylistLoopMode _playlistLoopMode = PlaylistLoopMode.None;
  98. [SerializeField] MediaPlaylist _playlist = new MediaPlaylist();
  99. [Tooltip("Pause the previously playing video. This is useful for systems that will struggle to play 2 videos at once")]
  100. [SerializeField] bool _pausePreviousOnTransition = true;
  101. [SerializeField] Transition _defaultTransition = Transition.None;
  102. [SerializeField] float _defaultTransitionDuration = 1f;
  103. [SerializeField] Easing.Preset _defaultTransitionEasing = Easing.Preset.Linear;
  104. private static readonly LazyShaderProperty PropFromTex = new LazyShaderProperty("_FromTex");
  105. private static readonly LazyShaderProperty PropFade = new LazyShaderProperty("_Fade");
  106. private bool _isPaused = false;
  107. private int _playlistIndex = 0;
  108. private MediaPlayer _nextPlayer;
  109. private Material _material;
  110. private Transition _currentTransition = Transition.None;
  111. private string _currentTransitionName = "LERP_NONE";
  112. private float _currentTransitionDuration = 1f;
  113. private Easing.Preset _currentTransitionEasing = Easing.Preset.Linear;
  114. private float _textureTimer;
  115. private float _transitionTimer;
  116. private System.Func<float, float> _easeFunc;
  117. private RenderTexture _rt;
  118. private MediaPlaylist.MediaItem _currentItem;
  119. private MediaPlaylist.MediaItem _nextItem;
  120. public MediaPlayer CurrentPlayer
  121. {
  122. get
  123. {
  124. if (NextPlayer == _playerA)
  125. {
  126. return _playerB;
  127. }
  128. return _playerA;
  129. }
  130. }
  131. public MediaPlayer NextPlayer
  132. {
  133. get
  134. {
  135. return _nextPlayer;
  136. }
  137. }
  138. public MediaPlaylist Playlist { get { return _playlist; } }
  139. public int PlaylistIndex { get { return _playlistIndex; } }
  140. public MediaPlaylist.MediaItem PlaylistItem { get { if (_playlist.HasItemAt(_playlistIndex)) return _playlist.Items[_playlistIndex]; return null; } }
  141. /// <summary>
  142. /// The default transition to use if the transition is not overridden in the MediaItem
  143. /// </summary>
  144. public Transition DefaultTransition { get { return _defaultTransition; } set { _defaultTransition = value; } }
  145. /// <summary>
  146. /// The default duration the transition will take (in seconds) if the transition is not overridden in the MediaItem
  147. /// </summary>
  148. public float DefaultTransitionDuration { get { return _defaultTransitionDuration; } set { _defaultTransitionDuration = value; } }
  149. /// <summary>
  150. /// The default easing the transition will use if the transition is not overridden in the MediaItem
  151. /// </summary>
  152. public Easing.Preset DefaultTransitionEasing { get { return _defaultTransitionEasing; } set { _defaultTransitionEasing = value; } }
  153. /// <summary>
  154. /// Closes videos that aren't playing. This will save memory but adds extra overhead
  155. /// </summary>
  156. public bool AutoCloseVideo { get { return _autoCloseVideo; } set { _autoCloseVideo = value; } }
  157. /// <summary>
  158. /// None: Do not loop the playlist when the end is reached.<br/>Loop: Rewind the playlist and play again when the each is reached
  159. /// </summary>
  160. public PlaylistLoopMode LoopMode { get { return _playlistLoopMode; } set { _playlistLoopMode = value; } }
  161. /// <summary>
  162. /// Enable the playlist to progress to the next item automatically, or wait for manual trigger via scripting
  163. /// </summary>
  164. public bool AutoProgress { get { return _playlistAutoProgress; } set { _playlistAutoProgress = value; } }
  165. /// <summary>
  166. /// Returns the IMediaInfo interface for the MediaPlayer that is playing the current active item in the playlist (returned by CurrentPlayer property). This will change during each transition.
  167. /// </summary>
  168. public override IMediaInfo Info
  169. {
  170. get { if (CurrentPlayer != null) return CurrentPlayer.Info; return null; }
  171. }
  172. /// <summary>
  173. /// Returns the IMediaControl interface for the MediaPlayer that is playing the current active item in the playlist (returned by CurrentPlayer property). This will change during each transition.
  174. /// </summary>
  175. public override IMediaControl Control
  176. {
  177. get { if (CurrentPlayer != null) return CurrentPlayer.Control; return null; }
  178. }
  179. public override ITextureProducer TextureProducer
  180. {
  181. get
  182. {
  183. if (CurrentPlayer != null)
  184. {
  185. if (IsTransitioning())
  186. {
  187. return this;
  188. }
  189. /*if (_currentItem != null && _currentItem.sourceType == MediaPlaylist.MediaItem.SourceType.Texture2D && _currentItem.texture != null)
  190. {
  191. return this;
  192. }*/
  193. return CurrentPlayer.TextureProducer;
  194. }
  195. return null;
  196. }
  197. }
  198. [SerializeField, Range(0.0f, 1.0f)] float _playlistAudioVolume = 1.0f;
  199. [SerializeField] bool _playlistAudioMuted = false;
  200. public override float AudioVolume
  201. {
  202. get { return _playlistAudioVolume; }
  203. set { _playlistAudioVolume = Mathf.Clamp01(value); if (!IsTransitioning() && CurrentPlayer != null) CurrentPlayer.AudioVolume = _playlistAudioVolume; }
  204. }
  205. public override bool AudioMuted
  206. {
  207. get { return _playlistAudioMuted; }
  208. set { _playlistAudioMuted = value; if (!IsTransitioning() && CurrentPlayer != null) CurrentPlayer.AudioMuted = _playlistAudioMuted; }
  209. }
  210. public override void Play()
  211. {
  212. _isPaused = false;
  213. if (Control != null)
  214. {
  215. Control.Play();
  216. }
  217. if (IsTransitioning())
  218. {
  219. if (!_pausePreviousOnTransition && NextPlayer.Control != null)
  220. {
  221. NextPlayer.Control.Play();
  222. }
  223. }
  224. }
  225. public override void Pause()
  226. {
  227. _isPaused = true;
  228. if (Control != null)
  229. {
  230. Control.Pause();
  231. }
  232. if (IsTransitioning())
  233. {
  234. if (NextPlayer.Control != null)
  235. {
  236. NextPlayer.Control.Pause();
  237. }
  238. }
  239. }
  240. public bool IsPaused()
  241. {
  242. return _isPaused;
  243. }
  244. private void SwapPlayers()
  245. {
  246. // Pause the previously playing video
  247. // This is useful for systems that will struggle to play 2 videos at once
  248. if (_pausePreviousOnTransition)
  249. {
  250. CurrentPlayer.Pause();
  251. }
  252. // Tell listeners that the playlist item has changed
  253. Events.Invoke(this, MediaPlayerEvent.EventType.PlaylistItemChanged, ErrorCode.None);
  254. // Start the transition
  255. if (_currentTransition != Transition.None)
  256. {
  257. // Create a new transition texture if required
  258. Texture currentTexture = GetCurrentTexture();
  259. Texture nextTexture = GetNextTexture();
  260. if (currentTexture != null && nextTexture != null)
  261. {
  262. int maxWidth = Mathf.Max(nextTexture.width, currentTexture.width);
  263. int maxHeight = Mathf.Max(nextTexture.height, currentTexture.height);
  264. if (_rt != null)
  265. {
  266. if (_rt.width != maxWidth || _rt.height != maxHeight)
  267. {
  268. RenderTexture.ReleaseTemporary(_rt);
  269. _rt = null;
  270. }
  271. }
  272. if (_rt == null)
  273. {
  274. _rt = RenderTexture.GetTemporary(maxWidth, maxHeight, 0, RenderTextureFormat.Default, RenderTextureReadWrite.Default, 1);
  275. }
  276. Graphics.Blit(currentTexture, _rt);
  277. _material.SetTexture(PropFromTex.Id, currentTexture);
  278. _easeFunc = Easing.GetFunction(_currentTransitionEasing);
  279. _transitionTimer = 0f;
  280. }
  281. else
  282. {
  283. // Immediately complete the transition
  284. _transitionTimer = _currentTransitionDuration;
  285. // Immediately update the audio volume
  286. NextPlayer.AudioVolume = this.AudioVolume;
  287. CurrentPlayer.AudioVolume = 0f;
  288. if (_autoCloseVideo)
  289. {
  290. CurrentPlayer.MediaPath.Path = string.Empty;
  291. CurrentPlayer.CloseMedia();
  292. }
  293. }
  294. }
  295. // Swap the videos
  296. if (NextPlayer == _playerA)
  297. {
  298. _nextPlayer = _playerB;
  299. }
  300. else
  301. {
  302. _nextPlayer = _playerA;
  303. }
  304. // Swap the items
  305. _currentItem = _nextItem;
  306. _nextItem = null;
  307. }
  308. private Texture GetCurrentTexture()
  309. {
  310. /*if (_currentItem != null && _currentItem.sourceType == MediaPlaylist.MediaItem.SourceType.Texture2D && _currentItem.texture != null)
  311. {
  312. return _currentItem.texture;
  313. }
  314. else*/ if (CurrentPlayer != null && CurrentPlayer.TextureProducer != null)
  315. {
  316. return CurrentPlayer.TextureProducer.GetTexture();
  317. }
  318. return null;
  319. }
  320. private Texture GetNextTexture()
  321. {
  322. /*if (_nextItem != null && _nextItem.sourceType == MediaPlaylist.MediaItem.SourceType.Texture2D && _nextItem.texture != null)
  323. {
  324. return _nextItem.texture;
  325. }
  326. else*/ if (_nextPlayer != null && _nextPlayer.TextureProducer != null)
  327. {
  328. return _nextPlayer.TextureProducer.GetTexture();
  329. }
  330. return null;
  331. }
  332. private void Awake()
  333. {
  334. #if UNITY_IOS && !UNITY_EDITOR_OSX
  335. Application.targetFrameRate = 60;
  336. #endif
  337. _nextPlayer = _playerA;
  338. if (_transitionShader == null)
  339. {
  340. _transitionShader = Shader.Find("AVProVideo/Internal/Transition");
  341. if (_transitionShader == null)
  342. {
  343. Debug.LogError("[AVProVideo] Missing transition shader");
  344. }
  345. }
  346. _material = new Material(_transitionShader);
  347. _easeFunc = Easing.GetFunction(_defaultTransitionEasing);
  348. }
  349. protected override void OnDestroy()
  350. {
  351. if (_rt != null)
  352. {
  353. RenderTexture.ReleaseTemporary(_rt);
  354. _rt = null;
  355. }
  356. if (_material != null)
  357. {
  358. if (Application.isPlaying)
  359. {
  360. Material.Destroy(_material);
  361. }
  362. else
  363. {
  364. Material.DestroyImmediate(_material);
  365. }
  366. _material = null;
  367. }
  368. base.OnDestroy();
  369. }
  370. private void Start()
  371. {
  372. if (Application.isPlaying)
  373. {
  374. if (CurrentPlayer)
  375. {
  376. CurrentPlayer.Events.AddListener(OnVideoEvent);
  377. if (NextPlayer)
  378. {
  379. NextPlayer.Events.AddListener(OnVideoEvent);
  380. }
  381. }
  382. JumpToItem(0);
  383. }
  384. }
  385. public void OnVideoEvent(MediaPlayer mp, MediaPlayerEvent.EventType et, ErrorCode errorCode)
  386. {
  387. if (mp == CurrentPlayer)
  388. {
  389. Events.Invoke(mp, et, errorCode);
  390. }
  391. switch (et)
  392. {
  393. case MediaPlayerEvent.EventType.FirstFrameReady:
  394. if (mp == NextPlayer)
  395. {
  396. SwapPlayers();
  397. Events.Invoke(mp, et, errorCode);
  398. }
  399. break;
  400. case MediaPlayerEvent.EventType.FinishedPlaying:
  401. if (_playlistAutoProgress && mp == CurrentPlayer && _currentItem.progressMode == ProgressMode.OnFinish)
  402. {
  403. NextItem();
  404. }
  405. break;
  406. }
  407. }
  408. public bool PrevItem()
  409. {
  410. return JumpToItem(_playlistIndex - 1);
  411. }
  412. public bool NextItem()
  413. {
  414. bool result = JumpToItem(_playlistIndex + 1);
  415. if (!result)
  416. {
  417. Events.Invoke(this, MediaPlayerEvent.EventType.PlaylistFinished, ErrorCode.None);
  418. }
  419. return result;
  420. }
  421. public bool CanJumpToItem(int index)
  422. {
  423. if (_playlistLoopMode == PlaylistLoopMode.Loop)
  424. {
  425. if (_playlist.Items.Count > 0)
  426. {
  427. index %= _playlist.Items.Count;
  428. if (index < 0)
  429. {
  430. index += _playlist.Items.Count;
  431. }
  432. }
  433. }
  434. return _playlist.HasItemAt(index);
  435. }
  436. public bool JumpToItem(int index)
  437. {
  438. if (_playlistLoopMode == PlaylistLoopMode.Loop)
  439. {
  440. if (_playlist.Items.Count > 0)
  441. {
  442. index %= _playlist.Items.Count;
  443. if (index < 0)
  444. {
  445. index += _playlist.Items.Count;
  446. }
  447. }
  448. }
  449. if (_playlist.HasItemAt(index))
  450. {
  451. _playlistIndex = index;
  452. _nextItem = _playlist.Items[_playlistIndex];
  453. OpenVideoFile(_nextItem);
  454. return true;
  455. }
  456. return false;
  457. }
  458. public void OpenVideoFile(MediaPlaylist.MediaItem mediaItem)
  459. {
  460. bool isMediaAlreadyLoaded = false;
  461. if (NextPlayer.MediaPath == mediaItem.mediaPath)
  462. {
  463. isMediaAlreadyLoaded = true;
  464. }
  465. if (!mediaItem.isOverrideTransition)
  466. {
  467. SetTransition(_defaultTransition, _defaultTransitionDuration, _defaultTransitionEasing);
  468. }
  469. else
  470. {
  471. SetTransition(mediaItem.overrideTransition, mediaItem.overrideTransitionDuration, mediaItem.overrideTransitionEasing);
  472. }
  473. this.Loop = NextPlayer.Loop = mediaItem.loop;
  474. NextPlayer.MediaPath = new MediaPath(mediaItem.mediaPath);
  475. this.MediaPath = new MediaPath(mediaItem.mediaPath);
  476. NextPlayer.AudioMuted = _playlistAudioMuted;
  477. NextPlayer.AudioVolume = _playlistAudioVolume;
  478. if (_transitionTimer < _currentTransitionDuration && _currentTransition != Transition.None)
  479. {
  480. NextPlayer.AudioVolume = 0f;
  481. }
  482. if (isMediaAlreadyLoaded)
  483. {
  484. NextPlayer.Rewind(false);
  485. if (_nextItem.startMode == StartMode.Immediate)
  486. {
  487. NextPlayer.Play();
  488. }
  489. // TODO: We probably want to wait until the new frame arrives before swapping after a Rewind()
  490. SwapPlayers();
  491. }
  492. else
  493. {
  494. if (string.IsNullOrEmpty(NextPlayer.MediaPath.Path))
  495. {
  496. NextPlayer.CloseMedia();
  497. }
  498. else
  499. {
  500. NextPlayer.OpenMedia(NextPlayer.MediaPath.PathType, NextPlayer.MediaPath.Path, _nextItem.startMode == StartMode.Immediate);
  501. }
  502. }
  503. }
  504. private bool IsTransitioning()
  505. {
  506. if (_rt != null && _transitionTimer < _currentTransitionDuration && _currentTransition != Transition.None)
  507. {
  508. return true;
  509. }
  510. return false;
  511. }
  512. private void SetTransition(Transition transition, float duration, Easing.Preset easing)
  513. {
  514. if (transition == Transition.Random)
  515. {
  516. transition = (Transition)Random.Range(0, (int)Transition.Random);
  517. }
  518. if (transition != _currentTransition)
  519. {
  520. // Disable the previous transition
  521. if (!string.IsNullOrEmpty(_currentTransitionName))
  522. {
  523. _material.DisableKeyword(_currentTransitionName);
  524. }
  525. // Enable the next transition
  526. _currentTransition = transition;
  527. _currentTransitionName = GetTransitionName(transition);
  528. _material.EnableKeyword(_currentTransitionName);
  529. }
  530. _currentTransitionDuration = duration;
  531. _currentTransitionEasing = easing;
  532. }
  533. protected override void Update()
  534. {
  535. if (!Application.isPlaying) return;
  536. if (!IsPaused())
  537. {
  538. if (IsTransitioning())
  539. {
  540. _transitionTimer += Time.deltaTime;
  541. float t = _easeFunc(Mathf.Clamp01(_transitionTimer / _currentTransitionDuration));
  542. // Fade the audio volume
  543. NextPlayer.AudioVolume = (1f - t) * this.AudioVolume;
  544. CurrentPlayer.AudioVolume = t * this.AudioVolume;
  545. // TODO: support going from mono to stereo
  546. // TODO: support videos of different aspect ratios by rendering with scaling to fit
  547. // This can be done by blitting twice, once for each eye
  548. // If the stereo mode is different for playera/b then both should be set to stereo during the transition
  549. // if (CurrentPlayer.m_StereoPacking == StereoPacking.TopBottom)....
  550. _material.SetFloat(PropFade.Id, t);
  551. _rt.DiscardContents();
  552. Graphics.Blit(GetCurrentTexture(), _rt, _material);
  553. // After the transition is now complete, close/pause the previous video if required
  554. bool isTransitioning = IsTransitioning();
  555. if (!isTransitioning)
  556. {
  557. if (_autoCloseVideo)
  558. {
  559. if (NextPlayer != null)
  560. {
  561. NextPlayer.MediaPath.Path = string.Empty;
  562. NextPlayer.CloseMedia();
  563. }
  564. }
  565. else if (!_pausePreviousOnTransition)
  566. {
  567. if (NextPlayer != null && NextPlayer.Control.IsPlaying())
  568. {
  569. NextPlayer.Pause();
  570. }
  571. }
  572. }
  573. }
  574. else
  575. {
  576. if (_playlistAutoProgress && _nextItem == null && _currentItem != null && _currentItem.progressMode == ProgressMode.BeforeFinish && Control != null && Control.HasMetaData() && Control.GetCurrentTime() >= (Info.GetDuration() - (_currentItem.progressTimeSeconds)))
  577. {
  578. this.NextItem();
  579. }
  580. else if (_playlistAutoProgress && _currentItem == null)
  581. {
  582. JumpToItem(_playlistIndex);
  583. }
  584. }
  585. }
  586. base.Update();
  587. }
  588. #region Implementing ITextureProducer
  589. public Texture GetTexture(int index = 0)
  590. {
  591. // TODO: support iOS YCbCr by supporting multiple textures
  592. /*if (!IsTransitioning())
  593. {
  594. if (_currentItem != null && _currentItem.sourceType == MediaPlaylist.MediaItem.SourceType.Texture2D && _currentItem.texture != null)
  595. {
  596. return _currentItem.texture;
  597. }
  598. }*/
  599. return _rt;
  600. }
  601. public int GetTextureCount()
  602. {
  603. return CurrentPlayer.TextureProducer.GetTextureCount();
  604. }
  605. public int GetTextureFrameCount()
  606. {
  607. return CurrentPlayer.TextureProducer.GetTextureFrameCount();
  608. }
  609. public bool SupportsTextureFrameCount()
  610. {
  611. return CurrentPlayer.TextureProducer.SupportsTextureFrameCount();
  612. }
  613. public long GetTextureTimeStamp()
  614. {
  615. return CurrentPlayer.TextureProducer.GetTextureTimeStamp();
  616. }
  617. public float GetTexturePixelAspectRatio()
  618. {
  619. return CurrentPlayer.TextureProducer.GetTexturePixelAspectRatio();
  620. }
  621. public bool RequiresVerticalFlip()
  622. {
  623. return CurrentPlayer.TextureProducer.RequiresVerticalFlip();
  624. }
  625. public Matrix4x4 GetYpCbCrTransform()
  626. {
  627. return CurrentPlayer.TextureProducer.GetYpCbCrTransform();
  628. }
  629. public StereoPacking GetTextureStereoPacking()
  630. {
  631. return CurrentPlayer.TextureProducer.GetTextureStereoPacking();
  632. }
  633. public TransparencyMode GetTextureTransparency()
  634. {
  635. return CurrentPlayer.TextureProducer.GetTextureTransparency();
  636. }
  637. public AlphaPacking GetTextureAlphaPacking()
  638. {
  639. return CurrentPlayer.TextureProducer.GetTextureAlphaPacking();
  640. }
  641. #endregion Implementing ITextureProducer
  642. private static string GetTransitionName(Transition transition)
  643. {
  644. switch (transition)
  645. {
  646. case Transition.None: return "LERP_NONE";
  647. case Transition.Fade: return "LERP_FADE";
  648. case Transition.Black: return "LERP_BLACK";
  649. case Transition.White: return "LERP_WHITE";
  650. case Transition.Transparent:return "LERP_TRANSP";
  651. case Transition.Horiz: return "LERP_HORIZ";
  652. case Transition.Vert: return "LERP_VERT";
  653. case Transition.Diag: return "LERP_DIAG";
  654. case Transition.MirrorH: return "LERP_HORIZ_MIRROR";
  655. case Transition.MirrorV: return "LERP_VERT_MIRROR";
  656. case Transition.MirrorD: return "LERP_DIAG_MIRROR";
  657. case Transition.ScrollV: return "LERP_SCROLL_VERT";
  658. case Transition.ScrollH: return "LERP_SCROLL_HORIZ";
  659. case Transition.Circle: return "LERP_CIRCLE";
  660. case Transition.Diamond: return "LERP_DIAMOND";
  661. case Transition.Blinds: return "LERP_BLINDS";
  662. case Transition.Arrows: return "LERP_ARROW";
  663. case Transition.SlideH: return "LERP_SLIDE_HORIZ";
  664. case Transition.SlideV: return "LERP_SLIDE_VERT";
  665. case Transition.Zoom: return "LERP_ZOOM_FADE";
  666. case Transition.RectV: return "LERP_RECTS_VERT";
  667. }
  668. return string.Empty;
  669. }
  670. #region Easing
  671. /// <summary>
  672. /// Easing functions
  673. /// </summary>
  674. [System.Serializable]
  675. public class Easing
  676. {
  677. public Preset preset = Preset.Linear;
  678. public enum Preset
  679. {
  680. Step,
  681. Linear,
  682. InQuad,
  683. OutQuad,
  684. InOutQuad,
  685. InCubic,
  686. OutCubic,
  687. InOutCubic,
  688. InQuint,
  689. OutQuint,
  690. InOutQuint,
  691. InQuart,
  692. OutQuart,
  693. InOutQuart,
  694. InExpo,
  695. OutExpo,
  696. InOutExpo,
  697. Random,
  698. RandomNotStep,
  699. }
  700. public static System.Func<float, float> GetFunction(Preset preset)
  701. {
  702. System.Func<float, float> result = null;
  703. switch (preset)
  704. {
  705. case Preset.Step:
  706. result = Step;
  707. break;
  708. case Preset.Linear:
  709. result = Linear;
  710. break;
  711. case Preset.InQuad:
  712. result = InQuad;
  713. break;
  714. case Preset.OutQuad:
  715. result = OutQuad;
  716. break;
  717. case Preset.InOutQuad:
  718. result = InOutQuad;
  719. break;
  720. case Preset.InCubic:
  721. result = InCubic;
  722. break;
  723. case Preset.OutCubic:
  724. result = OutCubic;
  725. break;
  726. case Preset.InOutCubic:
  727. result = InOutCubic;
  728. break;
  729. case Preset.InQuint:
  730. result = InQuint;
  731. break;
  732. case Preset.OutQuint:
  733. result = OutQuint;
  734. break;
  735. case Preset.InOutQuint:
  736. result = InOutQuint;
  737. break;
  738. case Preset.InQuart:
  739. result = InQuart;
  740. break;
  741. case Preset.OutQuart:
  742. result = OutQuart;
  743. break;
  744. case Preset.InOutQuart:
  745. result = InOutQuart;
  746. break;
  747. case Preset.InExpo:
  748. result = InExpo;
  749. break;
  750. case Preset.OutExpo:
  751. result = OutExpo;
  752. break;
  753. case Preset.InOutExpo:
  754. result = InOutExpo;
  755. break;
  756. case Preset.Random:
  757. result = GetFunction((Preset)Random.Range(0, (int)Preset.Random));
  758. break;
  759. case Preset.RandomNotStep:
  760. result = GetFunction((Preset)Random.Range((int)Preset.Step+1, (int)Preset.Random));
  761. break;
  762. }
  763. return result;
  764. }
  765. public static float PowerEaseIn(float t, float power)
  766. {
  767. return Mathf.Pow(t, power);
  768. }
  769. public static float PowerEaseOut(float t, float power)
  770. {
  771. return 1f - Mathf.Abs(Mathf.Pow(t - 1f, power));
  772. }
  773. public static float PowerEaseInOut(float t, float power)
  774. {
  775. float result;
  776. if (t < 0.5f)
  777. {
  778. result = PowerEaseIn(t * 2f, power) / 2f;
  779. }
  780. else
  781. {
  782. result = PowerEaseOut(t * 2f - 1f, power) / 2f + 0.5f;
  783. }
  784. return result;
  785. }
  786. public static float Step(float t)
  787. {
  788. float result = 0f;
  789. if (t >= 0.5f)
  790. {
  791. result = 1f;
  792. }
  793. return result;
  794. }
  795. public static float Linear(float t)
  796. {
  797. return t;
  798. }
  799. public static float InQuad(float t)
  800. {
  801. return PowerEaseIn(t, 2f);
  802. }
  803. public static float OutQuad(float t)
  804. {
  805. return PowerEaseOut(t, 2f);
  806. //return t * (2f - t);
  807. }
  808. public static float InOutQuad(float t)
  809. {
  810. return PowerEaseInOut(t, 2f);
  811. //return t < 0.5 ? (2f * t * t) : (-1f + (4f - 2f * t) * t);
  812. }
  813. public static float InCubic(float t)
  814. {
  815. return PowerEaseIn(t, 3f);
  816. //return t * t * t;
  817. }
  818. public static float OutCubic(float t)
  819. {
  820. return PowerEaseOut(t, 3f);
  821. //return (--t) * t * t + 1f;
  822. }
  823. public static float InOutCubic(float t)
  824. {
  825. return PowerEaseInOut(t, 3f);
  826. //return t < .5f ? (4f * t * t * t) : ((t - 1f) * (2f * t - 2f) * (2f * t - 2f) + 1f);
  827. }
  828. public static float InQuart(float t)
  829. {
  830. return PowerEaseIn(t, 4f);
  831. //return t * t * t * t;
  832. }
  833. public static float OutQuart(float t)
  834. {
  835. return PowerEaseOut(t, 4f);
  836. //return 1f - (--t) * t * t * t;
  837. }
  838. public static float InOutQuart(float t)
  839. {
  840. return PowerEaseInOut(t, 4f);
  841. //return t < 0.5f ? (8f * t * t * t * t) : (1f - 8f * (--t) * t * t * t);
  842. }
  843. public static float InQuint(float t)
  844. {
  845. return PowerEaseIn(t, 5f);
  846. //return t * t * t * t * t;
  847. }
  848. public static float OutQuint(float t)
  849. {
  850. return PowerEaseOut(t, 5f);
  851. //return 1f + (--t) * t * t * t * t;
  852. }
  853. public static float InOutQuint(float t)
  854. {
  855. return PowerEaseInOut(t, 5f);
  856. //return t < 0.5f ? (16f * t * t * t * t * t) : (1f + 16f * (--t) * t * t * t * t);
  857. }
  858. public static float InExpo(float t)
  859. {
  860. float result = 0f;
  861. if (t != 0f)
  862. {
  863. result = Mathf.Pow(2f, 10f * (t - 1f));
  864. }
  865. return result;
  866. }
  867. public static float OutExpo(float t)
  868. {
  869. float result = 1f;
  870. if (t != 1f)
  871. {
  872. result = -Mathf.Pow(2f, -10f * t) + 1f;
  873. }
  874. return result;
  875. }
  876. public static float InOutExpo(float t)
  877. {
  878. float result = 0f;
  879. if (t > 0f)
  880. {
  881. result = 1f;
  882. if (t < 1f)
  883. {
  884. t *= 2f;
  885. if (t < 1f)
  886. {
  887. result = 0.5f * Mathf.Pow(2f, 10f * (t - 1f));
  888. }
  889. else
  890. {
  891. t--;
  892. result = 0.5f * (-Mathf.Pow(2f, -10f * t) + 2f);
  893. }
  894. }
  895. }
  896. return result;
  897. }
  898. }
  899. #endregion Easing
  900. }
  901. }