MediaPlayer_TimeScale.cs 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. using UnityEngine;
  2. //-----------------------------------------------------------------------------
  3. // Copyright 2015-2022 RenderHeads Ltd. All rights reserved.
  4. //-----------------------------------------------------------------------------
  5. namespace RenderHeads.Media.AVProVideo
  6. {
  7. public partial class MediaPlayer : MonoBehaviour
  8. {
  9. #region Support for Time Scale
  10. #if AVPROVIDEO_BETA_SUPPORT_TIMESCALE
  11. // Adjust this value to get faster performance but may drop frames.
  12. // Wait longer to ensure there is enough time for frames to process
  13. private const float TimeScaleTimeoutMs = 20f;
  14. private bool _timeScaleIsControlling;
  15. private double _timeScaleVideoTime;
  16. private void UpdateTimeScale()
  17. {
  18. if (Time.timeScale != 1f || Time.captureFramerate != 0)
  19. {
  20. if (_controlInterface.IsPlaying())
  21. {
  22. _controlInterface.Pause();
  23. _timeScaleIsControlling = true;
  24. _timeScaleVideoTime = _controlInterface.GetCurrentTime();
  25. }
  26. if (_timeScaleIsControlling)
  27. {
  28. // Progress time
  29. _timeScaleVideoTime += Time.deltaTime;
  30. // Handle looping
  31. if (_controlInterface.IsLooping() && _timeScaleVideoTime >= Info.GetDuration())
  32. {
  33. // TODO: really we should seek to (_timeScaleVideoTime % Info.GetDuration())
  34. _timeScaleVideoTime = 0.0;
  35. }
  36. int preSeekFrameCount = TextureProducer.GetTextureFrameCount();
  37. // Seek to the new time
  38. {
  39. double preSeekTime = Control.GetCurrentTime();
  40. // Seek
  41. _controlInterface.Seek(_timeScaleVideoTime);
  42. // Early out, if after the seek the time hasn't changed, the seek was probably too small to go to the next frame.
  43. // TODO: This behaviour may be different on other platforms (not Windows) and needs more testing.
  44. if (Mathf.Approximately((float)preSeekTime, (float)_controlInterface.GetCurrentTime()))
  45. {
  46. return;
  47. }
  48. }
  49. // Wait for the new frame to arrive
  50. if (!_controlInterface.WaitForNextFrame(GetDummyCamera(), preSeekFrameCount))
  51. {
  52. // If WaitForNextFrame fails (e.g. in android single threaded), we run the below code to asynchronously wait for the frame
  53. System.DateTime startTime = System.DateTime.Now;
  54. int lastFrameCount = TextureProducer.GetTextureFrameCount();
  55. while (_controlInterface != null && (System.DateTime.Now - startTime).TotalMilliseconds < (double)TimeScaleTimeoutMs)
  56. {
  57. _playerInterface.Update();
  58. _playerInterface.Render();
  59. GetDummyCamera().Render();
  60. if (lastFrameCount != TextureProducer.GetTextureFrameCount())
  61. {
  62. break;
  63. }
  64. }
  65. }
  66. }
  67. }
  68. else
  69. {
  70. // Restore playback when timeScale becomes 1
  71. if (_timeScaleIsControlling)
  72. {
  73. _controlInterface.Play();
  74. _timeScaleIsControlling = false;
  75. }
  76. }
  77. }
  78. #endif
  79. #endregion // Support for Time Scale
  80. }
  81. }