using System; using System.Collections; using System.Collections.Generic; using System.IO; using UnityEngine; namespace RenderHeads.Media.AVProVideo { [AddComponentMenu("AVPro Video/Media Player", -100)] [HelpURL("http://renderheads.com/product/avpro-video/")] public class MediaPlayer : MonoBehaviour { public Resampler FrameResampler { get { return this.m_Resampler; } } public bool DisplayDebugGUI { get { return this.m_DebugGui; } set { this.m_DebugGui = value; } } public bool DisplayDebugGUIControls { get { return this.m_DebugGuiControls; } set { this.m_DebugGuiControls = value; } } public bool Persistent { get { return this.m_Persistent; } set { this.m_Persistent = value; } } public IMediaInfo Info { get { return this.m_Info; } } public IMediaControl Control { get { return this.m_Control; } } public IMediaPlayer Player { get { return this.m_Player; } } public virtual IMediaProducer TextureProducer { get { return this.m_Texture; } } public virtual IMediaSubtitles Subtitles { get { return this.m_Subtitles; } } public MediaPlayerEvent Events { get { if (this.m_events == null) { this.m_events = new MediaPlayerEvent(); } return this.m_events; } } public bool VideoOpened { get { return this.m_VideoOpened; } } public Transform AudioHeadTransform { get { return this.m_AudioHeadTransform; } set { this.m_AudioHeadTransform = value; } } public bool AudioFocusEnabled { get { return this.m_AudioFocusEnabled; } set { this.m_AudioFocusEnabled = value; } } public float AudioFocusOffLevelDB { get { return this.m_AudioFocusOffLevelDB; } set { this.m_AudioFocusOffLevelDB = value; } } public float AudioFocusWidthDegrees { get { return this.m_AudioFocusWidthDegrees; } set { this.m_AudioFocusWidthDegrees = value; } } public Transform AudioFocusTransform { get { return this.m_AudioFocusTransform; } set { this.m_AudioFocusTransform = value; } } public MediaPlayer.OptionsWindows PlatformOptionsWindows { get { return this._optionsWindows; } } public MediaPlayer.OptionsMacOSX PlatformOptionsMacOSX { get { return this._optionsMacOSX; } } public MediaPlayer.OptionsIOS PlatformOptionsIOS { get { return this._optionsIOS; } } public MediaPlayer.OptionsTVOS PlatformOptionsTVOS { get { return this._optionsTVOS; } } public MediaPlayer.OptionsAndroid PlatformOptionsAndroid { get { return this._optionsAndroid; } } public MediaPlayer.OptionsWindowsPhone PlatformOptionsWindowsPhone { get { return this._optionsWindowsPhone; } } public MediaPlayer.OptionsWindowsUWP PlatformOptionsWindowsUWP { get { return this._optionsWindowsUWP; } } public MediaPlayer.OptionsWebGL PlatformOptionsWebGL { get { return this._optionsWebGL; } } public MediaPlayer.OptionsPS4 PlatformOptionsPS4 { get { return this._optionsPS4; } } private void Awake() { if (this.m_Persistent) { UnityEngine.Object.DontDestroyOnLoad(base.gameObject); } } protected void Initialise() { BaseMediaPlayer baseMediaPlayer = this.CreatePlatformMediaPlayer(); if (baseMediaPlayer != null) { this.m_Control = baseMediaPlayer; this.m_Texture = baseMediaPlayer; this.m_Info = baseMediaPlayer; this.m_Player = baseMediaPlayer; this.m_Subtitles = baseMediaPlayer; this.m_Dispose = baseMediaPlayer; if (!MediaPlayer.s_GlobalStartup) { Helper.LogInfo(string.Format("Initialising AVPro Video (script v{0} plugin v{1}) on {2}/{3} (MT {4}) on {5}", new object[] { "1.7.5", baseMediaPlayer.GetVersion(), SystemInfo.graphicsDeviceName, SystemInfo.graphicsDeviceVersion, SystemInfo.graphicsMultiThreaded, Application.platform }), null); MediaPlayer.s_GlobalStartup = true; } } } private void Start() { if (this.m_Control == null) { this.Initialise(); } if (this.m_Control != null) { if (this.m_AutoOpen) { this.OpenVideoFromFile(); if (this.m_LoadSubtitles && this.m_Subtitles != null && !string.IsNullOrEmpty(this.m_SubtitlePath)) { this.EnableSubtitles(this.m_SubtitleLocation, this.m_SubtitlePath); } } this.StartRenderCoroutine(); } } public bool OpenVideoFromFile(MediaPlayer.FileLocation location, string path, bool autoPlay = true) { this.m_VideoLocation = location; this.m_VideoPath = path; this.m_AutoStart = autoPlay; if (this.m_Control == null) { this.Initialise(); } return this.OpenVideoFromFile(); } public bool OpenVideoFromBuffer(byte[] buffer, bool autoPlay = true) { this.m_VideoLocation = MediaPlayer.FileLocation.AbsolutePathOrURL; this.m_VideoPath = "buffer"; this.m_AutoStart = autoPlay; if (this.m_Control == null) { this.Initialise(); } return this.OpenVideoFromBufferInternal(buffer); } public bool SubtitlesEnabled { get { return this.m_LoadSubtitles; } } public string SubtitlePath { get { return this.m_SubtitlePath; } } public MediaPlayer.FileLocation SubtitleLocation { get { return this.m_SubtitleLocation; } } public bool EnableSubtitles(MediaPlayer.FileLocation fileLocation, string filePath) { bool result = false; if (this.m_Subtitles != null) { if (!string.IsNullOrEmpty(filePath)) { string platformFilePath = this.GetPlatformFilePath(MediaPlayer.GetPlatform(), ref filePath, ref fileLocation); bool flag = true; if (platformFilePath.Contains("://")) { flag = false; } if (flag && !File.Exists(platformFilePath)) { Debug.LogError("[AVProVideo] Subtitle file not found: " + platformFilePath, this); } else { Helper.LogInfo("Opening subtitles " + platformFilePath, this); this.m_previousSubtitleIndex = -1; try { if (platformFilePath.Contains("://")) { if (this.m_loadSubtitlesRoutine != null) { base.StopCoroutine(this.m_loadSubtitlesRoutine); this.m_loadSubtitlesRoutine = null; } this.m_loadSubtitlesRoutine = base.StartCoroutine(this.LoadSubtitlesCoroutine(platformFilePath, fileLocation, filePath)); } else { string data = File.ReadAllText(platformFilePath); if (this.m_Subtitles.LoadSubtitlesSRT(data)) { this.m_SubtitleLocation = fileLocation; this.m_SubtitlePath = filePath; this.m_LoadSubtitles = false; result = true; } else { Debug.LogError("[AVProVideo] Failed to load subtitles" + platformFilePath, this); } } } catch (Exception exception) { Debug.LogError("[AVProVideo] Failed to load subtitles " + platformFilePath, this); Debug.LogException(exception, this); } } } else { Debug.LogError("[AVProVideo] No subtitle file path specified", this); } } else { this.m_queueSubtitleLocation = fileLocation; this.m_queueSubtitlePath = filePath; } return result; } private IEnumerator LoadSubtitlesCoroutine(string url, MediaPlayer.FileLocation fileLocation, string filePath) { WWW www = new WWW(url); yield return www; string subtitleData = string.Empty; if (string.IsNullOrEmpty(www.error)) { subtitleData = www.text; } else { Debug.LogError("[AVProVideo] Error loading subtitles '" + www.error + "' from " + url); } if (this.m_Subtitles.LoadSubtitlesSRT(subtitleData)) { this.m_SubtitleLocation = fileLocation; this.m_SubtitlePath = filePath; this.m_LoadSubtitles = false; } else { Debug.LogError("[AVProVideo] Failed to load subtitles" + url, this); } this.m_loadSubtitlesRoutine = null; yield break; } public void DisableSubtitles() { if (this.m_loadSubtitlesRoutine != null) { base.StopCoroutine(this.m_loadSubtitlesRoutine); this.m_loadSubtitlesRoutine = null; } if (this.m_Subtitles != null) { this.m_previousSubtitleIndex = -1; this.m_LoadSubtitles = false; this.m_Subtitles.LoadSubtitlesSRT(string.Empty); } else { this.m_queueSubtitlePath = string.Empty; } } private bool OpenVideoFromBufferInternal(byte[] buffer) { bool result = false; if (this.m_Control != null) { this.CloseVideo(); this.m_VideoOpened = true; this.m_AutoStartTriggered = !this.m_AutoStart; this.m_EventFired_MetaDataReady = false; this.m_EventFired_ReadyToPlay = false; this.m_EventFired_Started = false; this.m_EventFired_FirstFrameReady = false; this.m_EventFired_FinishedPlaying = false; this.m_previousSubtitleIndex = -1; Helper.LogInfo("Opening buffer of length " + buffer.Length, this); if (!this.m_Control.OpenVideoFromBuffer(buffer)) { Debug.LogError("[AVProVideo] Failed to open buffer", this); if (this.GetCurrentPlatformOptions() != this.PlatformOptionsWindows || this.PlatformOptionsWindows.videoApi != Windows.VideoApi.DirectShow) { Debug.LogError("[AVProVideo] Loading from buffer is currently only supported in Windows when using the DirectShow API"); } } else { this.SetPlaybackOptions(); result = true; this.StartRenderCoroutine(); } } return result; } private bool OpenVideoFromFile() { bool result = false; if (this.m_Control != null) { this.CloseVideo(); this.m_VideoOpened = true; this.m_AutoStartTriggered = !this.m_AutoStart; this.m_EventFired_MetaDataReady = false; this.m_EventFired_ReadyToPlay = false; this.m_EventFired_Started = false; this.m_EventFired_FirstFrameReady = false; this.m_EventFired_FinishedPlaying = false; this.m_FinishedFrameOpenCheck = true; this.m_previousSubtitleIndex = -1; long platformFileOffset = this.GetPlatformFileOffset(); string platformFilePath = this.GetPlatformFilePath(MediaPlayer.GetPlatform(), ref this.m_VideoPath, ref this.m_VideoLocation); if (!string.IsNullOrEmpty(this.m_VideoPath)) { string httpHeaderJson = null; bool flag = true; if (platformFilePath.Contains("://")) { flag = false; httpHeaderJson = this.GetPlatformHttpHeaderJson(); } if (flag && !File.Exists(platformFilePath)) { Debug.LogError("[AVProVideo] File not found: " + platformFilePath, this); } else { Helper.LogInfo(string.Concat(new object[] { "Opening ", platformFilePath, " (offset ", platformFileOffset, ")" }), this); if (this._optionsWindows.enableAudio360) { this.m_Control.SetAudioChannelMode(this._optionsWindows.audio360ChannelMode); } if (!this.m_Control.OpenVideoFromFile(platformFilePath, platformFileOffset, httpHeaderJson)) { Debug.LogError("[AVProVideo] Failed to open " + platformFilePath, this); } else { this.SetPlaybackOptions(); result = true; this.StartRenderCoroutine(); } } } else { Debug.LogError("[AVProVideo] No file path specified", this); } } return result; } private void SetPlaybackOptions() { if (this.m_Control != null) { this.m_Control.SetLooping(this.m_Loop); this.m_Control.SetVolume(this.m_Volume); this.m_Control.SetBalance(this.m_Balance); this.m_Control.SetPlaybackRate(this.m_PlaybackRate); this.m_Control.MuteAudio(this.m_Muted); this.m_Control.SetTextureProperties(this.m_FilterMode, this.m_WrapMode, this.m_AnisoLevel); } } public void CloseVideo() { if (this.m_Control != null) { if (this.m_events != null && this.m_VideoOpened) { this.m_events.Invoke(this, MediaPlayerEvent.EventType.Closing, ErrorCode.None); } this.m_AutoStartTriggered = false; this.m_VideoOpened = false; this.m_EventFired_ReadyToPlay = false; this.m_EventFired_Started = false; this.m_EventFired_MetaDataReady = false; this.m_EventFired_FirstFrameReady = false; this.m_EventFired_FinishedPlaying = false; if (this.m_loadSubtitlesRoutine != null) { base.StopCoroutine(this.m_loadSubtitlesRoutine); this.m_loadSubtitlesRoutine = null; } this.m_previousSubtitleIndex = -1; this.m_isPlaybackStalled = false; this.m_Control.CloseVideo(); } if (this.m_Resampler != null) { this.m_Resampler.Reset(); } this.StopRenderCoroutine(); } public void Play() { if (this.m_Control != null && this.m_Control.CanPlay()) { this.m_Control.Play(); this.m_EventFired_ReadyToPlay = true; } else { this.m_AutoStart = true; } } public void Pause() { if (this.m_Control != null && this.m_Control.IsPlaying()) { this.m_Control.Pause(); } } public void Stop() { if (this.m_Control != null) { this.m_Control.Stop(); } } public void Rewind(bool pause) { if (this.m_Control != null) { if (pause) { this.Pause(); } this.m_Control.Rewind(); } } private void Update() { if (this.m_Control != null) { if (this.m_VideoOpened && this.m_AutoStart && !this.m_AutoStartTriggered && this.m_Control.CanPlay()) { this.m_AutoStartTriggered = true; this.Play(); } if (this._renderingCoroutine == null && this.m_Control.CanPlay()) { this.StartRenderCoroutine(); } if (this.m_Subtitles != null && !string.IsNullOrEmpty(this.m_queueSubtitlePath)) { this.EnableSubtitles(this.m_queueSubtitleLocation, this.m_queueSubtitlePath); this.m_queueSubtitlePath = string.Empty; } this.UpdateAudioHeadTransform(); this.UpdateAudioFocus(); this.m_Player.Update(); this.UpdateErrors(); this.UpdateEvents(); } } private void LateUpdate() { if (this.m_Resample && this.m_Resampler == null) { this.m_Resampler = new Resampler(this, base.gameObject.name, this.m_ResampleBufferSize, this.m_ResampleMode); } if (this.m_Resampler != null) { this.m_Resampler.Update(); this.m_Resampler.UpdateTimestamp(); } } private void OnEnable() { if (this.m_Control != null && this.m_WasPlayingOnPause) { this.m_AutoStart = true; this.m_AutoStartTriggered = false; this.m_WasPlayingOnPause = false; } if (this.m_Player != null) { this.m_Player.OnEnable(); } this.StartRenderCoroutine(); } private void OnDisable() { if (this.m_Control != null && this.m_Control.IsPlaying()) { this.m_WasPlayingOnPause = true; this.Pause(); } this.StopRenderCoroutine(); } private void OnDestroy() { this.CloseVideo(); if (this.m_Dispose != null) { this.m_Dispose.Dispose(); this.m_Dispose = null; } this.m_Control = null; this.m_Texture = null; this.m_Info = null; this.m_Player = null; if (this.m_Resampler != null) { this.m_Resampler.Release(); this.m_Resampler = null; } } private void OnApplicationQuit() { if (MediaPlayer.s_GlobalStartup) { Helper.LogInfo("Shutdown", null); MediaPlayer[] array = Resources.FindObjectsOfTypeAll(); if (array != null && array.Length > 0) { for (int i = 0; i < array.Length; i++) { array[i].CloseVideo(); } } WindowsMediaPlayer.DeinitPlatform(); MediaPlayer.s_GlobalStartup = false; } } private void StartRenderCoroutine() { if (this._renderingCoroutine == null) { this._renderingCoroutine = base.StartCoroutine(this.FinalRenderCapture()); } } private void StopRenderCoroutine() { if (this._renderingCoroutine != null) { base.StopCoroutine(this._renderingCoroutine); this._renderingCoroutine = null; } } private IEnumerator FinalRenderCapture() { YieldInstruction wait = new WaitForEndOfFrame(); while (Application.isPlaying) { yield return wait; if (base.enabled && this.m_Player != null) { this.m_Player.Render(); } } yield break; } public static Platform GetPlatform() { return Platform.Windows; } public MediaPlayer.PlatformOptions GetCurrentPlatformOptions() { return this._optionsWindows; } public static string GetPath(MediaPlayer.FileLocation location) { string text = string.Empty; switch (location) { case MediaPlayer.FileLocation.RelativeToProjectFolder: { string path = ".."; text = Path.GetFullPath(Path.Combine(Application.dataPath, path)); text = text.Replace('\\', '/'); break; } case MediaPlayer.FileLocation.RelativeToStreamingAssetsFolder: text = Application.streamingAssetsPath; break; case MediaPlayer.FileLocation.RelativeToDataFolder: text = Application.dataPath; break; case MediaPlayer.FileLocation.RelativeToPeristentDataFolder: text = Application.persistentDataPath; break; } return text; } public static string GetFilePath(string path, MediaPlayer.FileLocation location) { string result = string.Empty; if (!string.IsNullOrEmpty(path)) { switch (location) { case MediaPlayer.FileLocation.AbsolutePathOrURL: result = path; break; case MediaPlayer.FileLocation.RelativeToProjectFolder: case MediaPlayer.FileLocation.RelativeToStreamingAssetsFolder: case MediaPlayer.FileLocation.RelativeToDataFolder: case MediaPlayer.FileLocation.RelativeToPeristentDataFolder: result = Path.Combine(MediaPlayer.GetPath(location), path); break; } } return result; } private long GetPlatformFileOffset() { return 0L; } private string GetPlatformHttpHeaderJson() { string text = null; if (!string.IsNullOrEmpty(text)) { text = text.Trim(); } return text; } private string GetPlatformFilePath(Platform platform, ref string filePath, ref MediaPlayer.FileLocation fileLocation) { string empty = string.Empty; if (platform != Platform.Unknown) { MediaPlayer.PlatformOptions currentPlatformOptions = this.GetCurrentPlatformOptions(); if (currentPlatformOptions != null && currentPlatformOptions.overridePath) { filePath = currentPlatformOptions.path; fileLocation = currentPlatformOptions.pathLocation; } } return MediaPlayer.GetFilePath(filePath, fileLocation); } public virtual BaseMediaPlayer CreatePlatformMediaPlayer() { BaseMediaPlayer baseMediaPlayer = null; if (WindowsMediaPlayer.InitialisePlatform()) { baseMediaPlayer = new WindowsMediaPlayer(this._optionsWindows.videoApi, this._optionsWindows.useHardwareDecoding, this._optionsWindows.useTextureMips, this._optionsWindows.hintAlphaChannel, this._optionsWindows.useLowLatency, this._optionsWindows.forceAudioOutputDeviceName, this._optionsWindows.useUnityAudio, this._optionsWindows.forceAudioResample, this._optionsWindows.preferredFilters); } if (baseMediaPlayer == null) { Debug.LogError(string.Format("[AVProVideo] Not supported on this platform {0} {1} {2} {3}. Using null media player!", new object[] { Application.platform, SystemInfo.deviceModel, SystemInfo.processorType, SystemInfo.operatingSystem })); baseMediaPlayer = new NullMediaPlayer(); } return baseMediaPlayer; } private bool ForceWaitForNewFrame(int lastFrameCount, float timeoutMs) { bool result = false; DateTime now = DateTime.Now; int num = 0; while (this.Control != null && (DateTime.Now - now).TotalMilliseconds < (double)timeoutMs) { this.m_Player.Update(); if (lastFrameCount != this.TextureProducer.GetTextureFrameCount()) { result = true; break; } num++; } this.m_Player.Render(); return result; } private void UpdateAudioFocus() { this.m_Control.SetAudioFocusEnabled(this.m_AudioFocusEnabled); this.m_Control.SetAudioFocusProperties(this.m_AudioFocusOffLevelDB, this.m_AudioFocusWidthDegrees); this.m_Control.SetAudioFocusRotation((!(this.m_AudioFocusTransform == null)) ? this.m_AudioFocusTransform.rotation : Quaternion.identity); } private void UpdateAudioHeadTransform() { if (this.m_AudioHeadTransform != null) { this.m_Control.SetAudioHeadRotation(this.m_AudioHeadTransform.rotation); } else { this.m_Control.ResetAudioHeadRotation(); } } private void UpdateErrors() { ErrorCode lastError = this.m_Control.GetLastError(); if (lastError != ErrorCode.None) { Debug.LogError("[AVProVideo] Error: " + Helper.GetErrorMessage(lastError)); if (this.m_events != null) { this.m_events.Invoke(this, MediaPlayerEvent.EventType.Error, lastError); } } } private void UpdateEvents() { if (this.m_events != null && this.m_Control != null) { this.m_FinishedFrameOpenCheck = false; if (this.FireEventIfPossible(MediaPlayerEvent.EventType.FinishedPlaying, this.m_EventFired_FinishedPlaying)) { this.m_EventFired_FinishedPlaying = !this.m_FinishedFrameOpenCheck; } if (this.m_EventFired_Started && this.m_Control != null && !this.m_Control.IsPlaying() && !this.m_Control.IsSeeking()) { this.m_EventFired_Started = false; } if (this.m_EventFired_FinishedPlaying && this.m_Control != null && this.m_Control.IsPlaying() && !this.m_Control.IsFinished()) { bool flag = false; float num = 1000f / this.m_Info.GetVideoFrameRate(); if (this.m_Info.GetDurationMs() - this.m_Control.GetCurrentTimeMs() > num) { flag = true; } if (flag) { this.m_EventFired_FinishedPlaying = false; } } this.m_EventFired_MetaDataReady = this.FireEventIfPossible(MediaPlayerEvent.EventType.MetaDataReady, this.m_EventFired_MetaDataReady); this.m_EventFired_ReadyToPlay = this.FireEventIfPossible(MediaPlayerEvent.EventType.ReadyToPlay, this.m_EventFired_ReadyToPlay); this.m_EventFired_Started = this.FireEventIfPossible(MediaPlayerEvent.EventType.Started, this.m_EventFired_Started); this.m_EventFired_FirstFrameReady = this.FireEventIfPossible(MediaPlayerEvent.EventType.FirstFrameReady, this.m_EventFired_FirstFrameReady); if (this.FireEventIfPossible(MediaPlayerEvent.EventType.SubtitleChange, false)) { this.m_previousSubtitleIndex = this.m_Subtitles.GetSubtitleIndex(); } bool flag2 = this.m_Info.IsPlaybackStalled(); if (flag2 != this.m_isPlaybackStalled) { this.m_isPlaybackStalled = flag2; MediaPlayerEvent.EventType eventType = (!this.m_isPlaybackStalled) ? MediaPlayerEvent.EventType.Unstalled : MediaPlayerEvent.EventType.Stalled; this.FireEventIfPossible(eventType, false); } } } private bool FireEventIfPossible(MediaPlayerEvent.EventType eventType, bool hasFired) { if (this.CanFireEvent(eventType, hasFired)) { hasFired = true; this.m_events.Invoke(this, eventType, ErrorCode.None); } return hasFired; } private bool CanFireEvent(MediaPlayerEvent.EventType et, bool hasFired) { bool result = false; if (this.m_events != null && this.m_Control != null && !hasFired) { switch (et) { case MediaPlayerEvent.EventType.MetaDataReady: result = this.m_Control.HasMetaData(); break; case MediaPlayerEvent.EventType.ReadyToPlay: result = (!this.m_Control.IsPlaying() && this.m_Control.CanPlay() && !this.m_AutoStart); break; case MediaPlayerEvent.EventType.Started: result = this.m_Control.IsPlaying(); break; case MediaPlayerEvent.EventType.FirstFrameReady: result = (this.m_Texture != null && this.m_Control.CanPlay() && this.m_Texture.GetTextureFrameCount() > 0); break; case MediaPlayerEvent.EventType.FinishedPlaying: result = ((!this.m_Control.IsLooping() && this.m_Control.CanPlay() && this.m_Control.IsFinished()) || (this.m_Control.GetCurrentTimeMs() > this.m_Info.GetDurationMs() && !this.m_Control.IsLooping())); break; case MediaPlayerEvent.EventType.SubtitleChange: result = (this.m_previousSubtitleIndex != this.m_Subtitles.GetSubtitleIndex()); break; case MediaPlayerEvent.EventType.Stalled: result = this.m_Info.IsPlaybackStalled(); break; case MediaPlayerEvent.EventType.Unstalled: result = !this.m_Info.IsPlaybackStalled(); break; } } return result; } private void OnApplicationFocus(bool focusStatus) { } private void OnApplicationPause(bool pauseStatus) { } [ContextMenu("Save Frame To PNG")] public void SaveFrameToPng() { Texture2D texture2D = this.ExtractFrame(null, -1f, true, 1000); if (texture2D != null) { byte[] array = texture2D.EncodeToPNG(); if (array != null) { string str = Mathf.FloorToInt(this.Control.GetCurrentTimeMs()).ToString("D8"); File.WriteAllBytes("frame-" + str + ".png", array); } UnityEngine.Object.Destroy(texture2D); } } private static Camera GetDummyCamera() { if (MediaPlayer.m_DummyCamera == null) { GameObject gameObject = GameObject.Find("AVPro Video Dummy Camera"); if (gameObject == null) { gameObject = new GameObject("AVPro Video Dummy Camera"); gameObject.hideFlags = (HideFlags.HideInHierarchy | HideFlags.DontSaveInEditor | HideFlags.DontSaveInBuild | HideFlags.DontUnloadUnusedAsset); gameObject.SetActive(false); UnityEngine.Object.DontDestroyOnLoad(gameObject); MediaPlayer.m_DummyCamera = gameObject.AddComponent(); MediaPlayer.m_DummyCamera.hideFlags = (HideFlags.HideInInspector | HideFlags.DontSaveInEditor | HideFlags.DontSaveInBuild | HideFlags.DontUnloadUnusedAsset); MediaPlayer.m_DummyCamera.cullingMask = 0; MediaPlayer.m_DummyCamera.clearFlags = CameraClearFlags.Nothing; MediaPlayer.m_DummyCamera.enabled = false; } else { MediaPlayer.m_DummyCamera = gameObject.GetComponent(); } } return MediaPlayer.m_DummyCamera; } private IEnumerator ExtractFrameCoroutine(Texture2D target, MediaPlayer.ProcessExtractedFrame callback, float timeSeconds = -1f, bool accurateSeek = true, int timeoutMs = 1000) { Texture2D result = target; Texture frame = null; if (this.m_Control != null) { if (timeSeconds >= 0f) { this.Pause(); float seekTimeMs = timeSeconds * 1000f; if (this.TextureProducer.GetTexture(0) != null && this.m_Control.GetCurrentTimeMs() == seekTimeMs) { frame = this.TextureProducer.GetTexture(0); } else { int preSeekFrameCount = this.m_Texture.GetTextureFrameCount(); if (accurateSeek) { this.m_Control.Seek(seekTimeMs); } else { this.m_Control.SeekFast(seekTimeMs); } if (!this.m_Control.WaitForNextFrame(MediaPlayer.GetDummyCamera(), preSeekFrameCount)) { int currFc = this.TextureProducer.GetTextureFrameCount(); int iterations = 0; int maxIterations = 50; while (currFc + 1 >= this.TextureProducer.GetTextureFrameCount()) { int num; iterations = (num = iterations) + 1; if (num >= maxIterations) { break; } yield return null; } } frame = this.TextureProducer.GetTexture(0); } } else { frame = this.TextureProducer.GetTexture(0); } } if (frame != null) { result = Helper.GetReadableTexture(frame, this.TextureProducer.RequiresVerticalFlip(), Helper.GetOrientation(this.Info.GetTextureTransform()), target); } callback(result); yield return null; yield break; } public void ExtractFrameAsync(Texture2D target, MediaPlayer.ProcessExtractedFrame callback, float timeSeconds = -1f, bool accurateSeek = true, int timeoutMs = 1000) { base.StartCoroutine(this.ExtractFrameCoroutine(target, callback, timeSeconds, accurateSeek, timeoutMs)); } public Texture2D ExtractFrame(Texture2D target, float timeSeconds = -1f, bool accurateSeek = true, int timeoutMs = 1000) { Texture2D result = target; Texture texture = this.ExtractFrame(timeSeconds, accurateSeek, timeoutMs); if (texture != null) { result = Helper.GetReadableTexture(texture, this.TextureProducer.RequiresVerticalFlip(), Helper.GetOrientation(this.Info.GetTextureTransform()), target); } return result; } private Texture ExtractFrame(float timeSeconds = -1f, bool accurateSeek = true, int timeoutMs = 1000) { Texture result = null; if (this.m_Control != null) { if (timeSeconds >= 0f) { this.Pause(); float num = timeSeconds * 1000f; if (this.TextureProducer.GetTexture(0) != null && this.m_Control.GetCurrentTimeMs() == num) { result = this.TextureProducer.GetTexture(0); } else { int textureFrameCount = this.TextureProducer.GetTextureFrameCount(); if (accurateSeek) { this.m_Control.Seek(num); } else { this.m_Control.SeekFast(num); } this.ForceWaitForNewFrame(textureFrameCount, (float)timeoutMs); result = this.TextureProducer.GetTexture(0); } } else { result = this.TextureProducer.GetTexture(0); } } return result; } public void SetGuiPositionFromVideoIndex(int index) { this.m_GuiPositionX = Mathf.FloorToInt(15f + (float)(180 * index) * 1.5f); } public void SetDebugGuiEnabled(bool bEnabled) { this.m_DebugGui = bEnabled; } private void OnGUI() { if (this.m_Info != null && this.m_DebugGui) { GUI.depth = -1000; GUI.matrix = Matrix4x4.TRS(new Vector3((float)this.m_GuiPositionX, 10f, 0f), Quaternion.identity, new Vector3(1.5f, 1.5f, 1f)); GUILayout.BeginVertical("box", new GUILayoutOption[] { GUILayout.MaxWidth(180f) }); GUILayout.Label(Path.GetFileName(this.m_VideoPath), new GUILayoutOption[0]); GUILayout.Label(string.Concat(new object[] { "Dimensions: ", this.m_Info.GetVideoWidth(), "x", this.m_Info.GetVideoHeight(), "@", this.m_Info.GetVideoFrameRate().ToString("F2") }), new GUILayoutOption[0]); GUILayout.Label(string.Concat(new string[] { "Time: ", (this.m_Control.GetCurrentTimeMs() * 0.001f).ToString("F1"), "s / ", (this.m_Info.GetDurationMs() * 0.001f).ToString("F1"), "s" }), new GUILayoutOption[0]); GUILayout.Label("Rate: " + this.m_Info.GetVideoDisplayRate().ToString("F2") + "Hz", new GUILayoutOption[0]); if (this.m_Resample && this.m_Resampler != null) { GUILayout.BeginVertical(new GUILayoutOption[0]); GUILayout.Label("Resampler Info:", new GUILayoutOption[0]); GUILayout.Label("Resampler timestamp: " + this.m_Resampler.TextureTimeStamp, new GUILayoutOption[0]); GUILayout.Label("Resampler frames dropped: " + this.m_Resampler.DroppedFrames, new GUILayoutOption[0]); GUILayout.Label("Resampler frame displayed timer: " + this.m_Resampler.FrameDisplayedTimer, new GUILayoutOption[0]); GUILayout.EndVertical(); } if (this.TextureProducer != null && this.TextureProducer.GetTexture(0) != null) { GUILayout.BeginHorizontal(new GUILayoutOption[0]); Rect rect = GUILayoutUtility.GetRect(32f, 32f); GUILayout.Space(8f); Rect rect2 = GUILayoutUtility.GetRect(32f, 32f); Matrix4x4 matrix = GUI.matrix; if (this.TextureProducer.RequiresVerticalFlip()) { GUIUtility.ScaleAroundPivot(new Vector2(1f, -1f), new Vector2(0f, rect.y + rect.height / 2f)); } GUI.DrawTexture(rect, this.TextureProducer.GetTexture(0), ScaleMode.ScaleToFit, false); GUI.DrawTexture(rect2, this.TextureProducer.GetTexture(0), ScaleMode.ScaleToFit, true); GUI.matrix = matrix; GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); } if (this.m_DebugGuiControls) { GUILayout.BeginHorizontal(new GUILayoutOption[0]); if (this.m_Control.IsPaused()) { if (GUILayout.Button("Play", new GUILayoutOption[] { GUILayout.Width(50f) })) { this.m_Control.Play(); } } else if (GUILayout.Button("Pause", new GUILayoutOption[] { GUILayout.Width(50f) })) { this.m_Control.Pause(); } float durationMs = this.m_Info.GetDurationMs(); float currentTimeMs = this.m_Control.GetCurrentTimeMs(); float num = GUILayout.HorizontalSlider(currentTimeMs, 0f, durationMs, new GUILayoutOption[0]); if (num != currentTimeMs) { this.m_Control.Seek(num); } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); } } public MediaPlayer.FileLocation m_VideoLocation = MediaPlayer.FileLocation.RelativeToStreamingAssetsFolder; public string m_VideoPath; public bool m_AutoOpen = true; public bool m_AutoStart = true; public bool m_Loop; [Range(0f, 1f)] public float m_Volume = 1f; [SerializeField] [Range(-1f, 1f)] private float m_Balance; public bool m_Muted; [SerializeField] [Range(-4f, 4f)] public float m_PlaybackRate = 1f; public bool m_Resample; public Resampler.ResampleMode m_ResampleMode; [Range(3f, 10f)] public int m_ResampleBufferSize = 5; private Resampler m_Resampler; [SerializeField] private bool m_DebugGui; [SerializeField] private bool m_DebugGuiControls = true; [SerializeField] private bool m_Persistent; public StereoPacking m_StereoPacking; public AlphaPacking m_AlphaPacking; public bool m_DisplayDebugStereoColorTint; public FilterMode m_FilterMode = FilterMode.Bilinear; public TextureWrapMode m_WrapMode = TextureWrapMode.Clamp; [Range(0f, 16f)] public int m_AnisoLevel; [SerializeField] private bool m_LoadSubtitles; [SerializeField] private MediaPlayer.FileLocation m_SubtitleLocation = MediaPlayer.FileLocation.RelativeToStreamingAssetsFolder; private MediaPlayer.FileLocation m_queueSubtitleLocation; [SerializeField] private string m_SubtitlePath; private string m_queueSubtitlePath; private Coroutine m_loadSubtitlesRoutine; [SerializeField] private Transform m_AudioHeadTransform; [SerializeField] private bool m_AudioFocusEnabled; [SerializeField] private Transform m_AudioFocusTransform; [SerializeField] [Range(40f, 120f)] private float m_AudioFocusWidthDegrees = 90f; [SerializeField] [Range(-24f, 0f)] private float m_AudioFocusOffLevelDB; [SerializeField] private MediaPlayerEvent m_events; private IMediaControl m_Control; private IMediaProducer m_Texture; private IMediaInfo m_Info; private IMediaPlayer m_Player; private IMediaSubtitles m_Subtitles; private IDisposable m_Dispose; private bool m_VideoOpened; private bool m_AutoStartTriggered; private bool m_WasPlayingOnPause; private Coroutine _renderingCoroutine; private const int s_GuiDepth = -1000; private const float s_GuiScale = 1.5f; private const int s_GuiStartWidth = 10; private const int s_GuiWidth = 180; private int m_GuiPositionX = 10; private static bool s_GlobalStartup; private bool m_EventFired_ReadyToPlay; private bool m_EventFired_Started; private bool m_EventFired_FirstFrameReady; private bool m_EventFired_FinishedPlaying; private bool m_EventFired_MetaDataReady; private int m_previousSubtitleIndex = -1; private bool m_isPlaybackStalled; private static Camera m_DummyCamera; private bool m_FinishedFrameOpenCheck; [SerializeField] private MediaPlayer.OptionsWindows _optionsWindows = new MediaPlayer.OptionsWindows(); [SerializeField] private MediaPlayer.OptionsMacOSX _optionsMacOSX = new MediaPlayer.OptionsMacOSX(); [SerializeField] private MediaPlayer.OptionsIOS _optionsIOS = new MediaPlayer.OptionsIOS(); [SerializeField] private MediaPlayer.OptionsTVOS _optionsTVOS = new MediaPlayer.OptionsTVOS(); [SerializeField] private MediaPlayer.OptionsAndroid _optionsAndroid = new MediaPlayer.OptionsAndroid(); [SerializeField] private MediaPlayer.OptionsWindowsPhone _optionsWindowsPhone = new MediaPlayer.OptionsWindowsPhone(); [SerializeField] private MediaPlayer.OptionsWindowsUWP _optionsWindowsUWP = new MediaPlayer.OptionsWindowsUWP(); [SerializeField] private MediaPlayer.OptionsWebGL _optionsWebGL = new MediaPlayer.OptionsWebGL(); [SerializeField] private MediaPlayer.OptionsPS4 _optionsPS4 = new MediaPlayer.OptionsPS4(); [Serializable] public class Setup { public bool displayDebugGUI; public bool persistent; } public enum FileLocation { AbsolutePathOrURL, RelativeToProjectFolder, RelativeToStreamingAssetsFolder, RelativeToDataFolder, RelativeToPeristentDataFolder } [Serializable] public class PlatformOptions { public virtual bool IsModified() { return this.overridePath; } public bool overridePath; public MediaPlayer.FileLocation pathLocation = MediaPlayer.FileLocation.RelativeToStreamingAssetsFolder; public string path; } [Serializable] public class OptionsWindows : MediaPlayer.PlatformOptions { public override bool IsModified() { return base.IsModified() || !this.useHardwareDecoding || this.useTextureMips || this.hintAlphaChannel || this.useLowLatency || this.useUnityAudio || this.videoApi != Windows.VideoApi.MediaFoundation || !this.forceAudioResample || this.enableAudio360 || this.audio360ChannelMode != Audio360ChannelMode.TBE_8_2 || !string.IsNullOrEmpty(this.forceAudioOutputDeviceName) || this.preferredFilters.Count != 0; } public Windows.VideoApi videoApi; public bool useHardwareDecoding = true; public bool useUnityAudio; public bool forceAudioResample = true; public bool useTextureMips; public bool hintAlphaChannel; public bool useLowLatency; public string forceAudioOutputDeviceName = string.Empty; public List preferredFilters = new List(); public bool enableAudio360; public Audio360ChannelMode audio360ChannelMode; } [Serializable] public class OptionsMacOSX : MediaPlayer.PlatformOptions { public override bool IsModified() { return base.IsModified() || !string.IsNullOrEmpty(this.httpHeaderJson); } [Multiline] public string httpHeaderJson; } [Serializable] public class OptionsIOS : MediaPlayer.PlatformOptions { public override bool IsModified() { return base.IsModified() || !string.IsNullOrEmpty(this.httpHeaderJson) || !this.useYpCbCr420Textures; } public bool useYpCbCr420Textures = true; [Multiline] public string httpHeaderJson; } [Serializable] public class OptionsTVOS : MediaPlayer.PlatformOptions { public override bool IsModified() { return base.IsModified() || !string.IsNullOrEmpty(this.httpHeaderJson) || !this.useYpCbCr420Textures; } public bool useYpCbCr420Textures = true; [Multiline] public string httpHeaderJson; } [Serializable] public class OptionsAndroid : MediaPlayer.PlatformOptions { public override bool IsModified() { return base.IsModified() || this.fileOffset != 0 || this.useFastOesPath || this.showPosterFrame || this.videoApi != Android.VideoApi.MediaPlayer || !string.IsNullOrEmpty(this.httpHeaderJson) || this.enableAudio360 || this.audio360ChannelMode != Audio360ChannelMode.TBE_8_2; } public Android.VideoApi videoApi = Android.VideoApi.MediaPlayer; public bool useFastOesPath; public bool showPosterFrame; public bool enableAudio360; public Audio360ChannelMode audio360ChannelMode; [Multiline] public string httpHeaderJson; [SerializeField] [Tooltip("Byte offset into the file where the media file is located. This is useful when hiding or packing media files within another file.")] public int fileOffset; } [Serializable] public class OptionsWindowsPhone : MediaPlayer.PlatformOptions { public override bool IsModified() { return base.IsModified() || !this.useHardwareDecoding || this.useTextureMips || this.useLowLatency || this.useUnityAudio || !this.forceAudioResample; } public bool useHardwareDecoding = true; public bool useUnityAudio; public bool forceAudioResample = true; public bool useTextureMips; public bool useLowLatency; } [Serializable] public class OptionsWindowsUWP : MediaPlayer.PlatformOptions { public override bool IsModified() { return base.IsModified() || !this.useHardwareDecoding || this.useTextureMips || this.useLowLatency || this.useUnityAudio || !this.forceAudioResample; } public bool useHardwareDecoding = true; public bool useUnityAudio; public bool forceAudioResample = true; public bool useTextureMips; public bool useLowLatency; } [Serializable] public class OptionsWebGL : MediaPlayer.PlatformOptions { } [Serializable] public class OptionsPS4 : MediaPlayer.PlatformOptions { } public delegate void ProcessExtractedFrame(Texture2D extractedFrame); } }