| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775 | using UnityEngine;using System;using System.Collections.Generic;//-----------------------------------------------------------------------------// Copyright 2015-2022 RenderHeads Ltd.  All rights reserved.//-----------------------------------------------------------------------------namespace RenderHeads.Media.AVProVideo{	public partial class MediaPlayer : MonoBehaviour	{#region PlatformOptions		[System.Serializable]		public class PlatformOptions		{			public enum TextureFormat : int			{				BGRA,				YCbCr420_OES,			}			public enum Resolution : int			{				NoPreference,				_480p,				_720p,				_1080p,				_1440p,				_2160p,				Custom			}			public enum AudioMode : int			{				SystemDirect,				Unity,				SystemDirectWithCapture,				FacebookAudio360,			}			public enum BitRateUnits : int			{				bps,				Kbps,				Mbps			}			public virtual bool IsModified()			{				return (httpHeaders.IsModified()				|| keyAuth.IsModified()				);			}			public virtual bool HasChanged()			{				return false;			}			public virtual void ClearChanges()			{			}			public HttpHeaderData httpHeaders = new HttpHeaderData();			public KeyAuthData keyAuth = new KeyAuthData();			// Decryption support			public virtual string GetKeyServerAuthToken() { return keyAuth.keyServerToken; }			//public virtual string GetKeyServerURL() { return null; }			public virtual byte[] GetOverrideDecryptionKey() { return keyAuth.overrideDecryptionKey; }			public virtual bool StartWithHighestBandwidth() { return false; }		}		[System.Serializable]		public class OptionsWindows : PlatformOptions, ISerializationCallbackReceiver		{			public Windows.VideoApi videoApi = Windows.VideoApi.MediaFoundation;			public bool useHardwareDecoding = true;			public bool useRendererSync = true;			public bool useTextureMips = false;			public bool use10BitTextures = false;			public bool hintAlphaChannel = false;			public bool useLowLatency = false;			public bool useCustomMovParser = false;			public bool useHapNotchLC = false;			public bool useStereoDetection = true;			public bool useTextTrackSupport = true;			public bool useFacebookAudio360Support = true;			public bool useAudioDelay = false;			public BufferedFrameSelectionMode bufferedFrameSelection = BufferedFrameSelectionMode.None;			public bool pauseOnPrerollComplete = false;			public string forceAudioOutputDeviceName = string.Empty;			public List<string> preferredFilters = new List<string>();			public Windows.AudioOutput _audioMode = Windows.AudioOutput.System;			public Audio360ChannelMode audio360ChannelMode = Audio360ChannelMode.TBE_8_2;			/// WinRT only			public bool startWithHighestBitrate = false;			/// WinRT only			public bool useLowLiveLatency = false;			/// Hap & NotchLC only			[Range(1, 16)]			public int parallelFrameCount = 3;			/// Hap & NotchLC only			[Range(1, 16)]			public int prerollFrameCount = 4;			public override bool IsModified()			{				return (base.IsModified()				|| !useHardwareDecoding				|| !useRendererSync				|| useTextureMips				|| use10BitTextures				|| hintAlphaChannel				|| useLowLatency				|| useCustomMovParser				|| useHapNotchLC				|| !useStereoDetection				|| !useTextTrackSupport				|| !useFacebookAudio360Support				|| useAudioDelay				|| pauseOnPrerollComplete				|| bufferedFrameSelection != BufferedFrameSelectionMode.None				|| videoApi != Windows.VideoApi.MediaFoundation				|| _audioMode != Windows.AudioOutput.System				|| audio360ChannelMode != Audio360ChannelMode.TBE_8_2				|| !string.IsNullOrEmpty(forceAudioOutputDeviceName)				|| preferredFilters.Count != 0				|| startWithHighestBitrate				|| useLowLiveLatency				|| parallelFrameCount != 3				|| prerollFrameCount != 4				);			}			public override bool StartWithHighestBandwidth() { return startWithHighestBitrate; }			#region Upgrade from Version 1.x			[SerializeField, HideInInspector]			private bool useUnityAudio = false;			[SerializeField, HideInInspector]			private bool enableAudio360 = false;			void ISerializationCallbackReceiver.OnBeforeSerialize() { }			void ISerializationCallbackReceiver.OnAfterDeserialize()			{				if (useUnityAudio && _audioMode == Windows.AudioOutput.System)				{					_audioMode = Windows.AudioOutput.Unity;					useUnityAudio = false;				}				if (enableAudio360 && _audioMode == Windows.AudioOutput.System)				{					_audioMode = Windows.AudioOutput.FacebookAudio360;					enableAudio360 = false;				}			}			#endregion	// Upgrade from Version 1.x		}		[System.Serializable]		public class OptionsWindowsUWP : PlatformOptions		{			public bool useHardwareDecoding = true;			public bool useRendererSync = true;			public bool useTextureMips = false;			public bool use10BitTextures = false;			public bool hintOutput10Bit = false;			public bool useLowLatency = false;			public WindowsUWP.VideoApi videoApi = WindowsUWP.VideoApi.WinRT;			public WindowsUWP.AudioOutput audioOutput = WindowsUWP.AudioOutput.System;			public Audio360ChannelMode audio360ChannelMode = Audio360ChannelMode.TBE_8_2;			/// WinRT only			public bool startWithHighestBitrate = false;			/// WinRT only			public bool useLowLiveLatency = false;			public override bool IsModified()			{				return (base.IsModified()				|| !useHardwareDecoding				|| !useRendererSync				|| useTextureMips				|| use10BitTextures				|| useLowLatency				|| audioOutput != WindowsUWP.AudioOutput.System				|| (audio360ChannelMode != Audio360ChannelMode.TBE_8_2)				|| videoApi != WindowsUWP.VideoApi.WinRT				|| startWithHighestBitrate				|| useLowLiveLatency				);			}			public override bool StartWithHighestBandwidth() { return startWithHighestBitrate; }		}		[System.Serializable]		public class OptionsApple: PlatformOptions		{			[Flags]			public enum Flags: int			{				// Common				None = 0,				GenerateMipMaps = 1 << 0,				// iOS & macOS				AllowExternalPlayback = 1 <<  8,				PlayWithoutBuffering  = 1 <<  9,				UseSinglePlayerItem   = 1 << 10,				// iOS				ResumeMediaPlaybackAfterAudioSessionRouteChange = 1 << 16,			}			private readonly TextureFormat DefaultTextureFormat;			private readonly Flags DefaultFlags;			public TextureFormat textureFormat;						private AudioMode _previousAudioMode = AudioMode.SystemDirect;			public AudioMode previousAudioMode			{				get { return _previousAudioMode; }			}			[SerializeField]			private AudioMode _audioMode;			public AudioMode audioMode			{				get { return _audioMode; }				set				{					if (_audioMode != value)					{						_previousAudioMode = _audioMode;						_audioMode = value;						_changed |= ChangeFlags.AudioMode;					}				}			}			[SerializeField]			private Flags _flags;			public Flags flags			{				get { return _flags; }				set				{					Flags changed = _flags ^ value;					if (changed != 0)					{						if ((changed & Flags.PlayWithoutBuffering) == Flags.PlayWithoutBuffering)						{							_changed |= ChangeFlags.PlayWithoutBuffering;						}						if ((changed & Flags.ResumeMediaPlaybackAfterAudioSessionRouteChange) == Flags.ResumeMediaPlaybackAfterAudioSessionRouteChange)						{							_changed |= ChangeFlags.ResumeMediaPlaybackAfterAudioSessionRouteChange;						}						_flags = value;					}				}			}			public float maximumPlaybackRate = 2.0f;			[Flags]			public enum ChangeFlags: int			{				None                                            = 0,				PreferredPeakBitRate                            = 1 << 1,				PreferredForwardBufferDuration                  = 1 << 2,				PlayWithoutBuffering                            = 1 << 3,				PreferredMaximumResolution                      = 1 << 4,				AudioMode                                       = 1 << 5,				ResumeMediaPlaybackAfterAudioSessionRouteChange = 1 << 6,				All = -1			}			private ChangeFlags _changed = ChangeFlags.None;			[SerializeField]			private float _preferredPeakBitRate = 0.0f;			public float preferredPeakBitRate			{				get { return _preferredPeakBitRate; }				set				{					if (_preferredPeakBitRate != value)					{						_changed |= ChangeFlags.PreferredPeakBitRate;						_preferredPeakBitRate = value;					}				}			}			[SerializeField]			private BitRateUnits _preferredPeakBitRateUnits = BitRateUnits.Kbps;			public BitRateUnits preferredPeakBitRateUnits			{				get { return _preferredPeakBitRateUnits; }				set				{					if (_preferredPeakBitRateUnits != value)					{						_changed |= ChangeFlags.PreferredPeakBitRate;						_preferredPeakBitRateUnits = value;					}				}			}			[SerializeField]			private double _preferredForwardBufferDuration = 0.0;			public double preferredForwardBufferDuration			{				get				{					return _preferredForwardBufferDuration;				}				set				{					if (_preferredForwardBufferDuration != value)					{						_changed |= ChangeFlags.PreferredForwardBufferDuration;						_preferredForwardBufferDuration = value;					}				}			}			[SerializeField]			private Resolution _preferredMaximumResolution = Resolution.NoPreference;			public Resolution preferredMaximumResolution			{				get				{					return _preferredMaximumResolution;				}				set				{					if (_preferredMaximumResolution != value)					{						_changed |= ChangeFlags.PreferredMaximumResolution;						_preferredMaximumResolution = value;					}				}			}#if UNITY_2017_2_OR_NEWER			[SerializeField]			private Vector2Int _customPreferredMaximumResolution = Vector2Int.zero;			public Vector2Int customPreferredMaximumResolution			{				get				{					return _customPreferredMaximumResolution;				}				set				{					if (_customPreferredMaximumResolution != value)					{						_changed |= ChangeFlags.PreferredMaximumResolution;						_customPreferredMaximumResolution = value;					}				}			}#endif			private static double BitRateInBitsPerSecond(float value, BitRateUnits units)			{				switch (units)				{					case BitRateUnits.bps:						return (double)value;					case BitRateUnits.Kbps:						return (double)value * 1000.0;					case BitRateUnits.Mbps:						return (double)value * 1000000.0;					default:						return 0.0;				}			}			public double GetPreferredPeakBitRateInBitsPerSecond()			{				return BitRateInBitsPerSecond(preferredPeakBitRate, preferredPeakBitRateUnits);			}			public OptionsApple(TextureFormat defaultTextureFormat, Flags defaultFlags)			{				DefaultTextureFormat = defaultTextureFormat;				DefaultFlags = defaultFlags;				textureFormat = defaultTextureFormat;				audioMode = AudioMode.SystemDirect;				flags = defaultFlags;			}			public override bool IsModified()			{				return base.IsModified()					|| textureFormat != DefaultTextureFormat					|| audioMode != AudioMode.SystemDirect					|| flags != DefaultFlags					|| preferredMaximumResolution != Resolution.NoPreference					|| preferredPeakBitRate != 0.0f					|| preferredForwardBufferDuration != 0.0;			}			public override bool HasChanged()			{				return HasChanged(ChangeFlags.All);			}			public bool HasChanged(ChangeFlags flags)			{				return (_changed & flags) != ChangeFlags.None;			}			public override void ClearChanges()			{				_changed = ChangeFlags.None;			}		}		[System.Serializable]		public class OptionsAndroid : PlatformOptions, ISerializationCallbackReceiver		{			[Flags]			public enum ChangeFlags : int			{				None = 0,				PreferredPeakBitRate			= 1 << 1,				PreferredMaximumResolution		= 1 << 2,				PreferredCustomResolution		= 1 << 3,				AudioMode						= 1 << 4,				All = -1			}			private ChangeFlags _changed = ChangeFlags.None;			private readonly TextureFormat DefaultTextureFormat;			public TextureFormat textureFormat;			private AudioMode _previousAudioMode = AudioMode.SystemDirect;			public AudioMode previousAudioMode			{				get { return _previousAudioMode; }			}			[SerializeField]			private AudioMode _audioMode;			public AudioMode audioMode			{				get { return _audioMode; }				set				{					if (_audioMode != value)					{						_previousAudioMode = _audioMode;						_audioMode = value;						_changed |= ChangeFlags.AudioMode;					}				}			}			[SerializeField]			private Resolution _preferredMaximumResolution = Resolution.NoPreference;			public Resolution preferredMaximumResolution			{				get { return _preferredMaximumResolution; }				set				{					if (_preferredMaximumResolution != value)					{						_changed |= ChangeFlags.PreferredMaximumResolution;						_preferredMaximumResolution = value;					}				}			}#if UNITY_2017_2_OR_NEWER			[SerializeField]			private Vector2Int _customPreferredMaximumResolution = Vector2Int.zero;			public Vector2Int customPreferredMaximumResolution			{				get { return _customPreferredMaximumResolution; }				set				{					if (_customPreferredMaximumResolution != value)					{						_changed |= ChangeFlags.PreferredCustomResolution;						_customPreferredMaximumResolution = value;					}				}			}#endif			[SerializeField]			private float _preferredPeakBitRate = 0.0f;			public float preferredPeakBitRate			{				get { return _preferredPeakBitRate; }				set				{					if (_preferredPeakBitRate != value)					{						_changed |= ChangeFlags.PreferredPeakBitRate;						_preferredPeakBitRate = value;					}				}			}			[SerializeField]			private BitRateUnits _preferredPeakBitRateUnits = BitRateUnits.Kbps;			public BitRateUnits preferredPeakBitRateUnits			{				get { return _preferredPeakBitRateUnits; }				set				{					if (_preferredPeakBitRateUnits != value)					{						_changed |= ChangeFlags.PreferredPeakBitRate;						_preferredPeakBitRateUnits = value;					}				}			}			public Android.VideoApi videoApi = Android.VideoApi.ExoPlayer;//			public bool showPosterFrame = false;			public Audio360ChannelMode audio360ChannelMode = Audio360ChannelMode.TBE_8_2;			public int audio360LatencyMS = 0;			public bool preferSoftwareDecoder = false;			public bool forceRtpTCP = false;			public bool forceEnableMediaCodecAsynchronousQueueing = false;			[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 = 0;			public bool startWithHighestBitrate = false;			public int minBufferMs							= Android.Default_MinBufferTimeMs;			public int maxBufferMs							= Android.Default_MaxBufferTimeMs;			public int bufferForPlaybackMs					= Android.Default_BufferForPlaybackMs;			public int bufferForPlaybackAfterRebufferMs		= Android.Default_BufferForPlaybackAfterRebufferMs;			[Obsolete("useFastOesPath is deprecated and replaced with TextureFormat")]			public bool useFastOesPath;			[Obsolete("audioOutput is deprecated and replaced with audioMode")]			public int audioOutput;			[Obsolete("blitTextureFiltering is deprecated and its functionality has been removed")]			public int blitTextureFiltering;			[Obsolete("forceEnableMediaCodecAsyncQueueing is deprecated and replaced with forceEnableMediaCodecAsynchronousQueueing")]			public bool forceEnableMediaCodecAsyncQueueing;			public override bool IsModified()			{				return (base.IsModified()					|| (fileOffset != 0)					|| textureFormat != DefaultTextureFormat					|| audioMode != AudioMode.SystemDirect//					|| showPosterFrame					|| (videoApi != Android.VideoApi.ExoPlayer)					|| (audio360ChannelMode != Audio360ChannelMode.TBE_8_2)					|| (audio360LatencyMS != 0 )					|| preferSoftwareDecoder					|| forceRtpTCP					|| forceEnableMediaCodecAsynchronousQueueing					|| startWithHighestBitrate					|| (minBufferMs != Android.Default_MinBufferTimeMs)					|| (maxBufferMs != Android.Default_MaxBufferTimeMs)					|| (bufferForPlaybackMs != Android.Default_BufferForPlaybackMs)					|| (bufferForPlaybackAfterRebufferMs != Android.Default_BufferForPlaybackAfterRebufferMs)					|| (preferredMaximumResolution != Resolution.NoPreference)					|| (preferredPeakBitRate != 0.0f)				);			}			private static double BitRateInBitsPerSecond(float value, BitRateUnits units)			{				switch (units)				{					case BitRateUnits.bps:						return (double)value;					case BitRateUnits.Kbps:						return (double)value * 1000.0;					case BitRateUnits.Mbps:						return (double)value * 1000000.0;					default:						return 0.0;				}			}			public double GetPreferredPeakBitRateInBitsPerSecond()			{				_changed &= ~ChangeFlags.PreferredPeakBitRate;				return BitRateInBitsPerSecond(preferredPeakBitRate, preferredPeakBitRateUnits);			}			public override bool StartWithHighestBandwidth()			{				return startWithHighestBitrate;			}			public override bool HasChanged()			{				return HasChanged(ChangeFlags.All, false);			}						public bool HasChanged(ChangeFlags flags, bool bClearFlags = false)			{				bool bReturn = ((_changed & flags) != ChangeFlags.None);				if (bClearFlags)				{					_changed = ChangeFlags.None;				}				return bReturn;			}			public override void ClearChanges()			{				_changed = ChangeFlags.None;			}			#region Upgrade from Version 1.x			[SerializeField, HideInInspector]			private bool enableAudio360 = false;			void ISerializationCallbackReceiver.OnBeforeSerialize()	{ }			void ISerializationCallbackReceiver.OnAfterDeserialize()			{#if false				if (enableAudio360 && audioOutput == Android.AudioOutput.System)				{					audioOutput = Android.AudioOutput.FacebookAudio360;					enableAudio360 = false;				}#else				if (enableAudio360 && audioMode == AudioMode.SystemDirect)				{					audioMode = AudioMode.FacebookAudio360;					enableAudio360 = false;				}#endif			}			#endregion	// Upgrade from Version 1.x		}		[System.Serializable]		public class OptionsWebGL : PlatformOptions		{			public WebGL.ExternalLibrary externalLibrary = WebGL.ExternalLibrary.None;			public bool useTextureMips = false;			public override bool IsModified()			{				return (base.IsModified() || externalLibrary != WebGL.ExternalLibrary.None || useTextureMips);			}			// Decryption support			public override string GetKeyServerAuthToken() { return null; }			public override byte[] GetOverrideDecryptionKey() { return null; }		}		// TODO: move these to a Setup object		[SerializeField] OptionsWindows _optionsWindows = new OptionsWindows();		[SerializeField] OptionsApple _options_macOS = new OptionsApple(OptionsApple.TextureFormat.BGRA, OptionsApple.Flags.None);		[SerializeField] OptionsApple _options_iOS = new OptionsApple(OptionsApple.TextureFormat.BGRA, OptionsApple.Flags.None);		[SerializeField] OptionsApple _options_tvOS = new OptionsApple(OptionsApple.TextureFormat.BGRA, OptionsApple.Flags.None);		[SerializeField] OptionsApple _options_visionOS = new OptionsApple(OptionsApple.TextureFormat.BGRA, OptionsApple.Flags.None);		[SerializeField] OptionsAndroid _optionsAndroid = new OptionsAndroid();		[SerializeField] OptionsWindowsUWP _optionsWindowsUWP = new OptionsWindowsUWP();		[SerializeField] OptionsWebGL _optionsWebGL = new OptionsWebGL();		public OptionsWindows PlatformOptionsWindows { get { return _optionsWindows; } }		public OptionsApple PlatformOptions_macOS { get { return _options_macOS; } }		public OptionsApple PlatformOptions_iOS { get { return _options_iOS; } }		public OptionsApple PlatformOptions_tvOS { get { return _options_tvOS; } }		public OptionsApple PlatformOptions_visionOS { get { return _options_visionOS; } }		public OptionsAndroid PlatformOptionsAndroid { get { return _optionsAndroid; } }		public OptionsWindowsUWP PlatformOptionsWindowsUWP { get { return _optionsWindowsUWP; } }		public OptionsWebGL PlatformOptionsWebGL { get { return _optionsWebGL; } }#endregion // PlatformOptions	}#region PlatformOptionsExtensions	public static class OptionsAppleExtensions	{		public static bool GenerateMipmaps(this MediaPlayer.OptionsApple.Flags flags)		{			return (flags & MediaPlayer.OptionsApple.Flags.GenerateMipMaps) == MediaPlayer.OptionsApple.Flags.GenerateMipMaps;		}		public static MediaPlayer.OptionsApple.Flags SetGenerateMipMaps(this MediaPlayer.OptionsApple.Flags flags, bool b)		{			if (flags.GenerateMipmaps() ^ b)			{				flags = b ? flags | MediaPlayer.OptionsApple.Flags.GenerateMipMaps						  : flags & ~MediaPlayer.OptionsApple.Flags.GenerateMipMaps;			}			return flags;		}		public static bool AllowExternalPlayback(this MediaPlayer.OptionsApple.Flags flags)		{			return (flags & MediaPlayer.OptionsApple.Flags.AllowExternalPlayback) == MediaPlayer.OptionsApple.Flags.AllowExternalPlayback;		}		public static MediaPlayer.OptionsApple.Flags SetAllowExternalPlayback(this MediaPlayer.OptionsApple.Flags flags, bool b)		{			if (flags.AllowExternalPlayback() ^ b)			{				flags = b ? flags | MediaPlayer.OptionsApple.Flags.AllowExternalPlayback						  : flags & ~MediaPlayer.OptionsApple.Flags.AllowExternalPlayback;			}			return flags;		}		public static bool PlayWithoutBuffering(this MediaPlayer.OptionsApple.Flags flags)		{			return (flags & MediaPlayer.OptionsApple.Flags.PlayWithoutBuffering) == MediaPlayer.OptionsApple.Flags.PlayWithoutBuffering;		}		public static MediaPlayer.OptionsApple.Flags SetPlayWithoutBuffering(this MediaPlayer.OptionsApple.Flags flags, bool b)		{			if (flags.PlayWithoutBuffering() ^ b)			{				flags = b ? flags | MediaPlayer.OptionsApple.Flags.PlayWithoutBuffering						  : flags & ~MediaPlayer.OptionsApple.Flags.PlayWithoutBuffering;			}			return flags;		}		public static bool UseSinglePlayerItem(this MediaPlayer.OptionsApple.Flags flags)		{			return (flags & MediaPlayer.OptionsApple.Flags.UseSinglePlayerItem) == MediaPlayer.OptionsApple.Flags.UseSinglePlayerItem;		}		public static MediaPlayer.OptionsApple.Flags SetUseSinglePlayerItem(this MediaPlayer.OptionsApple.Flags flags, bool b)		{			if (flags.UseSinglePlayerItem() ^ b)			{				flags = b ? flags | MediaPlayer.OptionsApple.Flags.UseSinglePlayerItem						  : flags & ~MediaPlayer.OptionsApple.Flags.UseSinglePlayerItem;			}			return flags;		}		public static bool ResumePlaybackAfterAudioSessionRouteChange(this MediaPlayer.OptionsApple.Flags flags)		{			return (flags & MediaPlayer.OptionsApple.Flags.ResumeMediaPlaybackAfterAudioSessionRouteChange) == MediaPlayer.OptionsApple.Flags.ResumeMediaPlaybackAfterAudioSessionRouteChange;		}		public static MediaPlayer.OptionsApple.Flags SetResumePlaybackAfterAudioSessionRouteChange(this MediaPlayer.OptionsApple.Flags flags, bool b)		{			if (flags.ResumePlaybackAfterAudioSessionRouteChange() ^ b)			{				flags = b ? flags | MediaPlayer.OptionsApple.Flags.ResumeMediaPlaybackAfterAudioSessionRouteChange						  : flags & ~MediaPlayer.OptionsApple.Flags.ResumeMediaPlaybackAfterAudioSessionRouteChange;			}			return flags;		}	}#endregion // PlatformOptionsExtensions}
 |