123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- using UnityEngine;
- //-----------------------------------------------------------------------------
- // Copyright 2015-2022 RenderHeads Ltd. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace RenderHeads.Media.AVProVideo
- {
- public partial class MediaPlayer : MonoBehaviour
- {
- #region Events
- // Event state
- private bool _eventFired_MetaDataReady = false;
- private bool _eventFired_ReadyToPlay = false;
- private bool _eventFired_Started = false;
- private bool _eventFired_FirstFrameReady = false;
- private bool _eventFired_FinishedPlaying = false;
- private bool _eventState_PlaybackBuffering = false;
- private bool _eventState_PlaybackSeeking = false;
- private bool _eventState_PlaybackStalled = false;
- private int _eventState_PreviousWidth = 0;
- private int _eventState_PreviousHeight = 0;
- private int _previousSubtitleIndex = -1;
- private bool _finishedFrameOpenCheck = false;
- #if UNITY_EDITOR
- public static MediaPlayerLoadEvent InternalMediaLoadedEvent = new MediaPlayerLoadEvent();
- #endif
- private void ResetEvents()
- {
- _eventFired_MetaDataReady = false;
- _eventFired_ReadyToPlay = false;
- _eventFired_Started = false;
- _eventFired_FirstFrameReady = false;
- _eventFired_FinishedPlaying = false;
- _eventState_PlaybackBuffering = false;
- _eventState_PlaybackSeeking = false;
- _eventState_PlaybackStalled = false;
- _eventState_PreviousWidth = 0;
- _eventState_PreviousHeight = 0;
- _previousSubtitleIndex = -1;
- _finishedFrameOpenCheck = false;
- }
- private void UpdateEvents()
- {
- if (_events != null && _controlInterface != null && _events.HasListeners())
- {
- //NOTE: Fixes a bug where the event was being fired immediately, so when a file is opened, the finishedPlaying fired flag gets set but
- //is then set to true immediately afterwards due to the returned value
- _finishedFrameOpenCheck = false;
- if (IsHandleEvent(MediaPlayerEvent.EventType.FinishedPlaying))
- {
- if (FireEventIfPossible(MediaPlayerEvent.EventType.FinishedPlaying, _eventFired_FinishedPlaying))
- {
- _eventFired_FinishedPlaying = !_finishedFrameOpenCheck;
- }
- }
- // Reset some event states that can reset during playback
- {
- // Keep track of whether the Playing state has changed
- if (_eventFired_Started && IsHandleEvent(MediaPlayerEvent.EventType.Started) &&
- _controlInterface != null && !_controlInterface.IsPlaying() && !_controlInterface.IsSeeking())
- {
- // Playing has stopped
- _eventFired_Started = false;
- }
- // NOTE: We check _controlInterface isn't null in case the scene is unloaded in response to the FinishedPlaying event
- if (_eventFired_FinishedPlaying && IsHandleEvent(MediaPlayerEvent.EventType.FinishedPlaying) &&
- _controlInterface != null && _controlInterface.IsPlaying() && !_controlInterface.IsFinished())
- {
- bool reset = true;
- #if UNITY_EDITOR_WIN || (!UNITY_EDITOR && (UNITY_STANDALONE_WIN || UNITY_WSA))
- reset = false;
- if (_infoInterface.HasVideo())
- {
- // Some streaming HLS/Dash content don't provide a frame rate
- if (_infoInterface.GetVideoFrameRate() > 0f)
- {
- // Don't reset if within a frame of the end of the video, important for time > duration workaround
- float secondsPerFrame = 1f / _infoInterface.GetVideoFrameRate();
- if (_infoInterface.GetDuration() - _controlInterface.GetCurrentTime() > secondsPerFrame)
- {
- reset = true;
- }
- }
- else
- {
- // Just check if we're not beyond the duration
- if (_controlInterface.GetCurrentTime() < _infoInterface.GetDuration())
- {
- reset = true;
- }
- }
- }
- else
- {
- // For audio only media just check if we're not beyond the duration
- if (_controlInterface.GetCurrentTime() < _infoInterface.GetDuration())
- {
- reset = true;
- }
- }
- #endif
- if (reset)
- {
- //Debug.Log("Reset");
- _eventFired_FinishedPlaying = false;
- }
- }
- }
- // Events that can only fire once
- {
- _eventFired_MetaDataReady = FireEventIfPossible(MediaPlayerEvent.EventType.MetaDataReady, _eventFired_MetaDataReady);
- _eventFired_ReadyToPlay = FireEventIfPossible(MediaPlayerEvent.EventType.ReadyToPlay, _eventFired_ReadyToPlay);
- _eventFired_Started = FireEventIfPossible(MediaPlayerEvent.EventType.Started, _eventFired_Started);
- _eventFired_FirstFrameReady = FireEventIfPossible(MediaPlayerEvent.EventType.FirstFrameReady, _eventFired_FirstFrameReady);
- }
- // Events that can fire multiple times
- {
- // Subtitle changing
- if (FireEventIfPossible(MediaPlayerEvent.EventType.SubtitleChange, false))
- {
- _previousSubtitleIndex = _subtitlesInterface.GetSubtitleIndex();
- }
- // Resolution changing
- if (FireEventIfPossible(MediaPlayerEvent.EventType.ResolutionChanged, false))
- {
- _eventState_PreviousWidth = _infoInterface.GetVideoWidth();
- _eventState_PreviousHeight = _infoInterface.GetVideoHeight();
- }
- // Stalling
- if (IsHandleEvent(MediaPlayerEvent.EventType.Stalled))
- {
- bool newState = _infoInterface.IsPlaybackStalled();
- if (newState != _eventState_PlaybackStalled)
- {
- _eventState_PlaybackStalled = newState;
- var newEvent = _eventState_PlaybackStalled ? MediaPlayerEvent.EventType.Stalled : MediaPlayerEvent.EventType.Unstalled;
- FireEventIfPossible(newEvent, false);
- }
- }
- // Seeking
- if (IsHandleEvent(MediaPlayerEvent.EventType.StartedSeeking))
- {
- bool newState = _controlInterface.IsSeeking();
- if (newState != _eventState_PlaybackSeeking)
- {
- _eventState_PlaybackSeeking = newState;
- var newEvent = _eventState_PlaybackSeeking ? MediaPlayerEvent.EventType.StartedSeeking : MediaPlayerEvent.EventType.FinishedSeeking;
- FireEventIfPossible(newEvent, false);
- }
- }
- // Buffering
- if (IsHandleEvent(MediaPlayerEvent.EventType.StartedBuffering))
- {
- bool newState = _controlInterface.IsBuffering();
- if (newState != _eventState_PlaybackBuffering)
- {
- _eventState_PlaybackBuffering = newState;
- var newEvent = _eventState_PlaybackBuffering ? MediaPlayerEvent.EventType.StartedBuffering : MediaPlayerEvent.EventType.FinishedBuffering;
- FireEventIfPossible(newEvent, false);
- }
- }
- }
- }
- }
- protected bool IsHandleEvent(MediaPlayerEvent.EventType eventType)
- {
- return ((uint)_eventMask & (1 << (int)eventType)) != 0;
- }
- private bool FireEventIfPossible(MediaPlayerEvent.EventType eventType, bool hasFired)
- {
- if (CanFireEvent(eventType, hasFired))
- {
- #if UNITY_EDITOR
- // Special internal global event, called when media is loaded
- // Currently used by the RecentItem class
- if (eventType == MediaPlayerEvent.EventType.Started)
- {
- string fullPath = GetResolvedFilePath(_mediaPath.Path, _mediaPath.PathType);
- InternalMediaLoadedEvent.Invoke(fullPath);
- }
- #endif
- hasFired = true;
- _events.Invoke(this, eventType, ErrorCode.None);
- }
- return hasFired;
- }
- private bool CanFireEvent(MediaPlayerEvent.EventType et, bool hasFired)
- {
- bool result = false;
- if (_events != null && _controlInterface != null && !hasFired && IsHandleEvent(et))
- {
- switch (et)
- {
- case MediaPlayerEvent.EventType.FinishedPlaying:
- result = (!_controlInterface.IsLooping() && _controlInterface.CanPlay() && _controlInterface.IsFinished());
- break;
- case MediaPlayerEvent.EventType.MetaDataReady:
- result = (_controlInterface.HasMetaData());
- break;
- case MediaPlayerEvent.EventType.FirstFrameReady:
- // [MOZ 20/1/21] Removed HasMetaData check as preventing the event from being triggered on (i|mac|tv)OS
- result = (_textureInterface != null && _controlInterface.CanPlay() /*&& _controlInterface.HasMetaData()*/ && _textureInterface.GetTextureFrameCount() > 0);
- break;
- case MediaPlayerEvent.EventType.ReadyToPlay:
- result = (!_controlInterface.IsPlaying() && _controlInterface.CanPlay() && !_autoPlayOnStart);
- break;
- case MediaPlayerEvent.EventType.Started:
- result = (_controlInterface.IsPlaying());
- break;
- case MediaPlayerEvent.EventType.SubtitleChange:
- {
- result = (_previousSubtitleIndex != _subtitlesInterface.GetSubtitleIndex());
- if (!result)
- {
- result = _baseMediaPlayer.InternalIsChangedTextCue();
- }
- break;
- }
- case MediaPlayerEvent.EventType.Stalled:
- result = _infoInterface.IsPlaybackStalled();
- break;
- case MediaPlayerEvent.EventType.Unstalled:
- result = !_infoInterface.IsPlaybackStalled();
- break;
- case MediaPlayerEvent.EventType.StartedSeeking:
- result = _controlInterface.IsSeeking();
- break;
- case MediaPlayerEvent.EventType.FinishedSeeking:
- result = !_controlInterface.IsSeeking();
- break;
- case MediaPlayerEvent.EventType.StartedBuffering:
- result = _controlInterface.IsBuffering();
- break;
- case MediaPlayerEvent.EventType.FinishedBuffering:
- result = !_controlInterface.IsBuffering();
- break;
- case MediaPlayerEvent.EventType.ResolutionChanged:
- result = (_infoInterface != null && (_eventState_PreviousWidth != _infoInterface.GetVideoWidth() || _eventState_PreviousHeight != _infoInterface.GetVideoHeight()));
- break;
- default:
- Debug.LogWarning("[AVProVideo] Unhandled event type");
- break;
- }
- }
- return result;
- }
- #endregion // Events
- }
- }
|