| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496 | //#define AVPROVIDEO_BETA_SUPPORT_TIMESCALE		// BETA FEATURE: comment this in if you want to support frame stepping based on changes in Time.timeScale or Time.captureFramerate//#define AVPROVIDEO_FORCE_NULL_MEDIAPLAYER		// DEV FEATURE: comment this out to make all mediaplayers use the null mediaplayer//#define AVPROVIDEO_DISABLE_LOGGING			// DEV FEATURE: disables Debug.Log from AVPro Video#define AVPROVIDEO_SUPPORT_LIVEEDITMODEusing UnityEngine;using UnityEngine.Serialization;using System.Collections;using System.Collections.Generic;//-----------------------------------------------------------------------------// Copyright 2015-2022 RenderHeads Ltd.  All rights reserved.//-----------------------------------------------------------------------------namespace RenderHeads.Media.AVProVideo{	/// <summary>	/// This is the primary AVPro Video component and handles all media loading,	/// seeking, information retrieving etc.  This component does not do any display	/// of the video.  Instead this is handled by other components such as	/// ApplyToMesh, ApplyToMaterial, DisplayIMGUI, DisplayUGUI.	/// </summary>#if AVPROVIDEO_SUPPORT_LIVEEDITMODE	[ExecuteInEditMode]#endif	[AddComponentMenu("AVPro Video/Media Player", -100)]	[HelpURL("https://www.renderheads.com/products/avpro-video/")]	public partial class MediaPlayer : MonoBehaviour	{		// These fields are just used to setup the default properties for a new video that is about to be loaded		// Once a video has been loaded you should use the interfaces exposed in the properties to		// change playback properties (eg volume, looping, mute)		// Media source		[SerializeField] MediaSource _mediaSource = MediaSource.Reference;		public MediaSource MediaSource { get { return _mediaSource; } internal set { _mediaSource = value; } }		[SerializeField] MediaReference _mediaReference = null;		public MediaReference MediaReference { get { return _mediaReference; } internal set { _mediaReference = value; } }		[SerializeField] MediaPath _mediaPath = new MediaPath();		public MediaPath MediaPath { get { return _mediaPath; } internal set { _mediaPath = value; } }		[SerializeField] MediaHints _fallbackMediaHints = MediaHints.Default;		public MediaHints FallbackMediaHints { get { return _fallbackMediaHints; } set { _fallbackMediaHints = value; } }		[FormerlySerializedAs("m_AutoOpen")]		[SerializeField] bool _autoOpen = true;		public bool AutoOpen { get { return _autoOpen; } set { _autoOpen = value; } }		[FormerlySerializedAs("m_AutoStart")]		[SerializeField] bool _autoPlayOnStart = true;		public bool AutoStart { get { return _autoPlayOnStart; } set { _autoPlayOnStart = value; } }		// Basic controls		[FormerlySerializedAs("m_Loop")]		[SerializeField] bool _loop = false;		public bool Loop		{			get			{				return (_controlInterface != null) ? _controlInterface.IsLooping() : _loop;			}			set			{				_loop = value;				if (_controlInterface != null)					_controlInterface.SetLooping(_loop);			}		}		[FormerlySerializedAs("m_Volume")]		[Range(0.0f, 1.0f)]		[SerializeField] float _audioVolume = 1.0f;		public virtual float AudioVolume		{			get			{				return (_controlInterface != null) ? _controlInterface.GetVolume() : _audioVolume;			}			set			{				_audioVolume = Mathf.Clamp01(value);				if (_controlInterface != null)					_controlInterface.SetVolume(_audioVolume);			}		}		[FormerlySerializedAs("m_Balance")]		[Range(-1.0f, 1.0f)]		[SerializeField] float _audioBalance = 0.0f;		public float AudioBalance		{			get			{				return (_controlInterface != null) ? _controlInterface.GetBalance() : _audioBalance;			}			set			{				_audioBalance = Mathf.Clamp(value, -1f, 1f);				if (_controlInterface != null)					_controlInterface.SetBalance(_audioBalance);			}		}		[FormerlySerializedAs("m_Muted")]		[SerializeField] bool _audioMuted = false;		public virtual bool AudioMuted		{			get			{				return (_controlInterface != null) ? _controlInterface.IsMuted() : _audioMuted;			}			set			{				_audioMuted = value;				if (_controlInterface != null)				{					#if !UNITY_EDITOR						_controlInterface.MuteAudio(_audioMuted);					#else						_controlInterface.MuteAudio(_audioMuted || UnityEditor.EditorUtility.audioMasterMute);					#endif				}			}		}		private AudioSource _audioSource = null;		public AudioSource AudioSource { get { return _audioSource; } internal set { _audioSource = value; } }		[FormerlySerializedAs("m_PlaybackRate")]		[Range(-4.0f, 4.0f)]		[SerializeField] float _playbackRate = 1.0f;		public float PlaybackRate		{			get			{				return (_controlInterface != null) ? _controlInterface.GetPlaybackRate() : _playbackRate;			}			set			{				_playbackRate = value;				if (_controlInterface != null)					_controlInterface.SetPlaybackRate(_playbackRate);			}		}		// Resampler		[FormerlySerializedAs("m_Resample")]		[SerializeField] bool _useResampler = false;		public bool UseResampler { get { return _useResampler; } set { _useResampler = value; } }		[FormerlySerializedAs("m_ResampleMode")]		[SerializeField] Resampler.ResampleMode _resampleMode = Resampler.ResampleMode.POINT;		public Resampler.ResampleMode ResampleMode { get { return _resampleMode; } set { _resampleMode = value; } }		[FormerlySerializedAs("m_ResampleBufferSize")]		[Range(3, 10)]		[SerializeField] int _resampleBufferSize = 5;		public int ResampleBufferSize { get { return _resampleBufferSize; } set { _resampleBufferSize = value; } }		private Resampler _resampler = null;		public Resampler FrameResampler	{ get { return _resampler; } }		// Visual options		[FormerlySerializedAs("m_videoMapping")]		[SerializeField] VideoMapping _videoMapping = VideoMapping.Unknown;		public VideoMapping VideoLayoutMapping { get { return _videoMapping; } set { _videoMapping = value; } }		[FormerlySerializedAs("m_FilterMode")]		[SerializeField] FilterMode _textureFilterMode = FilterMode.Bilinear;		public FilterMode TextureFilterMode		{			get			{				if (_controlInterface != null)				{					FilterMode filterMode = FilterMode.Point;					TextureWrapMode textureWrapMode = TextureWrapMode.Repeat;					int anisoLevel = 0;					_controlInterface.GetTextureProperties(out filterMode, out textureWrapMode, out anisoLevel);					return filterMode;				}				else					return _textureFilterMode;			}			set			{				_textureFilterMode = value;				if (_controlInterface != null)					_controlInterface.SetTextureProperties(_textureFilterMode, _textureWrapMode, _textureAnisoLevel);			}		}		[FormerlySerializedAs("m_WrapMode")]		[SerializeField] TextureWrapMode _textureWrapMode = TextureWrapMode.Clamp;		public TextureWrapMode TextureWrapMode		{			get			{				if (_controlInterface != null)				{					FilterMode filterMode = FilterMode.Point;					TextureWrapMode textureWrapMode = TextureWrapMode.Repeat;					int anisoLevel = 0;					_controlInterface.GetTextureProperties(out filterMode, out textureWrapMode, out anisoLevel);					return textureWrapMode;				}				else					return _textureWrapMode;			}			set			{				_textureWrapMode = value;				if (_controlInterface != null)					_controlInterface.SetTextureProperties(_textureFilterMode, _textureWrapMode, _textureAnisoLevel);			}		}		[FormerlySerializedAs("m_AnisoLevel")]		[Range(0, 16)]		[SerializeField] int _textureAnisoLevel = 0;		public int TextureAnisoLevel		{			get			{				if (_controlInterface != null)				{					FilterMode filterMode = FilterMode.Point;					TextureWrapMode textureWrapMode = TextureWrapMode.Repeat;					int anisoLevel = 0;					_controlInterface.GetTextureProperties(out filterMode, out textureWrapMode, out anisoLevel);					return anisoLevel;				}				else					return _textureAnisoLevel;			}			set			{				_textureAnisoLevel = value;				if (_controlInterface != null)					_controlInterface.SetTextureProperties(_textureFilterMode, _textureWrapMode, _textureAnisoLevel);			}		}#if AVPRO_FEATURE_VIDEORESOLVE		[SerializeField] bool _useVideoResolve = false;		public bool UseVideoResolve { get { return _useVideoResolve; } set { _useVideoResolve = value; } }		[SerializeField] VideoResolveOptions _videoResolveOptions = VideoResolveOptions.Create();		public VideoResolveOptions VideoResolveOptions { get { return _videoResolveOptions; } set { _videoResolveOptions = value; } }		[SerializeField] VideoResolve _videoResolve = new VideoResolve();#endif		// Sideloaded subtitles		[FormerlySerializedAs("m_LoadSubtitles")]		[SerializeField] bool _sideloadSubtitles;		public bool SideloadSubtitles { get { return _sideloadSubtitles; } set { _sideloadSubtitles = value; } }		[SerializeField] MediaPath _subtitlePath;		public MediaPath SubtitlePath { get { return _subtitlePath; } set { _subtitlePath = value; } }		// Audio 360		[FormerlySerializedAs("m_AudioHeadTransform")]		[SerializeField] Transform _audioHeadTransform;		public Transform AudioHeadTransform { set { _audioHeadTransform = value; }	get { return _audioHeadTransform; } }		[FormerlySerializedAs("m_AudioFocusEnabled")]		[SerializeField] bool _audioFocusEnabled;		public bool AudioFocusEnabled { get { return _audioFocusEnabled; } set { _audioFocusEnabled = value; } }		[FormerlySerializedAs("m_AudioFocusTransform")]		[SerializeField] Transform _audioFocusTransform;		public Transform AudioFocusTransform { get { return _audioFocusTransform; } set { _audioFocusTransform = value; } }		[FormerlySerializedAs("m_AudioFocusWidthDegrees")]		[SerializeField, Range(40f, 120f)] float _audioFocusWidthDegrees = 90f;		public float AudioFocusWidthDegrees { get { return _audioFocusWidthDegrees; } set { _audioFocusWidthDegrees = value; } }		[FormerlySerializedAs("m_AudioFocusOffLevelDB")]		[SerializeField, Range(-24f, 0f)] float _audioFocusOffLevelDB = 0f;		public float AudioFocusOffLevelDB { get { return _audioFocusOffLevelDB; } set { _audioFocusOffLevelDB = value; } }		// Network		[SerializeField] HttpHeaderData _httpHeaders = new HttpHeaderData();		public HttpHeaderData HttpHeaders { get { return _httpHeaders; } set { _httpHeaders = value; } }		[SerializeField] KeyAuthData _keyAuth = new KeyAuthData();		public KeyAuthData KeyAuth { get { return _keyAuth; } set { _keyAuth = value; } }		// Events		[FormerlySerializedAs("m_events")]		[SerializeField] MediaPlayerEvent _events = null;		public MediaPlayerEvent Events		{			get			{				if (_events == null)				{					_events = new MediaPlayerEvent();				}				return _events;			}		}		[FormerlySerializedAs("m_eventMask")]		[SerializeField] int _eventMask = -1;		public int EventMask { get { return _eventMask; } set { _eventMask = value; } }		[SerializeField] bool _pauseMediaOnAppPause = true;		public bool PauseMediaOnAppPause { get { return _pauseMediaOnAppPause; } set { _pauseMediaOnAppPause = value; }	}		[SerializeField] bool _playMediaOnAppUnpause = true;		public bool PlayMediaOnAppUnpause { get { return _playMediaOnAppUnpause; } set { _playMediaOnAppUnpause = value; } }		// Misc options		[FormerlySerializedAs("m_Persistent")]		[SerializeField] bool _persistent = false;		public bool Persistent { get { return _persistent; } set { _persistent = value; } }		[FormerlySerializedAs("m_forceFileFormat")]		[SerializeField] FileFormat _forceFileFormat = FileFormat.Unknown;		public FileFormat ForceFileFormat { get { return _forceFileFormat; } set { _forceFileFormat = value; } }		// Interfaces		private BaseMediaPlayer _baseMediaPlayer;		private IMediaControl _controlInterface;		private ITextureProducer _textureInterface;		private IMediaInfo _infoInterface;		private IMediaPlayer _playerInterface;		private IMediaSubtitles _subtitlesInterface;		private IMediaCache _cacheInterface;		private IBufferedDisplay _bufferedDisplayInterface;		private IVideoTracks _videoTracksInterface;		private IAudioTracks _audioTracksInterface;		private ITextTracks _textTracksInterface;		private System.IDisposable _disposeInterface;		public virtual IMediaInfo Info { get { return _infoInterface; } }		public virtual IMediaControl Control { get { return _controlInterface; } }		public virtual IMediaPlayer Player { get { return _playerInterface; } }		public virtual ITextureProducer TextureProducer	{ get { return _textureInterface; }	}		public virtual IMediaSubtitles Subtitles {	get { return _subtitlesInterface; }	}		public virtual IVideoTracks VideoTracks {	get { return _videoTracksInterface; } }		public virtual IAudioTracks AudioTracks {	get { return _audioTracksInterface; } }		public virtual ITextTracks TextTracks {	get { return _textTracksInterface; } }		public virtual IMediaCache Cache { get { return _cacheInterface; } }		public virtual IBufferedDisplay BufferedDisplay { get { return _bufferedDisplayInterface; } }		// State		private bool _isMediaOpened = false;		public bool MediaOpened	{ get { return _isMediaOpened; }	}		private bool _autoPlayOnStartTriggered = false;		private bool _wasPlayingOnPause = false;		private Coroutine _renderingCoroutine = null;		// Global init		private static bool s_GlobalStartup = false;		private static bool s_TrialVersion = false;		// Subtitle state		private MediaPath _queueSubtitlePath;		private Coroutine _loadSubtitlesRoutine;		// Extract frame		private static Camera _dummyCamera = null;		public delegate void ProcessExtractedFrame(Texture2D extractedFrame);		/// <summary>		/// Methods		/// </summary>		#if UNITY_EDITOR		static MediaPlayer()		{			SetupEditorPlayPauseSupport();		}		#endif		void Awake()		{			if (_persistent)			{				// TODO: set "this.transform.root.gameObject" to also DontDestroyOnLoad?				DontDestroyOnLoad(this.gameObject);			}		}		protected void Initialise()		{			BaseMediaPlayer mediaPlayer = CreateMediaPlayer();			if (mediaPlayer != null)			{				// Set-up interface				_baseMediaPlayer = mediaPlayer;				_controlInterface = mediaPlayer;				_textureInterface = mediaPlayer;				_infoInterface = mediaPlayer;				_playerInterface = mediaPlayer;				_subtitlesInterface = mediaPlayer;				_videoTracksInterface = mediaPlayer;				_audioTracksInterface = mediaPlayer;				_textTracksInterface = mediaPlayer;				_disposeInterface = mediaPlayer;				_cacheInterface = mediaPlayer;				_bufferedDisplayInterface = mediaPlayer;				string nativePluginVersion = mediaPlayer.GetVersion();				string expectedNativePluginVersion = mediaPlayer.GetExpectedVersion();				// Check that the plugin version number is not too old				if (!nativePluginVersion.StartsWith(expectedNativePluginVersion))				{					Debug.LogError("[AVProVideo] Plugin version number " + nativePluginVersion + " doesn't match the expected version number " + expectedNativePluginVersion + ".  It looks like the plugin didn't upgrade correctly.  To resolve this please restart Unity and try to upgrade the package again.");				}				s_TrialVersion = nativePluginVersion.Contains("-trial");				if (!s_GlobalStartup)				{					Helper.LogInfo(string.Format("Initialising AVPro Video v{0} (native plugin v{1}) on {2}/{3} (MT {4}) on {5}", Helper.AVProVideoVersion, nativePluginVersion, SystemInfo.graphicsDeviceName, SystemInfo.graphicsDeviceVersion, SystemInfo.graphicsMultiThreaded, Application.platform));					#if AVPROVIDEO_BETA_SUPPORT_TIMESCALE					Debug.LogWarning("[AVProVideo] TimeScale support used.  This could affect performance when changing Time.timeScale or Time.captureFramerate.  This feature is useful for supporting video capture system that adjust time scale during capturing.");					#endif					s_GlobalStartup = true;				}			}		}		void Start()		{#if UNITY_WEBGL			_useResampler = false;#endif			if (_controlInterface == null)			{				if (Application.isPlaying)				{					Initialise();					if (_controlInterface != null)					{						if (_autoOpen)						{							OpenMedia(_autoPlayOnStart);							if (_sideloadSubtitles && _subtitlesInterface != null && _subtitlePath != null && !string.IsNullOrEmpty(_subtitlePath.Path))							{								EnableSubtitles(_subtitlePath);							}						}						StartRenderCoroutine();					}				}			}		}		public bool OpenMedia(MediaPath path, bool autoPlay = true)		{			return OpenMedia(path.PathType, path.Path, autoPlay);		}		public bool OpenMedia(MediaPathType pathType, string path, bool autoPlay = true)		{			_mediaSource = MediaSource.Path;			_mediaPath.Path = path;			_mediaPath.PathType = pathType;			return OpenMedia(autoPlay);		}		public bool OpenMedia(MediaReference mediaReference, bool autoPlay = true)		{			_mediaSource = MediaSource.Reference;			_mediaReference = mediaReference;			return OpenMedia(autoPlay);		}		public bool OpenMedia(bool autoPlay = true)		{			_autoPlayOnStart = autoPlay;			if (_controlInterface == null)			{				//_autoOpen = false;		 // If OpenVideoFromFile() is called before Start() then set _autoOpen to false so that it doesn't load the video a second time during Start()				Initialise();			}			return InternalOpenMedia();		}		private bool InternalOpenMedia()		{			bool result = false;			// Open the video file			if (_controlInterface != null)			{				CloseMedia();				_isMediaOpened = true;				_autoPlayOnStartTriggered = !_autoPlayOnStart;				_finishedFrameOpenCheck = true;				long fileOffset = GetPlatformFileOffset();	// TODO: replace this with MediaReference				MediaPath mediaPath = null;				MediaHints mediaHints = _fallbackMediaHints;				if (_mediaSource == MediaSource.Reference)				{					if (_mediaReference != null)					{						mediaPath = _mediaReference.GetCurrentPlatformMediaReference().MediaPath;						mediaHints = _mediaReference.GetCurrentPlatformMediaReference().Hints;						if (string.IsNullOrEmpty(mediaPath.Path))						{							mediaPath = null;						}					}					else					{						Debug.LogError("[AVProVideo] No MediaReference specified", this);					}				}				else if (_mediaSource == MediaSource.Path)				{					if (!string.IsNullOrEmpty(_mediaPath.Path))					{						mediaPath = _mediaPath;					}					else					{						Debug.LogError("[AVProVideo] No file path specified", this);					}				}				if (null != mediaPath)				{					string fullPath = mediaPath.GetResolvedFullPath();					string customHttpHeaders = null;					bool checkForFileExist = true;					bool isURL = fullPath.Contains("://");					if (isURL)					{						checkForFileExist = false;						customHttpHeaders = GetPlatformHttpHeadersAsString();					}#if (!UNITY_EDITOR && UNITY_ANDROID)					checkForFileExist = false;#endif					if (checkForFileExist && !System.IO.File.Exists(fullPath))					{						Debug.LogError("[AVProVideo] File not found: " + fullPath, this);					}					else					{						Helper.LogInfo(string.Format("Opening {0} (offset {1}) with API {2}", fullPath, fileOffset, GetPlatformVideoApiString()), this);#if UNITY_EDITOR_WIN || (!UNITY_EDITOR && UNITY_STANDALONE_WIN)						// NOTE: We don't need to call SetAudioChannelMode on Android,						// as it's set when the AndroidMediaPlayer object is created						if (_optionsWindows._audioMode == Windows.AudioOutput.FacebookAudio360)						{							_controlInterface.SetAudioChannelMode(_optionsWindows.audio360ChannelMode);						}						else						{							_controlInterface.SetAudioChannelMode(Audio360ChannelMode.INVALID);						}#elif (!UNITY_EDITOR && UNITY_WSA_10_0)						if (_optionsWindowsUWP.audioOutput == WindowsUWP.AudioOutput.FacebookAudio360)						{							_controlInterface.SetAudioChannelMode(_optionsWindowsUWP.audio360ChannelMode);						}						else						{							_controlInterface.SetAudioChannelMode(Audio360ChannelMode.INVALID);						}#endif						PlatformOptions options = GetCurrentPlatformOptions();						bool startWithHighestBitrate = false;						if (options != null)						{							startWithHighestBitrate = options.StartWithHighestBandwidth();						}						SetLoadOptions();						SetPlaybackOptions();						if (_controlInterface.OpenMedia(fullPath, fileOffset, customHttpHeaders, mediaHints, (int)_forceFileFormat, startWithHighestBitrate))						{							StartRenderCoroutine();							result = true;						}						else						{							Debug.LogError("[AVProVideo] Failed to open " + fullPath, this);						}					}				}				else				{					Debug.LogError("[AVProVideo] No file path specified", this);				}			}			return result;		}		private void SetLoadOptions()		{			// On some platforms we can update the loading options without having to recreate the player	#if !AVPROVIDEO_FORCE_NULL_MEDIAPLAYER		#if (UNITY_EDITOR_OSX && UNITY_IOS) || (!UNITY_EDITOR && UNITY_IOS)		#elif (UNITY_EDITOR_OSX && UNITY_TVOS) || (!UNITY_EDITOR && UNITY_TVOS)		#elif (UNITY_EDITOR_OSX || (!UNITY_EDITOR && UNITY_STANDALONE_OSX))		#elif (UNITY_EDITOR_WIN) || (!UNITY_EDITOR && UNITY_STANDALONE_WIN)		#elif (!UNITY_EDITOR && UNITY_WSA_10_0)		#elif (!UNITY_EDITOR && UNITY_ANDROID)		#elif (!UNITY_EDITOR && UNITY_WEBGL)			((WebGLMediaPlayer)_baseMediaPlayer).SetOptions(_optionsWebGL);		#endif	#endif			// Encryption support			PlatformOptions options = GetCurrentPlatformOptions();			if (options != null)			{				_controlInterface.SetKeyServerAuthToken(options.GetKeyServerAuthToken());				//_controlInterface.SetKeyServerURL(options.GetKeyServerURL());				_controlInterface.SetOverrideDecryptionKey(options.GetOverrideDecryptionKey());			}		}		private void SetPlaybackOptions()		{			// Set playback options			if (_controlInterface != null)			{				_controlInterface.SetLooping(_loop);				_controlInterface.SetPlaybackRate(_playbackRate);				_controlInterface.SetVolume(_audioVolume);				_controlInterface.SetBalance(_audioBalance);				#if !UNITY_EDITOR				_controlInterface.MuteAudio(_audioMuted);				#else				_controlInterface.MuteAudio(_audioMuted || UnityEditor.EditorUtility.audioMasterMute);				#endif				_controlInterface.SetTextureProperties(_textureFilterMode, _textureWrapMode, _textureAnisoLevel);			}		}		public void CloseMedia()		{			// Close the media file			if (_controlInterface != null)			{				if (_events != null && _isMediaOpened && _events.HasListeners() && IsHandleEvent(MediaPlayerEvent.EventType.Closing))				{					_events.Invoke(this, MediaPlayerEvent.EventType.Closing, ErrorCode.None);				}				_autoPlayOnStartTriggered = false;				_isMediaOpened = false;				ResetEvents();				if (_loadSubtitlesRoutine != null)				{					StopCoroutine(_loadSubtitlesRoutine);					_loadSubtitlesRoutine = null;				}				_controlInterface.CloseMedia();			}			if (_resampler != null)			{				_resampler.Reset();			}			StopRenderCoroutine();		}		public void RewindPrerollPause()		{			PlatformOptionsWindows.pauseOnPrerollComplete = true;			if (BufferedDisplay != null)			{				BufferedDisplay.SetBufferedDisplayOptions(true);			}			Rewind(false);			Play();		}		public virtual void Play()		{			if (_controlInterface != null && _controlInterface.CanPlay())			{				_controlInterface.Play();				// Mark this event as done because it's irrelevant once playback starts				_eventFired_ReadyToPlay = true;			}			else			{				// Can't play, perhaps it's still loading?  Queuing play using _autoPlayOnStart to play after loading				_autoPlayOnStart = true;				_autoPlayOnStartTriggered = false;			}		}		public virtual void Pause()		{			if (_controlInterface != null && _controlInterface.IsPlaying())			{				_controlInterface.Pause();			}			_wasPlayingOnPause = false;#if AVPROVIDEO_BETA_SUPPORT_TIMESCALE			_timeScaleIsControlling = false;#endif		}		public void Stop()		{			if (_controlInterface != null)			{				_controlInterface.Stop();			}#if AVPROVIDEO_BETA_SUPPORT_TIMESCALE			_timeScaleIsControlling = false;#endif		}		public void Rewind(bool pause)		{			if (_controlInterface != null)			{				if (pause)				{					Pause();				}				_controlInterface.Rewind();			}		}		public void SeekToLiveTime(double offset = 0.0)		{			if (_controlInterface != null)			{				double liveTime = _controlInterface.GetBufferedTimes().MaxTime;				if (liveTime > 0.0)				{					_controlInterface.Seek(liveTime - offset);				}			}		}#if UNITY_EDITOR && AVPROVIDEO_SUPPORT_LIVEEDITMODE		public bool EditorUpdate()		{			if (_playerInterface != null)			{				Update();				_playerInterface.BeginRender();				_playerInterface.Render();				return true;			}			return false;		}#endif		protected virtual void Update()		{			if (_controlInterface != null)			{				// Auto start the playback				if (_isMediaOpened && _autoPlayOnStart && !_autoPlayOnStartTriggered && _controlInterface.CanPlay())				{					_autoPlayOnStartTriggered = true;					Play();				}				if (Application.isPlaying)				{					if (_renderingCoroutine == null && _controlInterface.CanPlay())					{						StartRenderCoroutine();					}				}				if (_subtitlesInterface != null && _queueSubtitlePath != null && !string.IsNullOrEmpty(_queueSubtitlePath.Path))				{					EnableSubtitles(_queueSubtitlePath);					_queueSubtitlePath = null;				}#if AVPROVIDEO_BETA_SUPPORT_TIMESCALE				UpdateTimeScale();#endif				UpdateAudioHeadTransform();				UpdateAudioFocus();				_playerInterface.Update();				// Render (done in co-routine)				//_playerInterface.Render();				UpdateErrors();				UpdateEvents();				_playerInterface.EndUpdate();			}#if UNITY_EDITOR			CheckEditorAudioMute();#endif		}		private void LateUpdate()		{			UpdateResampler();			// RJT TODO: Better location?			if (_playerInterface != null)			{				_playerInterface.BeginRender();			}		}		private void UpdateResampler()		{#if !UNITY_WEBGL			if (_useResampler)			{				if (_resampler == null)				{					_resampler = new Resampler(this, gameObject.name, _resampleBufferSize, _resampleMode);				}			}#else			_useResampler = false;#endif			if (_resampler != null)			{				_resampler.Update();				_resampler.UpdateTimestamp();			}		}		void OnEnable()		{			if (_controlInterface != null && _wasPlayingOnPause)			{				_autoPlayOnStart = true;				_autoPlayOnStartTriggered = false;				_wasPlayingOnPause = false;			}			if(_playerInterface != null)			{				_playerInterface.OnEnable();				StartRenderCoroutine();			}		}		void OnDisable()		{			if (_controlInterface != null)			{				if (_controlInterface.IsPlaying())				{					Pause();					// Force an update to ensure the player state is synchronised with the plugin					Update();					// Needs to follow Pause() otherwise it will be reset.					_wasPlayingOnPause = true;				}			}			StopRenderCoroutine();		}		protected virtual void OnDestroy()		{			CloseMedia();			_baseMediaPlayer = null;			_controlInterface = null;			_textureInterface = null;			_infoInterface = null;			_playerInterface = null;			_subtitlesInterface = null;			_cacheInterface = null;			_bufferedDisplayInterface = null;			_videoTracksInterface = null;			_audioTracksInterface = null;			_textTracksInterface = null;			if (_disposeInterface != null)			{				_disposeInterface.Dispose();				_disposeInterface = null;			}			if (_resampler != null)			{				_resampler.Release();				_resampler = null;			}			// TODO: possible bug if MediaPlayers are created and destroyed manually (instantiated), OnApplicationQuit won't be called!		}		public void ForceDispose()		{			OnDisable();			OnDestroy();		}#if UNITY_EDITOR		public static void EditorAllPlayersDispose()		{			AllPlayersDispose();		}#endif		private static void AllPlayersDispose()		{			// Clean up any open media players			MediaPlayer[] players = Resources.FindObjectsOfTypeAll<MediaPlayer>();			if (players != null && players.Length > 0)			{				for (int i = 0; i < players.Length; i++)				{					players[i].ForceDispose();				}			}		}		void OnApplicationQuit()		{			if (s_GlobalStartup)			{				Helper.LogInfo("Shutdown");				AllPlayersDispose();#if UNITY_EDITOR	#if UNITY_EDITOR_WIN				WindowsMediaPlayer.DeinitPlatform();				WindowsRtMediaPlayer.DeinitPlatform();	#endif#else	#if (UNITY_STANDALONE_WIN)				WindowsMediaPlayer.DeinitPlatform();				WindowsRtMediaPlayer.DeinitPlatform();	#elif (UNITY_ANDROID)		#if false				AndroidMediaPlayer.DeinitPlatform();		#endif	#endif#endif				s_GlobalStartup = false;			}		}#region Rendering Coroutine		private void StartRenderCoroutine()		{			if (_renderingCoroutine == null)			{				// Use the method instead of the method name string to prevent garbage				_renderingCoroutine = StartCoroutine(FinalRenderCapture());			}		}		private void StopRenderCoroutine()		{			if (_renderingCoroutine != null)			{				StopCoroutine(_renderingCoroutine);				_renderingCoroutine = null;			}		}		private IEnumerator FinalRenderCapture()		{			// Preallocate the YieldInstruction to prevent garbage			YieldInstruction wait = new WaitForEndOfFrame();			while (Application.isPlaying)			{				// NOTE: in editor, if the game view isn't visible then WaitForEndOfFrame will never complete				yield return wait;				if (this.enabled)				{					if (_playerInterface != null)					{						_playerInterface.Render();					}				}			}		}#endregion // Rendering Coroutine#region Platform and Path		public static Platform GetPlatform()		{			Platform result = Platform.Unknown;			// Setup for running in the editor (Either OSX, Windows or Linux)#if UNITY_EDITOR#if (UNITY_EDITOR_OSX && UNITY_EDITOR_64)			result = Platform.macOS;#elif UNITY_EDITOR_WIN			result = Platform.Windows;#endif#else			// Setup for running builds#if (UNITY_STANDALONE_WIN)			result = Platform.Windows;#elif (UNITY_STANDALONE_OSX)			result = Platform.macOS;#elif (UNITY_IPHONE || UNITY_IOS)			result = Platform.iOS;#elif (UNITY_TVOS)			result = Platform.tvOS;#elif (UNITY_VISIONOS)			result = Platform.visionOS;#elif (UNITY_ANDROID)			result = Platform.Android;#elif (UNITY_WSA_10_0)			result = Platform.WindowsUWP;#elif (UNITY_WEBGL)			result = Platform.WebGL;#endif#endif			return result;		}		public PlatformOptions GetCurrentPlatformOptions()		{			PlatformOptions result = null;#if UNITY_EDITOR#if (UNITY_EDITOR_OSX && UNITY_EDITOR_64)			result = _options_macOS;#elif UNITY_EDITOR_WIN			result = _optionsWindows;#endif#else	// Setup for running builds#if (UNITY_STANDALONE_WIN)			result = _optionsWindows;#elif (UNITY_STANDALONE_OSX)			result = _options_macOS;#elif (UNITY_IPHONE || UNITY_IOS)			result = _options_iOS;#elif (UNITY_TVOS)			result = _options_tvOS;#elif (UNITY_VISIONOS)			result = _options_visionOS;#elif (UNITY_ANDROID)			result = _optionsAndroid;#elif (UNITY_WSA_10_0)			result = _optionsWindowsUWP;#elif (UNITY_WEBGL)			result = _optionsWebGL;#endif#endif			return result;		}#if UNITY_EDITOR		public PlatformOptions GetPlatformOptions(Platform platform)		{			PlatformOptions result = null;			switch (platform)			{				case Platform.Windows:					result = _optionsWindows;					break;				case Platform.macOS:					result = _options_macOS;					break;				case Platform.Android:					result = _optionsAndroid;					break;				case Platform.iOS:					result = _options_iOS;					break;				case Platform.tvOS:					result = _options_tvOS;					break;				case Platform.visionOS:					result = _options_visionOS;					break;				case Platform.WindowsUWP:					result = _optionsWindowsUWP;					break;				case Platform.WebGL:					result = _optionsWebGL;					break;			}			return result;		}		public static string GetPlatformOptionsVariable(Platform platform)		{			string result = string.Empty;			switch (platform)			{				case Platform.Windows:					result = "_optionsWindows";					break;				case Platform.macOS:					result = "_options_macOS";					break;				case Platform.iOS:					result = "_options_iOS";					break;				case Platform.tvOS:					result = "_options_tvOS";					break;				case Platform.visionOS:					result = "_options_visionOS";					break;				case Platform.Android:					result = "_optionsAndroid";					break;				case Platform.WindowsUWP:					result = "_optionsWindowsUWP";					break;				case Platform.WebGL:					result = "_optionsWebGL";					break;			}			return result;		}#endif		private string GetPlatformVideoApiString()		{			string result = string.Empty;#if UNITY_EDITOR	#if UNITY_EDITOR_OSX	#elif UNITY_EDITOR_WIN			result = _optionsWindows.videoApi.ToString();	#elif UNITY_EDITOR_LINUX	#endif#else	#if UNITY_STANDALONE_WIN			result = _optionsWindows.videoApi.ToString();	#elif UNITY_WSA_10_0			result = _optionsWindowsUWP.videoApi.ToString();	#elif UNITY_ANDROID			result = _optionsAndroid.videoApi.ToString();	#endif#endif			return result;		}		private long GetPlatformFileOffset()		{			long result = 0;#if UNITY_EDITOR	#if UNITY_EDITOR_OSX	#elif UNITY_EDITOR_WIN	#elif UNITY_EDITOR_LINUX	#endif#else	#if UNITY_ANDROID			result = _optionsAndroid.fileOffset;	#endif#endif			return result;		}		private string GetPlatformHttpHeadersAsString()		{			string result = null;#if UNITY_EDITOR	#if UNITY_EDITOR_OSX			result = _options_macOS.httpHeaders.ToValidatedString();	#elif UNITY_EDITOR_WIN			result = _optionsWindows.httpHeaders.ToValidatedString();	#elif UNITY_EDITOR_LINUX	#endif#else	#if UNITY_STANDALONE_OSX			result = _options_macOS.httpHeaders.ToValidatedString();	#elif UNITY_STANDALONE_WIN			result = _optionsWindows.httpHeaders.ToValidatedString();	#elif UNITY_WSA_10_0			result = _optionsWindowsUWP.httpHeaders.ToValidatedString();	#elif UNITY_IOS || UNITY_IPHONE			result = _options_iOS.httpHeaders.ToValidatedString();	#elif UNITY_TVOS			result = _options_tvOS.httpHeaders.ToValidatedString();	#elif UNITY_VISIONOS			result = _options_visionOS.httpHeaders.ToValidatedString();	#elif UNITY_ANDROID			result = _optionsAndroid.httpHeaders.ToValidatedString();	#elif UNITY_WEBGL	#endif#endif			if (!string.IsNullOrEmpty(result))			{				result = result.Trim();			}			string globalHeaders = _httpHeaders.ToValidatedString();			if (!string.IsNullOrEmpty(globalHeaders))			{				result += globalHeaders;				result = result.Trim();			}			return result;		}		private string GetResolvedFilePath(string filePath, MediaPathType fileLocation)		{			string result = string.Empty;			result = Helper.GetFilePath(filePath, fileLocation);			#if (UNITY_EDITOR_WIN || (!UNITY_EDITOR && UNITY_STANDALONE_WIN))			if (result.Length > 200 && !result.Contains("://"))			{				result = Helper.ConvertLongPathToShortDOS83Path(result);			}			#endif			return result;		}#endregion // Platform and Path#region Create MediaPlayers		#if (UNITY_EDITOR_WIN) || (!UNITY_EDITOR && UNITY_STANDALONE_WIN)		private static BaseMediaPlayer CreateMediaPlayer(OptionsWindows options)		{			BaseMediaPlayer result = null;			if (options.videoApi == Windows.VideoApi.WinRT)			{				if (WindowsRtMediaPlayer.InitialisePlatform())				{					result = new WindowsRtMediaPlayer(options);				}				else				{					Debug.LogWarning(string.Format("[AVProVideo] Failed to initialise WinRT API - platform {0} may not support it.  Trying another video API...", SystemInfo.operatingSystem));				}			}			if (result == null)			{				if (WindowsMediaPlayer.InitialisePlatform())				{					result = new WindowsMediaPlayer(options);				}			}			return result;		}		#endif		#if (!UNITY_EDITOR && UNITY_WSA_10_0)		private static BaseMediaPlayer CreateMediaPlayer(OptionsWindowsUWP options)		{			BaseMediaPlayer result = null;			if (options.videoApi == WindowsUWP.VideoApi.WinRT)			{				if (WindowsRtMediaPlayer.InitialisePlatform())				{					result = new WindowsRtMediaPlayer(options);				}				else				{					Debug.LogWarning(string.Format("[AVProVideo] Failed to initialise WinRT API - platform {0} may not support it.  Trying another video API...", SystemInfo.operatingSystem));				}			}			if (result == null)			{				if (WindowsMediaPlayer.InitialisePlatform())				{					result = new WindowsMediaPlayer(options);				}			}			return result;		}		#endif#if (!UNITY_EDITOR && UNITY_ANDROID)		private static BaseMediaPlayer CreateMediaPlayer(OptionsAndroid options)		{			PlatformMediaPlayer mediaPlayer = new PlatformMediaPlayer(options);			return mediaPlayer;		}#endif#if (UNITY_EDITOR_OSX) || (!UNITY_EDITOR && (UNITY_STANDALONE_OSX || UNITY_IPHONE || UNITY_IOS || UNITY_TVOS || UNITY_VISIONOS || UNITY_ANDROID))		private static BaseMediaPlayer CreateMediaPlayer(OptionsApple options)		{			PlatformMediaPlayer mediaPlayer = new PlatformMediaPlayer(options);			return mediaPlayer;		}#endif#if (!UNITY_EDITOR && UNITY_WEBGL)		private static BaseMediaPlayer CreateMediaPlayer(OptionsWebGL options)		{			BaseMediaPlayer result = null;			if (WebGLMediaPlayer.InitialisePlatform())			{				result = new WebGLMediaPlayer(options);			}			return result;		}#endif		private static BaseMediaPlayer CreateMediaPlayerNull()		{			return new NullMediaPlayer();		}		public virtual BaseMediaPlayer CreateMediaPlayer()		{			BaseMediaPlayer mediaPlayer = null;	#if !AVPROVIDEO_FORCE_NULL_MEDIAPLAYER		#if (UNITY_EDITOR_OSX && UNITY_IOS) || (!UNITY_EDITOR && UNITY_IOS)			mediaPlayer = CreateMediaPlayer(_options_iOS);		#elif (UNITY_EDITOR_OSX && UNITY_TVOS) || (!UNITY_EDITOR && UNITY_TVOS)			mediaPlayer = CreateMediaPlayer(_options_tvOS);		#elif (UNITY_EDITOR_OSX && UNITY_VISIONOS) || (!UNITY_EDITOR && UNITY_VISIONOS)			mediaPlayer = CreateMediaPlayer(_options_visionOS);		#elif (UNITY_EDITOR_OSX || (!UNITY_EDITOR && UNITY_STANDALONE_OSX))			mediaPlayer = CreateMediaPlayer(_options_macOS);		#elif (UNITY_EDITOR_WIN) || (!UNITY_EDITOR && UNITY_STANDALONE_WIN)			mediaPlayer = CreateMediaPlayer(_optionsWindows);		#elif (!UNITY_EDITOR && UNITY_WSA_10_0)			mediaPlayer = CreateMediaPlayer(_optionsWindowsUWP);		#elif (!UNITY_EDITOR && UNITY_ANDROID)			mediaPlayer = CreateMediaPlayer(_optionsAndroid);		#elif (!UNITY_EDITOR && UNITY_WEBGL)			mediaPlayer = CreateMediaPlayer(_optionsWebGL);		#endif	#endif			// Fallback			if (mediaPlayer == null)			{				Debug.LogError(string.Format("[AVProVideo] Not supported on this platform {0} {1} {2} {3}.  Using null media player!", Application.platform, SystemInfo.deviceModel, SystemInfo.processorType, SystemInfo.operatingSystem));				mediaPlayer = CreateMediaPlayerNull();			}			return mediaPlayer;		}#endregion // Create MediaPlayers		private void UpdateAudioFocus()		{			// TODO: we could use gizmos to draw the focus area			_controlInterface.SetAudioFocusEnabled(_audioFocusEnabled);			_controlInterface.SetAudioFocusProperties(_audioFocusOffLevelDB, _audioFocusWidthDegrees);			_controlInterface.SetAudioFocusRotation(_audioFocusTransform == null ? Quaternion.identity : _audioFocusTransform.rotation);		}		private void UpdateAudioHeadTransform()		{			if (_audioHeadTransform != null)			{				_controlInterface.SetAudioHeadRotation(_audioHeadTransform.rotation);			}			else			{				_controlInterface.ResetAudioHeadRotation();			}		}		private void UpdateErrors()		{			ErrorCode errorCode = _controlInterface.GetLastError();			if (ErrorCode.None != errorCode)			{				Debug.LogError("[AVProVideo] Error: " + Helper.GetErrorMessage(errorCode));				// Display additional information for load failures				if (ErrorCode.LoadFailed == errorCode)				{					#if !UNITY_EDITOR && UNITY_ANDROID					// TODO: Update this to handle case where media is MediaReference					if (_mediaPath.Path.ToLower().Contains("http://"))					{						Debug.LogError("Android 8 and above require HTTPS by default, change to HTTPS or enable ClearText in the AndroidManifest.xml");					}					#endif				}				if (_events != null && _events.HasListeners() && IsHandleEvent(MediaPlayerEvent.EventType.Error))				{					_events.Invoke(this, MediaPlayerEvent.EventType.Error, errorCode);				}			}		}		public bool IsUsingAndroidOESPath()		{			// Android OES mode is not available in the trial//			bool result = (PlatformOptionsAndroid.useFastOesPath && !s_TrialVersion);			bool result = ((PlatformOptionsAndroid.textureFormat == MediaPlayer.OptionsAndroid.TextureFormat.YCbCr420_OES) && !s_TrialVersion);			#if (UNITY_EDITOR || !UNITY_ANDROID)			result = false;			#endif			return result;		}#region Save Frame To PNG#if UNITY_EDITOR || (!UNITY_EDITOR && (UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX))		[ContextMenu("Save Frame To PNG")]		public void SaveFrameToPng()		{			Texture2D frame = ExtractFrame(null);			if (frame != null)			{				byte[] imageBytes = frame.EncodeToPNG();				if (imageBytes != null)				{					string timecode = Mathf.FloorToInt((float)(Control.GetCurrentTime() * 1000.0)).ToString("D8");					System.IO.File.WriteAllBytes("frame-" + timecode + ".png", imageBytes);				}				Destroy(frame);			}		}		[ContextMenu("Save Frame To EXR")]		public void SaveFrameToExr()		{			Texture frame = (Texture)TextureProducer.GetTexture(0);			if (frame != null)			{				RenderTexture rt = new RenderTexture(frame.width, frame.height, 0, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear);				rt.Create();				Graphics.Blit(frame, rt);				Texture2D frameRead = new Texture2D(frame.width, frame.height, TextureFormat.RGBAFloat, false, true);				RenderTexture.active = rt;				frameRead.ReadPixels(new Rect(0f, 0f, frame.width, frame.height), 0, 0, false);				frameRead.Apply(false, false);				RenderTexture.active = null;				byte[] imageBytes = frameRead.EncodeToEXR();				if (imageBytes != null)				{					string timecode = Mathf.FloorToInt((float)(Control.GetCurrentTime() * 1000.0)).ToString("D8");					System.IO.File.WriteAllBytes("frame-" + timecode + ".exr", imageBytes);				}				Destroy(frame);				Texture2D.Destroy(frameRead);				RenderTexture.Destroy(rt);			}		}#endif#endregion // Save Frame To PNG	}}
 |