public override void Update() { Native.Update(_playerInstance); UpdateTracks(); UpdateTextCue(); _lastError = (ErrorCode)Native.GetLastErrorCode(_playerInstance); UpdateTimeRanges(); UpdateSubtitles(); Update_Textures(); UpdateDisplayFrameRate(); if (!_isMediaLoaded) { if (HasVideo() && _eyeTextures[0].texture != null) { Native.VideoTrack videoTrack; if (Native.GetActiveVideoTrackInfo(_playerInstance, out videoTrack)) { Helper.LogInfo("Using playback path: " + _playerDescription + " (" + videoTrack.frameWidth + "x" + videoTrack.frameHeight + "@" + videoTrack.frameRate.ToString("F2") + ")"); _isMediaLoaded = true; } } else if (HasAudio() && !HasVideo()) { Helper.LogInfo("Using playback path: " + _playerDescription); _isMediaLoaded = true; } } }
public override void Update() { if (AVPPlayerUpdate(_player)) { IssuePluginEvent(AVPPluginEventType.PlayerRender); } _lastError = AVPPlayerGetLastError(_player); UpdateTexture(); // Check for meta data to become available if (!_isMetaDataReady) { if (AVPPlayerHasMetaData(_player) || CanPlay()) { // MOZ - had to move this outside of HasVideo check _isMetaDataReady = true; if (HasVideo()) { if (_width > 0 && _height > 0) { if (Mathf.Max(_width, _height) > SystemInfo.maxTextureSize) { Debug.LogError("[AVProVideo] Video dimensions larger than maxTextureSize"); } } _playerDescription = "AVFoundation"; Helper.LogInfo("Using playback path: " + _playerDescription + " (" + _width + "x" + _height + "@" + GetVideoFrameRate().ToString("F2") + ")"); } else if (HasAudio()) { } } } }
void OnApplicationPause(bool pauseStatus) { #if !(UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN) // Debug.Log("OnApplicationPause: pauseStatus: " + pauseStatus); if (pauseStatus) { if (_pauseMediaOnAppPause) { if (Control != null && Control.IsPlaying()) { _wasPlayingOnPause = true; #if !UNITY_IPHONE Control.Pause(); #endif Helper.LogInfo("OnApplicationPause: pausing video"); } } } else { if (_playMediaOnAppUnpause) { // Catch coming back from power off state when no lock screen OnApplicationFocus(true); } } #endif }
public void UpdateTexture() { IntPtr native; int width; int height; TextureFormat format; bool flipped; if (AVPPlayerGetTexture(_player, out native, out width, out height, out format, out flipped)) { if (_texture == null || _texture.width != width || _texture.height != height || _texture.format != format) { Helper.LogInfo("CreateExternalTexture(" + width + ", " + height + ", " + format + ", false, false, " + native + ")"); _texture = Texture2D.CreateExternalTexture(width, height, format, /*mipmap*/ false, /*linear*/ false, native); _width = width; _height = height; } else { _texture.UpdateExternalTexture(native); } _flipped = flipped; } }
public AndroidMediaPlayer(bool useFastOesPath, bool showPosterFrame, Android.VideoApi api, bool enable360Audio, Audio360ChannelMode channelMode, bool preferSoftware) { m_API = api; // Create a java-size video class up front m_Video = s_Interface.Call <AndroidJavaObject>("CreatePlayer", (int)m_API, useFastOesPath, enable360Audio, (int)channelMode, preferSoftware); if (m_Video != null) { m_Method_SetHeadRotation = AndroidJNIHelper.GetMethodID(m_Video.GetRawClass(), "SetHeadRotation", "(FFFF)V", false); m_Method_SetFocusProps = AndroidJNIHelper.GetMethodID(m_Video.GetRawClass(), "SetFocusProps", "(FF)V", false); m_Method_SetFocusEnabled = AndroidJNIHelper.GetMethodID(m_Video.GetRawClass(), "SetFocusEnabled", "(Z)V", false); m_Method_SetFocusRotation = AndroidJNIHelper.GetMethodID(m_Video.GetRawClass(), "SetFocusRotation", "(FFFF)V", false); m_Method_GetCurrentTimeMs = AndroidJNIHelper.GetMethodID(m_Video.GetRawClass(), "GetCurrentTimeMs", "()J", false); m_Method_GetSourceVideoFrameRate = AndroidJNIHelper.GetMethodID(m_Video.GetRawClass(), "GetSourceVideoFrameRate", "()F", false); m_Method_IsPlaying = AndroidJNIHelper.GetMethodID(m_Video.GetRawClass(), "IsPlaying", "()Z", false); m_Method_IsPaused = AndroidJNIHelper.GetMethodID(m_Video.GetRawClass(), "IsPaused", "()Z", false); m_Method_IsFinished = AndroidJNIHelper.GetMethodID(m_Video.GetRawClass(), "IsFinished", "()Z", false); m_Method_IsSeeking = AndroidJNIHelper.GetMethodID(m_Video.GetRawClass(), "IsSeeking", "()Z", false); m_Method_IsBuffering = AndroidJNIHelper.GetMethodID(m_Video.GetRawClass(), "IsBuffering", "()Z", false); m_Method_IsLooping = AndroidJNIHelper.GetMethodID(m_Video.GetRawClass(), "IsLooping", "()Z", false); m_Method_HasVideo = AndroidJNIHelper.GetMethodID(m_Video.GetRawClass(), "HasVideo", "()Z", false); m_Method_HasAudio = AndroidJNIHelper.GetMethodID(m_Video.GetRawClass(), "HasAudio", "()Z", false); m_iPlayerIndex = m_Video.Call <int>("GetPlayerIndex"); Helper.LogInfo("Creating player " + m_iPlayerIndex); //Debug.Log( "AVPro: useFastOesPath: " + useFastOesPath ); SetOptions(useFastOesPath, showPosterFrame); // Initialise renderer, on the render thread AndroidMediaPlayer.IssuePluginEvent(Native.AVPPluginEvent.PlayerSetup, m_iPlayerIndex); } }
private bool StartOpenMediaFromBufferInternal(ulong length) { bool result = false; // Open the video file if (_controlInterface != null) { CloseMedia(); _isMediaOpened = true; _autoPlayOnStartTriggered = !_autoPlayOnStart; Helper.LogInfo("Starting Opening buffer of length " + length, this); if (!_controlInterface.StartOpenMediaFromBuffer(length)) { Debug.LogError("[AVProVideo] Failed to start open video from buffer", this); if (GetCurrentPlatformOptions() != PlatformOptionsWindows || PlatformOptionsWindows.videoApi != Windows.VideoApi.DirectShow) { Debug.LogError("[AVProVideo] Loading from buffer is currently only supported in Windows when using the DirectShow API"); } } else { SetPlaybackOptions(); result = true; StartRenderCoroutine(); } } return(result); }
public void OnApplicationQuit() { if (s_GlobalStartup) { Helper.LogInfo("Shutdown"); // 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].CloseVideo(); } } #if UNITY_EDITOR #if UNITY_EDITOR_WIN WindowsMediaPlayer.DeinitPlatform(); #endif #else #if (UNITY_STANDALONE_WIN) WindowsMediaPlayer.DeinitPlatform(); #endif #endif s_GlobalStartup = false; } }
protected void Initialise() { BaseMediaPlayer mediaPlayer = CreatePlatformMediaPlayer(); if (mediaPlayer != null) { // Set-up interface m_Control = mediaPlayer; m_Texture = mediaPlayer; m_Info = mediaPlayer; m_Player = mediaPlayer; m_Dispose = mediaPlayer; if (!s_GlobalStartup) { #if UNITY_5 Helper.LogInfo(string.Format("Initialising AVPro Video (script v{0} plugin v{1}) on {2}/{3} (MT {4})", Helper.ScriptVersion, mediaPlayer.GetVersion(), SystemInfo.graphicsDeviceName, SystemInfo.graphicsDeviceVersion, SystemInfo.graphicsMultiThreaded)); #else Helper.LogInfo(string.Format("Initialising AVPro Video (script v{0} plugin v{1}) on {2}/{3}", Helper.ScriptVersion, mediaPlayer.GetVersion(), SystemInfo.graphicsDeviceName, SystemInfo.graphicsDeviceVersion)); #endif #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; } } }
private bool OpenVideoFromFile() { bool result = false; // Open the video file if (m_Control != null) { CloseVideo(); m_VideoOpened = true; m_AutoStartTriggered = !m_AutoStart; m_EventFired_MetaDataReady = false; m_EventFired_ReadyToPlay = false; m_EventFired_Started = false; m_EventFired_FirstFrameReady = false; // Potentially override the file location long fileOffset = GetPlatformFileOffset(); string fullPath = GetPlatformFilePath(GetPlatform(), ref m_VideoPath, ref m_VideoLocation); if (!string.IsNullOrEmpty(m_VideoPath)) { bool checkForFileExist = true; if (fullPath.Contains("://")) { checkForFileExist = false; } #if (UNITY_ANDROID) checkForFileExist = false; #endif if (checkForFileExist && !System.IO.File.Exists(fullPath)) { Debug.LogError("[AVProVideo] File not found: " + fullPath, this); } else { Helper.LogInfo("Opening " + fullPath + " (offset " + fileOffset + ")", this); if (!m_Control.OpenVideoFromFile(fullPath, fileOffset)) { Debug.LogError("[AVProVideo] Failed to open " + fullPath, this); } else { SetPlaybackOptions(); result = true; StartRenderCoroutine(); } } } else { Debug.LogError("[AVProVideo] No file path specified", this); } } return(result); }
public override void Render() { if (m_Video != null) { //GL.InvalidateState(); AndroidMediaPlayer.IssuePluginEvent(AVPPluginEvent.PlayerUpdate, m_iPlayerIndex); //GL.InvalidateState(); // Check if we can create the texture // Scan for a change in resolution if (m_Texture != null) { int newWidth = m_Video.Call <int>("GetWidth"); int newHeight = m_Video.Call <int>("GetHeight"); if (newWidth != m_Width || newHeight != m_Height) { m_Texture = null; m_TextureHandle = 0; } } int textureHandle = m_Video.Call <int>("GetTextureHandle"); if (textureHandle > 0 && textureHandle != m_TextureHandle) { int newWidth = m_Video.Call <int>("GetWidth"); int newHeight = m_Video.Call <int>("GetHeight"); if (Mathf.Max(newWidth, newHeight) > SystemInfo.maxTextureSize) { m_Width = newWidth; m_Height = newHeight; m_TextureHandle = textureHandle; Debug.LogError("[AVProVideo] Video dimensions larger than maxTextureSize"); } else if (newWidth > 0 && newHeight > 0) { m_Width = newWidth; m_Height = newHeight; m_TextureHandle = textureHandle; _playerDescription = "MediaPlayer"; Helper.LogInfo("Using playback path: " + _playerDescription + " (" + m_Width + "x" + m_Height + "@" + GetVideoFrameRate().ToString("F2") + ")"); m_Texture = Texture2D.CreateExternalTexture(m_Width, m_Height, TextureFormat.RGBA32, false, false, new System.IntPtr(textureHandle)); if (m_Texture != null) { ApplyTextureProperties(m_Texture); } Helper.LogInfo("Texture ID: " + textureHandle); } } if (m_DurationMs == 0.0f) { m_DurationMs = (float)(m_Video.Call <long>("GetDurationMs")); // if( m_DurationMs > 0.0f ) { Helper.LogInfo("Duration: " + m_DurationMs); } } } }
private void AddEvent(MediaPlayerEvent.EventType et) { Helper.LogInfo("[MediaPlayer] Event: " + et.ToString(), this); _eventLog.Enqueue(et.ToString()); if (_eventLog.Count > 5) { _eventLog.Dequeue(); _eventTimer = 1f; } }
private bool OpenVideoFromFile() { bool result = false; if (m_Control != null) { CloseVideo(); m_VideoOpened = true; m_AutoStartTriggered = !m_AutoStart; m_EventFired_MetaDataReady = false; m_EventFired_ReadyToPlay = false; m_EventFired_Started = false; m_EventFired_FirstFrameReady = false; long platformFileOffset = GetPlatformFileOffset(); string platformFilePath = GetPlatformFilePath(GetPlatform(), ref m_VideoPath, ref m_VideoLocation); if (!string.IsNullOrEmpty(m_VideoPath)) { bool flag = true; if (platformFilePath.Contains("://")) { flag = false; } if (flag && !File.Exists(platformFilePath)) { Debug.LogError("[AVProVideo] File not found: " + platformFilePath, this); } else { Helper.LogInfo("Opening " + platformFilePath + " (offset " + platformFileOffset + ")", this); if (!m_Control.OpenVideoFromFile(platformFilePath, platformFileOffset)) { Debug.LogError("[AVProVideo] Failed to open " + platformFilePath, this); } else { SetPlaybackOptions(); result = true; StartRenderCoroutine(); } } } else { Debug.LogError("[AVProVideo] No file path specified", this); } } return result; }
private void OnApplicationQuit() { if (s_GlobalStartup) { Helper.LogInfo("Shutdown"); MediaPlayer[] array = Resources.FindObjectsOfTypeAll<MediaPlayer>(); if (array != null && array.Length > 0) { for (int i = 0; i < array.Length; i++) { array[i].CloseVideo(); } } WindowsMediaPlayer.DeinitPlatform(); s_GlobalStartup = false; } }
protected void Initialise() { BaseMediaPlayer baseMediaPlayer = CreatePlatformMediaPlayer(); if (baseMediaPlayer != null) { m_Control = baseMediaPlayer; m_Texture = baseMediaPlayer; m_Info = baseMediaPlayer; m_Player = baseMediaPlayer; m_Dispose = baseMediaPlayer; if (!s_GlobalStartup) { Helper.LogInfo(string.Format("Initialising AVPro Video (script v{0} plugin v{1}) on {2}/{3} (MT {4})", "1.5.8", baseMediaPlayer.GetVersion(), SystemInfo.graphicsDeviceName, SystemInfo.graphicsDeviceVersion, SystemInfo.graphicsMultiThreaded)); s_GlobalStartup = true; } } }
void OnApplicationFocus(bool focusStatus) { #if !(UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN) // Debug.Log("OnApplicationFocus: focusStatus: " + focusStatus); if (focusStatus) { if (Control != null && _wasPlayingOnPause) { _wasPlayingOnPause = false; Control.Play(); Helper.LogInfo("OnApplicationFocus: playing video again"); } } #endif }
public AndroidMediaPlayer(bool useFastOesPath, bool showPosterFrame, Android.VideoApi api, bool enable360Audio, Audio360ChannelMode channelMode) { m_API = api; // Create a java-size video class up front m_Video = s_Interface.Call <AndroidJavaObject>("CreatePlayer", (int)m_API, enable360Audio, (int)channelMode); if (m_Video != null) { m_iPlayerIndex = m_Video.Call <int>("GetPlayerIndex"); Helper.LogInfo("Creating player " + m_iPlayerIndex); //Debug.Log( "AVPro: useFastOesPath: " + useFastOesPath ); SetOptions(useFastOesPath, showPosterFrame); // Initialise renderer, on the render thread AndroidMediaPlayer.IssuePluginEvent(Native.AVPPluginEvent.PlayerSetup, m_iPlayerIndex); } }
public AndroidMediaPlayer(bool useFastOesPath, bool showPosterFrame, Android.VideoApi api, bool enable360Audio, Audio360ChannelMode channelMode, bool preferSoftware) { #if UNITY_5 || UNITY_5_4_OR_NEWER Debug.Assert(s_Interface != null); Debug.Assert(s_bInitialised); #endif m_API = api; // Create a java-size video class up front m_Video = s_Interface.Call <AndroidJavaObject>("CreatePlayer", (int)m_API, useFastOesPath, enable360Audio, (int)channelMode, preferSoftware); if (m_Video != null) { m_Method_Update = GetMethod("Update", "()V"); m_Method_SetHeadRotation = GetMethod("SetHeadRotation", "(FFFF)V"); m_Method_SetFocusProps = GetMethod("SetFocusProps", "(FF)V"); m_Method_SetFocusEnabled = GetMethod("SetFocusEnabled", "(Z)V"); m_Method_SetFocusRotation = GetMethod("SetFocusRotation", "(FFFF)V"); m_Method_GetCurrentTimeMs = GetMethod("GetCurrentTimeMs", "()J"); m_Method_GetSourceVideoFrameRate = GetMethod("GetSourceVideoFrameRate", "()F"); m_Method_IsPlaying = GetMethod("IsPlaying", "()Z"); m_Method_IsPaused = GetMethod("IsPaused", "()Z"); m_Method_IsFinished = GetMethod("IsFinished", "()Z"); m_Method_IsSeeking = GetMethod("IsSeeking", "()Z"); m_Method_IsBuffering = GetMethod("IsBuffering", "()Z"); m_Method_IsLooping = GetMethod("IsLooping", "()Z"); m_Method_HasVideo = GetMethod("HasVideo", "()Z"); m_Method_HasAudio = GetMethod("HasAudio", "()Z"); m_iPlayerIndex = m_Video.Call <int>("GetPlayerIndex"); Helper.LogInfo("Creating player " + m_iPlayerIndex); Debug.Log("AVPro: useFastOesPath: " + useFastOesPath); SetOptions(useFastOesPath, showPosterFrame); // Initialise renderer, on the render thread AndroidMediaPlayer.IssuePluginEvent(Native.AVPPluginEvent.PlayerSetup, m_iPlayerIndex); } else { Debug.LogError("[AVProVideo] Failed to create player instance"); } }
public void OnApplicationPause(bool pauseStatus) { #if !(UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN) // Debug.Log("OnApplicationPause: pauseStatus: " + pauseStatus); if (pauseStatus) { if (m_Control != null && m_Control.IsPlaying()) { m_WasPlayingOnPause = true; m_Control.Pause(); Helper.LogInfo("OnApplicationPause: pausing video"); } } else { // Catch coming back from power off state when no lock screen OnApplicationFocus(true); } #endif }
public override void Render() { if (m_Video != null) { if (m_UseFastOesPath) { // This is needed for at least Unity 5.5.0, otherwise it just renders black in OES mode GL.InvalidateState(); } AndroidMediaPlayer.IssuePluginEvent(Native.AVPPluginEvent.PlayerUpdate, m_iPlayerIndex); if (m_UseFastOesPath) { GL.InvalidateState(); } // Check if we can create the texture // Scan for a change in resolution int newWidth = -1; int newHeight = -1; if (m_Texture != null) { #if DLL_METHODS newWidth = Native._GetWidth(m_iPlayerIndex); newHeight = Native._GetHeight(m_iPlayerIndex); #else newWidth = m_Video.Call <int>("GetWidth"); newHeight = m_Video.Call <int>("GetHeight"); #endif if (newWidth != m_Width || newHeight != m_Height) { m_Texture = null; m_TextureHandle = 0; } } #if DLL_METHODS int textureHandle = Native._GetTextureHandle(m_iPlayerIndex); #else int textureHandle = m_Video.Call <int>("GetTextureHandle"); #endif if (textureHandle != 0 && textureHandle != m_TextureHandle) { // Already got? (from above) if (newWidth == -1 || newHeight == -1) { #if DLL_METHODS newWidth = Native._GetWidth(m_iPlayerIndex); newHeight = Native._GetHeight(m_iPlayerIndex); #else newWidth = m_Video.Call <int>("GetWidth"); newHeight = m_Video.Call <int>("GetHeight"); #endif } if (Mathf.Max(newWidth, newHeight) > SystemInfo.maxTextureSize) { m_Width = newWidth; m_Height = newHeight; m_TextureHandle = textureHandle; Debug.LogError("[AVProVideo] Video dimensions larger than maxTextureSize"); } else if (newWidth > 0 && newHeight > 0) { m_Width = newWidth; m_Height = newHeight; m_TextureHandle = textureHandle; switch (m_API) { case Android.VideoApi.MediaPlayer: _playerDescription = "MediaPlayer"; break; case Android.VideoApi.ExoPlayer: _playerDescription = "ExoPlayer"; break; default: _playerDescription = "UnknownPlayer"; break; } Helper.LogInfo("Using playback path: " + _playerDescription + " (" + m_Width + "x" + m_Height + "@" + GetVideoFrameRate().ToString("F2") + ")"); // NOTE: From Unity 5.4.x when using OES textures, an error "OPENGL NATIVE PLUG-IN ERROR: GL_INVALID_OPERATION: Operation illegal in current state" will be logged. // We assume this is because we're passing in TextureFormat.RGBA32 which isn't the true texture format. This error should be safe to ignore. m_Texture = Texture2D.CreateExternalTexture(m_Width, m_Height, TextureFormat.RGBA32, false, false, new System.IntPtr(textureHandle)); if (m_Texture != null) { ApplyTextureProperties(m_Texture); } Helper.LogInfo("Texture ID: " + textureHandle); } } #if AVPROVIDEO_FIXREGRESSION_TEXTUREQUALITY_UNITY542 // In Unity 5.4.2 and above the video texture turns black when changing the TextureQuality in the Quality Settings // The code below gets around this issue. A bug report has been sent to Unity. So far we have tested and replicated the // "bug" in Windows only, but a user has reported it in Android too. // Texture.GetNativeTexturePtr() must sync with the rendering thread, so this is a large performance hit! if (_textureQuality != QualitySettings.masterTextureLimit) { if (m_Texture != null && textureHandle > 0 && m_Texture.GetNativeTexturePtr() == System.IntPtr.Zero) { //Debug.Log("RECREATING"); m_Texture.UpdateExternalTexture(new System.IntPtr(textureHandle)); } _textureQuality = QualitySettings.masterTextureLimit; } #endif } }
public bool EnableSubtitles(MediaPath mediaPath) { bool result = false; if (_subtitlesInterface != null) { if (mediaPath != null && !string.IsNullOrEmpty(mediaPath.Path)) { string fullPath = mediaPath.GetResolvedFullPath(); bool checkForFileExist = true; if (fullPath.Contains("://")) { checkForFileExist = false; } #if (!UNITY_EDITOR && UNITY_ANDROID) checkForFileExist = false; #endif if (checkForFileExist && !System.IO.File.Exists(fullPath)) { Debug.LogError("[AVProVideo] Subtitle file not found: " + fullPath, this); } else { Helper.LogInfo("Opening subtitles " + fullPath, this); _previousSubtitleIndex = -1; try { if (fullPath.Contains("://")) { // Use coroutine and WWW class for loading if (_loadSubtitlesRoutine != null) { StopCoroutine(_loadSubtitlesRoutine); _loadSubtitlesRoutine = null; } _loadSubtitlesRoutine = StartCoroutine(LoadSubtitlesCoroutine(fullPath, mediaPath)); } else { // Load directly from file string subtitleData = System.IO.File.ReadAllText(fullPath); if (_subtitlesInterface.LoadSubtitlesSRT(subtitleData)) { _subtitlePath = mediaPath; _sideloadSubtitles = false; result = true; } else { Debug.LogError("[AVProVideo] Failed to load subtitles" + fullPath, this); } } } catch (System.Exception e) { Debug.LogError("[AVProVideo] Failed to load subtitles " + fullPath, this); Debug.LogException(e, this); } } } else { Debug.LogError("[AVProVideo] No subtitle file path specified", this); } } else { _queueSubtitlePath = mediaPath; } return(result); }
//public override void SetAudioDeviceName(string name) //{ //} public override void Update() { Native.Update(_instance); _lastError = (ErrorCode)Native.GetLastErrorCode(_instance); if (_queueSetAudioTrackIndex >= 0 && _hasAudio) { // We have to queue the setting of the audio track, as doing it from the UI can result in a crash (for some unknown reason) Native.SetAudioTrack(_instance, _queueSetAudioTrackIndex); _queueSetAudioTrackIndex = -1; } // Update network buffering { _bufferedTimeRangeCount = Native.GetBufferedRanges(_instance, _bufferedTimeRanges, _bufferedTimeRanges.Length / 2); if (_bufferedTimeRangeCount > (_bufferedTimeRanges.Length / 2)) { _bufferedTimeRanges = new float[_bufferedTimeRangeCount * 2]; _bufferedTimeRangeCount = Native.GetBufferedRanges(_instance, _bufferedTimeRanges, _bufferedTimeRanges.Length / 2); } } UpdateSubtitles(); if (!_canPlay) { if (!_hasMetaData) { if (Native.HasMetaData(_instance)) { if (Native.HasVideo(_instance)) { _width = Native.GetWidth(_instance); _height = Native.GetHeight(_instance); _frameRate = Native.GetFrameRate(_instance); // Sometimes the dimensions aren't available yet, in which case fail and poll them again next loop if (_width > 0 && _height > 0) { _hasVideo = true; // Note: If the Unity editor Build platform isn't set to Windows then maxTextureSize will not be correct if (Mathf.Max(_width, _height) > SystemInfo.maxTextureSize // If we're running in the editor it may be emulating another platform // in which case maxTextureSize won't be correct, so ignore it. #if UNITY_EDITOR && !SystemInfo.graphicsDeviceName.ToLower().Contains("emulated") #endif ) { Debug.LogError(string.Format("[AVProVideo] Video dimensions ({0}x{1}) larger than maxTextureSize ({2} for current build target)", _width, _height, SystemInfo.maxTextureSize)); _width = _height = 0; _hasVideo = false; } } if (_hasVideo) { if (Native.HasAudio(_instance)) { _hasAudio = true; } } } else { if (Native.HasAudio(_instance)) { _hasAudio = true; } } if (_hasVideo || _hasAudio) { _hasMetaData = true; } _playerDescription = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(Native.GetPlayerDescription(_instance)); _supportsLinearColorSpace = !_playerDescription.Contains("MF-MediaEngine-Hardware"); Helper.LogInfo("Using playback path: " + _playerDescription + " (" + _width + "x" + _height + "@" + GetVideoFrameRate().ToString("F2") + ")"); if (_hasVideo) { OnTextureSizeChanged(); } } } if (_hasMetaData) { _canPlay = Native.CanPlay(_instance); } } #if UNITY_WSA // NOTE: I think this issue has been resolved now as of version 1.5.24. // The issue was caused by functions returning booleans incorrectly (4 bytes vs 1) // and as been resolved by specifying the return type during marshalling.. // Still we'll keep this code here until after more testing. // WSA has an issue where it can load the audio track first and the video track later // Here we try to handle this case and get the video track information when it arrives if (_hasAudio && !_hasVideo) { _width = Native.GetWidth(_instance); _height = Native.GetHeight(_instance); _frameRate = Native.GetFrameRate(_instance); if (_width > 0 && _height > 0) { _hasVideo = true; OnTextureSizeChanged(); } } #endif if (_hasVideo) { System.IntPtr newPtr = Native.GetTexturePointer(_instance); // Check for texture recreation (due to device loss or change in texture size) if (_texture != null && _nativeTexture != System.IntPtr.Zero && _nativeTexture != newPtr) { _width = Native.GetWidth(_instance); _height = Native.GetHeight(_instance); if (newPtr == System.IntPtr.Zero || (_width != _texture.width || _height != _texture.height)) { if (_width != _texture.width || _height != _texture.height) { Helper.LogInfo("Texture size changed: " + _width + " X " + _height); OnTextureSizeChanged(); } _nativeTexture = System.IntPtr.Zero; Texture2D.Destroy(_texture); _texture = null; } else if (_nativeTexture != newPtr) { _texture.UpdateExternalTexture(newPtr); _nativeTexture = newPtr; } } #if AVPROVIDEO_FIXREGRESSION_TEXTUREQUALITY_UNITY542 // In Unity 5.4.2 and above the video texture turns black when changing the TextureQuality in the Quality Settings // The code below gets around this issue. A bug report has been sent to Unity. So far we have tested and replicated the // "bug" in Windows only, but a user has reported it in Android too. // Texture.GetNativeTexturePtr() must sync with the rendering thread, so this is a large performance hit! if (_textureQuality != QualitySettings.masterTextureLimit) { if (_texture != null && _nativeTexture != System.IntPtr.Zero && _texture.GetNativeTexturePtr() == System.IntPtr.Zero) { //Debug.Log("RECREATING"); _texture.UpdateExternalTexture(_nativeTexture); } _textureQuality = QualitySettings.masterTextureLimit; } #endif // Check if a new texture has to be created if (_texture == null && _width > 0 && _height > 0 && newPtr != System.IntPtr.Zero) { _isTextureTopDown = Native.IsTextureTopDown(_instance); bool isLinear = (!_supportsLinearColorSpace && QualitySettings.activeColorSpace == ColorSpace.Linear); _texture = Texture2D.CreateExternalTexture(_width, _height, TextureFormat.RGBA32, _useTextureMips, isLinear, newPtr); if (_texture != null) { _texture.name = "AVProVideo"; _nativeTexture = newPtr; ApplyTextureProperties(_texture); } else { Debug.LogError("[AVProVideo] Failed to create texture"); } } } }
public override void Render() { if (m_Video != null) { //GL.InvalidateState(); AndroidMediaPlayer.IssuePluginEvent(Native.AVPPluginEvent.PlayerUpdate, m_iPlayerIndex); //GL.InvalidateState(); // Check if we can create the texture // Scan for a change in resolution int newWidth = -1; int newHeight = -1; if (m_Texture != null) { #if DLL_METHODS newWidth = Native._GetWidth(m_iPlayerIndex); newHeight = Native._GetHeight(m_iPlayerIndex); #else newWidth = m_Video.Call <int>("GetWidth"); newHeight = m_Video.Call <int>("GetHeight"); #endif if (newWidth != m_Width || newHeight != m_Height) { m_Texture = null; m_TextureHandle = 0; } } #if DLL_METHODS int textureHandle = Native._GetTextureHandle(m_iPlayerIndex); #else int textureHandle = m_Video.Call <int>("GetTextureHandle"); #endif if (textureHandle > 0 && textureHandle != m_TextureHandle) { // Already got? (from above) if (newWidth == -1 || newHeight == -1) { #if DLL_METHODS newWidth = Native._GetWidth(m_iPlayerIndex); newHeight = Native._GetHeight(m_iPlayerIndex); #else newWidth = m_Video.Call <int>("GetWidth"); newHeight = m_Video.Call <int>("GetHeight"); #endif } if (Mathf.Max(newWidth, newHeight) > SystemInfo.maxTextureSize) { m_Width = newWidth; m_Height = newHeight; m_TextureHandle = textureHandle; Debug.LogError("[AVProVideo] Video dimensions larger than maxTextureSize"); } else if (newWidth > 0 && newHeight > 0) { m_Width = newWidth; m_Height = newHeight; m_TextureHandle = textureHandle; _playerDescription = "MediaPlayer"; Helper.LogInfo("Using playback path: " + _playerDescription + " (" + m_Width + "x" + m_Height + "@" + GetVideoFrameRate().ToString("F2") + ")"); // NOTE: From Unity 5.4.x when using OES textures, an error "OPENGL NATIVE PLUG-IN ERROR: GL_INVALID_OPERATION: Operation illegal in current state" will be logged. // We assume this is because we're passing in TextureFormat.RGBA32 which isn't the true texture format. This error should be safe to ignore. m_Texture = Texture2D.CreateExternalTexture(m_Width, m_Height, TextureFormat.RGBA32, false, false, new System.IntPtr(textureHandle)); if (m_Texture != null) { ApplyTextureProperties(m_Texture); } Helper.LogInfo("Texture ID: " + textureHandle); } } #if UNITY_5_4_OR_NEWER // In Unity 5.4.2 and above the vidoe texture turns black when changing the TextureQuality in the Quality Settings // The code below gets around this issue. A bug report has been sent to Unity. So far we have tested and replicated the // "bug" in Windows only, but a user has reported it in Android too if (m_Texture != null && textureHandle > 0 && m_Texture.GetNativeTexturePtr() == System.IntPtr.Zero) { //Debug.Log("RECREATING"); m_Texture.UpdateExternalTexture(new System.IntPtr(textureHandle)); } #endif if (m_DurationMs == 0.0f) { #if DLL_METHODS m_DurationMs = (float)(Native._GetDuration(m_iPlayerIndex)); #else m_DurationMs = (float)(m_Video.Call <long>("GetDurationMs")); #endif // if( m_DurationMs > 0.0f ) { Helper.LogInfo("Duration: " + m_DurationMs); } } } }
public override void Update() { Native.Update(_instance); _lastError = (ErrorCode)Native.GetLastErrorCode(_instance); if (_queueSetAudioTrackIndex >= 0 && _hasAudio) { // We have to queue the setting of the audio track, as doing it from the UI can result in a crash (for some unknown reason) Native.SetAudioTrack(_instance, _queueSetAudioTrackIndex); _queueSetAudioTrackIndex = -1; } // Update network buffering { _bufferedTimeRangeCount = Native.GetBufferedRanges(_instance, _bufferedTimeRanges, _bufferedTimeRanges.Length / 2); if (_bufferedTimeRangeCount > (_bufferedTimeRanges.Length / 2)) { _bufferedTimeRanges = new float[_bufferedTimeRangeCount * 2]; _bufferedTimeRangeCount = Native.GetBufferedRanges(_instance, _bufferedTimeRanges, _bufferedTimeRanges.Length / 2); } } if (!_canPlay) { if (!_hasMetaData) { if (Native.HasMetaData(_instance)) { if (Native.HasVideo(_instance)) { _width = Native.GetWidth(_instance); _height = Native.GetHeight(_instance); _frameRate = Native.GetFrameRate(_instance); // Sometimes the dimensions aren't available yet, in which case fail and poll them again next loop if (_width > 0 && _height > 0) { _hasVideo = true; // Note: If the Unity editor Build platform isn't set to Windows then maxTextureSize will not be correct if (Mathf.Max(_width, _height) > SystemInfo.maxTextureSize) { Debug.LogError(string.Format("[AVProVideo] Video dimensions ({0}x{1}) larger than maxTextureSize ({2})", _width, _height, SystemInfo.maxTextureSize)); _width = _height = 0; _hasVideo = false; } } if (_hasVideo) { if (Native.HasAudio(_instance)) { _hasAudio = true; } } } else { if (Native.HasAudio(_instance)) { _hasAudio = true; } } if (_hasVideo || _hasAudio) { _hasMetaData = true; } _playerDescription = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(Native.GetPlayerDescription(_instance)); _supportsLinearColorSpace = !_playerDescription.Contains("MF-MediaEngine-Hardware"); Helper.LogInfo("Using playback path: " + _playerDescription + " (" + _width + "x" + _height + "@" + GetVideoFrameRate().ToString("F2") + ")"); if (_hasVideo) { OnTextureSizeChanged(); } } } if (_hasMetaData) { _canPlay = Native.CanPlay(_instance); } } if (_hasVideo) { System.IntPtr newPtr = Native.GetTexturePointer(_instance); // Check for texture recreation (due to device loss or change in texture size) if (_texture != null && _nativeTexture != System.IntPtr.Zero && _nativeTexture != newPtr) { _width = Native.GetWidth(_instance); _height = Native.GetHeight(_instance); if (newPtr == System.IntPtr.Zero || (_width != _texture.width || _height != _texture.height)) { if (_width != _texture.width || _height != _texture.height) { Helper.LogInfo("Texture size changed: " + _width + " X " + _height); OnTextureSizeChanged(); } _nativeTexture = System.IntPtr.Zero; Texture2D.Destroy(_texture); _texture = null; } else if (_nativeTexture != newPtr) { _texture.UpdateExternalTexture(newPtr); _nativeTexture = newPtr; } } #if UNITY_5_4_OR_NEWER // In Unity 5.4.2 and above the vidoe texture turns black when changing the TextureQuality in the Quality Settings // The code below gets around this issue. A bug report has been sent to Unity. So far we have tested and replicated the // "bug" in Windows only, but a user has reported it in Android too if (_texture != null && _nativeTexture != System.IntPtr.Zero && _texture.GetNativeTexturePtr() == System.IntPtr.Zero) { //Debug.Log("RECREATING"); _texture.UpdateExternalTexture(_nativeTexture); } #endif // Check if a new texture has to be created if (_texture == null && _width > 0 && _height > 0 && newPtr != System.IntPtr.Zero) { _isTextureTopDown = Native.IsTextureTopDown(_instance); _texture = Texture2D.CreateExternalTexture(_width, _height, TextureFormat.RGBA32, false, false, newPtr); if (_texture != null) { _nativeTexture = newPtr; ApplyTextureProperties(_texture); } else { Debug.LogError("[AVProVideo] Failed to create texture"); } } } }
public override void Update() { Native.Update(_instance); _lastError = (ErrorCode)Native.GetLastErrorCode(_instance); if (_queueSetAudioTrackIndex >= 0 && _hasAudio) { Native.SetAudioTrack(_instance, _queueSetAudioTrackIndex); _queueSetAudioTrackIndex = -1; } _bufferedTimeRangeCount = Native.GetBufferedRanges(_instance, _bufferedTimeRanges, _bufferedTimeRanges.Length / 2); if (_bufferedTimeRangeCount > _bufferedTimeRanges.Length / 2) { _bufferedTimeRanges = new float[_bufferedTimeRangeCount * 2]; _bufferedTimeRangeCount = Native.GetBufferedRanges(_instance, _bufferedTimeRanges, _bufferedTimeRanges.Length / 2); } if (!_canPlay) { if (!_hasMetaData && Native.HasMetaData(_instance)) { if (Native.HasVideo(_instance)) { _width = Native.GetWidth(_instance); _height = Native.GetHeight(_instance); _frameRate = Native.GetFrameRate(_instance); if (_width > 0 && _height > 0) { _hasVideo = true; if (Mathf.Max(_width, _height) > SystemInfo.maxTextureSize) { Debug.LogError($"[AVProVideo] Video dimensions ({_width}x{_height}) larger than maxTextureSize ({SystemInfo.maxTextureSize})"); _width = (_height = 0); _hasVideo = false; } } if (_hasVideo && Native.HasAudio(_instance)) { _hasAudio = true; } } else if (Native.HasAudio(_instance)) { _hasAudio = true; } if (_hasVideo || _hasAudio) { _hasMetaData = true; } _playerDescription = Marshal.PtrToStringAnsi(Native.GetPlayerDescription(_instance)); _supportsLinearColorSpace = !_playerDescription.Contains("MF-MediaEngine-Hardware"); Helper.LogInfo("Using playback path: " + _playerDescription + " (" + _width + "x" + _height + "@" + GetVideoFrameRate().ToString("F2") + ")"); if (_hasVideo) { OnTextureSizeChanged(); } } if (_hasMetaData) { _canPlay = Native.CanPlay(_instance); } } if (_hasVideo) { IntPtr texturePointer = Native.GetTexturePointer(_instance); if (_texture != null && _nativeTexture != IntPtr.Zero && _nativeTexture != texturePointer) { _width = Native.GetWidth(_instance); _height = Native.GetHeight(_instance); if (texturePointer == IntPtr.Zero || _width != _texture.width || _height != _texture.height) { if (_width != _texture.width || _height != _texture.height) { Helper.LogInfo("Texture size changed: " + _width + " X " + _height); OnTextureSizeChanged(); } _nativeTexture = IntPtr.Zero; UnityEngine.Object.Destroy(_texture); _texture = null; } else if (_nativeTexture != texturePointer) { _texture.UpdateExternalTexture(texturePointer); _nativeTexture = texturePointer; } } if (_texture == null && _width > 0 && _height > 0 && texturePointer != IntPtr.Zero) { _isTextureTopDown = Native.IsTextureTopDown(_instance); _texture = Texture2D.CreateExternalTexture(_width, _height, TextureFormat.RGBA32, /*mipmap:*/ false, /*linear:*/ false, texturePointer); if (_texture != null) { _nativeTexture = texturePointer; ApplyTextureProperties(_texture); } else { Debug.LogError("[AVProVideo] Failed to create texture"); } } } }
public override void Update() { Native.Update(_instance); _lastError = (ErrorCode)Native.GetLastErrorCode(_instance); if (_queueSetAudioTrackIndex >= 0 && _hasAudio) { // We have to queue the setting of the audio track, as doing it from the UI can result in a crash (for some unknown reason) Native.SetAudioTrack(_instance, _queueSetAudioTrackIndex); _queueSetAudioTrackIndex = -1; } if (!_canPlay) { if (!_hasMetaData) { if (Native.HasMetaData(_instance)) { if (Native.HasVideo(_instance)) { _width = Native.GetWidth(_instance); _height = Native.GetHeight(_instance); _frameRate = Native.GetFrameRate(_instance); // Sometimes the dimensions aren't available yet, in which case fail and poll them again next loop if (_width > 0 && _height > 0) { _hasVideo = true; // Note: If the Unity editor Build platform isn't set to Windows then maxTextureSize will not be correct if (Mathf.Max(_width, _height) > SystemInfo.maxTextureSize) { Debug.LogError(string.Format("[AVProVideo] Video dimensions ({0}x{1}) larger than maxTextureSize ({2})", _width, _height, SystemInfo.maxTextureSize)); _width = _height = 0; _hasVideo = false; } } if (_hasVideo) { if (Native.HasAudio(_instance)) { _hasAudio = true; } } } else { if (Native.HasAudio(_instance)) { _hasAudio = true; } } if (_hasVideo || _hasAudio) { _hasMetaData = true; } _playerDescription = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(Native.GetPlayerDescription(_instance)); _supportsLinearColorSpace = !_playerDescription.Contains("MF-MediaEngine-Hardware"); Helper.LogInfo("Using playback path: " + _playerDescription + " (" + _width + "x" + _height + "@" + GetVideoFrameRate().ToString("F2") + ")"); if (_hasVideo) { OnTextureSizeChanged(); } } } if (_hasMetaData) { _canPlay = Native.CanPlay(_instance); } } if (_hasVideo) { System.IntPtr newPtr = Native.GetTexturePointer(_instance); // Check for texture recreation (due to device loss or change in texture size) if (_texture != null && _nativeTexture != System.IntPtr.Zero && _nativeTexture != newPtr) { _width = Native.GetWidth(_instance); _height = Native.GetHeight(_instance); if (newPtr == System.IntPtr.Zero || (_width != _texture.width || _height != _texture.height)) { if (_width != _texture.width || _height != _texture.height) { Helper.LogInfo("Texture size changed: " + _width + " X " + _height); OnTextureSizeChanged(); } _nativeTexture = System.IntPtr.Zero; Texture2D.Destroy(_texture); _texture = null; } else if (_nativeTexture != newPtr) { _texture.UpdateExternalTexture(newPtr); _nativeTexture = newPtr; } } // Check if a new texture has to be created if (_texture == null && _width > 0 && _height > 0 && newPtr != System.IntPtr.Zero) { _isTextureTopDown = Native.IsTextureTopDown(_instance); _texture = Texture2D.CreateExternalTexture(_width, _height, TextureFormat.RGBA32, false, false, newPtr); if (_texture != null) { _nativeTexture = newPtr; ApplyTextureProperties(_texture); } else { Debug.LogError("[AVProVideo] Failed to create texture"); } } } }