using System; using System.Collections; using UnityEngine; using UMP.Wrappers; using System.IO; namespace UMP { public class MediaPlayerWebGL : IPlayer { private MonoBehaviour _monoObject; private WrapperInternal _wrapper; private float _frameRate; private float _tmpTime; private int _tmpFramesCounter; private bool _isStarted; private bool _isPlaying; private bool _isLoad; private bool _isReady; private bool _isImageReady; private bool _isTextureExist; private string _dataSource; private PlayerBufferVideo _videoBuffer; private PlayerManagerEvents _eventManager; private PlayerOptions _options; private Texture2D _videoTexture; private GameObject[] _videoOutputObjects; private IEnumerator _updateVideoTextureEnum; private delegate void UpdateTexture(int index); UpdateTexture _updateTexture; IntPtr _updatePointer; #region Constructors /// /// Create instance of MediaPlayerWebGL object with additional arguments /// /// MonoBehaviour instanse /// Objects that will be rendering video output /// Additional player options public MediaPlayerWebGL(MonoBehaviour monoObject, GameObject[] videoOutputObjects, PlayerOptions options) { _monoObject = monoObject; _videoOutputObjects = videoOutputObjects; _options = options; _wrapper = new WrapperInternal(null); if (_options != null) { if (_options.FixedVideoSize != Vector2.zero) { _videoBuffer = new PlayerBufferVideo((int)_options.FixedVideoSize.x, (int)_options.FixedVideoSize.y); } } _eventManager = new PlayerManagerEvents(_monoObject, this); _eventManager.PlayerPlayingListener += OnPlayerPlaying; _eventManager.PlayerPausedListener += OnPlayerPaused; } #endregion #region Private methods private void UpdateFpsCounter() { float timeDelta = UnityEngine.Time.time; timeDelta = (timeDelta > _tmpTime) ? timeDelta - _tmpTime : 0; if (timeDelta >= 1f) { _frameRate = FramesCounter - _tmpFramesCounter; _tmpFramesCounter = FramesCounter; _tmpTime = UnityEngine.Time.time; } } private IEnumerator UpdateVideoTexture() { while (true) { if (FramesCounter > 0) { UpdateFpsCounter(); if (!_isTextureExist) { if (_videoTexture != null) { UnityEngine.Object.Destroy(_videoTexture); _videoTexture = null; } if (_options.FixedVideoSize == Vector2.zero) { int width = VideoWidth; int height = VideoHeight; if (_videoBuffer == null || (_videoBuffer != null && _videoBuffer.Width != width || _videoBuffer.Height != height)) { if (_videoBuffer != null) _videoBuffer.ClearFramePixels(); _videoBuffer = new PlayerBufferVideo(width, height); } } _videoTexture = MediaPlayerHelper.GenPluginTexture(_videoBuffer.Width, _videoBuffer.Height); MediaPlayerHelper.ApplyTextureToRenderingObjects(_videoTexture, _videoOutputObjects); _isTextureExist = true; _isImageReady = false; } _wrapper.NativeUpdateTexture(_videoTexture.GetNativeTexturePtr()); if (!_isImageReady) { _eventManager.SetEvent(PlayerState.ImageReady, _videoTexture); _isImageReady = true; } } if (_wrapper.PlayerIsReady() && !_isReady) { _isReady = true; if (_isLoad) { _eventManager.ReplaceEvent(PlayerState.Paused, PlayerState.Prepared, new Vector2(VideoWidth, VideoHeight)); Pause(); } else { _eventManager.SetEvent(PlayerState.Prepared, new Vector2(VideoWidth, VideoHeight)); _eventManager.SetEvent(PlayerState.Playing); } } yield return null; } } private void OnPlayerPlaying() { _isPlaying = true; } private void OnPlayerPaused() { _isPlaying = false; } #endregion public GameObject[] VideoOutputObjects { set { _videoOutputObjects = value; MediaPlayerHelper.ApplyTextureToRenderingObjects(_videoTexture, _videoOutputObjects); } get { return _videoOutputObjects; } } public PlayerManagerEvents EventManager { get { return _eventManager; } } public PlayerOptions Options { get { return _options; } } public PlayerState State { get { return _wrapper.PlayerGetState(); } } public object StateValue { get { return _wrapper.PlayerGetStateValue(); } } public void AddMediaListener(IMediaListener listener) { if (_eventManager != null) { _eventManager.PlayerOpeningListener += listener.OnPlayerOpening; _eventManager.PlayerBufferingListener += listener.OnPlayerBuffering; _eventManager.PlayerImageReadyListener += listener.OnPlayerImageReady; _eventManager.PlayerPreparedListener += listener.OnPlayerPrepared; _eventManager.PlayerPlayingListener += listener.OnPlayerPlaying; _eventManager.PlayerPausedListener += listener.OnPlayerPaused; _eventManager.PlayerStoppedListener += listener.OnPlayerStopped; _eventManager.PlayerEndReachedListener += listener.OnPlayerEndReached; _eventManager.PlayerEncounteredErrorListener += listener.OnPlayerEncounteredError; } } public void RemoveMediaListener(IMediaListener listener) { if (_eventManager != null) { _eventManager.PlayerOpeningListener -= listener.OnPlayerOpening; _eventManager.PlayerBufferingListener -= listener.OnPlayerBuffering; _eventManager.PlayerImageReadyListener -= listener.OnPlayerImageReady; _eventManager.PlayerPreparedListener -= listener.OnPlayerPrepared; _eventManager.PlayerPlayingListener -= listener.OnPlayerPlaying; _eventManager.PlayerPausedListener -= listener.OnPlayerPaused; _eventManager.PlayerStoppedListener -= listener.OnPlayerStopped; _eventManager.PlayerEndReachedListener -= listener.OnPlayerEndReached; _eventManager.PlayerEncounteredErrorListener -= listener.OnPlayerEncounteredError; } } public void Prepare() { _isLoad = true; Play(); } /// /// Play or resume (True if playback started (and was already started), or False on error. /// /// public bool Play() { if (!_isStarted) { if (_eventManager != null) _eventManager.StartListener(); _eventManager.SetEvent(PlayerState.Opening); } if (_updateVideoTextureEnum == null) { _updateVideoTextureEnum = UpdateVideoTexture(); _monoObject.StartCoroutine(_updateVideoTextureEnum); } _isStarted = _wrapper.PlayerPlay(); if (_isStarted) { if (_isReady && !_isPlaying) _eventManager.SetEvent(PlayerState.Playing); } else { Stop(); } return _isStarted; } public void Pause() { if (_videoOutputObjects == null && _updateVideoTextureEnum != null) { _monoObject.StopCoroutine(_updateVideoTextureEnum); _updateVideoTextureEnum = null; } _wrapper.PlayerPause(); } public void Stop(bool resetTexture) { if (_isStarted) { _wrapper.PlayerStop(); if (_updateVideoTextureEnum != null) { _monoObject.StopCoroutine(_updateVideoTextureEnum); _updateVideoTextureEnum = null; } _frameRate = 0; _tmpFramesCounter = 0; _tmpTime = 0; _isStarted = false; _isPlaying = false; _isLoad = false; _isReady = false; _isImageReady = false; _isTextureExist = !resetTexture; if (resetTexture) { if (_videoTexture != null) { UnityEngine.Object.Destroy(_videoTexture); _videoTexture = null; } } if (_eventManager != null) _eventManager.StopListener(); } } public void Stop() { Stop(true); } public void Release() { Stop(); if (_eventManager != null) { _eventManager.RemoveAllEvents(); _eventManager = null; } _wrapper.PlayerRelease(); } public string DataSource { get { return _dataSource; } set { _dataSource = value; var path = _dataSource; if (path.StartsWith("file:///")) { path = path.Substring("file:///".Length); if (!path.Contains(":/")) path = Path.Combine(Application.streamingAssetsPath, path); } _wrapper.PlayerSetDataSource(path); } } public bool IsPlaying { get { return _wrapper.PlayerIsPlaying(); } } public bool IsReady { get { return _isReady; } } public bool AbleToPlay { get { return _dataSource != null && !string.IsNullOrEmpty(_dataSource.ToString()); } } /// /// Get the current movie length (in ms). /// /// public long Length { get { return _wrapper.PlayerGetLength(); } } /// /// Get the current movie formatted length (hh:mm:ss[:ms]). /// /// True: formatted length will be with [:ms] /// public string GetFormattedLength(bool detail) { var length = TimeSpan.FromMilliseconds(Length); var format = detail ? "{0:D2}:{1:D2}:{2:D2}:{3:D3}" : "{0:D2}:{1:D2}:{2:D2}"; return string.Format(format, length.Hours, length.Minutes, length.Seconds, length.Milliseconds); } public float FrameRate { get { return _frameRate; } } public int FramesCounter { get { return _wrapper.PlayerVideoFramesCounter(); } } public byte[] FramePixels { get { return null; } } public long Time { get { return _wrapper.PlayerGetTime(); } set { _wrapper.PlayerSetTime(value); } } public float Position { get { return _wrapper.PlayerGetPosition(); } set { _wrapper.PlayerSetPosition(value); } } public float PlaybackRate { get { return _wrapper.PlayerGetRate(); } set { _wrapper.PlayerSetRate(value); } } public int Volume { get { return _wrapper.PlayerGetVolume(); } set { _wrapper.PlayerSetVolume(value); } } public bool Mute { get { return _wrapper.PlayerGetMute(); } set { _wrapper.PlayerSetMute(value); } } public int VideoWidth { get { var width = _wrapper.PlayerVideoWidth(); if (_videoBuffer != null && (width <= 0 || _options.FixedVideoSize != Vector2.zero)) width = _videoBuffer.Width; return width; } } public int VideoHeight { get { var height = _wrapper.PlayerVideoHeight(); if (_videoBuffer != null && (height <= 0 || _options.FixedVideoSize != Vector2.zero)) height = _videoBuffer.Height; return height; } } public Vector2 VideoSize { get { return new Vector2(VideoWidth, VideoHeight); } } } }