123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368 |
- #if UNITY_5_6_OR_NEWER
- #if UNITY_2018_3_OR_NEWER // The "length" property is only supported from 2018.3
- using UnityEngine;
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine.SceneManagement;
- using UnityEngine.Video;
- //-----------------------------------------------------------------------------
- // Copyright 2012-2022 RenderHeads Ltd. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace RenderHeads.Media.AVProMovieCapture
- {
- /// <summary>
- /// Controls VideoPlayer updates time during offline captures
- /// </summary>
- [AddComponentMenu("AVPro Movie Capture/Utils/VideoPlayer Controller", 300)]
- public class VideoPlayerController : MonoBehaviour
- {
- public enum ScanFrequencyMode
- {
- SceneLoad,
- Frame,
- }
- [SerializeField] ScanFrequencyMode _scanFrequency = ScanFrequencyMode.SceneLoad;
- public ScanFrequencyMode ScanFrequency
- {
- get { return _scanFrequency; }
- set { _scanFrequency = value; ResetSceneLoading(); }
- }
- internal class VideoPlayerInstance
- {
- private VideoPlayer _videoPlayer = null;
- private bool _isCapturing = false;
- private bool _isControlling = false;
- private bool _isSeekPending = false;
- private double _videoTime = 0.0;
- private float _postSeekTimer = 0f;
- internal VideoPlayerInstance(VideoPlayer videoPlayer)
- {
- _videoPlayer = videoPlayer;
- }
- internal bool Is(VideoPlayer videoPlayer)
- {
- return (_videoPlayer == videoPlayer);
- }
- internal void StartCapture()
- {
- // First capture to touch the playable directors
- if (!_isCapturing)
- {
- // Null check in case director no longer exists
- if (_videoPlayer != null)
- {
- TryTakeControl();
- }
- _isCapturing = true;
- }
- }
- internal bool IsSeekPending()
- {
- float d = (Time.realtimeSinceStartup - _postSeekTimer);
- return (_isSeekPending || (d < 0.2f));
- }
- internal void TryTakeControl()
- {
- if (!_isControlling)
- {
- if (_videoPlayer.isPrepared)
- {
- if (_videoPlayer.isPlaying && _videoPlayer.frame >= 0)
- {
- _videoPlayer.seekCompleted += VideoSeekCompleted;
- _videoPlayer.frameReady += VideoFrameReady;
- _videoPlayer.sendFrameReadyEvents = true;
- _videoPlayer.Pause();
- _isControlling = true;
- _videoTime = _videoPlayer.time;
- //Debug.Log("pause");
- //Debug.Log(_videoPlayer.canSetSkipOnDrop + " " + _videoPlayer.skipOnDrop);
- _videoPlayer.skipOnDrop = true;
- _postSeekTimer = Time.realtimeSinceStartup - 2f;
- Debug.Log("start " + _videoPlayer.frame + " " + _videoTime + " " + (_videoPlayer.time * 1000));
- }
- }
- }
- }
- void VideoFrameReady(VideoPlayer source, long frameIdx)
- {
- Debug.Log("frame " + frameIdx);
- _postSeekTimer = Time.realtimeSinceStartup - 2f;
- _isSeekPending = false;
- }
- void VideoSeekCompleted(VideoPlayer source)
- {
- Debug.Log("seek complete " + source.frame + " " + source.time * 1000);
- _isSeekPending = false;
- _postSeekTimer = Time.realtimeSinceStartup;
- }
- internal void ReleaseControl()
- {
- _isControlling = false;
- _isSeekPending = false;
- _videoPlayer.seekCompleted -= VideoSeekCompleted;
- }
- internal bool Update(float deltaTime)
- {
- bool updated = false;
- if (_isCapturing)
- {
- if (_videoPlayer != null)
- {
- if (!_isControlling)
- {
- TryTakeControl();
- }
- if (_isControlling)
- {
- if (!_videoPlayer.isPrepared)
- {
- ReleaseControl();
- }
- if (_isControlling && !_isSeekPending)
- {
- float delta = Time.realtimeSinceStartup - _postSeekTimer;
- //Debug.Log("post " + _postSeekTimer);
- if (delta > 0.2f)
- {
- _videoTime += deltaTime;
- if (_videoPlayer.isLooping && _videoTime >= _videoPlayer.length)
- {
- _videoTime %= _videoPlayer.length;
- }
- _isSeekPending = true;
- Debug.Log("seek begin " + _videoPlayer.frame + " " + _videoTime + " " + (_videoPlayer.time * 1000) + " " + (deltaTime * 1000));
- _videoPlayer.time = _videoTime;
- //_videoPlayer.frame = 18;
- //Debug.Log("seek begin2 " + _videoPlayer.frame + " " + (_videoPlayer.time * 1000));
- updated = true;
- //_isSeekPending = false;
- }
- }
- }
- }
- }
- return updated;
- }
- internal void StopCapture()
- {
- if (_isCapturing)
- {
- // TODO: what happens to the VideoPlayer when the scene is unloaded?
- if (_videoPlayer != null)
- {
- // We were controlling?
- if (_isControlling)
- {
- // Restore to original state
- _videoPlayer.Play();
- }
- }
- ReleaseControl();
- _isCapturing = false;
- }
- }
- }
- private List<VideoPlayerInstance> _instances = new List<VideoPlayerInstance>(8);
- void Awake()
- {
- ResetSceneLoading();
- }
- void Start()
- {
- //StartCapture();
- }
- void OnValidate()
- {
- ResetSceneLoading();
- }
- void Update()
- {
- //UpdateFrame();
- }
- internal void UpdateFrame()
- {
- if (!this.isActiveAndEnabled)
- return;
- if (_scanFrequency == ScanFrequencyMode.Frame)
- {
- ScanForVideoPlayers();
- }
- bool anyUpdates = false;
- foreach (VideoPlayerInstance instance in _instances)
- {
- //if (Input.GetKeyDown(KeyCode.P))
- {
- if (instance.Update(Time.deltaTime))
- {
- anyUpdates = true;
- }
- }
- }
- if (anyUpdates)
- {
- //StartCoroutine(WaitforSeekCompletes());
- //WaitforSeekCompletes2();
- //System.Threading.Thread.Sleep(500);
- }
- }
- public bool CanContinue()
- {
- bool result = true;
- foreach (VideoPlayerInstance instance in _instances)
- {
- if (instance.IsSeekPending())
- {
- result = false;
- break;
- }
- }
- return result;
- }
- internal IEnumerator WaitforSeekCompletes()
- {
- yield return new WaitUntil(() =>
- {
- bool isSeekPending = false;
- foreach (VideoPlayerInstance instance in _instances)
- {
- if (instance.IsSeekPending())
- {
- isSeekPending = true;
- break;
- }
- }
- return !isSeekPending;
- });
- System.Threading.Thread.Sleep(100);
- yield return new WaitForEndOfFrame();
- }
- internal void WaitforSeekCompletes2()
- {
- /*bool isSeekPending = false;
- foreach (VideoPlayerInstance instance in _instances)
- {
- if (instance.IsSeekPending())
- {
- isSeekPending = true;
- break;
- }
- }*/
- //Debug.Log("any pending: " + isSeekPending);
- }
- internal void StartCapture()
- {
- Debug.Log("startcap");
- ScanForVideoPlayers();
- foreach (VideoPlayerInstance instance in _instances)
- {
- instance.StartCapture();
- }
- }
- internal void StopCapture()
- {
- foreach (VideoPlayerInstance instance in _instances)
- {
- instance.StopCapture();
- }
- }
- public void ScanForVideoPlayers()
- {
- Debug.Log("scan");
- // Remove any VideoPlayer instances with deleted (null) VideoPlayers
- for (int i = 0; i < _instances.Count; i++)
- {
- VideoPlayerInstance instance = _instances[i];
- if (instance.Is(null))
- {
- _instances.RemoveAt(i); i--;
- }
- }
- // Find all inactive and active VideoPlayers
- VideoPlayer[] videoPlayers = Resources.FindObjectsOfTypeAll<VideoPlayer>();
- // Create a unique instance for each director
- foreach (VideoPlayer videoPlayer in videoPlayers)
- {
- // Check we don't already have this VideoPlayer
- bool hasVideoPlayer = false;
- foreach (VideoPlayerInstance instance in _instances)
- {
- if (instance.Is(videoPlayer))
- {
- hasVideoPlayer = true;
- break;
- }
- }
- // Add to the list
- if (!hasVideoPlayer)
- {
- _instances.Add(new VideoPlayerInstance(videoPlayer));
- Debug.Log("add");
- }
- }
- }
- void OnDestroy()
- {
- SceneManager.sceneLoaded -= OnSceneLoaded;
- StopCapture();
- }
- void ResetSceneLoading()
- {
- SceneManager.sceneLoaded -= OnSceneLoaded;
- if (_scanFrequency == ScanFrequencyMode.SceneLoad)
- {
- SceneManager.sceneLoaded += OnSceneLoaded;
- }
- }
-
- void OnSceneLoaded(Scene scene, LoadSceneMode mode)
- {
- if (_scanFrequency == ScanFrequencyMode.SceneLoad)
- {
- ScanForVideoPlayers();
- }
- }
- }
- }
- #endif
- #endif
|